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;

+      size_t outSizeProcessed = 0;

+      const CSzFileItem *f = db.db.Files + i;

+      size_t len;

+      WCHAR *temp;

+      len = SzArEx_GetFileNameUtf16(&db, i, NULL);

+      

+      if (len >= MAX_PATH)

+      {

+        res = SZ_ERROR_FAIL;

+        break;

+      }

+      

+      temp = path + pathLen;

+      

+      SzArEx_GetFileNameUtf16(&db, i, temp);

+      {

+        res = SzArEx_Extract(&db, &lookStream.s, i,

+          &blockIndex, &outBuffer, &outBufferSize,

+          &offset, &outSizeProcessed,

+          &allocImp, &allocTempImp);

+        if (res != SZ_OK)

+          break;

+      }

+      {

+        CSzFile outFile;

+        size_t processedSize;

+        size_t j;

+        size_t nameStartPos = 0;

+        for (j = 0; temp[j] != 0; j++)

+        {

+          if (temp[j] == '/')

+          {

+            temp[j] = 0;

+            MyCreateDir(path);

+            temp[j] = CHAR_PATH_SEPARATOR;

+            nameStartPos = j + 1;

+          }

+        }

+

+        if (f->IsDir)

+        {

+          MyCreateDir(path);

+          continue;

+        }

+        else

+        {

+          unsigned extLen;

+          const WCHAR *name = temp + nameStartPos;

+          unsigned len = (unsigned)wcslen(name);

+          unsigned nameLen = FindExt(temp + nameStartPos, &extLen);

+          unsigned extPrice = FindItem(kExts, sizeof(kExts) / sizeof(kExts[0]), name + len - extLen, extLen);

+          unsigned namePrice = FindItem(kNames, sizeof(kNames) / sizeof(kNames[0]), name, nameLen);

+

+          unsigned price = namePrice + extPrice * 64 + (nameStartPos == 0 ? 0 : (1 << 12));

+          if (minPrice > price)

+          {

+            minPrice = price;

+            executeFileIndex = i;

+            useShellExecute = (extPrice != k_EXE_ExtIndex);

+          }

+         

+          if (DoesFileOrDirExist(path))

+          {

+            errorMessage = "Duplicate file";

+            res = SZ_ERROR_FAIL;

+            break;

+          }

+          if (OutFile_OpenW(&outFile, path))

+          {

+            errorMessage = "Can't open output file";

+            res = SZ_ERROR_FAIL;

+            break;

+          }

+        }

+        processedSize = outSizeProcessed;

+        if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)

+        {

+          errorMessage = "Can't write output file";

+          res = SZ_ERROR_FAIL;

+        }

+        

+        #ifdef USE_WINDOWS_FILE

+        if (f->MTimeDefined)

+        {

+          FILETIME mTime;

+          mTime.dwLowDateTime = f->MTime.Low;

+          mTime.dwHighDateTime = f->MTime.High;

+          SetFileTime(outFile.handle, NULL, NULL, &mTime);

+        }

+        #endif

+        

+        {

+          SRes res2 = File_Close(&outFile);

+          if (res != SZ_OK)

+            break;

+          if (res2 != SZ_OK)

+          {

+            res = res2;

+            break;

+          }

+        }

+        #ifdef USE_WINDOWS_FILE

+        if (f->AttribDefined)

+          SetFileAttributesW(path, f->Attrib);

+        #endif

+      }

+    }

+

+    if (res == SZ_OK)

+    {

+      if (executeFileIndex == (UInt32)(Int32)-1)

+      {

+        errorMessage = "There is no file to execute";

+        res = SZ_ERROR_FAIL;

+      }

+      else

+      {

+        WCHAR *temp = path + pathLen;

+        UInt32 j;

+        SzArEx_GetFileNameUtf16(&db, executeFileIndex, temp);

+        for (j = 0; temp[j] != 0; j++)

+          if (temp[j] == '/')

+            temp[j] = CHAR_PATH_SEPARATOR;

+      }

+    }

+    IAlloc_Free(&allocImp, outBuffer);

+  }

+  SzArEx_Free(&db, &allocImp);

+

+  File_Close(&archiveStream.file);

+

+  if (res == SZ_OK)

+  {

+    HANDLE hProcess = 0;

+    if (useShellExecute)

+    {

+      SHELLEXECUTEINFO ei;

+      UINT32 executeRes;

+      BOOL success;

+      

+      memset(&ei, 0, sizeof(ei));

+      ei.cbSize = sizeof(ei);

+      ei.lpFile = path;

+      ei.fMask = SEE_MASK_NOCLOSEPROCESS

+          #ifndef UNDER_CE

+          | SEE_MASK_FLAG_DDEWAIT

+          #endif

+          /* | SEE_MASK_NO_CONSOLE */

+          ;

+      if (wcslen(cmdLineParams) != 0)

+        ei.lpParameters = cmdLineParams;

+      ei.nShow = SW_SHOWNORMAL; /* SW_HIDE; */

+      success = ShellExecuteEx(&ei);

+      executeRes = (UINT32)(UINT_PTR)ei.hInstApp;

+      if (!success || (executeRes <= 32 && executeRes != 0))  /* executeRes = 0 in Windows CE */

+        res = SZ_ERROR_FAIL;

+      else

+        hProcess = ei.hProcess;

+    }

+    else

+    {

+      STARTUPINFOW si;

+      PROCESS_INFORMATION pi;

+      WCHAR cmdLine[MAX_PATH * 3];

+

+      wcscpy(cmdLine, path);

+      wcscat(cmdLine, cmdLineParams);

+      memset(&si, 0, sizeof(si));

+      si.cb = sizeof(si);

+      if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0)

+        res = SZ_ERROR_FAIL;

+      else

+      {

+        CloseHandle(pi.hThread);

+        hProcess = pi.hProcess;

+      }

+    }

+    if (hProcess != 0)

+    {

+      WaitForSingleObject(hProcess, INFINITE);

+      CloseHandle(hProcess);

+    }

+  }

+

+  path[pathLen] = L'\0';

+  RemoveDirWithSubItems(path);

+

+  if (res == SZ_OK)

+    return 0;

+  

+  {

+    if (res == SZ_ERROR_UNSUPPORTED)

+      errorMessage = "Decoder doesn't support this archive";

+    else if (res == SZ_ERROR_MEM)

+      errorMessage = "Can't allocate required memory";

+    else if (res == SZ_ERROR_CRC)

+      errorMessage = "CRC error";

+    else

+    {

+      if (!errorMessage)

+        errorMessage = "ERROR";

+    }

+    if (errorMessage)

+      PrintErrorMessage(errorMessage);

+  }

+  return 1;

+}

diff --git a/C/Util/SfxSetup/SfxSetup.dsp b/C/Util/SfxSetup/SfxSetup.dsp
new file mode 100755
index 0000000..10814a5
--- /dev/null
+++ b/C/Util/SfxSetup/SfxSetup.dsp
@@ -0,0 +1,198 @@
+# Microsoft Developer Studio Project File - Name="SfxSetup" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Application" 0x0101

+

+CFG=SfxSetup - 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 "SfxSetup.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 "SfxSetup.mak" CFG="SfxSetup - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "SfxSetup - Win32 Release" (based on "Win32 (x86) Application")

+!MESSAGE "SfxSetup - Win32 Debug" (based on "Win32 (x86) Application")

+!MESSAGE 

+

+# Begin Project

+# PROP AllowPerConfigDependencies 0

+# PROP Scc_ProjName ""

+# PROP Scc_LocalPath ""

+CPP=cl.exe

+MTL=midl.exe

+RSC=rc.exe

+

+!IF  "$(CFG)" == "SfxSetup - 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 Target_Dir ""

+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c

+# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /FD /c

+# 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 /subsystem:windows /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 /subsystem:windows /machine:I386

+

+!ELSEIF  "$(CFG)" == "SfxSetup - 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 "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c

+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c

+# 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 /subsystem:windows /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 /subsystem:windows /debug /machine:I386 /pdbtype:sept

+

+!ENDIF 

+

+# Begin Target

+

+# Name "SfxSetup - Win32 Release"

+# Name "SfxSetup - 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

+# 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=..\..\Types.h

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=.\SfxSetup.c

+# End Source File

+# End Target

+# End Project

diff --git a/C/Util/SfxSetup/SfxSetup.dsw b/C/Util/SfxSetup/SfxSetup.dsw
new file mode 100755
index 0000000..128fcdd
--- /dev/null
+++ b/C/Util/SfxSetup/SfxSetup.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00

+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

+

+###############################################################################

+

+Project: "SfxSetup"=.\SfxSetup.dsp - Package Owner=<4>

+

+Package=<5>

+{{{

+}}}

+

+Package=<4>

+{{{

+}}}

+

+###############################################################################

+

+Global:

+

+Package=<5>

+{{{

+}}}

+

+Package=<3>

+{{{

+}}}

+

+###############################################################################

+

diff --git a/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile
new file mode 100755
index 0000000..5d91be1
--- /dev/null
+++ b/C/Util/SfxSetup/makefile
@@ -0,0 +1,35 @@
+PROG = 7zS2.sfx

+LIBS = $(LIBS) 

+CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE

+

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

+

+7Z_OBJS = \

+  $O\SfxSetup.obj \

+

+OBJS = \

+  $(7Z_OBJS) \

+  $(C_OBJS) \

+  $O\resource.res

+

+!include "../../../CPP/Build.mak"

+

+$(7Z_OBJS): $(*B).c

+	$(COMPL_O1)

+$(C_OBJS): ../../$(*B).c

+	$(COMPL_O1)

diff --git a/C/Util/SfxSetup/makefile_con b/C/Util/SfxSetup/makefile_con
new file mode 100755
index 0000000..3fbb6b6
--- /dev/null
+++ b/C/Util/SfxSetup/makefile_con
@@ -0,0 +1,35 @@
+PROG = 7zS2con.sfx

+LIBS = $(LIBS) 

+CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE -D_CONSOLE

+

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

+

+7Z_OBJS = \

+  $O\SfxSetup.obj \

+

+OBJS = \

+  $(7Z_OBJS) \

+  $(C_OBJS) \

+  $O\resource.res

+

+!include "../../../CPP/Build.mak"

+

+$(7Z_OBJS): $(*B).c

+	$(COMPL_O1)

+$(C_OBJS): ../../$(*B).c

+	$(COMPL_O1)

diff --git a/C/Util/SfxSetup/resource.rc b/C/Util/SfxSetup/resource.rc
new file mode 100755
index 0000000..efff95e
--- /dev/null
+++ b/C/Util/SfxSetup/resource.rc
@@ -0,0 +1,6 @@
+#include "../../../CPP/7zip/MyVersionInfo.rc"

+

+MY_VERSION_INFO_APP("7z Setup SFX small", "7zS2.sfx")

+

+1  ICON "setup.ico"

+

diff --git a/C/Util/SfxSetup/setup.ico b/C/Util/SfxSetup/setup.ico
new file mode 100755
index 0000000..dbb6ca8
--- /dev/null
+++ b/C/Util/SfxSetup/setup.ico
Binary files differ
diff --git a/C/Xz.c b/C/Xz.c
new file mode 100755
index 0000000..0bdf047
--- /dev/null
+++ b/C/Xz.c
@@ -0,0 +1,88 @@
+/* Xz.c - Xz

+2009-04-15 : Igor Pavlov : Public domain */

+

+#include "7zCrc.h"

+#include "CpuArch.h"

+#include "Xz.h"

+#include "XzCrc64.h"

+

+Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };

+Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' };

+

+unsigned Xz_WriteVarInt(Byte *buf, UInt64 v)

+{

+  unsigned i = 0;

+  do

+  {

+    buf[i++] = (Byte)((v & 0x7F) | 0x80);

+    v >>= 7;

+  }

+  while (v != 0);

+  buf[i - 1] &= 0x7F;

+  return i;

+}

+

+void Xz_Construct(CXzStream *p)

+{

+  p->numBlocks = p->numBlocksAllocated = 0;

+  p->blocks = 0;

+  p->flags = 0;

+}

+

+void Xz_Free(CXzStream *p, ISzAlloc *alloc)

+{

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

+  p->numBlocks = p->numBlocksAllocated = 0;

+  p->blocks = 0;

+}

+

+unsigned XzFlags_GetCheckSize(CXzStreamFlags f)

+{

+  int t = XzFlags_GetCheckType(f);

+  return (t == 0) ? 0 : (4 << ((t - 1) / 3));

+}

+

+void XzCheck_Init(CXzCheck *p, int mode)

+{

+  p->mode = mode;

+  switch (mode)

+  {

+    case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break;

+    case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break;

+    case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break;

+  }

+}

+

+void XzCheck_Update(CXzCheck *p, const void *data, size_t size)

+{

+  switch (p->mode)

+  {

+    case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break;

+    case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break;

+    case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break;

+  }

+}

+

+int XzCheck_Final(CXzCheck *p, Byte *digest)

+{

+  switch (p->mode)

+  {

+    case XZ_CHECK_CRC32:

+      SetUi32(digest, CRC_GET_DIGEST(p->crc));

+      break;

+    case XZ_CHECK_CRC64:

+    {

+      int i;

+      UInt64 v = CRC64_GET_DIGEST(p->crc64);

+      for (i = 0; i < 8; i++, v >>= 8)

+        digest[i] = (Byte)(v & 0xFF);

+      break;

+    }

+    case XZ_CHECK_SHA256:

+      Sha256_Final(&p->sha, digest);

+      break;

+    default:

+      return 0;

+  }

+  return 1;

+}

diff --git a/C/Xz.h b/C/Xz.h
new file mode 100755
index 0000000..d307963
--- /dev/null
+++ b/C/Xz.h
@@ -0,0 +1,252 @@
+/* Xz.h - Xz interface

+2010-09-17 : Igor Pavlov : Public domain */

+

+#ifndef __XZ_H

+#define __XZ_H

+

+#include "Sha256.h"

+

+EXTERN_C_BEGIN

+

+#define XZ_ID_Subblock 1

+#define XZ_ID_Delta 3

+#define XZ_ID_X86 4

+#define XZ_ID_PPC 5

+#define XZ_ID_IA64 6

+#define XZ_ID_ARM 7

+#define XZ_ID_ARMT 8

+#define XZ_ID_SPARC 9

+#define XZ_ID_LZMA2 0x21

+

+unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value);

+unsigned Xz_WriteVarInt(Byte *buf, UInt64 v);

+

+/* ---------- xz block ---------- */

+

+#define XZ_BLOCK_HEADER_SIZE_MAX 1024

+

+#define XZ_NUM_FILTERS_MAX 4

+#define XZ_BF_NUM_FILTERS_MASK 3

+#define XZ_BF_PACK_SIZE (1 << 6)

+#define XZ_BF_UNPACK_SIZE (1 << 7)

+

+#define XZ_FILTER_PROPS_SIZE_MAX 20

+

+typedef struct

+{

+  UInt64 id;

+  UInt32 propsSize;

+  Byte props[XZ_FILTER_PROPS_SIZE_MAX];

+} CXzFilter;

+

+typedef struct

+{

+  UInt64 packSize;

+  UInt64 unpackSize;

+  Byte flags;

+  CXzFilter filters[XZ_NUM_FILTERS_MAX];

+} CXzBlock;

+

+#define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)

+#define XzBlock_HasPackSize(p)   (((p)->flags & XZ_BF_PACK_SIZE) != 0)

+#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)

+

+SRes XzBlock_Parse(CXzBlock *p, const Byte *header);

+SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes);

+

+/* ---------- xz stream ---------- */

+

+#define XZ_SIG_SIZE 6

+#define XZ_FOOTER_SIG_SIZE 2

+

+extern Byte XZ_SIG[XZ_SIG_SIZE];

+extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];

+

+#define XZ_STREAM_FLAGS_SIZE 2

+#define XZ_STREAM_CRC_SIZE 4

+

+#define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE)

+#define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4)

+

+#define XZ_CHECK_MASK 0xF

+#define XZ_CHECK_NO 0

+#define XZ_CHECK_CRC32 1

+#define XZ_CHECK_CRC64 4

+#define XZ_CHECK_SHA256 10

+

+typedef struct

+{

+  int mode;

+  UInt32 crc;

+  UInt64 crc64;

+  CSha256 sha;

+} CXzCheck;

+

+void XzCheck_Init(CXzCheck *p, int mode);

+void XzCheck_Update(CXzCheck *p, const void *data, size_t size);

+int XzCheck_Final(CXzCheck *p, Byte *digest);

+

+typedef UInt16 CXzStreamFlags;

+

+#define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK)

+#define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK)

+#define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32)

+unsigned XzFlags_GetCheckSize(CXzStreamFlags f);

+

+SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf);

+SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream);

+

+typedef struct

+{

+  UInt64 unpackSize;

+  UInt64 totalSize;

+} CXzBlockSizes;

+

+typedef struct

+{

+  CXzStreamFlags flags;

+  size_t numBlocks;

+  size_t numBlocksAllocated;

+  CXzBlockSizes *blocks;

+  UInt64 startOffset;

+} CXzStream;

+

+void Xz_Construct(CXzStream *p);

+void Xz_Free(CXzStream *p, ISzAlloc *alloc);

+

+#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)

+

+UInt64 Xz_GetUnpackSize(const CXzStream *p);

+UInt64 Xz_GetPackSize(const CXzStream *p);

+

+typedef struct

+{

+  size_t num;

+  size_t numAllocated;

+  CXzStream *streams;

+} CXzs;

+

+void Xzs_Construct(CXzs *p);

+void Xzs_Free(CXzs *p, ISzAlloc *alloc);

+SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc);

+

+UInt64 Xzs_GetNumBlocks(const CXzs *p);

+UInt64 Xzs_GetUnpackSize(const CXzs *p);

+

+typedef enum

+{

+  CODER_STATUS_NOT_SPECIFIED,               /* use main error code instead */

+  CODER_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */

+  CODER_STATUS_NOT_FINISHED,                /* stream was not finished */

+  CODER_STATUS_NEEDS_MORE_INPUT             /* you must provide more input bytes */

+} ECoderStatus;

+

+typedef enum

+{

+  CODER_FINISH_ANY,   /* finish at any point */

+  CODER_FINISH_END    /* block must be finished at the end */

+} ECoderFinishMode;

+

+typedef struct _IStateCoder

+{

+  void *p;

+  void (*Free)(void *p, ISzAlloc *alloc);

+  SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);

+  void (*Init)(void *p);

+  SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

+      int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished);

+} IStateCoder;

+

+#define MIXCODER_NUM_FILTERS_MAX 4

+

+typedef struct

+{

+  ISzAlloc *alloc;

+  Byte *buf;

+  int numCoders;

+  int finished[MIXCODER_NUM_FILTERS_MAX - 1];

+  size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];

+  size_t size[MIXCODER_NUM_FILTERS_MAX - 1];

+  UInt64 ids[MIXCODER_NUM_FILTERS_MAX];

+  IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];

+} CMixCoder;

+

+void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);

+void MixCoder_Free(CMixCoder *p);

+void MixCoder_Init(CMixCoder *p);

+SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId);

+SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,

+    const Byte *src, SizeT *srcLen, int srcWasFinished,

+    ECoderFinishMode finishMode, ECoderStatus *status);

+

+typedef enum

+{

+  XZ_STATE_STREAM_HEADER,

+  XZ_STATE_STREAM_INDEX,

+  XZ_STATE_STREAM_INDEX_CRC,

+  XZ_STATE_STREAM_FOOTER,

+  XZ_STATE_STREAM_PADDING,

+  XZ_STATE_BLOCK_HEADER,

+  XZ_STATE_BLOCK,

+  XZ_STATE_BLOCK_FOOTER

+} EXzState;

+

+typedef struct

+{

+  EXzState state;

+  UInt32 pos;

+  unsigned alignPos;

+  unsigned indexPreSize;

+

+  CXzStreamFlags streamFlags;

+  

+  UInt32 blockHeaderSize;

+  UInt64 packSize;

+  UInt64 unpackSize;

+

+  UInt64 numBlocks;

+  UInt64 indexSize;

+  UInt64 indexPos;

+  UInt64 padSize;

+

+  UInt64 numStreams;

+

+  UInt32 crc;

+  CMixCoder decoder;

+  CXzBlock block;

+  CXzCheck check;

+  CSha256 sha;

+  Byte shaDigest[SHA256_DIGEST_SIZE];

+  Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];

+} CXzUnpacker;

+

+SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc);

+void XzUnpacker_Free(CXzUnpacker *p);

+

+/*

+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 XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,

+    const Byte *src, SizeT *srcLen, /* int srcWasFinished, */ int finishMode,

+    ECoderStatus *status);

+

+Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);

+

+EXTERN_C_END

+

+#endif

diff --git a/C/XzCrc64.c b/C/XzCrc64.c
new file mode 100755
index 0000000..f688b07
--- /dev/null
+++ b/C/XzCrc64.c
@@ -0,0 +1,33 @@
+/* XzCrc64.c -- CRC64 calculation

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

+

+#include "XzCrc64.h"

+

+#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42)

+UInt64 g_Crc64Table[256];

+

+void MY_FAST_CALL Crc64GenerateTable(void)

+{

+  UInt32 i;

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

+  {

+    UInt64 r = i;

+    int j;

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

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

+    g_Crc64Table[i] = r;

+  }

+}

+

+UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size)

+{

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

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

+    v = CRC64_UPDATE_BYTE(v, *p);

+  return v;

+}

+

+UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size)

+{

+  return CRC64_GET_DIGEST(Crc64Update(CRC64_INIT_VAL, data, size));

+}

diff --git a/C/XzCrc64.h b/C/XzCrc64.h
new file mode 100755
index 0000000..05d0d09
--- /dev/null
+++ b/C/XzCrc64.h
@@ -0,0 +1,26 @@
+/* XzCrc64.h -- CRC64 calculation

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

+

+#ifndef __XZ_CRC64_H

+#define __XZ_CRC64_H

+

+#include <stddef.h>

+

+#include "Types.h"

+

+EXTERN_C_BEGIN

+

+extern UInt64 g_Crc64Table[];

+

+void MY_FAST_CALL Crc64GenerateTable(void);

+

+#define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF)

+#define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL)

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

+

+UInt64 MY_FAST_CALL Crc64Update(UInt64 crc, const void *data, size_t size);

+UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size);

+

+EXTERN_C_END

+

+#endif

diff --git a/C/XzDec.c b/C/XzDec.c
new file mode 100755
index 0000000..2eca1af
--- /dev/null
+++ b/C/XzDec.c
@@ -0,0 +1,875 @@
+/* XzDec.c -- Xz Decode

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

+

+/* #define XZ_DUMP */

+

+#ifdef XZ_DUMP

+#include <stdio.h>

+#endif

+

+#include <stdlib.h>

+#include <string.h>

+

+#include "7zCrc.h"

+#include "Alloc.h"

+#include "Bra.h"

+#include "CpuArch.h"

+#include "Delta.h"

+#include "Lzma2Dec.h"

+

+#ifdef USE_SUBBLOCK

+#include "SbDec.h"

+#endif

+

+#include "Xz.h"

+

+#define XZ_CHECK_SIZE_MAX 64

+

+#define CODER_BUF_SIZE (1 << 17)

+

+unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)

+{

+  int i, limit;

+  *value = 0;

+  limit = (maxSize > 9) ? 9 : (int)maxSize;

+

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

+  {

+    Byte b = p[i];

+    *value |= (UInt64)(b & 0x7F) << (7 * i++);

+    if ((b & 0x80) == 0)

+      return (b == 0 && i != 1) ? 0 : i;

+  }

+  return 0;

+}

+

+/* ---------- BraState ---------- */

+

+#define BRA_BUF_SIZE (1 << 14)

+

+typedef struct

+{

+  size_t bufPos;

+  size_t bufConv;

+  size_t bufTotal;

+

+  UInt32 methodId;

+  int encodeMode;

+  UInt32 delta;

+  UInt32 ip;

+  UInt32 x86State;

+  Byte deltaState[DELTA_STATE_SIZE];

+

+  Byte buf[BRA_BUF_SIZE];

+} CBraState;

+

+void BraState_Free(void *pp, ISzAlloc *alloc)

+{

+  alloc->Free(alloc, pp);

+}

+

+SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)

+{

+  CBraState *p = ((CBraState *)pp);

+  alloc = alloc;

+  p->encodeMode = 0;

+  p->ip = 0;

+  if (p->methodId == XZ_ID_Delta)

+  {

+    if (propSize != 1)

+      return SZ_ERROR_UNSUPPORTED;

+    p->delta = (unsigned)props[0] + 1;

+  }

+  else

+  {

+    if (propSize == 4)

+    {

+      UInt32 v = GetUi32(props);

+      switch(p->methodId)

+      {

+        case XZ_ID_PPC:

+        case XZ_ID_ARM:

+        case XZ_ID_SPARC:

+          if ((v & 3) != 0)

+            return SZ_ERROR_UNSUPPORTED;

+          break;

+        case XZ_ID_ARMT:

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

+            return SZ_ERROR_UNSUPPORTED;

+          break;

+        case XZ_ID_IA64:

+          if ((v & 0xF) != 0)

+            return SZ_ERROR_UNSUPPORTED;

+          break;

+      }

+      p->ip = v;

+    }

+    else if (propSize != 0)

+      return SZ_ERROR_UNSUPPORTED;

+  }

+  return SZ_OK;

+}

+

+void BraState_Init(void *pp)

+{

+  CBraState *p = ((CBraState *)pp);

+  p->bufPos = p->bufConv = p->bufTotal = 0;

+  x86_Convert_Init(p->x86State);

+  if (p->methodId == XZ_ID_Delta)

+    Delta_Init(p->deltaState);

+}

+

+#define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break;

+

+static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

+    int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)

+{

+  CBraState *p = ((CBraState *)pp);

+  SizeT destLenOrig = *destLen;

+  SizeT srcLenOrig = *srcLen;

+  *destLen = 0;

+  *srcLen = 0;

+  finishMode = finishMode;

+  *wasFinished = 0;

+  while (destLenOrig > 0)

+  {

+    if (p->bufPos != p->bufConv)

+    {

+      size_t curSize = p->bufConv - p->bufPos;

+      if (curSize > destLenOrig)

+        curSize = destLenOrig;

+      memcpy(dest, p->buf + p->bufPos, curSize);

+      p->bufPos += curSize;

+      *destLen += curSize;

+      dest += curSize;

+      destLenOrig -= curSize;

+      continue;

+    }

+    p->bufTotal -= p->bufPos;

+    memmove(p->buf, p->buf + p->bufPos, p->bufTotal);

+    p->bufPos = 0;

+    p->bufConv = 0;

+    {

+      size_t curSize = BRA_BUF_SIZE - p->bufTotal;

+      if (curSize > srcLenOrig)

+        curSize = srcLenOrig;

+      memcpy(p->buf + p->bufTotal, src, curSize);

+      *srcLen += curSize;

+      src += curSize;

+      srcLenOrig -= curSize;

+      p->bufTotal += curSize;

+    }

+    if (p->bufTotal == 0)

+      break;

+    switch(p->methodId)

+    {

+      case XZ_ID_Delta:

+        if (p->encodeMode)

+          Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal);

+        else

+          Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal);

+        p->bufConv = p->bufTotal;

+        break;

+      case XZ_ID_X86:

+        p->bufConv = x86_Convert(p->buf, p->bufTotal, p->ip, &p->x86State, p->encodeMode);

+        break;

+      CASE_BRA_CONV(PPC)

+      CASE_BRA_CONV(IA64)

+      CASE_BRA_CONV(ARM)

+      CASE_BRA_CONV(ARMT)

+      CASE_BRA_CONV(SPARC)

+      default:

+        return SZ_ERROR_UNSUPPORTED;

+    }

+    p->ip += (UInt32)p->bufConv;

+

+    if (p->bufConv == 0)

+    {

+      if (!srcWasFinished)

+        break;

+      p->bufConv = p->bufTotal;

+    }

+  }

+  if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished)

+    *wasFinished = 1;

+  return SZ_OK;

+}

+

+SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc)

+{

+  CBraState *decoder;

+  if (id != XZ_ID_Delta &&

+      id != XZ_ID_X86 &&

+      id != XZ_ID_PPC &&

+      id != XZ_ID_IA64 &&

+      id != XZ_ID_ARM &&

+      id != XZ_ID_ARMT &&

+      id != XZ_ID_SPARC)

+    return SZ_ERROR_UNSUPPORTED;

+  p->p = 0;

+  decoder = alloc->Alloc(alloc, sizeof(CBraState));

+  if (decoder == 0)

+    return SZ_ERROR_MEM;

+  decoder->methodId = (UInt32)id;

+  p->p = decoder;

+  p->Free = BraState_Free;

+  p->SetProps = BraState_SetProps;

+  p->Init = BraState_Init;

+  p->Code = BraState_Code;

+  return SZ_OK;

+}

+

+/* ---------- SbState ---------- */

+

+#ifdef USE_SUBBLOCK

+

+static void SbState_Free(void *pp, ISzAlloc *alloc)

+{

+  CSubblockDec *p = (CSubblockDec *)pp;

+  SubblockDec_Free(p, alloc);

+  alloc->Free(alloc, pp);

+}

+

+static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)

+{

+  pp = pp;

+  props = props;

+  alloc = alloc;

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

+}

+

+static void SbState_Init(void *pp)

+{

+  SubblockDec_Init((CSubblockDec *)pp);

+}

+

+static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

+    int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)

+{

+  ECoderStatus status;

+  SRes res = SubblockDec_Decode((CSubblockDec *)pp, dest, destLen, src, srcLen, finishMode, &status);

+  srcWasFinished = srcWasFinished;

+  *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);

+  return res;

+}

+

+SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)

+{

+  CSubblockDec *decoder;

+  p->p = 0;

+  decoder = alloc->Alloc(alloc, sizeof(CSubblockDec));

+  if (decoder == 0)

+    return SZ_ERROR_MEM;

+  p->p = decoder;

+  p->Free = SbState_Free;

+  p->SetProps = SbState_SetProps;

+  p->Init = SbState_Init;

+  p->Code = SbState_Code;

+  SubblockDec_Construct(decoder);

+  return SZ_OK;

+}

+#endif

+

+/* ---------- Lzma2State ---------- */

+

+static void Lzma2State_Free(void *pp, ISzAlloc *alloc)

+{

+  Lzma2Dec_Free((CLzma2Dec *)pp, alloc);

+  alloc->Free(alloc, pp);

+}

+

+static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)

+{

+  if (propSize != 1)

+    return SZ_ERROR_UNSUPPORTED;

+  return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc);

+}

+

+static void Lzma2State_Init(void *pp)

+{

+  Lzma2Dec_Init((CLzma2Dec *)pp);

+}

+

+static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

+    int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)

+{

+  ELzmaStatus status;

+  /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */

+  SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, finishMode, &status);

+  srcWasFinished = srcWasFinished;

+  *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);

+  return res;

+}

+

+static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)

+{

+  CLzma2Dec *decoder = alloc->Alloc(alloc, sizeof(CLzma2Dec));

+  p->p = decoder;

+  if (decoder == 0)

+    return SZ_ERROR_MEM;

+  p->Free = Lzma2State_Free;

+  p->SetProps = Lzma2State_SetProps;

+  p->Init = Lzma2State_Init;

+  p->Code = Lzma2State_Code;

+  Lzma2Dec_Construct(decoder);

+  return SZ_OK;

+}

+

+

+void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)

+{

+  int i;

+  p->alloc = alloc;

+  p->buf = 0;

+  p->numCoders = 0;

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

+    p->coders[i].p = NULL;

+}

+

+void MixCoder_Free(CMixCoder *p)

+{

+  int i;

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

+  {

+    IStateCoder *sc = &p->coders[i];

+    if (p->alloc && sc->p)

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

+  }

+  p->numCoders = 0;

+  if (p->buf)

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

+}

+

+void MixCoder_Init(CMixCoder *p)

+{

+  int i;

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

+  {

+    p->size[i] = 0;

+    p->pos[i] = 0;

+    p->finished[i] = 0;

+  }

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

+  {

+    IStateCoder *coder = &p->coders[i];

+    coder->Init(coder->p);

+  }

+}

+

+SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId)

+{

+  IStateCoder *sc = &p->coders[coderIndex];

+  p->ids[coderIndex] = methodId;

+  switch(methodId)

+  {

+    case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);

+    #ifdef USE_SUBBLOCK

+    case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);

+    #endif

+  }

+  if (coderIndex == 0)

+    return SZ_ERROR_UNSUPPORTED;

+  return BraState_SetFromMethod(sc, methodId, p->alloc);

+}

+

+SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,

+    const Byte *src, SizeT *srcLen, int srcWasFinished,

+    ECoderFinishMode finishMode, ECoderStatus *status)

+{

+  SizeT destLenOrig = *destLen;

+  SizeT srcLenOrig = *srcLen;

+  Bool allFinished = True;

+  *destLen = 0;

+  *srcLen = 0;

+  *status = CODER_STATUS_NOT_FINISHED;

+

+  if (p->buf == 0)

+  {

+    p->buf = p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));

+    if (p->buf == 0)

+      return SZ_ERROR_MEM;

+  }

+

+  if (p->numCoders != 1)

+    finishMode = CODER_FINISH_ANY;

+

+  for (;;)

+  {

+    Bool processed = False;

+    int i;

+    /*

+    if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)

+      break;

+    */

+

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

+    {

+      SRes res;

+      IStateCoder *coder = &p->coders[i];

+      Byte *destCur;

+      SizeT destLenCur, srcLenCur;

+      const Byte *srcCur;

+      int srcFinishedCur;

+      int encodingWasFinished;

+      

+      if (i == 0)

+      {

+        srcCur = src;

+        srcLenCur = srcLenOrig - *srcLen;

+        srcFinishedCur = srcWasFinished;

+      }

+      else

+      {

+        srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1];

+        srcLenCur = p->size[i - 1] - p->pos[i - 1];

+        srcFinishedCur = p->finished[i - 1];

+      }

+      

+      if (i == p->numCoders - 1)

+      {

+        destCur = dest;

+        destLenCur = destLenOrig - *destLen;

+      }

+      else

+      {

+        if (p->pos[i] != p->size[i])

+          continue;

+        destCur = p->buf + (CODER_BUF_SIZE * i);

+        destLenCur = CODER_BUF_SIZE;

+      }

+      

+      res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished);

+

+      if (!encodingWasFinished)

+        allFinished = False;

+

+      if (i == 0)

+      {

+        *srcLen += srcLenCur;

+        src += srcLenCur;

+      }

+      else

+      {

+        p->pos[i - 1] += srcLenCur;

+      }

+

+      if (i == p->numCoders - 1)

+      {

+        *destLen += destLenCur;

+        dest += destLenCur;

+      }

+      else

+      {

+        p->size[i] = destLenCur;

+        p->pos[i] = 0;

+        p->finished[i] = encodingWasFinished;

+      }

+      

+      if (res != SZ_OK)

+        return res;

+

+      if (destLenCur != 0 || srcLenCur != 0)

+        processed = True;

+    }

+    if (!processed)

+      break;

+  }

+  if (allFinished)

+    *status = CODER_STATUS_FINISHED_WITH_MARK;

+  return SZ_OK;

+}

+

+SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)

+{

+  *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);

+  if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=

+      GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))

+    return SZ_ERROR_NO_ARCHIVE;

+  return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;

+}

+

+static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)

+{

+  return

+      indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) &&

+      (GetUi32(buf) == CrcCalc(buf + 4, 6) &&

+      flags == GetBe16(buf + 8) &&

+      memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0);

+}

+

+#define READ_VARINT_AND_CHECK(buf, pos, size, res) \

+  { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \

+  if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }

+

+

+SRes XzBlock_Parse(CXzBlock *p, const Byte *header)

+{

+  unsigned pos;

+  int numFilters, i;

+  UInt32 headerSize = (UInt32)header[0] << 2;

+

+  if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))

+    return SZ_ERROR_ARCHIVE;

+

+  pos = 1;

+  if (pos == headerSize)

+    return SZ_ERROR_ARCHIVE;

+  p->flags = header[pos++];

+

+  if (XzBlock_HasPackSize(p))

+  {

+    READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);

+    if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)

+      return SZ_ERROR_ARCHIVE;

+  }

+

+  if (XzBlock_HasUnpackSize(p))

+    READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);

+

+  numFilters = XzBlock_GetNumFilters(p);

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

+  {

+    CXzFilter *filter = p->filters + i;

+    UInt64 size;

+    READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);

+    READ_VARINT_AND_CHECK(header, pos, headerSize, &size);

+    if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)

+      return SZ_ERROR_ARCHIVE;

+    filter->propsSize = (UInt32)size;

+    memcpy(filter->props, header + pos, (size_t)size);

+    pos += (unsigned)size;

+

+    #ifdef XZ_DUMP

+    printf("\nf[%d] = %2X: ", i, filter->id);

+    {

+      int i;

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

+        printf(" %2X", filter->props[i]);

+    }

+    #endif

+  }

+

+  while (pos < headerSize)

+    if (header[pos++] != 0)

+      return SZ_ERROR_ARCHIVE;

+  return SZ_OK;

+}

+

+SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)

+{

+  int i;

+  Bool needReInit = True;

+  int numFilters = XzBlock_GetNumFilters(block);

+  if (numFilters == p->numCoders)

+  {

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

+      if (p->ids[i] != block->filters[numFilters - 1 - i].id)

+        break;

+    needReInit = (i != numFilters);

+  }

+  if (needReInit)

+  {

+    MixCoder_Free(p);

+    p->numCoders = numFilters;

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

+    {

+      const CXzFilter *f = &block->filters[numFilters - 1 - i];

+      RINOK(MixCoder_SetFromMethod(p, i, f->id));

+    }

+  }

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

+  {

+    const CXzFilter *f = &block->filters[numFilters - 1 - i];

+    IStateCoder *sc = &p->coders[i];

+    RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));

+  }

+  MixCoder_Init(p);

+  return SZ_OK;

+}

+

+SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc)

+{

+  MixCoder_Construct(&p->decoder, alloc);

+  p->state = XZ_STATE_STREAM_HEADER;

+  p->pos = 0;

+  p->numStreams = 0;

+  return SZ_OK;

+}

+

+void XzUnpacker_Free(CXzUnpacker *p)

+{

+  MixCoder_Free(&p->decoder);

+}

+

+SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,

+    const Byte *src, SizeT *srcLen, int finishMode, ECoderStatus *status)

+{

+  SizeT destLenOrig = *destLen;

+  SizeT srcLenOrig = *srcLen;

+  *destLen = 0;

+  *srcLen = 0;

+  *status = CODER_STATUS_NOT_SPECIFIED;

+  for (;;)

+  {

+    SizeT srcRem = srcLenOrig - *srcLen;

+

+    if (p->state == XZ_STATE_BLOCK)

+    {

+      SizeT destLen2 = destLenOrig - *destLen;

+      SizeT srcLen2 = srcLenOrig - *srcLen;

+      SRes res;

+      if (srcLen2 == 0 && destLen2 == 0)

+      {

+        *status = CODER_STATUS_NOT_FINISHED;

+        return SZ_OK;

+      }

+      

+      res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);

+      XzCheck_Update(&p->check, dest, destLen2);

+      

+      (*srcLen) += srcLen2;

+      src += srcLen2;

+      p->packSize += srcLen2;

+      

+      (*destLen) += destLen2;

+      dest += destLen2;

+      p->unpackSize += destLen2;

+      

+      RINOK(res);

+      

+      if (*status == CODER_STATUS_FINISHED_WITH_MARK)

+      {

+        Byte temp[32];

+        unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));

+        num += Xz_WriteVarInt(temp + num, p->unpackSize);

+        Sha256_Update(&p->sha, temp, num);

+        p->indexSize += num;

+        p->numBlocks++;

+        

+        p->state = XZ_STATE_BLOCK_FOOTER;

+        p->pos = 0;

+        p->alignPos = 0;

+      }

+      else if (srcLen2 == 0 && destLen2 == 0)

+        return SZ_OK;

+      

+      continue;

+    }

+

+    if (srcRem == 0)

+    {

+      *status = CODER_STATUS_NEEDS_MORE_INPUT;

+      return SZ_OK;

+    }

+

+    switch(p->state)

+    {

+      case XZ_STATE_STREAM_HEADER:

+      {

+        if (p->pos < XZ_STREAM_HEADER_SIZE)

+        {

+          if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])

+            return SZ_ERROR_NO_ARCHIVE;

+          p->buf[p->pos++] = *src++;

+          (*srcLen)++;

+        }

+        else

+        {

+          RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));

+          p->state = XZ_STATE_BLOCK_HEADER;

+          Sha256_Init(&p->sha);

+          p->indexSize = 0;

+          p->numBlocks = 0;

+          p->pos = 0;

+        }

+        break;

+      }

+

+      case XZ_STATE_BLOCK_HEADER:

+      {

+        if (p->pos == 0)

+        {

+          p->buf[p->pos++] = *src++;

+          (*srcLen)++;

+          if (p->buf[0] == 0)

+          {

+            p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);

+            p->indexPos = p->indexPreSize;

+            p->indexSize += p->indexPreSize;

+            Sha256_Final(&p->sha, p->shaDigest);

+            Sha256_Init(&p->sha);

+            p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);

+            p->state = XZ_STATE_STREAM_INDEX;

+          }

+          p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;

+        }

+        else if (p->pos != p->blockHeaderSize)

+        {

+          UInt32 cur = p->blockHeaderSize - p->pos;

+          if (cur > srcRem)

+            cur = (UInt32)srcRem;

+          memcpy(p->buf + p->pos, src, cur);

+          p->pos += cur;

+          (*srcLen) += cur;

+          src += cur;

+        }

+        else

+        {

+          RINOK(XzBlock_Parse(&p->block, p->buf));

+          p->state = XZ_STATE_BLOCK;

+          p->packSize = 0;

+          p->unpackSize = 0;

+          XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));

+          RINOK(XzDec_Init(&p->decoder, &p->block));

+        }

+        break;

+      }

+

+      case XZ_STATE_BLOCK_FOOTER:

+      {

+        if (((p->packSize + p->alignPos) & 3) != 0)

+        {

+          (*srcLen)++;

+          p->alignPos++;

+          if (*src++ != 0)

+            return SZ_ERROR_CRC;

+        }

+        else

+        {

+          UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);

+          UInt32 cur = checkSize - p->pos;

+          if (cur != 0)

+          {

+            if (cur > srcRem)

+              cur = (UInt32)srcRem;

+            memcpy(p->buf + p->pos, src, cur);

+            p->pos += cur;

+            (*srcLen) += cur;

+            src += cur;

+          }

+          else

+          {

+            Byte digest[XZ_CHECK_SIZE_MAX];

+            p->state = XZ_STATE_BLOCK_HEADER;

+            p->pos = 0;

+            if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)

+              return SZ_ERROR_CRC;

+          }

+        }

+        break;

+      }

+

+      case XZ_STATE_STREAM_INDEX:

+      {

+        if (p->pos < p->indexPreSize)

+        {

+          (*srcLen)++;

+          if (*src++ != p->buf[p->pos++])

+            return SZ_ERROR_CRC;

+        }

+        else

+        {

+          if (p->indexPos < p->indexSize)

+          {

+            UInt64 cur = p->indexSize - p->indexPos;

+            if (srcRem > cur)

+              srcRem = (SizeT)cur;

+            p->crc = CrcUpdate(p->crc, src, srcRem);

+            Sha256_Update(&p->sha, src, srcRem);

+            (*srcLen) += srcRem;

+            src += srcRem;

+            p->indexPos += srcRem;

+          }

+          else if ((p->indexPos & 3) != 0)

+          {

+            Byte b = *src++;

+            p->crc = CRC_UPDATE_BYTE(p->crc, b);

+            (*srcLen)++;

+            p->indexPos++;

+            p->indexSize++;

+            if (b != 0)

+              return SZ_ERROR_CRC;

+          }

+          else

+          {

+            Byte digest[SHA256_DIGEST_SIZE];

+            p->state = XZ_STATE_STREAM_INDEX_CRC;

+            p->indexSize += 4;

+            p->pos = 0;

+            Sha256_Final(&p->sha, digest);

+            if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)

+              return SZ_ERROR_CRC;

+          }

+        }

+        break;

+      }

+

+      case XZ_STATE_STREAM_INDEX_CRC:

+      {

+        if (p->pos < 4)

+        {

+          (*srcLen)++;

+          p->buf[p->pos++] = *src++;

+        }

+        else

+        {

+          p->state = XZ_STATE_STREAM_FOOTER;

+          p->pos = 0;

+          if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))

+            return SZ_ERROR_CRC;

+        }

+        break;

+      }

+

+      case XZ_STATE_STREAM_FOOTER:

+      {

+        UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;

+        if (cur > srcRem)

+          cur = (UInt32)srcRem;

+        memcpy(p->buf + p->pos, src, cur);

+        p->pos += cur;

+        (*srcLen) += cur;

+        src += cur;

+        if (p->pos == XZ_STREAM_FOOTER_SIZE)

+        {

+          p->state = XZ_STATE_STREAM_PADDING;

+          p->numStreams++;

+          p->padSize = 0;

+          if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))

+            return SZ_ERROR_CRC;

+        }

+        break;

+      }

+

+      case XZ_STATE_STREAM_PADDING:

+      {

+        if (*src != 0)

+        {

+          if (((UInt32)p->padSize & 3) != 0)

+            return SZ_ERROR_NO_ARCHIVE;

+          p->pos = 0;

+          p->state = XZ_STATE_STREAM_HEADER;

+        }

+        else

+        {

+          (*srcLen)++;

+          src++;

+          p->padSize++;

+        }

+        break;

+      }

+      

+      case XZ_STATE_BLOCK: break; /* to disable GCC warning */

+    }

+  }

+  /*

+  if (p->state == XZ_STATE_FINISHED)

+    *status = CODER_STATUS_FINISHED_WITH_MARK;

+  return SZ_OK;

+  */

+}

+

+Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)

+{

+  return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);

+}

diff --git a/C/XzEnc.c b/C/XzEnc.c
new file mode 100755
index 0000000..e610140
--- /dev/null
+++ b/C/XzEnc.c
@@ -0,0 +1,497 @@
+/* XzEnc.c -- Xz Encode

+2009-06-04 : Igor Pavlov : Public domain */

+

+#include <stdlib.h>

+#include <string.h>

+

+#include "7zCrc.h"

+#include "Alloc.h"

+#include "Bra.h"

+#include "CpuArch.h"

+#ifdef USE_SUBBLOCK

+#include "SbEnc.h"

+#endif

+

+#include "XzEnc.h"

+

+static void *SzBigAlloc(void *p, size_t size) { p = p; return BigAlloc(size); }

+static void SzBigFree(void *p, void *address) { p = p; BigFree(address); }

+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

+

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

+

+#define XzBlock_ClearFlags(p)       (p)->flags = 0;

+#define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1);

+#define XzBlock_SetHasPackSize(p)   (p)->flags |= XZ_BF_PACK_SIZE;

+#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE;

+

+static SRes WriteBytes(ISeqOutStream *s, const void *buf, UInt32 size)

+{

+  return (s->Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE;

+}

+

+static SRes WriteBytesAndCrc(ISeqOutStream *s, const void *buf, UInt32 size, UInt32 *crc)

+{

+  *crc = CrcUpdate(*crc, buf, size);

+  return WriteBytes(s, buf, size);

+}

+

+SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)

+{

+  UInt32 crc;

+  Byte header[XZ_STREAM_HEADER_SIZE];

+  memcpy(header, XZ_SIG, XZ_SIG_SIZE);

+  header[XZ_SIG_SIZE] = (Byte)(f >> 8);

+  header[XZ_SIG_SIZE + 1] = (Byte)(f & 0xFF);

+  crc = CrcCalc(header + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE);

+  SetUi32(header + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE, crc);

+  return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE);

+}

+

+SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)

+{

+  Byte header[XZ_BLOCK_HEADER_SIZE_MAX];

+

+  unsigned pos = 1;

+  int numFilters, i;

+  header[pos++] = p->flags;

+

+  if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize);

+  if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize);

+  numFilters = XzBlock_GetNumFilters(p);

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

+  {

+    const CXzFilter *f = &p->filters[i];

+    pos += Xz_WriteVarInt(header + pos, f->id);

+    pos += Xz_WriteVarInt(header + pos, f->propsSize);

+    memcpy(header + pos, f->props, f->propsSize);

+    pos += f->propsSize;

+  }

+  while((pos & 3) != 0)

+    header[pos++] = 0;

+  header[0] = (Byte)(pos >> 2);

+  SetUi32(header + pos, CrcCalc(header, pos));

+  return WriteBytes(s, header, pos + 4);

+}

+

+SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)

+{

+  Byte buf[32];

+  UInt64 globalPos;

+  {

+    UInt32 crc = CRC_INIT_VAL;

+    unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks);

+    size_t i;

+

+    globalPos = pos;

+    buf[0] = 0;

+    RINOK(WriteBytesAndCrc(s, buf, pos, &crc));

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

+    {

+      const CXzBlockSizes *block = &p->blocks[i];

+      pos = Xz_WriteVarInt(buf, block->totalSize);

+      pos += Xz_WriteVarInt(buf + pos, block->unpackSize);

+      globalPos += pos;

+      RINOK(WriteBytesAndCrc(s, buf, pos, &crc));

+    }

+    pos = ((unsigned)globalPos & 3);

+    if (pos != 0)

+    {

+      buf[0] = buf[1] = buf[2] = 0;

+      RINOK(WriteBytesAndCrc(s, buf, 4 - pos, &crc));

+      globalPos += 4 - pos;

+    }

+    {

+      SetUi32(buf, CRC_GET_DIGEST(crc));

+      RINOK(WriteBytes(s, buf, 4));

+      globalPos += 4;

+    }

+  }

+

+  {

+    UInt32 indexSize = (UInt32)((globalPos >> 2) - 1);

+    SetUi32(buf + 4, indexSize);

+    buf[8] = (Byte)(p->flags >> 8);

+    buf[9] = (Byte)(p->flags & 0xFF);

+    SetUi32(buf, CrcCalc(buf + 4, 6));

+    memcpy(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE);

+    return WriteBytes(s, buf, 12);

+  }

+}

+

+SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)

+{

+  if (p->blocks == 0 || p->numBlocksAllocated == p->numBlocks)

+  {

+    size_t num = (p->numBlocks + 1) * 2;

+    size_t newSize = sizeof(CXzBlockSizes) * num;

+    CXzBlockSizes *blocks;

+    if (newSize / sizeof(CXzBlockSizes) != num)

+      return SZ_ERROR_MEM;

+    blocks = alloc->Alloc(alloc, newSize);

+    if (blocks == 0)

+      return SZ_ERROR_MEM;

+    if (p->numBlocks != 0)

+    {

+      memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes));

+      Xz_Free(p, alloc);

+    }

+    p->blocks = blocks;

+    p->numBlocksAllocated = num;

+  }

+  {

+    CXzBlockSizes *block = &p->blocks[p->numBlocks++];

+    block->totalSize = totalSize;

+    block->unpackSize = unpackSize;

+  }

+  return SZ_OK;

+}

+

+/* ---------- CSeqCheckInStream ---------- */

+

+typedef struct

+{

+  ISeqInStream p;

+  ISeqInStream *realStream;

+  UInt64 processed;

+  CXzCheck check;

+} CSeqCheckInStream;

+

+void SeqCheckInStream_Init(CSeqCheckInStream *p, int mode)

+{

+  p->processed = 0;

+  XzCheck_Init(&p->check, mode);

+}

+

+void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)

+{

+  XzCheck_Final(&p->check, digest);

+}

+

+static SRes SeqCheckInStream_Read(void *pp, void *data, size_t *size)

+{

+  CSeqCheckInStream *p = (CSeqCheckInStream *)pp;

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

+  XzCheck_Update(&p->check, data, *size);

+  p->processed += *size;

+  return res;

+}

+

+/* ---------- CSeqSizeOutStream ---------- */

+

+typedef struct

+{

+  ISeqOutStream p;

+  ISeqOutStream *realStream;

+  UInt64 processed;

+} CSeqSizeOutStream;

+

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

+{

+  CSeqSizeOutStream *p = (CSeqSizeOutStream *)pp;

+  size = p->realStream->Write(p->realStream, data, size);

+  p->processed += size;

+  return size;

+}

+

+/* ---------- CSeqInFilter ---------- */

+

+/*

+typedef struct _IFilter

+{

+  void *p;

+  void (*Free)(void *p, ISzAlloc *alloc);

+  SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);

+  void (*Init)(void *p);

+  size_t (*Filter)(void *p, Byte *data, SizeT destLen);

+} IFilter;

+

+#define FILT_BUF_SIZE (1 << 19)

+

+typedef struct

+{

+  ISeqInStream p;

+  ISeqInStream *realStream;

+  UInt32 x86State;

+  UInt32 ip;

+  UInt64 processed;

+  CXzCheck check;

+  Byte buf[FILT_BUF_SIZE];

+  UInt32 bufferPos;

+  UInt32 convertedPosBegin;

+  UInt32 convertedPosEnd;

+  IFilter *filter;

+} CSeqInFilter;

+

+static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)

+{

+  CSeqInFilter *p = (CSeqInFilter *)pp;

+  size_t remSize = *size;

+  *size = 0;

+

+  while (remSize > 0)

+  {

+    int i;

+    if (p->convertedPosBegin != p->convertedPosEnd)

+    {

+      UInt32 sizeTemp = p->convertedPosEnd - p->convertedPosBegin;

+      if (remSize < sizeTemp)

+        sizeTemp = (UInt32)remSize;

+      memmove(data, p->buf + p->convertedPosBegin, sizeTemp);

+      p->convertedPosBegin += sizeTemp;

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

+      remSize -= sizeTemp;

+      *size += sizeTemp;

+      break;

+    }

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

+      p->buf[i] = p->buf[i + p->convertedPosEnd];

+    p->bufferPos = i;

+    p->convertedPosBegin = p->convertedPosEnd = 0;

+    {

+      size_t processedSizeTemp = FILT_BUF_SIZE - p->bufferPos;

+      RINOK(p->realStream->Read(p->realStream, p->buf + p->bufferPos, &processedSizeTemp));

+      p->bufferPos = p->bufferPos + (UInt32)processedSizeTemp;

+    }

+    p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos);

+    if (p->convertedPosEnd == 0)

+    {

+      if (p->bufferPos == 0)

+        break;

+      else

+      {

+        p->convertedPosEnd = p->bufferPos;

+        continue;

+      }

+    }

+    if (p->convertedPosEnd > p->bufferPos)

+    {

+      for (; p->bufferPos < p->convertedPosEnd; p->bufferPos++)

+        p->buf[p->bufferPos] = 0;

+      p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos);

+    }

+  }

+  return SZ_OK;

+}

+*/

+

+/*

+typedef struct

+{

+  ISeqInStream p;

+  ISeqInStream *realStream;

+  CMixCoder mixCoder;

+  Byte buf[FILT_BUF_SIZE];

+  UInt32 bufPos;

+  UInt32 bufSize;

+} CMixCoderSeqInStream;

+

+static SRes CMixCoderSeqInStream_Read(void *pp, void *data, size_t *size)

+{

+  CMixCoderSeqInStream *p = (CMixCoderSeqInStream *)pp;

+  SRes res = SZ_OK;

+  size_t remSize = *size;

+  *size = 0;

+  while (remSize > 0)

+  {

+    if (p->bufPos == p->bufSize)

+    {

+      size_t curSize;

+      p->bufPos = p->bufSize = 0;

+      if (*size != 0)

+        break;

+      curSize = FILT_BUF_SIZE;

+      RINOK(p->realStream->Read(p->realStream, p->buf, &curSize));

+      p->bufSize = (UInt32)curSize;

+    }

+    {

+      SizeT destLen = remSize;

+      SizeT srcLen = p->bufSize - p->bufPos;

+      res = MixCoder_Code(&p->mixCoder, data, &destLen, p->buf + p->bufPos, &srcLen, 0);

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

+      remSize -= destLen;

+      *size += destLen;

+      p->bufPos += srcLen;

+    }

+  }

+  return res;

+}

+*/

+

+#ifdef USE_SUBBLOCK

+typedef struct

+{

+  ISeqInStream p;

+  CSubblockEnc sb;

+  UInt64 processed;

+} CSbEncInStream;

+

+void SbEncInStream_Init(CSbEncInStream *p)

+{

+  p->processed = 0;

+  SubblockEnc_Init(&p->sb);

+}

+

+static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)

+{

+  CSbEncInStream *p = (CSbEncInStream *)pp;

+  SRes res = SubblockEnc_Read(&p->sb, data, size);

+  p->processed += *size;

+  return res;

+}

+#endif

+

+typedef struct

+{

+  /* CMixCoderSeqInStream inStream; */

+  CLzma2EncHandle lzma2;

+  #ifdef USE_SUBBLOCK

+  CSbEncInStream sb;

+  #endif

+  ISzAlloc *alloc;

+  ISzAlloc *bigAlloc;

+} CLzma2WithFilters;

+

+

+static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, ISzAlloc *bigAlloc)

+{

+  p->alloc = alloc;

+  p->bigAlloc = bigAlloc;

+  p->lzma2 = NULL;

+  #ifdef USE_SUBBLOCK

+  p->sb.p.Read = SbEncInStream_Read;

+  SubblockEnc_Construct(&p->sb.sb, p->alloc);

+  #endif

+}

+

+static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)

+{

+  p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc);

+  if (p->lzma2 == 0)

+    return SZ_ERROR_MEM;

+  return SZ_OK;

+}

+

+static void Lzma2WithFilters_Free(CLzma2WithFilters *p)

+{

+  #ifdef USE_SUBBLOCK

+  SubblockEnc_Free(&p->sb.sb);

+  #endif

+  if (p->lzma2)

+  {

+    Lzma2Enc_Destroy(p->lzma2);

+    p->lzma2 = NULL;

+  }

+}

+

+static SRes Xz_Compress(CXzStream *xz,

+    CLzma2WithFilters *lzmaf,

+    ISeqOutStream *outStream,

+    ISeqInStream *inStream,

+    const CLzma2EncProps *lzma2Props,

+    Bool useSubblock,

+    ICompressProgress *progress)

+{

+  xz->flags = XZ_CHECK_CRC32;

+

+  RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, lzma2Props));

+  RINOK(Xz_WriteHeader(xz->flags, outStream));

+

+  {

+    CSeqCheckInStream checkInStream;

+    CSeqSizeOutStream seqSizeOutStream;

+    CXzBlock block;

+    int filterIndex = 0;

+    

+    XzBlock_ClearFlags(&block);

+    XzBlock_SetNumFilters(&block, 1 + (useSubblock ? 1 : 0));

+    

+    if (useSubblock)

+    {

+      CXzFilter *f = &block.filters[filterIndex++];

+      f->id = XZ_ID_Subblock;

+      f->propsSize = 0;

+    }

+

+    {

+      CXzFilter *f = &block.filters[filterIndex++];

+      f->id = XZ_ID_LZMA2;

+      f->propsSize = 1;

+      f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2);

+    }

+

+    seqSizeOutStream.p.Write = MyWrite;

+    seqSizeOutStream.realStream = outStream;

+    seqSizeOutStream.processed = 0;

+    

+    RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.p));

+    

+    checkInStream.p.Read = SeqCheckInStream_Read;

+    checkInStream.realStream = inStream;

+    SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags));

+    

+    #ifdef USE_SUBBLOCK

+    if (useSubblock)

+    {

+      lzmaf->sb.sb.inStream = &checkInStream.p;

+      SubblockEnc_Init(&lzmaf->sb.sb);

+    }

+    #endif

+    

+    {

+      UInt64 packPos = seqSizeOutStream.processed;

+      SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,

+        #ifdef USE_SUBBLOCK

+        useSubblock ? &lzmaf->sb.p:

+        #endif

+        &checkInStream.p,

+        progress);

+      RINOK(res);

+      block.unpackSize = checkInStream.processed;

+      block.packSize = seqSizeOutStream.processed - packPos;

+    }

+

+    {

+      unsigned padSize = 0;

+      Byte buf[128];

+      while((((unsigned)block.packSize + padSize) & 3) != 0)

+        buf[padSize++] = 0;

+      SeqCheckInStream_GetDigest(&checkInStream, buf + padSize);

+      RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags)));

+      RINOK(Xz_AddIndexRecord(xz, block.unpackSize, seqSizeOutStream.processed - padSize, &g_Alloc));

+    }

+  }

+  return Xz_WriteFooter(xz, outStream);

+}

+

+SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,

+    const CLzma2EncProps *lzma2Props, Bool useSubblock,

+    ICompressProgress *progress)

+{

+  SRes res;

+  CXzStream xz;

+  CLzma2WithFilters lzmaf;

+  Xz_Construct(&xz);

+  Lzma2WithFilters_Construct(&lzmaf, &g_Alloc, &g_BigAlloc);

+  res = Lzma2WithFilters_Create(&lzmaf);

+  if (res == SZ_OK)

+    res = Xz_Compress(&xz, &lzmaf, outStream, inStream,

+        lzma2Props, useSubblock, progress);

+  Lzma2WithFilters_Free(&lzmaf);

+  Xz_Free(&xz, &g_Alloc);

+  return res;

+}

+

+SRes Xz_EncodeEmpty(ISeqOutStream *outStream)

+{

+  SRes res;

+  CXzStream xz;

+  Xz_Construct(&xz);

+  res = Xz_WriteHeader(xz.flags, outStream);

+  if (res == SZ_OK)

+    res = Xz_WriteFooter(&xz, outStream);

+  Xz_Free(&xz, &g_Alloc);

+  return res;

+}

diff --git a/C/XzEnc.h b/C/XzEnc.h
new file mode 100755
index 0000000..aad9aa4
--- /dev/null
+++ b/C/XzEnc.h
@@ -0,0 +1,25 @@
+/* XzEnc.h -- Xz Encode

+2009-04-15 : Igor Pavlov : Public domain */

+

+#ifndef __XZ_ENC_H

+#define __XZ_ENC_H

+

+#include "Lzma2Enc.h"

+

+#include "Xz.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,

+    const CLzma2EncProps *lzma2Props, Bool useSubblock,

+    ICompressProgress *progress);

+

+SRes Xz_EncodeEmpty(ISeqOutStream *outStream);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/XzIn.c b/C/XzIn.c
new file mode 100755
index 0000000..356d019
--- /dev/null
+++ b/C/XzIn.c
@@ -0,0 +1,306 @@
+/* XzIn.c - Xz input

+2009-06-19 : Igor Pavlov : Public domain */

+

+#include <string.h>

+

+#include "7zCrc.h"

+#include "CpuArch.h"

+#include "Xz.h"

+

+SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream)

+{

+  Byte sig[XZ_STREAM_HEADER_SIZE];

+  RINOK(SeqInStream_Read2(inStream, sig, XZ_STREAM_HEADER_SIZE, SZ_ERROR_NO_ARCHIVE));

+  if (memcmp(sig, XZ_SIG, XZ_SIG_SIZE) != 0)

+    return SZ_ERROR_NO_ARCHIVE;

+  return Xz_ParseHeader(p, sig);

+}

+

+#define READ_VARINT_AND_CHECK(buf, pos, size, res) \

+  { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \

+  if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }

+

+SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes)

+{

+  Byte header[XZ_BLOCK_HEADER_SIZE_MAX];

+  unsigned headerSize;

+  *headerSizeRes = 0;

+  RINOK(SeqInStream_ReadByte(inStream, &header[0]));

+  headerSize = ((unsigned)header[0] << 2) + 4;

+  if (headerSize == 0)

+  {

+    *headerSizeRes = 1;

+    *isIndex = True;

+    return SZ_OK;

+  }

+

+  *isIndex = False;

+  *headerSizeRes = headerSize;

+  RINOK(SeqInStream_Read(inStream, header + 1, headerSize - 1));

+  return XzBlock_Parse(p, header);

+}

+

+#define ADD_SIZE_CHECH(size, val) \

+  { UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; }

+

+UInt64 Xz_GetUnpackSize(const CXzStream *p)

+{

+  UInt64 size = 0;

+  size_t i;

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

+    ADD_SIZE_CHECH(size, p->blocks[i].unpackSize);

+  return size;

+}

+

+UInt64 Xz_GetPackSize(const CXzStream *p)

+{

+  UInt64 size = 0;

+  size_t i;

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

+    ADD_SIZE_CHECH(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3);

+  return size;

+}

+

+/*

+SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStream *inStream)

+{

+  return SeqInStream_Read(inStream, p->check, XzFlags_GetCheckSize(f));

+}

+*/

+

+static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc)

+{

+  size_t i, numBlocks, crcStartPos, pos = 1;

+  UInt32 crc;

+

+  if (size < 5 || buf[0] != 0)

+    return SZ_ERROR_ARCHIVE;

+

+  size -= 4;

+  crc = CrcCalc(buf, size);

+  if (crc != GetUi32(buf + size))

+    return SZ_ERROR_ARCHIVE;

+

+  {

+    UInt64 numBlocks64;

+    READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64);

+    numBlocks = (size_t)numBlocks64;

+    if (numBlocks != numBlocks64 || numBlocks * 2 > size)

+      return SZ_ERROR_ARCHIVE;

+  }

+  

+  crcStartPos = pos;

+  Xz_Free(p, alloc);

+  if (numBlocks != 0)

+  {

+    p->numBlocks = numBlocks;

+    p->numBlocksAllocated = numBlocks;

+    p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);

+    if (p->blocks == 0)

+      return SZ_ERROR_MEM;

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

+    {

+      CXzBlockSizes *block = &p->blocks[i];

+      READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize);

+      READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize);

+      if (block->totalSize == 0)

+        return SZ_ERROR_ARCHIVE;

+    }

+  }

+  while ((pos & 3) != 0)

+    if (buf[pos++] != 0)

+      return SZ_ERROR_ARCHIVE;

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

+}

+

+static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize, ISzAlloc *alloc)

+{

+  SRes res;

+  size_t size;

+  Byte *buf;

+  if (indexSize > ((UInt32)1 << 31))

+    return SZ_ERROR_UNSUPPORTED;

+  size = (size_t)indexSize;

+  if (size != indexSize)

+    return SZ_ERROR_UNSUPPORTED;

+  buf = alloc->Alloc(alloc, size);

+  if (buf == 0)

+    return SZ_ERROR_MEM;

+  res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED);

+  if (res == SZ_OK)

+    res = Xz_ReadIndex2(p, buf, size, alloc);

+  alloc->Free(alloc, buf);

+  return res;

+}

+

+static SRes SeekFromCur(ILookInStream *inStream, Int64 *res)

+{

+  return inStream->Seek(inStream, res, SZ_SEEK_CUR);

+}

+

+static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc)

+{

+  UInt64 indexSize;

+  Byte buf[XZ_STREAM_FOOTER_SIZE];

+

+  if ((*startOffset & 3) != 0 || *startOffset < XZ_STREAM_FOOTER_SIZE)

+    return SZ_ERROR_NO_ARCHIVE;

+  *startOffset = -XZ_STREAM_FOOTER_SIZE;

+  RINOK(SeekFromCur(stream, startOffset));

+

+  RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));

+  

+  if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)

+  {

+    Int64 i = 0;

+    *startOffset += XZ_STREAM_FOOTER_SIZE;

+    for (;;)

+    {

+      int j;

+      size_t processedSize;

+      #define TEMP_BUF_SIZE (1 << 10)

+      Byte tempBuf[TEMP_BUF_SIZE];

+      if (*startOffset < XZ_STREAM_FOOTER_SIZE || i > (1 << 16))

+        return SZ_ERROR_NO_ARCHIVE;

+      processedSize = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset;

+      i += processedSize;

+      *startOffset = -(Int64)processedSize;

+      RINOK(SeekFromCur(stream, startOffset));

+      RINOK(LookInStream_Read2(stream, tempBuf, processedSize, SZ_ERROR_NO_ARCHIVE));

+      for (j = (int)processedSize; j >= 0; j--)

+        if (tempBuf[j -1] != 0)

+          break;

+      if (j != 0)

+      {

+        if ((j & 3) != 0)

+          return SZ_ERROR_NO_ARCHIVE;

+        *startOffset += j;

+        if (*startOffset < XZ_STREAM_FOOTER_SIZE)

+          return SZ_ERROR_NO_ARCHIVE;

+        *startOffset -= XZ_STREAM_FOOTER_SIZE;

+        RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));

+        RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));

+        if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)

+          return SZ_ERROR_NO_ARCHIVE;

+        break;

+      }

+    }

+  }

+  

+  p->flags = (CXzStreamFlags)GetBe16(buf + 8);

+

+  if (!XzFlags_IsSupported(p->flags))

+    return SZ_ERROR_UNSUPPORTED;

+

+  if (GetUi32(buf) != CrcCalc(buf + 4, 6))

+    return SZ_ERROR_ARCHIVE;

+

+  indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2;

+

+  *startOffset = -(Int64)(indexSize + XZ_STREAM_FOOTER_SIZE);

+  RINOK(SeekFromCur(stream, startOffset));

+

+  RINOK(Xz_ReadIndex(p, stream, indexSize, alloc));

+

+  {

+    UInt64 totalSize = Xz_GetPackSize(p);

+    UInt64 sum = XZ_STREAM_HEADER_SIZE + totalSize + indexSize;

+    if (totalSize == XZ_SIZE_OVERFLOW ||

+      sum >= ((UInt64)1 << 63) ||

+      totalSize >= ((UInt64)1 << 63))

+      return SZ_ERROR_ARCHIVE;

+    *startOffset = -(Int64)sum;

+    RINOK(SeekFromCur(stream, startOffset));

+  }

+  {

+    CXzStreamFlags headerFlags;

+    CSecToRead secToRead;

+    SecToRead_CreateVTable(&secToRead);

+    secToRead.realStream = stream;

+

+    RINOK(Xz_ReadHeader(&headerFlags, &secToRead.s));

+    return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE;

+  }

+}

+

+

+/* ---------- Xz Streams ---------- */

+

+void Xzs_Construct(CXzs *p)

+{

+  p->num = p->numAllocated = 0;

+  p->streams = 0;

+}

+

+void Xzs_Free(CXzs *p, ISzAlloc *alloc)

+{

+  size_t i;

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

+    Xz_Free(&p->streams[i], alloc);

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

+  p->num = p->numAllocated = 0;

+  p->streams = 0;

+}

+

+UInt64 Xzs_GetNumBlocks(const CXzs *p)

+{

+  UInt64 num = 0;

+  size_t i;

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

+    num += p->streams[i].numBlocks;

+  return num;

+}

+

+UInt64 Xzs_GetUnpackSize(const CXzs *p)

+{

+  UInt64 size = 0;

+  size_t i;

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

+    ADD_SIZE_CHECH(size, Xz_GetUnpackSize(&p->streams[i]));

+  return size;

+}

+

+/*

+UInt64 Xzs_GetPackSize(const CXzs *p)

+{

+  UInt64 size = 0;

+  size_t i;

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

+    ADD_SIZE_CHECH(size, Xz_GetTotalSize(&p->streams[i]));

+  return size;

+}

+*/

+

+SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc)

+{

+  Int64 endOffset = 0;

+  RINOK(stream->Seek(stream, &endOffset, SZ_SEEK_END));

+  *startOffset = endOffset;

+  for (;;)

+  {

+    CXzStream st;

+    SRes res;

+    Xz_Construct(&st);

+    res = Xz_ReadBackward(&st, stream, startOffset, alloc);

+    st.startOffset = *startOffset;

+    RINOK(res);

+    if (p->num == p->numAllocated)

+    {

+      size_t newNum = p->num + p->num / 4 + 1;

+      Byte *data = (Byte *)alloc->Alloc(alloc, newNum * sizeof(CXzStream));

+      if (data == 0)

+        return SZ_ERROR_MEM;

+      p->numAllocated = newNum;

+      memcpy(data, p->streams, p->num * sizeof(CXzStream));

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

+      p->streams = (CXzStream *)data;

+    }

+    p->streams[p->num++] = st;

+    if (*startOffset == 0)

+      break;

+    RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));

+    if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK)

+      return SZ_ERROR_PROGRESS;

+  }

+  return SZ_OK;

+}

diff --git a/CPP/7zip/Aes.mak b/CPP/7zip/Aes.mak
new file mode 100755
index 0000000..7ce28cf
--- /dev/null
+++ b/CPP/7zip/Aes.mak
@@ -0,0 +1,7 @@
+C_OBJS = $(C_OBJS) \

+  $O\Aes.obj

+

+!IF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM"

+ASM_OBJS = $(ASM_OBJS) \

+  $O\AesOpt.obj

+!ENDIF

diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/CPP/7zip/Archive/7z/7zCompressionMode.cpp
new file mode 100755
index 0000000..232c638
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.cpp
@@ -0,0 +1,3 @@
+// CompressionMethod.cpp

+

+#include "StdAfx.h"

diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
new file mode 100755
index 0000000..a388e1f
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -0,0 +1,50 @@
+// 7zCompressionMode.h

+

+#ifndef __7Z_COMPRESSION_MODE_H

+#define __7Z_COMPRESSION_MODE_H

+

+#include "../../../Common/MyString.h"

+

+#include "../../../Windows/PropVariant.h"

+

+#include "../../Common/MethodProps.h"

+

+namespace NArchive {

+namespace N7z {

+

+struct CMethodFull: public CMethod

+{

+  UInt32 NumInStreams;

+  UInt32 NumOutStreams;

+  bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }

+};

+

+struct CBind

+{

+  UInt32 InCoder;

+  UInt32 InStream;

+  UInt32 OutCoder;

+  UInt32 OutStream;

+};

+

+struct CCompressionMethodMode

+{

+  CObjectVector<CMethodFull> Methods;

+  CRecordVector<CBind> Binds;

+  #ifndef _7ZIP_ST

+  UInt32 NumThreads;

+  #endif

+  bool PasswordIsDefined;

+  UString Password;

+

+  bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }

+  CCompressionMethodMode(): PasswordIsDefined(false)

+      #ifndef _7ZIP_ST

+      , NumThreads(1)

+      #endif

+  {}

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
new file mode 100755
index 0000000..3fcdd5f
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -0,0 +1,332 @@
+// 7zDecode.cpp

+

+#include "StdAfx.h"

+

+#include "../../Common/LimitedStreams.h"

+#include "../../Common/LockedStream.h"

+#include "../../Common/ProgressUtils.h"

+#include "../../Common/StreamObjects.h"

+

+#include "7zDecode.h"

+

+namespace NArchive {

+namespace N7z {

+

+static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,

+    CBindInfoEx &bindInfo)

+{

+  bindInfo.Clear();

+  int i;

+  for (i = 0; i < folder.BindPairs.Size(); i++)

+  {

+    NCoderMixer::CBindPair bindPair;

+    bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;

+    bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;

+    bindInfo.BindPairs.Add(bindPair);

+  }

+  UInt32 outStreamIndex = 0;

+  for (i = 0; i < folder.Coders.Size(); i++)

+  {

+    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;

+    const CCoderInfo &coderInfo = folder.Coders[i];

+    coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;

+    coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;

+    bindInfo.Coders.Add(coderStreamsInfo);

+    bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);

+    for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)

+      if (folder.FindBindPairForOutStream(outStreamIndex) < 0)

+        bindInfo.OutStreams.Add(outStreamIndex);

+  }

+  for (i = 0; i < folder.PackStreams.Size(); i++)

+    bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);

+}

+

+static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,

+    const NCoderMixer::CCoderStreamsInfo &a2)

+{

+  return (a1.NumInStreams == a2.NumInStreams) &&

+    (a1.NumOutStreams == a2.NumOutStreams);

+}

+

+static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)

+{

+  return (a1.InIndex == a2.InIndex) &&

+    (a1.OutIndex == a2.OutIndex);

+}

+

+static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)

+{

+  if (a1.Coders.Size() != a2.Coders.Size())

+    return false;

+  int i;

+  for (i = 0; i < a1.Coders.Size(); i++)

+    if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))

+      return false;

+  if (a1.BindPairs.Size() != a2.BindPairs.Size())

+    return false;

+  for (i = 0; i < a1.BindPairs.Size(); i++)

+    if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))

+      return false;

+  for (i = 0; i < a1.CoderMethodIDs.Size(); i++)

+    if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])

+      return false;

+  if (a1.InStreams.Size() != a2.InStreams.Size())

+    return false;

+  if (a1.OutStreams.Size() != a2.OutStreams.Size())

+    return false;

+  return true;

+}

+

+CDecoder::CDecoder(bool multiThread)

+{

+  #ifndef _ST_MODE

+  multiThread = true;

+  #endif

+  _multiThread = multiThread;

+  _bindInfoExPrevIsDefined = false;

+}

+

+HRESULT CDecoder::Decode(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    IInStream *inStream,

+    UInt64 startPos,

+    const UInt64 *packSizes,

+    const CFolder &folderInfo,

+    ISequentialOutStream *outStream,

+    ICompressProgressInfo *compressProgress

+    #ifndef _NO_CRYPTO

+    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

+    #endif

+    #if !defined(_7ZIP_ST) && !defined(_SFX)

+    , bool mtMode, UInt32 numThreads

+    #endif

+    )

+{

+  if (!folderInfo.CheckStructure())

+    return E_NOTIMPL;

+  #ifndef _NO_CRYPTO

+  passwordIsDefined = false;

+  #endif

+  CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;

+  

+  CLockedInStream lockedInStream;

+  lockedInStream.Init(inStream);

+  

+  for (int j = 0; j < folderInfo.PackStreams.Size(); j++)

+  {

+    CLockedSequentialInStreamImp *lockedStreamImpSpec = new

+        CLockedSequentialInStreamImp;

+    CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;

+    lockedStreamImpSpec->Init(&lockedInStream, startPos);

+    startPos += packSizes[j];

+    

+    CLimitedSequentialInStream *streamSpec = new

+        CLimitedSequentialInStream;

+    CMyComPtr<ISequentialInStream> inStream = streamSpec;

+    streamSpec->SetStream(lockedStreamImp);

+    streamSpec->Init(packSizes[j]);

+    inStreams.Add(inStream);

+  }

+  

+  int numCoders = folderInfo.Coders.Size();

+  

+  CBindInfoEx bindInfo;

+  ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);

+  bool createNewCoders;

+  if (!_bindInfoExPrevIsDefined)

+    createNewCoders = true;

+  else

+    createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);

+  if (createNewCoders)

+  {

+    int i;

+    _decoders.Clear();

+    // _decoders2.Clear();

+    

+    _mixerCoder.Release();

+

+    if (_multiThread)

+    {

+      _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;

+      _mixerCoder = _mixerCoderMTSpec;

+      _mixerCoderCommon = _mixerCoderMTSpec;

+    }

+    else

+    {

+      #ifdef _ST_MODE

+      _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;

+      _mixerCoder = _mixerCoderSTSpec;

+      _mixerCoderCommon = _mixerCoderSTSpec;

+      #endif

+    }

+    RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));

+    

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

+    {

+      const CCoderInfo &coderInfo = folderInfo.Coders[i];

+

+  

+      CMyComPtr<ICompressCoder> decoder;

+      CMyComPtr<ICompressCoder2> decoder2;

+      RINOK(CreateCoder(

+          EXTERNAL_CODECS_LOC_VARS

+          coderInfo.MethodID, decoder, decoder2, false));

+      CMyComPtr<IUnknown> decoderUnknown;

+      if (coderInfo.IsSimpleCoder())

+      {

+        if (decoder == 0)

+          return E_NOTIMPL;

+

+        decoderUnknown = (IUnknown *)decoder;

+        

+        if (_multiThread)

+          _mixerCoderMTSpec->AddCoder(decoder);

+        #ifdef _ST_MODE

+        else

+          _mixerCoderSTSpec->AddCoder(decoder, false);

+        #endif

+      }

+      else

+      {

+        if (decoder2 == 0)

+          return E_NOTIMPL;

+        decoderUnknown = (IUnknown *)decoder2;

+        if (_multiThread)

+          _mixerCoderMTSpec->AddCoder2(decoder2);

+        #ifdef _ST_MODE

+        else

+          _mixerCoderSTSpec->AddCoder2(decoder2, false);

+        #endif

+      }

+      _decoders.Add(decoderUnknown);

+      #ifdef EXTERNAL_CODECS

+      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;

+      decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);

+      if (setCompressCodecsInfo)

+      {

+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));

+      }

+      #endif

+    }

+    _bindInfoExPrev = bindInfo;

+    _bindInfoExPrevIsDefined = true;

+  }

+  int i;

+  _mixerCoderCommon->ReInit();

+  

+  UInt32 packStreamIndex = 0, unpackStreamIndex = 0;

+  UInt32 coderIndex = 0;

+  // UInt32 coder2Index = 0;

+  

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

+  {

+    const CCoderInfo &coderInfo = folderInfo.Coders[i];

+    CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];

+    

+    {

+      CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;

+      decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);

+      if (setDecoderProperties)

+      {

+        const CByteBuffer &props = coderInfo.Props;

+        size_t size = props.GetCapacity();

+        if (size > 0xFFFFFFFF)

+          return E_NOTIMPL;

+        // if (size > 0)

+        {

+          RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));

+        }

+      }

+    }

+

+    #if !defined(_7ZIP_ST) && !defined(_SFX)

+    if (mtMode)

+    {

+      CMyComPtr<ICompressSetCoderMt> setCoderMt;

+      decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);

+      if (setCoderMt)

+      {

+        RINOK(setCoderMt->SetNumberOfThreads(numThreads));

+      }

+    }

+    #endif

+

+    #ifndef _NO_CRYPTO

+    {

+      CMyComPtr<ICryptoSetPassword> cryptoSetPassword;

+      decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);

+      if (cryptoSetPassword)

+      {

+        if (getTextPassword == 0)

+          return E_FAIL;

+        CMyComBSTR passwordBSTR;

+        RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));

+        CByteBuffer buffer;

+        passwordIsDefined = true;

+        const UString password(passwordBSTR);

+        const UInt32 sizeInBytes = password.Length() * 2;

+        buffer.SetCapacity(sizeInBytes);

+        for (int i = 0; i < password.Length(); i++)

+        {

+          wchar_t c = password[i];

+          ((Byte *)buffer)[i * 2] = (Byte)c;

+          ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);

+        }

+        RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));

+      }

+    }

+    #endif

+

+    coderIndex++;

+    

+    UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;

+    UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;

+    CRecordVector<const UInt64 *> packSizesPointers;

+    CRecordVector<const UInt64 *> unpackSizesPointers;

+    packSizesPointers.Reserve(numInStreams);

+    unpackSizesPointers.Reserve(numOutStreams);

+    UInt32 j;

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

+      unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]);

+    

+    for (j = 0; j < numInStreams; j++, packStreamIndex++)

+    {

+      int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);

+      if (bindPairIndex >= 0)

+        packSizesPointers.Add(

+        &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);

+      else

+      {

+        int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);

+        if (index < 0)

+          return E_FAIL;

+        packSizesPointers.Add(&packSizes[index]);

+      }

+    }

+    

+    _mixerCoderCommon->SetCoderInfo(i,

+        &packSizesPointers.Front(),

+        &unpackSizesPointers.Front());

+  }

+  UInt32 mainCoder, temp;

+  bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);

+

+  if (_multiThread)

+    _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);

+  /*

+  else

+    _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;

+  */

+  

+  if (numCoders == 0)

+    return 0;

+  CRecordVector<ISequentialInStream *> inStreamPointers;

+  inStreamPointers.Reserve(inStreams.Size());

+  for (i = 0; i < inStreams.Size(); i++)

+    inStreamPointers.Add(inStreams[i]);

+  ISequentialOutStream *outStreamPointer = outStream;

+  return _mixerCoder->Code(&inStreamPointers.Front(), NULL,

+    inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);

+}

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h
new file mode 100755
index 0000000..da213a1
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zDecode.h
@@ -0,0 +1,68 @@
+// 7zDecode.h

+

+#ifndef __7Z_DECODE_H

+#define __7Z_DECODE_H

+

+#include "../../IStream.h"

+#include "../../IPassword.h"

+

+#include "../Common/CoderMixer2.h"

+#include "../Common/CoderMixer2MT.h"

+#ifdef _ST_MODE

+#include "../Common/CoderMixer2ST.h"

+#endif

+

+#include "../../Common/CreateCoder.h"

+

+#include "7zItem.h"

+

+namespace NArchive {

+namespace N7z {

+

+struct CBindInfoEx: public NCoderMixer::CBindInfo

+{

+  CRecordVector<CMethodId> CoderMethodIDs;

+  void Clear()

+  {

+    CBindInfo::Clear();

+    CoderMethodIDs.Clear();

+  }

+};

+

+class CDecoder

+{

+  bool _bindInfoExPrevIsDefined;

+  CBindInfoEx _bindInfoExPrev;

+  

+  bool _multiThread;

+  #ifdef _ST_MODE

+  NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec;

+  #endif

+  NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec;

+  NCoderMixer::CCoderMixer2 *_mixerCoderCommon;

+  

+  CMyComPtr<ICompressCoder2> _mixerCoder;

+  CObjectVector<CMyComPtr<IUnknown> > _decoders;

+  // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2;

+public:

+  CDecoder(bool multiThread);

+  HRESULT Decode(

+      DECL_EXTERNAL_CODECS_LOC_VARS

+      IInStream *inStream,

+      UInt64 startPos,

+      const UInt64 *packSizes,

+      const CFolder &folder,

+      ISequentialOutStream *outStream,

+      ICompressProgressInfo *compressProgress

+      #ifndef _NO_CRYPTO

+      , ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined

+      #endif

+      #if !defined(_7ZIP_ST) && !defined(_SFX)

+      , bool mtMode, UInt32 numThreads

+      #endif

+      );

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
new file mode 100755
index 0000000..4b93449
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -0,0 +1,444 @@
+// 7zEncode.cpp

+

+#include "StdAfx.h"

+

+#include "../../Common/CreateCoder.h"

+#include "../../Common/FilterCoder.h"

+#include "../../Common/LimitedStreams.h"

+#include "../../Common/InOutTempBuffer.h"

+#include "../../Common/ProgressUtils.h"

+#include "../../Common/StreamObjects.h"

+

+#include "7zEncode.h"

+#include "7zSpecStream.h"

+

+static const UInt64 k_Delta = 0x03;

+static const UInt64 k_BCJ = 0x03030103;

+static const UInt64 k_BCJ2 = 0x0303011B;

+

+namespace NArchive {

+namespace N7z {

+

+static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo,

+    const CRecordVector<CMethodId> decompressionMethods,

+    CFolder &folder)

+{

+  folder.Coders.Clear();

+  // bindInfo.CoderMethodIDs.Clear();

+  // folder.OutStreams.Clear();

+  folder.PackStreams.Clear();

+  folder.BindPairs.Clear();

+  int i;

+  for (i = 0; i < bindInfo.BindPairs.Size(); i++)

+  {

+    CBindPair bindPair;

+    bindPair.InIndex = bindInfo.BindPairs[i].InIndex;

+    bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;

+    folder.BindPairs.Add(bindPair);

+  }

+  for (i = 0; i < bindInfo.Coders.Size(); i++)

+  {

+    CCoderInfo coderInfo;

+    const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];

+    coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;

+    coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;

+    coderInfo.MethodID = decompressionMethods[i];

+    folder.Coders.Add(coderInfo);

+  }

+  for (i = 0; i < bindInfo.InStreams.Size(); i++)

+    folder.PackStreams.Add(bindInfo.InStreams[i]);

+}

+

+HRESULT CEncoder::CreateMixerCoder(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    const UInt64 *inSizeForReduce)

+{

+  _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;

+  _mixerCoder = _mixerCoderSpec;

+  RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));

+  for (int i = 0; i < _options.Methods.Size(); i++)

+  {

+    const CMethodFull &methodFull = _options.Methods[i];

+    _codersInfo.Add(CCoderInfo());

+    CCoderInfo &encodingInfo = _codersInfo.Back();

+    encodingInfo.MethodID = methodFull.Id;

+    CMyComPtr<ICompressCoder> encoder;

+    CMyComPtr<ICompressCoder2> encoder2;

+    

+

+    RINOK(CreateCoder(

+        EXTERNAL_CODECS_LOC_VARS

+        methodFull.Id, encoder, encoder2, true));

+

+    if (!encoder && !encoder2)

+      return E_FAIL;

+

+    CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;

+   

+    #ifndef _7ZIP_ST

+    {

+      CMyComPtr<ICompressSetCoderMt> setCoderMt;

+      encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);

+      if (setCoderMt)

+      {

+        RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));

+      }

+    }

+    #endif

+        

+

+    RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon));

+

+    /*

+    CMyComPtr<ICryptoResetSalt> resetSalt;

+    encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);

+    if (resetSalt != NULL)

+    {

+      resetSalt->ResetSalt();

+    }

+    */

+

+    #ifdef EXTERNAL_CODECS

+    CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;

+    encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);

+    if (setCompressCodecsInfo)

+    {

+      RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));

+    }

+    #endif

+    

+    CMyComPtr<ICryptoSetPassword> cryptoSetPassword;

+    encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);

+

+    if (cryptoSetPassword)

+    {

+      CByteBuffer buffer;

+      const UInt32 sizeInBytes = _options.Password.Length() * 2;

+      buffer.SetCapacity(sizeInBytes);

+      for (int i = 0; i < _options.Password.Length(); i++)

+      {

+        wchar_t c = _options.Password[i];

+        ((Byte *)buffer)[i * 2] = (Byte)c;

+        ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);

+      }

+      RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));

+    }

+

+    if (encoder)

+      _mixerCoderSpec->AddCoder(encoder);

+    else

+      _mixerCoderSpec->AddCoder2(encoder2);

+  }

+  return S_OK;

+}

+

+HRESULT CEncoder::Encode(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    ISequentialInStream *inStream,

+    const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,

+    CFolder &folderItem,

+    ISequentialOutStream *outStream,

+    CRecordVector<UInt64> &packSizes,

+    ICompressProgressInfo *compressProgress)

+{

+  RINOK(EncoderConstr());

+

+  if (_mixerCoderSpec == NULL)

+  {

+    RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));

+  }

+  _mixerCoderSpec->ReInit();

+  // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);

+

+  CObjectVector<CInOutTempBuffer> inOutTempBuffers;

+  CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;

+  CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;

+  int numMethods = _bindInfo.Coders.Size();

+  int i;

+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

+  {

+    inOutTempBuffers.Add(CInOutTempBuffer());

+    inOutTempBuffers.Back().Create();

+    inOutTempBuffers.Back().InitWriting();

+  }

+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

+  {

+    CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp;

+    CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;

+    tempBufferSpec->Init(&inOutTempBuffers[i - 1]);

+    tempBuffers.Add(tempBuffer);

+    tempBufferSpecs.Add(tempBufferSpec);

+  }

+

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

+    _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);

+

+  if (_bindInfo.InStreams.IsEmpty())

+    return E_FAIL;

+  UInt32 mainCoderIndex, mainStreamIndex;

+  _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);

+  

+  if (inStreamSize != NULL)

+  {

+    CRecordVector<const UInt64 *> sizePointers;

+    for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)

+      if (i == mainStreamIndex)

+        sizePointers.Add(inStreamSize);

+      else

+        sizePointers.Add(NULL);

+    _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);

+  }

+

+  

+  // UInt64 outStreamStartPos;

+  // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));

+  

+  CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;

+  CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;

+  CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;

+  CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;

+

+  inStreamSizeCountSpec->Init(inStream);

+  outStreamSizeCountSpec->SetStream(outStream);

+  outStreamSizeCountSpec->Init();

+

+  CRecordVector<ISequentialInStream *> inStreamPointers;

+  CRecordVector<ISequentialOutStream *> outStreamPointers;

+  inStreamPointers.Add(inStreamSizeCount);

+  outStreamPointers.Add(outStreamSizeCount);

+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

+    outStreamPointers.Add(tempBuffers[i - 1]);

+

+  for (i = 0; i < _codersInfo.Size(); i++)

+  {

+    CCoderInfo &encodingInfo = _codersInfo[i];

+    

+    CMyComPtr<ICryptoResetInitVector> resetInitVector;

+    _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);

+    if (resetInitVector != NULL)

+    {

+      resetInitVector->ResetInitVector();

+    }

+

+    CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;

+    _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);

+    if (writeCoderProperties != NULL)

+    {

+      CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;

+      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);

+      outStreamSpec->Init();

+      writeCoderProperties->WriteCoderProperties(outStream);

+      outStreamSpec->CopyToBuffer(encodingInfo.Props);

+    }

+  }

+

+  UInt32 progressIndex = mainCoderIndex;

+

+  for (i = 0; i + 1 < _codersInfo.Size(); i++)

+  {

+    UInt64 m = _codersInfo[i].MethodID;

+    if (m == k_Delta || m == k_BCJ || m == k_BCJ2)

+      progressIndex = i + 1;

+  }

+

+  _mixerCoderSpec->SetProgressCoderIndex(progressIndex);

+  

+  RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,

+    &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));

+  

+  ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);

+  

+  packSizes.Add(outStreamSizeCountSpec->GetSize());

+  

+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)

+  {

+    CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];

+    RINOK(inOutTempBuffer.WriteToStream(outStream));

+    packSizes.Add(inOutTempBuffer.GetDataSize());

+  }

+  

+  for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)

+  {

+    int binder = _bindInfo.FindBinderForInStream(

+        _bindReverseConverter->DestOutToSrcInMap[i]);

+    UInt64 streamSize;

+    if (binder < 0)

+      streamSize = inStreamSizeCountSpec->GetSize();

+    else

+      streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);

+    folderItem.UnpackSizes.Add(streamSize);

+  }

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

+    folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;

+  return S_OK;

+}

+

+

+CEncoder::CEncoder(const CCompressionMethodMode &options):

+  _bindReverseConverter(0),

+  _constructed(false)

+{

+  if (options.IsEmpty())

+    throw 1;

+

+  _options = options;

+  _mixerCoderSpec = NULL;

+}

+

+HRESULT CEncoder::EncoderConstr()

+{

+  if (_constructed)

+    return S_OK;

+  if (_options.Methods.IsEmpty())

+  {

+    // it has only password method;

+    if (!_options.PasswordIsDefined)

+      throw 1;

+    if (!_options.Binds.IsEmpty())

+      throw 1;

+    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;

+    CMethodFull method;

+    

+    method.NumInStreams = 1;

+    method.NumOutStreams = 1;

+    coderStreamsInfo.NumInStreams = 1;

+    coderStreamsInfo.NumOutStreams = 1;

+    method.Id = k_AES;

+    

+    _options.Methods.Add(method);

+    _bindInfo.Coders.Add(coderStreamsInfo);

+  

+    _bindInfo.InStreams.Add(0);

+    _bindInfo.OutStreams.Add(0);

+  }

+  else

+  {

+

+  UInt32 numInStreams = 0, numOutStreams = 0;

+  int i;

+  for (i = 0; i < _options.Methods.Size(); i++)

+  {

+    const CMethodFull &methodFull = _options.Methods[i];

+    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;

+    coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;

+    coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;

+    if (_options.Binds.IsEmpty())

+    {

+      if (i < _options.Methods.Size() - 1)

+      {

+        NCoderMixer::CBindPair bindPair;

+        bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;

+        bindPair.OutIndex = numOutStreams;

+        _bindInfo.BindPairs.Add(bindPair);

+      }

+      else

+        _bindInfo.OutStreams.Insert(0, numOutStreams);

+      for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)

+        _bindInfo.OutStreams.Add(numOutStreams + j);

+    }

+    

+    numInStreams += coderStreamsInfo.NumInStreams;

+    numOutStreams += coderStreamsInfo.NumOutStreams;

+

+    _bindInfo.Coders.Add(coderStreamsInfo);

+  }

+

+  if (!_options.Binds.IsEmpty())

+  {

+    for (i = 0; i < _options.Binds.Size(); i++)

+    {

+      NCoderMixer::CBindPair bindPair;

+      const CBind &bind = _options.Binds[i];

+      bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;

+      bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;

+      _bindInfo.BindPairs.Add(bindPair);

+    }

+    for (i = 0; i < (int)numOutStreams; i++)

+      if (_bindInfo.FindBinderForOutStream(i) == -1)

+        _bindInfo.OutStreams.Add(i);

+  }

+

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

+    if (_bindInfo.FindBinderForInStream(i) == -1)

+      _bindInfo.InStreams.Add(i);

+

+  if (_bindInfo.InStreams.IsEmpty())

+    throw 1; // this is error

+

+  // Make main stream first in list

+  int inIndex = _bindInfo.InStreams[0];

+  for (;;)

+  {

+    UInt32 coderIndex, coderStreamIndex;

+    _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);

+    UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);

+    int binder = _bindInfo.FindBinderForOutStream(outIndex);

+    if (binder >= 0)

+    {

+      inIndex = _bindInfo.BindPairs[binder].InIndex;

+      continue;

+    }

+    for (i = 0; i < _bindInfo.OutStreams.Size(); i++)

+      if (_bindInfo.OutStreams[i] == outIndex)

+      {

+        _bindInfo.OutStreams.Delete(i);

+        _bindInfo.OutStreams.Insert(0, outIndex);

+        break;

+      }

+    break;

+  }

+

+  if (_options.PasswordIsDefined)

+  {

+    int numCryptoStreams = _bindInfo.OutStreams.Size();

+

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

+    {

+      NCoderMixer::CBindPair bindPair;

+      bindPair.InIndex = numInStreams + i;

+      bindPair.OutIndex = _bindInfo.OutStreams[i];

+      _bindInfo.BindPairs.Add(bindPair);

+    }

+    _bindInfo.OutStreams.Clear();

+

+    /*

+    if (numCryptoStreams == 0)

+      numCryptoStreams = 1;

+    */

+

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

+    {

+      NCoderMixer::CCoderStreamsInfo coderStreamsInfo;

+      CMethodFull method;

+      method.NumInStreams = 1;

+      method.NumOutStreams = 1;

+      coderStreamsInfo.NumInStreams = method.NumOutStreams;

+      coderStreamsInfo.NumOutStreams = method.NumInStreams;

+      method.Id = k_AES;

+

+      _options.Methods.Add(method);

+      _bindInfo.Coders.Add(coderStreamsInfo);

+      _bindInfo.OutStreams.Add(numOutStreams + i);

+    }

+  }

+

+  }

+

+  for (int i = _options.Methods.Size() - 1; i >= 0; i--)

+  {

+    const CMethodFull &methodFull = _options.Methods[i];

+    _decompressionMethods.Add(methodFull.Id);

+  }

+

+  _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);

+  _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);

+  _constructed = true;

+  return S_OK;

+}

+

+CEncoder::~CEncoder()

+{

+  delete _bindReverseConverter;

+}

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h
new file mode 100755
index 0000000..c75f02f
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zEncode.h
@@ -0,0 +1,55 @@
+// 7zEncode.h

+

+#ifndef __7Z_ENCODE_H

+#define __7Z_ENCODE_H

+

+// #include "../../Common/StreamObjects.h"

+

+#include "7zCompressionMode.h"

+

+#include "../Common/CoderMixer2.h"

+#include "../Common/CoderMixer2MT.h"

+#ifdef _ST_MODE

+#include "../Common/CoderMixer2ST.h"

+#endif

+#include "7zItem.h"

+

+#include "../../Common/CreateCoder.h"

+

+namespace NArchive {

+namespace N7z {

+

+class CEncoder

+{

+  NCoderMixer::CCoderMixer2MT *_mixerCoderSpec;

+  CMyComPtr<ICompressCoder2> _mixerCoder;

+

+  CObjectVector<CCoderInfo> _codersInfo;

+

+  CCompressionMethodMode _options;

+  NCoderMixer::CBindInfo _bindInfo;

+  NCoderMixer::CBindInfo _decompressBindInfo;

+  NCoderMixer::CBindReverseConverter *_bindReverseConverter;

+  CRecordVector<CMethodId> _decompressionMethods;

+

+  HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS

+      const UInt64 *inSizeForReduce);

+

+  bool _constructed;

+public:

+  CEncoder(const CCompressionMethodMode &options);

+  ~CEncoder();

+  HRESULT EncoderConstr();

+  HRESULT Encode(

+      DECL_EXTERNAL_CODECS_LOC_VARS

+      ISequentialInStream *inStream,

+      const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,

+      CFolder &folderItem,

+      ISequentialOutStream *outStream,

+      CRecordVector<UInt64> &packSizes,

+      ICompressProgressInfo *compressProgress);

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
new file mode 100755
index 0000000..6e31943
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -0,0 +1,270 @@
+// 7zExtract.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/ComTry.h"

+

+#include "../../Common/ProgressUtils.h"

+

+#include "7zDecode.h"

+// #include "7z1Decode.h"

+#include "7zFolderOutStream.h"

+#include "7zHandler.h"

+

+namespace NArchive {

+namespace N7z {

+

+struct CExtractFolderInfo

+{

+  #ifdef _7Z_VOL

+  int VolumeIndex;

+  #endif

+  CNum FileIndex;

+  CNum FolderIndex;

+  CBoolVector ExtractStatuses;

+  UInt64 UnpackSize;

+  CExtractFolderInfo(

+    #ifdef _7Z_VOL

+    int volumeIndex,

+    #endif

+    CNum fileIndex, CNum folderIndex):

+    #ifdef _7Z_VOL

+    VolumeIndex(volumeIndex),

+    #endif

+    FileIndex(fileIndex),

+    FolderIndex(folderIndex),

+    UnpackSize(0)

+  {

+    if (fileIndex != kNumNoIndex)

+    {

+      ExtractStatuses.Reserve(1);

+      ExtractStatuses.Add(true);

+    }

+  };

+};

+

+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,

+    Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)

+{

+  COM_TRY_BEGIN

+  bool testMode = (testModeSpec != 0);

+  CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;

+  UInt64 importantTotalUnpacked = 0;

+

+  bool allFilesMode = (numItems == (UInt32)-1);

+  if (allFilesMode)

+    numItems =

+    #ifdef _7Z_VOL

+    _refs.Size();

+    #else

+    _db.Files.Size();

+    #endif

+

+  if(numItems == 0)

+    return S_OK;

+

+  /*

+  if(_volumes.Size() != 1)

+    return E_FAIL;

+  const CVolume &volume = _volumes.Front();

+  const CArchiveDatabaseEx &_db = volume.Database;

+  IInStream *_inStream = volume.Stream;

+  */

+  

+  CObjectVector<CExtractFolderInfo> extractFolderInfoVector;

+  for (UInt32 ii = 0; ii < numItems; ii++)

+  {

+    // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex];

+    UInt32 ref2Index = allFilesMode ? ii : indices[ii];

+    // const CRef2 &ref2 = _refs[ref2Index];

+

+    // for (UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)

+    {

+      #ifdef _7Z_VOL

+      // const CRef &ref = ref2.Refs[ri];

+      const CRef &ref = _refs[ref2Index];

+

+      int volumeIndex = ref.VolumeIndex;

+      const CVolume &volume = _volumes[volumeIndex];

+      const CArchiveDatabaseEx &db = volume.Database;

+      UInt32 fileIndex = ref.ItemIndex;

+      #else

+      const CArchiveDatabaseEx &db = _db;

+      UInt32 fileIndex = ref2Index;

+      #endif

+

+      CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex];

+      if (folderIndex == kNumNoIndex)

+      {

+        extractFolderInfoVector.Add(CExtractFolderInfo(

+            #ifdef _7Z_VOL

+            volumeIndex,

+            #endif

+            fileIndex, kNumNoIndex));

+        continue;

+      }

+      if (extractFolderInfoVector.IsEmpty() ||

+        folderIndex != extractFolderInfoVector.Back().FolderIndex

+        #ifdef _7Z_VOL

+        || volumeIndex != extractFolderInfoVector.Back().VolumeIndex

+        #endif

+        )

+      {

+        extractFolderInfoVector.Add(CExtractFolderInfo(

+            #ifdef _7Z_VOL

+            volumeIndex,

+            #endif

+            kNumNoIndex, folderIndex));

+        const CFolder &folderInfo = db.Folders[folderIndex];

+        UInt64 unpackSize = folderInfo.GetUnpackSize();

+        importantTotalUnpacked += unpackSize;

+        extractFolderInfoVector.Back().UnpackSize = unpackSize;

+      }

+      

+      CExtractFolderInfo &efi = extractFolderInfoVector.Back();

+      

+      // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];

+      CNum startIndex = db.FolderStartFileIndex[folderIndex];

+      for (CNum index = efi.ExtractStatuses.Size();

+          index <= fileIndex - startIndex; index++)

+      {

+        // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize;

+        // Count partial_folder_size

+        // efi.UnpackSize += unpackSize;

+        // importantTotalUnpacked += unpackSize;

+        efi.ExtractStatuses.Add(index == fileIndex - startIndex);

+      }

+    }

+  }

+

+  RINOK(extractCallback->SetTotal(importantTotalUnpacked));

+

+  CDecoder decoder(

+    #ifdef _ST_MODE

+    false

+    #else

+    true

+    #endif

+    );

+  // CDecoder1 decoder;

+

+  UInt64 totalPacked = 0;

+  UInt64 totalUnpacked = 0;

+  UInt64 curPacked, curUnpacked;

+

+  CLocalProgress *lps = new CLocalProgress;

+  CMyComPtr<ICompressProgressInfo> progress = lps;

+  lps->Init(extractCallback, false);

+

+  for (int i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)

+  {

+    lps->OutSize = totalUnpacked;

+    lps->InSize = totalPacked;

+    RINOK(lps->SetCur());

+

+    if (i >= extractFolderInfoVector.Size())

+      break;

+    

+    const CExtractFolderInfo &efi = extractFolderInfoVector[i];

+    curUnpacked = efi.UnpackSize;

+    curPacked = 0;

+

+    CFolderOutStream *folderOutStream = new CFolderOutStream;

+    CMyComPtr<ISequentialOutStream> outStream(folderOutStream);

+

+    #ifdef _7Z_VOL

+    const CVolume &volume = _volumes[efi.VolumeIndex];

+    const CArchiveDatabaseEx &db = volume.Database;

+    #else

+    const CArchiveDatabaseEx &db = _db;

+    #endif

+

+    CNum startIndex;

+    if (efi.FileIndex != kNumNoIndex)

+      startIndex = efi.FileIndex;

+    else

+      startIndex = db.FolderStartFileIndex[efi.FolderIndex];

+

+    HRESULT result = folderOutStream->Init(&db,

+        #ifdef _7Z_VOL

+        volume.StartRef2Index,

+        #else

+        0,

+        #endif

+        startIndex,

+        &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0);

+

+    RINOK(result);

+

+    if (efi.FileIndex != kNumNoIndex)

+      continue;

+

+    CNum folderIndex = efi.FolderIndex;

+    const CFolder &folderInfo = db.Folders[folderIndex];

+

+    curPacked = _db.GetFolderFullPackSize(folderIndex);

+

+    CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex];

+    UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0);

+

+    #ifndef _NO_CRYPTO

+    CMyComPtr<ICryptoGetTextPassword> getTextPassword;

+    if (extractCallback)

+      extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);

+    #endif

+

+    try

+    {

+      #ifndef _NO_CRYPTO

+      bool passwordIsDefined;

+      #endif

+

+      HRESULT result = decoder.Decode(

+          EXTERNAL_CODECS_VARS

+          #ifdef _7Z_VOL

+          volume.Stream,

+          #else

+          _inStream,

+          #endif

+          folderStartPackPos,

+          &db.PackSizes[packStreamIndex],

+          folderInfo,

+          outStream,

+          progress

+          #ifndef _NO_CRYPTO

+          , getTextPassword, passwordIsDefined

+          #endif

+          #if !defined(_7ZIP_ST) && !defined(_SFX)

+          , true, _numThreads

+          #endif

+          );

+

+      if (result == S_FALSE)

+      {

+        RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));

+        continue;

+      }

+      if (result == E_NOTIMPL)

+      {

+        RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnSupportedMethod));

+        continue;

+      }

+      if (result != S_OK)

+        return result;

+      if (folderOutStream->WasWritingFinished() != S_OK)

+      {

+        RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));

+        continue;

+      }

+    }

+    catch(...)

+    {

+      RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));

+      continue;

+    }

+  }

+  return S_OK;

+  COM_TRY_END

+}

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
new file mode 100755
index 0000000..c49d341
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
@@ -0,0 +1,123 @@
+// 7zFolderInStream.cpp

+

+#include "StdAfx.h"

+

+#include "7zFolderInStream.h"

+

+namespace NArchive {

+namespace N7z {

+

+CFolderInStream::CFolderInStream()

+{

+  _inStreamWithHashSpec = new CSequentialInStreamWithCRC;

+  _inStreamWithHash = _inStreamWithHashSpec;

+}

+

+void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,

+    const UInt32 *fileIndices, UInt32 numFiles)

+{

+  _updateCallback = updateCallback;

+  _numFiles = numFiles;

+  _fileIndex = 0;

+  _fileIndices = fileIndices;

+  Processed.Clear();

+  CRCs.Clear();

+  Sizes.Clear();

+  _fileIsOpen = false;

+  _currentSizeIsDefined = false;

+}

+

+HRESULT CFolderInStream::OpenStream()

+{

+  _filePos = 0;

+  while (_fileIndex < _numFiles)

+  {

+    CMyComPtr<ISequentialInStream> stream;

+    HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);

+    if (result != S_OK && result != S_FALSE)

+      return result;

+    _fileIndex++;

+    _inStreamWithHashSpec->SetStream(stream);

+    _inStreamWithHashSpec->Init();

+    if (stream)

+    {

+      _fileIsOpen = true;

+      CMyComPtr<IStreamGetSize> streamGetSize;

+      stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);

+      if (streamGetSize)

+      {

+        RINOK(streamGetSize->GetSize(&_currentSize));

+        _currentSizeIsDefined = true;

+      }

+      return S_OK;

+    }

+    RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));

+    Sizes.Add(0);

+    Processed.Add(result == S_OK);

+    AddDigest();

+  }

+  return S_OK;

+}

+

+void CFolderInStream::AddDigest()

+{

+  CRCs.Add(_inStreamWithHashSpec->GetCRC());

+}

+

+HRESULT CFolderInStream::CloseStream()

+{

+  RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));

+  _inStreamWithHashSpec->ReleaseStream();

+  _fileIsOpen = false;

+  _currentSizeIsDefined = false;

+  Processed.Add(true);

+  Sizes.Add(_filePos);

+  AddDigest();

+  return S_OK;

+}

+

+STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize != 0)

+    *processedSize = 0;

+  while (size > 0)

+  {

+    if (_fileIsOpen)

+    {

+      UInt32 processed2;

+      RINOK(_inStreamWithHash->Read(data, size, &processed2));

+      if (processed2 == 0)

+      {

+        RINOK(CloseStream());

+        continue;

+      }

+      if (processedSize != 0)

+        *processedSize = processed2;

+      _filePos += processed2;

+      break;

+    }

+    if (_fileIndex >= _numFiles)

+      break;

+    RINOK(OpenStream());

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)

+{

+  *value = 0;

+  int index2 = (int)subStream;

+  if (index2 < 0 || subStream > Sizes.Size())

+    return E_FAIL;

+  if (index2 < Sizes.Size())

+  {

+    *value = Sizes[index2];

+    return S_OK;

+  }

+  if (!_currentSizeIsDefined)

+    return S_FALSE;

+  *value = _currentSize;

+  return S_OK;

+}

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h
new file mode 100755
index 0000000..fc27b9b
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.h
@@ -0,0 +1,58 @@
+// 7zFolderInStream.h

+

+#ifndef __7Z_FOLDER_IN_STREAM_H

+#define __7Z_FOLDER_IN_STREAM_H

+

+#include "../../ICoder.h"

+#include "../IArchive.h"

+#include "../Common/InStreamWithCRC.h"

+

+#include "7zItem.h"

+

+namespace NArchive {

+namespace N7z {

+

+class CFolderInStream:

+  public ISequentialInStream,

+  public ICompressGetSubStreamSize,

+  public CMyUnknownImp

+{

+  CSequentialInStreamWithCRC *_inStreamWithHashSpec;

+  CMyComPtr<ISequentialInStream> _inStreamWithHash;

+  CMyComPtr<IArchiveUpdateCallback> _updateCallback;

+

+  bool _currentSizeIsDefined;

+  bool _fileIsOpen;

+  UInt64 _currentSize;

+  UInt64 _filePos;

+  const UInt32 *_fileIndices;

+  UInt32 _numFiles;

+  UInt32 _fileIndex;

+

+  HRESULT OpenStream();

+  HRESULT CloseStream();

+  void AddDigest();

+

+public:

+  CRecordVector<bool> Processed;

+  CRecordVector<UInt32> CRCs;

+  CRecordVector<UInt64> Sizes;

+

+  MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);

+

+  CFolderInStream();

+  void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles);

+  UInt64 GetFullSize() const

+  {

+    UInt64 size = 0;

+    for (int i = 0; i < Sizes.Size(); i++)

+      size += Sizes[i];

+    return size;

+  }

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
new file mode 100755
index 0000000..403ca60
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
@@ -0,0 +1,149 @@
+// 7zFolderOutStream.cpp

+

+#include "StdAfx.h"

+

+#include "7zFolderOutStream.h"

+

+namespace NArchive {

+namespace N7z {

+

+CFolderOutStream::CFolderOutStream()

+{

+  _crcStreamSpec = new COutStreamWithCRC;

+  _crcStream = _crcStreamSpec;

+}

+

+HRESULT CFolderOutStream::Init(

+    const CArchiveDatabaseEx *db,

+    UInt32 ref2Offset, UInt32 startIndex,

+    const CBoolVector *extractStatuses,

+    IArchiveExtractCallback *extractCallback,

+    bool testMode, bool checkCrc)

+{

+  _db = db;

+  _ref2Offset = ref2Offset;

+  _startIndex = startIndex;

+

+  _extractStatuses = extractStatuses;

+  _extractCallback = extractCallback;

+  _testMode = testMode;

+  _checkCrc = checkCrc;

+

+  _currentIndex = 0;

+  _fileIsOpen = false;

+  return ProcessEmptyFiles();

+}

+

+HRESULT CFolderOutStream::OpenFile()

+{

+  Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ?

+      NExtract::NAskMode::kTest :

+      NExtract::NAskMode::kExtract) :

+      NExtract::NAskMode::kSkip;

+  CMyComPtr<ISequentialOutStream> realOutStream;

+  UInt32 index = _startIndex + _currentIndex;

+  RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));

+  _crcStreamSpec->SetStream(realOutStream);

+  _crcStreamSpec->Init(_checkCrc);

+  _fileIsOpen = true;

+  const CFileItem &fi = _db->Files[index];

+  _rem = fi.Size;

+  if (askMode == NExtract::NAskMode::kExtract && !realOutStream &&

+      !_db->IsItemAnti(index) && !fi.IsDir)

+    askMode = NExtract::NAskMode::kSkip;

+  return _extractCallback->PrepareOperation(askMode);

+}

+

+HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res)

+{

+  _crcStreamSpec->ReleaseStream();

+  _fileIsOpen = false;

+  _currentIndex++;

+  return _extractCallback->SetOperationResult(res);

+}

+

+HRESULT CFolderOutStream::CloseFileAndSetResult()

+{

+  const CFileItem &fi = _db->Files[_startIndex + _currentIndex];

+  return CloseFileAndSetResult(

+      (fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ?

+      NExtract::NOperationResult::kOK :

+      NExtract::NOperationResult::kCRCError);

+}

+

+HRESULT CFolderOutStream::ProcessEmptyFiles()

+{

+  while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)

+  {

+    RINOK(OpenFile());

+    RINOK(CloseFileAndSetResult());

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize != NULL)

+    *processedSize = 0;

+  while (size != 0)

+  {

+    if (_fileIsOpen)

+    {

+      UInt32 cur = size < _rem ? size : (UInt32)_rem;

+      RINOK(_crcStream->Write(data, cur, &cur));

+      if (cur == 0)

+        break;

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

+      size -= cur;

+      _rem -= cur;

+      if (processedSize != NULL)

+        *processedSize += cur;

+      if (_rem == 0)

+      {

+        RINOK(CloseFileAndSetResult());

+        RINOK(ProcessEmptyFiles());

+        continue;

+      }

+    }

+    else

+    {

+      RINOK(ProcessEmptyFiles());

+      if (_currentIndex == _extractStatuses->Size())

+      {

+        // we support partial extracting

+        if (processedSize != NULL)

+          *processedSize += size;

+        break;

+      }

+      RINOK(OpenFile());

+    }

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)

+{

+  *value = 0;

+  if ((int)subStream >= _extractStatuses->Size())

+    return S_FALSE;

+  *value = _db->Files[_startIndex + (int)subStream].Size;

+  return S_OK;

+}

+

+HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)

+{

+  while (_currentIndex < _extractStatuses->Size())

+  {

+    if (_fileIsOpen)

+    {

+      RINOK(CloseFileAndSetResult(resultEOperationResult));

+    }

+    else

+    {

+      RINOK(OpenFile());

+    }

+  }

+  return S_OK;

+}

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h
new file mode 100755
index 0000000..c964b1d
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h
@@ -0,0 +1,58 @@
+// 7zFolderOutStream.h

+

+#ifndef __7Z_FOLDER_OUT_STREAM_H

+#define __7Z_FOLDER_OUT_STREAM_H

+

+#include "../../IStream.h"

+#include "../IArchive.h"

+#include "../Common/OutStreamWithCRC.h"

+

+#include "7zIn.h"

+

+namespace NArchive {

+namespace N7z {

+

+class CFolderOutStream:

+  public ISequentialOutStream,

+  public ICompressGetSubStreamSize,

+  public CMyUnknownImp

+{

+  COutStreamWithCRC *_crcStreamSpec;

+  CMyComPtr<ISequentialOutStream> _crcStream;

+  const CArchiveDatabaseEx *_db;

+  const CBoolVector *_extractStatuses;

+  CMyComPtr<IArchiveExtractCallback> _extractCallback;

+  UInt32 _ref2Offset;

+  UInt32 _startIndex;

+  int _currentIndex;

+  bool _testMode;

+  bool _checkCrc;

+  bool _fileIsOpen;

+  UInt64 _rem;

+

+  HRESULT OpenFile();

+  HRESULT CloseFileAndSetResult(Int32 res);

+  HRESULT CloseFileAndSetResult();

+  HRESULT ProcessEmptyFiles();

+public:

+  MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)

+

+  CFolderOutStream();

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);

+

+  HRESULT Init(

+      const CArchiveDatabaseEx *db,

+      UInt32 ref2Offset, UInt32 startIndex,

+      const CBoolVector *extractStatuses,

+      IArchiveExtractCallback *extractCallback,

+      bool testMode, bool checkCrc);

+  HRESULT FlushCorrupted(Int32 resultEOperationResult);

+  HRESULT WasWritingFinished() const

+      { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
new file mode 100755
index 0000000..c404b9c
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -0,0 +1,482 @@
+// 7zHandler.cpp

+

+#include "StdAfx.h"

+

+#include "../../../../C/CpuArch.h"

+

+#include "../../../Common/ComTry.h"

+#include "../../../Common/IntToString.h"

+

+#ifndef __7Z_SET_PROPERTIES

+#include "../../../Windows/System.h"

+#endif

+

+#include "../Common/ItemNameUtils.h"

+

+#include "7zHandler.h"

+#include "7zProperties.h"

+

+#ifdef __7Z_SET_PROPERTIES

+#ifdef EXTRACT_ONLY

+#include "../Common/ParseProperties.h"

+#endif

+#endif

+

+using namespace NWindows;

+

+extern UString ConvertMethodIdToString(UInt64 id);

+

+namespace NArchive {

+namespace N7z {

+

+CHandler::CHandler()

+{

+  _crcSize = 4;

+

+  #ifndef _NO_CRYPTO

+  _passwordIsDefined = false;

+  #endif

+

+  #ifdef EXTRACT_ONLY

+  #ifdef __7Z_SET_PROPERTIES

+  _numThreads = NSystem::GetNumberOfProcessors();

+  #endif

+  #else

+  Init();

+  #endif

+}

+

+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)

+{

+  *numItems = _db.Files.Size();

+  return S_OK;

+}

+

+#ifdef _SFX

+

+IMP_IInArchive_ArcProps_NO

+

+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)

+{

+  return E_NOTIMPL;

+}

+

+STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,

+      BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)

+{

+  return E_NOTIMPL;

+}

+

+

+#else

+

+STATPROPSTG kArcProps[] =

+{

+  { NULL, kpidMethod, VT_BSTR},

+  { NULL, kpidSolid, VT_BOOL},

+  { NULL, kpidNumBlocks, VT_UI4},

+  { NULL, kpidPhySize, VT_UI8},

+  { NULL, kpidHeadersSize, VT_UI8},

+  { NULL, kpidOffset, VT_UI8}

+};

+

+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)

+{

+  COM_TRY_BEGIN

+  NCOM::CPropVariant prop;

+  switch(propID)

+  {

+    case kpidMethod:

+    {

+      UString resString;

+      CRecordVector<UInt64> ids;

+      int i;

+      for (i = 0; i < _db.Folders.Size(); i++)

+      {

+        const CFolder &f = _db.Folders[i];

+        for (int j = f.Coders.Size() - 1; j >= 0; j--)

+          ids.AddToUniqueSorted(f.Coders[j].MethodID);

+      }

+

+      for (i = 0; i < ids.Size(); i++)

+      {

+        UInt64 id = ids[i];

+        UString methodName;

+        /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);

+        if (methodName.IsEmpty())

+          methodName = ConvertMethodIdToString(id);

+        if (!resString.IsEmpty())

+          resString += L' ';

+        resString += methodName;

+      }

+      prop = resString;

+      break;

+    }

+    case kpidSolid: prop = _db.IsSolid(); break;

+    case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break;

+    case kpidHeadersSize:  prop = _db.HeadersSize; break;

+    case kpidPhySize:  prop = _db.PhySize; break;

+    case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break;

+  }

+  prop.Detach(value);

+  return S_OK;

+  COM_TRY_END

+}

+

+IMP_IInArchive_ArcProps

+

+#endif

+

+static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop)

+{

+  UInt64 value;

+  if (v.GetItem(index, value))

+  {

+    FILETIME ft;

+    ft.dwLowDateTime = (DWORD)value;

+    ft.dwHighDateTime = (DWORD)(value >> 32);

+    prop = ft;

+  }

+}

+

+#ifndef _SFX

+

+static UString ConvertUInt32ToString(UInt32 value)

+{

+  wchar_t buffer[32];

+  ConvertUInt64ToString(value, buffer);

+  return buffer;

+}

+

+static UString GetStringForSizeValue(UInt32 value)

+{

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

+    if ((UInt32(1) << i) == value)

+      return ConvertUInt32ToString(i);

+  UString result;

+  if (value % (1 << 20) == 0)

+  {

+    result += ConvertUInt32ToString(value >> 20);

+    result += L"m";

+  }

+  else if (value % (1 << 10) == 0)

+  {

+    result += ConvertUInt32ToString(value >> 10);

+    result += L"k";

+  }

+  else

+  {

+    result += ConvertUInt32ToString(value);

+    result += L"b";

+  }

+  return result;

+}

+

+static const UInt64 k_Copy = 0x0;

+static const UInt64 k_Delta = 3;

+static const UInt64 k_LZMA2 = 0x21;

+static const UInt64 k_LZMA  = 0x030101;

+static const UInt64 k_PPMD  = 0x030401;

+

+static wchar_t GetHex(Byte value)

+{

+  return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));

+}

+static inline void AddHexToString(UString &res, Byte value)

+{

+  res += GetHex((Byte)(value >> 4));

+  res += GetHex((Byte)(value & 0xF));

+}

+

+#endif

+

+bool CHandler::IsEncrypted(UInt32 index2) const

+{

+  CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];

+  if (folderIndex != kNumNoIndex)

+    return _db.Folders[folderIndex].IsEncrypted();

+  return false;

+}

+

+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)

+{

+  COM_TRY_BEGIN

+  NCOM::CPropVariant prop;

+  

+  /*

+  const CRef2 &ref2 = _refs[index];

+  if (ref2.Refs.IsEmpty())

+    return E_FAIL;

+  const CRef &ref = ref2.Refs.Front();

+  */

+  

+  const CFileItem &item = _db.Files[index];

+  UInt32 index2 = index;

+

+  switch(propID)

+  {

+    case kpidPath:

+      if (!item.Name.IsEmpty())

+        prop = NItemName::GetOSName(item.Name);

+      break;

+    case kpidIsDir:  prop = item.IsDir; break;

+    case kpidSize:

+    {

+      prop = item.Size;

+      // prop = ref2.Size;

+      break;

+    }

+    case kpidPackSize:

+    {

+      // prop = ref2.PackSize;

+      {

+        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];

+        if (folderIndex != kNumNoIndex)

+        {

+          if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)

+            prop = _db.GetFolderFullPackSize(folderIndex);

+          /*

+          else

+            prop = (UInt64)0;

+          */

+        }

+        else

+          prop = (UInt64)0;

+      }

+      break;

+    }

+    case kpidPosition:  { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; }

+    case kpidCTime:  SetPropFromUInt64Def(_db.CTime, index2, prop); break;

+    case kpidATime:  SetPropFromUInt64Def(_db.ATime, index2, prop); break;

+    case kpidMTime:  SetPropFromUInt64Def(_db.MTime, index2, prop); break;

+    case kpidAttrib:  if (item.AttribDefined) prop = item.Attrib; break;

+    case kpidCRC:  if (item.CrcDefined) prop = item.Crc; break;

+    case kpidEncrypted:  prop = IsEncrypted(index2); break;

+    case kpidIsAnti:  prop = _db.IsItemAnti(index2); break;

+    #ifndef _SFX

+    case kpidMethod:

+      {

+        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];

+        if (folderIndex != kNumNoIndex)

+        {

+          const CFolder &folderInfo = _db.Folders[folderIndex];

+          UString methodsString;

+          for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)

+          {

+            const CCoderInfo &coder = folderInfo.Coders[i];

+            if (!methodsString.IsEmpty())

+              methodsString += L' ';

+

+            UString methodName, propsString;

+            bool methodIsKnown = FindMethod(

+              EXTERNAL_CODECS_VARS

+              coder.MethodID, methodName);

+            

+            if (!methodIsKnown)

+              methodsString += ConvertMethodIdToString(coder.MethodID);

+            else

+            {

+              methodsString += methodName;

+              if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1)

+                propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1);

+              else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5)

+              {

+                UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);

+                propsString = GetStringForSizeValue(dicSize);

+              }

+              else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1)

+              {

+                Byte p = coder.Props[0];

+                UInt32 dicSize = (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11));

+                propsString = GetStringForSizeValue(dicSize);

+              }

+              else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5)

+              {

+                Byte order = *(const Byte *)coder.Props;

+                propsString = L'o';

+                propsString += ConvertUInt32ToString(order);

+                propsString += L":mem";

+                UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);

+                propsString += GetStringForSizeValue(dicSize);

+              }

+              else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1)

+              {

+                const Byte *data = (const Byte *)coder.Props;

+                Byte firstByte = *data++;

+                UInt32 numCyclesPower = firstByte & 0x3F;

+                propsString = ConvertUInt32ToString(numCyclesPower);

+                /*

+                if ((firstByte & 0xC0) != 0)

+                {

+                  UInt32 saltSize = (firstByte >> 7) & 1;

+                  UInt32 ivSize = (firstByte >> 6) & 1;

+                  if (coder.Props.GetCapacity() >= 2)

+                  {

+                    Byte secondByte = *data++;

+                    saltSize += (secondByte >> 4);

+                    ivSize += (secondByte & 0x0F);

+                  }

+                }

+                */

+              }

+            }

+            if (!propsString.IsEmpty())

+            {

+              methodsString += L':';

+              methodsString += propsString;

+            }

+            else if (coder.Props.GetCapacity() > 0)

+            {

+              methodsString += L":[";

+              for (size_t bi = 0; bi < coder.Props.GetCapacity(); bi++)

+              {

+                if (bi > 5 && bi + 1 < coder.Props.GetCapacity())

+                {

+                  methodsString += L"..";

+                  break;

+                }

+                else

+                  AddHexToString(methodsString, coder.Props[bi]);

+              }

+              methodsString += L']';

+            }

+          }

+          prop = methodsString;

+        }

+      }

+      break;

+    case kpidBlock:

+      {

+        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];

+        if (folderIndex != kNumNoIndex)

+          prop = (UInt32)folderIndex;

+      }

+      break;

+    case kpidPackedSize0:

+    case kpidPackedSize1:

+    case kpidPackedSize2:

+    case kpidPackedSize3:

+    case kpidPackedSize4:

+      {

+        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];

+        if (folderIndex != kNumNoIndex)

+        {

+          const CFolder &folderInfo = _db.Folders[folderIndex];

+          if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&

+              folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))

+          {

+            prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);

+          }

+          else

+            prop = (UInt64)0;

+        }

+        else

+          prop = (UInt64)0;

+      }

+      break;

+    #endif

+  }

+  prop.Detach(value);

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP CHandler::Open(IInStream *stream,

+    const UInt64 *maxCheckStartPosition,

+    IArchiveOpenCallback *openArchiveCallback)

+{

+  COM_TRY_BEGIN

+  Close();

+  #ifndef _SFX

+  _fileInfoPopIDs.Clear();

+  #endif

+  try

+  {

+    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;

+

+    #ifndef _NO_CRYPTO

+    CMyComPtr<ICryptoGetTextPassword> getTextPassword;

+    if (openArchiveCallback)

+    {

+      openArchiveCallbackTemp.QueryInterface(

+          IID_ICryptoGetTextPassword, &getTextPassword);

+    }

+    #endif

+    CInArchive archive;

+    RINOK(archive.Open(stream, maxCheckStartPosition));

+    #ifndef _NO_CRYPTO

+    _passwordIsDefined = false;

+    UString password;

+    #endif

+    HRESULT result = archive.ReadDatabase(

+      EXTERNAL_CODECS_VARS

+      _db

+      #ifndef _NO_CRYPTO

+      , getTextPassword, _passwordIsDefined

+      #endif

+      );

+    RINOK(result);

+    _db.Fill();

+    _inStream = stream;

+  }

+  catch(...)

+  {

+    Close();

+    return S_FALSE;

+  }

+  // _inStream = stream;

+  #ifndef _SFX

+  FillPopIDs();

+  #endif

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP CHandler::Close()

+{

+  COM_TRY_BEGIN

+  _inStream.Release();

+  _db.Clear();

+  return S_OK;

+  COM_TRY_END

+}

+

+#ifdef __7Z_SET_PROPERTIES

+#ifdef EXTRACT_ONLY

+

+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)

+{

+  COM_TRY_BEGIN

+  const UInt32 numProcessors = NSystem::GetNumberOfProcessors();

+  _numThreads = numProcessors;

+

+  for (int i = 0; i < numProperties; i++)

+  {

+    UString name = names[i];

+    name.MakeUpper();

+    if (name.IsEmpty())

+      return E_INVALIDARG;

+    const PROPVARIANT &value = values[i];

+    UInt32 number;

+    int index = ParseStringToUInt32(name, number);

+    if (index == 0)

+    {

+      if(name.Left(2).CompareNoCase(L"MT") == 0)

+      {

+        RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));

+        continue;

+      }

+      else

+        return E_INVALIDARG;

+    }

+  }

+  return S_OK;

+  COM_TRY_END

+}

+

+#endif

+#endif

+

+IMPL_ISetCompressCodecsInfo

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
new file mode 100755
index 0000000..c0fd0e0
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -0,0 +1,119 @@
+// 7z/Handler.h

+

+#ifndef __7Z_HANDLER_H

+#define __7Z_HANDLER_H

+

+#include "../../ICoder.h"

+#include "../IArchive.h"

+

+#include "../../Common/CreateCoder.h"

+

+#ifndef EXTRACT_ONLY

+#include "../Common/HandlerOut.h"

+#endif

+

+#include "7zCompressionMode.h"

+#include "7zIn.h"

+

+namespace NArchive {

+namespace N7z {

+

+#ifndef __7Z_SET_PROPERTIES

+

+#ifdef EXTRACT_ONLY

+#if !defined(_7ZIP_ST) && !defined(_SFX)

+#define __7Z_SET_PROPERTIES

+#endif

+#else

+#define __7Z_SET_PROPERTIES

+#endif

+

+#endif

+

+

+class CHandler:

+  #ifndef EXTRACT_ONLY

+  public NArchive::COutHandler,

+  #endif

+  public IInArchive,

+  #ifdef __7Z_SET_PROPERTIES

+  public ISetProperties,

+  #endif

+  #ifndef EXTRACT_ONLY

+  public IOutArchive,

+  #endif

+  PUBLIC_ISetCompressCodecsInfo

+  public CMyUnknownImp

+{

+public:

+  MY_QUERYINTERFACE_BEGIN2(IInArchive)

+  #ifdef __7Z_SET_PROPERTIES

+  MY_QUERYINTERFACE_ENTRY(ISetProperties)

+  #endif

+  #ifndef EXTRACT_ONLY

+  MY_QUERYINTERFACE_ENTRY(IOutArchive)

+  #endif

+  QUERY_ENTRY_ISetCompressCodecsInfo

+  MY_QUERYINTERFACE_END

+  MY_ADDREF_RELEASE

+

+  INTERFACE_IInArchive(;)

+

+  #ifdef __7Z_SET_PROPERTIES

+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);

+  #endif

+

+  #ifndef EXTRACT_ONLY

+  INTERFACE_IOutArchive(;)

+  #endif

+

+  DECL_ISetCompressCodecsInfo

+

+  CHandler();

+

+private:

+  CMyComPtr<IInStream> _inStream;

+  NArchive::N7z::CArchiveDatabaseEx _db;

+  #ifndef _NO_CRYPTO

+  bool _passwordIsDefined;

+  #endif

+

+  #ifdef EXTRACT_ONLY

+  

+  #ifdef __7Z_SET_PROPERTIES

+  UInt32 _numThreads;

+  #endif

+

+  UInt32 _crcSize;

+

+  #else

+  

+  CRecordVector<CBind> _binds;

+

+  HRESULT SetCompressionMethod(CCompressionMethodMode &method,

+      CObjectVector<COneMethodInfo> &methodsInfo

+      #ifndef _7ZIP_ST

+      , UInt32 numThreads

+      #endif

+      );

+

+  HRESULT SetCompressionMethod(

+      CCompressionMethodMode &method,

+      CCompressionMethodMode &headerMethod);

+

+  #endif

+

+  bool IsEncrypted(UInt32 index2) const;

+  #ifndef _SFX

+

+  CRecordVector<UInt64> _fileInfoPopIDs;

+  void FillPopIDs();

+

+  #endif

+

+  DECL_EXTERNAL_CODECS_VARS

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
new file mode 100755
index 0000000..59d6269
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -0,0 +1,483 @@
+// 7zHandlerOut.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Windows/PropVariant.h"

+

+#include "../../../Common/ComTry.h"

+#include "../../../Common/StringToInt.h"

+

+#include "../../ICoder.h"

+

+#include "../Common/ItemNameUtils.h"

+#include "../Common/ParseProperties.h"

+

+#include "7zHandler.h"

+#include "7zOut.h"

+#include "7zUpdate.h"

+

+using namespace NWindows;

+

+namespace NArchive {

+namespace N7z {

+

+static const wchar_t *kLZMAMethodName = L"LZMA";

+static const wchar_t *kCopyMethod = L"Copy";

+static const wchar_t *kDefaultMethodName = kLZMAMethodName;

+

+static const UInt32 kLzmaAlgorithmX5 = 1;

+static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";

+static const UInt32 kDictionaryForHeaders =

+  #ifdef UNDER_CE

+  1 << 18

+  #else

+  1 << 20

+  #endif

+;

+static const UInt32 kNumFastBytesForHeaders = 273;

+static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;

+

+static inline bool IsCopyMethod(const UString &methodName)

+  { return (methodName.CompareNoCase(kCopyMethod) == 0); }

+

+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)

+{

+  *type = NFileTimeType::kWindows;

+  return S_OK;

+}

+

+HRESULT CHandler::SetCompressionMethod(

+    CCompressionMethodMode &methodMode,

+    CCompressionMethodMode &headerMethod)

+{

+  HRESULT res = SetCompressionMethod(methodMode, _methods

+  #ifndef _7ZIP_ST

+  , _numThreads

+  #endif

+  );

+  RINOK(res);

+  methodMode.Binds = _binds;

+

+  if (_compressHeaders)

+  {

+    // headerMethod.Methods.Add(methodMode.Methods.Back());

+

+    CObjectVector<COneMethodInfo> headerMethodInfoVector;

+    COneMethodInfo oneMethodInfo;

+    oneMethodInfo.MethodName = kLZMAMethodName;

+    {

+      CProp prop;

+      prop.Id = NCoderPropID::kMatchFinder;

+      prop.Value = kLzmaMatchFinderForHeaders;

+      oneMethodInfo.Props.Add(prop);

+    }

+    {

+      CProp prop;

+      prop.Id = NCoderPropID::kAlgorithm;

+      prop.Value = kAlgorithmForHeaders;

+      oneMethodInfo.Props.Add(prop);

+    }

+    {

+      CProp prop;

+      prop.Id = NCoderPropID::kNumFastBytes;

+      prop.Value = (UInt32)kNumFastBytesForHeaders;

+      oneMethodInfo.Props.Add(prop);

+    }

+    {

+      CProp prop;

+      prop.Id = NCoderPropID::kDictionarySize;

+      prop.Value = (UInt32)kDictionaryForHeaders;

+      oneMethodInfo.Props.Add(prop);

+    }

+    headerMethodInfoVector.Add(oneMethodInfo);

+    HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector

+      #ifndef _7ZIP_ST

+      , 1

+      #endif

+    );

+    RINOK(res);

+  }

+  return S_OK;

+}

+

+HRESULT CHandler::SetCompressionMethod(

+    CCompressionMethodMode &methodMode,

+    CObjectVector<COneMethodInfo> &methodsInfo

+    #ifndef _7ZIP_ST

+    , UInt32 numThreads

+    #endif

+    )

+{

+  UInt32 level = _level;

+  

+  if (methodsInfo.IsEmpty())

+  {

+    COneMethodInfo oneMethodInfo;

+    oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName);

+    methodsInfo.Add(oneMethodInfo);

+  }

+

+  bool needSolid = false;

+  for(int i = 0; i < methodsInfo.Size(); i++)

+  {

+    COneMethodInfo &oneMethodInfo = methodsInfo[i];

+    SetCompressionMethod2(oneMethodInfo

+      #ifndef _7ZIP_ST

+      , numThreads

+      #endif

+      );

+

+    if (!IsCopyMethod(oneMethodInfo.MethodName))

+      needSolid = true;

+

+    CMethodFull methodFull;

+

+    if (!FindMethod(

+        EXTERNAL_CODECS_VARS

+        oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams))

+      return E_INVALIDARG;

+    methodFull.Props = oneMethodInfo.Props;

+    methodMode.Methods.Add(methodFull);

+

+    if (!_numSolidBytesDefined)

+    {

+      for (int j = 0; j < methodFull.Props.Size(); j++)

+      {

+        const CProp &prop = methodFull.Props[j];

+        if ((prop.Id == NCoderPropID::kDictionarySize ||

+             prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4)

+        {

+          _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7;

+          const UInt64 kMinSize = (1 << 24);

+          if (_numSolidBytes < kMinSize)

+            _numSolidBytes = kMinSize;

+          _numSolidBytesDefined = true;

+          break;

+        }

+      }

+    }

+  }

+

+  if (!needSolid && !_numSolidBytesDefined)

+  {

+    _numSolidBytesDefined = true;

+    _numSolidBytes  = 0;

+  }

+  return S_OK;

+}

+

+static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined)

+{

+  ft = 0;

+  ftDefined = false;

+  if (!writeTime)

+    return S_OK;

+  NCOM::CPropVariant prop;

+  RINOK(updateCallback->GetProperty(index, propID, &prop));

+  if (prop.vt == VT_FILETIME)

+  {

+    ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32);

+    ftDefined = true;

+  }

+  else if (prop.vt != VT_EMPTY)

+    return E_INVALIDARG;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,

+    IArchiveUpdateCallback *updateCallback)

+{

+  COM_TRY_BEGIN

+

+  const CArchiveDatabaseEx *db = 0;

+  #ifdef _7Z_VOL

+  if (_volumes.Size() > 1)

+    return E_FAIL;

+  const CVolume *volume = 0;

+  if (_volumes.Size() == 1)

+  {

+    volume = &_volumes.Front();

+    db = &volume->Database;

+  }

+  #else

+  if (_inStream != 0)

+    db = &_db;

+  #endif

+

+  CObjectVector<CUpdateItem> updateItems;

+  

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

+  {

+    Int32 newData, newProps;

+    UInt32 indexInArchive;

+    if (!updateCallback)

+      return E_FAIL;

+    RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));

+    CUpdateItem ui;

+    ui.NewProps = IntToBool(newProps);

+    ui.NewData = IntToBool(newData);

+    ui.IndexInArchive = indexInArchive;

+    ui.IndexInClient = i;

+    ui.IsAnti = false;

+    ui.Size = 0;

+

+    if (ui.IndexInArchive != -1)

+    {

+      if (db == 0 || ui.IndexInArchive >= db->Files.Size())

+        return E_INVALIDARG;

+      const CFileItem &fi = db->Files[ui.IndexInArchive];

+      ui.Name = fi.Name;

+      ui.IsDir = fi.IsDir;

+      ui.Size = fi.Size;

+      ui.IsAnti = db->IsItemAnti(ui.IndexInArchive);

+      

+      ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime);

+      ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime);

+      ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);

+    }

+

+    if (ui.NewProps)

+    {

+      bool nameIsDefined;

+      bool folderStatusIsDefined;

+      {

+        NCOM::CPropVariant prop;

+        RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop));

+        if (prop.vt == VT_EMPTY)

+          ui.AttribDefined = false;

+        else if (prop.vt != VT_UI4)

+          return E_INVALIDARG;

+        else

+        {

+          ui.Attrib = prop.ulVal;

+          ui.AttribDefined = true;

+        }

+      }

+      

+      // we need MTime to sort files.

+      RINOK(GetTime(updateCallback, i, WriteCTime, kpidCTime, ui.CTime, ui.CTimeDefined));

+      RINOK(GetTime(updateCallback, i, WriteATime, kpidATime, ui.ATime, ui.ATimeDefined));

+      RINOK(GetTime(updateCallback, i, true,       kpidMTime, ui.MTime, ui.MTimeDefined));

+

+      {

+        NCOM::CPropVariant prop;

+        RINOK(updateCallback->GetProperty(i, kpidPath, &prop));

+        if (prop.vt == VT_EMPTY)

+          nameIsDefined = false;

+        else if (prop.vt != VT_BSTR)

+          return E_INVALIDARG;

+        else

+        {

+          ui.Name = NItemName::MakeLegalName(prop.bstrVal);

+          nameIsDefined = true;

+        }

+      }

+      {

+        NCOM::CPropVariant prop;

+        RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop));

+        if (prop.vt == VT_EMPTY)

+          folderStatusIsDefined = false;

+        else if (prop.vt != VT_BOOL)

+          return E_INVALIDARG;

+        else

+        {

+          ui.IsDir = (prop.boolVal != VARIANT_FALSE);

+          folderStatusIsDefined = true;

+        }

+      }

+

+      {

+        NCOM::CPropVariant prop;

+        RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop));

+        if (prop.vt == VT_EMPTY)

+          ui.IsAnti = false;

+        else if (prop.vt != VT_BOOL)

+          return E_INVALIDARG;

+        else

+          ui.IsAnti = (prop.boolVal != VARIANT_FALSE);

+      }

+

+      if (ui.IsAnti)

+      {

+        ui.AttribDefined = false;

+

+        ui.CTimeDefined = false;

+        ui.ATimeDefined = false;

+        ui.MTimeDefined = false;

+        

+        ui.Size = 0;

+      }

+

+      if (!folderStatusIsDefined && ui.AttribDefined)

+        ui.SetDirStatusFromAttrib();

+    }

+

+    if (ui.NewData)

+    {

+      NCOM::CPropVariant prop;

+      RINOK(updateCallback->GetProperty(i, kpidSize, &prop));

+      if (prop.vt != VT_UI8)

+        return E_INVALIDARG;

+      ui.Size = (UInt64)prop.uhVal.QuadPart;

+      if (ui.Size != 0 && ui.IsAnti)

+        return E_INVALIDARG;

+    }

+    updateItems.Add(ui);

+  }

+

+  CCompressionMethodMode methodMode, headerMethod;

+  RINOK(SetCompressionMethod(methodMode, headerMethod));

+  #ifndef _7ZIP_ST

+  methodMode.NumThreads = _numThreads;

+  headerMethod.NumThreads = 1;

+  #endif

+

+  CMyComPtr<ICryptoGetTextPassword2> getPassword2;

+  updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);

+

+  if (getPassword2)

+  {

+    CMyComBSTR password;

+    Int32 passwordIsDefined;

+    RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));

+    methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);

+    if (methodMode.PasswordIsDefined)

+      methodMode.Password = password;

+  }

+  else

+    methodMode.PasswordIsDefined = false;

+

+  bool compressMainHeader = _compressHeaders;  // check it

+

+  bool encryptHeaders = false;

+

+  if (methodMode.PasswordIsDefined)

+  {

+    if (_encryptHeadersSpecified)

+      encryptHeaders = _encryptHeaders;

+    #ifndef _NO_CRYPTO

+    else

+      encryptHeaders = _passwordIsDefined;

+    #endif

+    compressMainHeader = true;

+    if (encryptHeaders)

+    {

+      headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined;

+      headerMethod.Password = methodMode.Password;

+    }

+  }

+

+  if (numItems < 2)

+    compressMainHeader = false;

+

+  CUpdateOptions options;

+  options.Method = &methodMode;

+  options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0;

+  options.UseFilters = _level != 0 && _autoFilter;

+  options.MaxFilter = _level >= 8;

+

+  options.HeaderOptions.CompressMainHeader = compressMainHeader;

+  options.HeaderOptions.WriteCTime = WriteCTime;

+  options.HeaderOptions.WriteATime = WriteATime;

+  options.HeaderOptions.WriteMTime = WriteMTime;

+  

+  options.NumSolidFiles = _numSolidFiles;

+  options.NumSolidBytes = _numSolidBytes;

+  options.SolidExtension = _solidExtension;

+  options.RemoveSfxBlock = _removeSfxBlock;

+  options.VolumeMode = _volumeMode;

+

+  COutArchive archive;

+  CArchiveDatabase newDatabase;

+

+  CMyComPtr<ICryptoGetTextPassword> getPassword;

+  updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);

+  

+  HRESULT res = Update(

+      EXTERNAL_CODECS_VARS

+      #ifdef _7Z_VOL

+      volume ? volume->Stream: 0,

+      volume ? db : 0,

+      #else

+      _inStream,

+      db,

+      #endif

+      updateItems,

+      archive, newDatabase, outStream, updateCallback, options

+      #ifndef _NO_CRYPTO

+      , getPassword

+      #endif

+      );

+

+  RINOK(res);

+

+  updateItems.ClearAndFree();

+

+  return archive.WriteDatabase(EXTERNAL_CODECS_VARS

+      newDatabase, options.HeaderMethod, options.HeaderOptions);

+

+  COM_TRY_END

+}

+

+static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)

+{

+  stream = 0;

+  int index = ParseStringToUInt32(srcString, coder);

+  if (index == 0)

+    return E_INVALIDARG;

+  srcString.Delete(0, index);

+  if (srcString[0] == 'S')

+  {

+    srcString.Delete(0);

+    int index = ParseStringToUInt32(srcString, stream);

+    if (index == 0)

+      return E_INVALIDARG;

+    srcString.Delete(0, index);

+  }

+  return S_OK;

+}

+

+static HRESULT GetBindInfo(UString &srcString, CBind &bind)

+{

+  RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream));

+  if (srcString[0] != ':')

+    return E_INVALIDARG;

+  srcString.Delete(0);

+  RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream));

+  if (!srcString.IsEmpty())

+    return E_INVALIDARG;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)

+{

+  COM_TRY_BEGIN

+  _binds.Clear();

+  BeforeSetProperty();

+

+  for (int i = 0; i < numProperties; i++)

+  {

+    UString name = names[i];

+    name.MakeUpper();

+    if (name.IsEmpty())

+      return E_INVALIDARG;

+

+    const PROPVARIANT &value = values[i];

+

+    if (name[0] == 'B')

+    {

+      name.Delete(0);

+      CBind bind;

+      RINOK(GetBindInfo(name, bind));

+      _binds.Add(bind);

+      continue;

+    }

+

+    RINOK(SetProperty(name, value));

+  }

+

+  return S_OK;

+  COM_TRY_END

+}

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zHeader.cpp b/CPP/7zip/Archive/7z/7zHeader.cpp
new file mode 100755
index 0000000..d93670c
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHeader.cpp
@@ -0,0 +1,14 @@
+// 7zHeader.cpp

+

+#include "StdAfx.h"

+#include "7zHeader.h"

+

+namespace NArchive {

+namespace N7z {

+

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

+#ifdef _7Z_VOL

+Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};

+#endif

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h
new file mode 100755
index 0000000..57f455b
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHeader.h
@@ -0,0 +1,97 @@
+// 7z/7zHeader.h

+

+#ifndef __7Z_HEADER_H

+#define __7Z_HEADER_H

+

+#include "../../../Common/Types.h"

+

+namespace NArchive {

+namespace N7z {

+

+const int kSignatureSize = 6;

+extern Byte kSignature[kSignatureSize];

+

+// #define _7Z_VOL

+// 7z-MultiVolume is not finished yet.

+// It can work already, but I still do not like some

+// things of that new multivolume format.

+// So please keep it commented.

+

+#ifdef _7Z_VOL

+extern Byte kFinishSignature[kSignatureSize];

+#endif

+

+struct CArchiveVersion

+{

+  Byte Major;

+  Byte Minor;

+};

+

+const Byte kMajorVersion = 0;

+

+struct CStartHeader

+{

+  UInt64 NextHeaderOffset;

+  UInt64 NextHeaderSize;

+  UInt32 NextHeaderCRC;

+};

+

+const UInt32 kStartHeaderSize = 20;

+

+#ifdef _7Z_VOL

+struct CFinishHeader: public CStartHeader

+{

+  UInt64 ArchiveStartOffset;  // data offset from end if that struct

+  UInt64 AdditionalStartBlockSize; // start  signature & start header size

+};

+

+const UInt32 kFinishHeaderSize = kStartHeaderSize + 16;

+#endif

+

+namespace NID

+{

+  enum EEnum

+  {

+    kEnd,

+

+    kHeader,

+

+    kArchiveProperties,

+    

+    kAdditionalStreamsInfo,

+    kMainStreamsInfo,

+    kFilesInfo,

+    

+    kPackInfo,

+    kUnpackInfo,

+    kSubStreamsInfo,

+

+    kSize,

+    kCRC,

+

+    kFolder,

+

+    kCodersUnpackSize,

+    kNumUnpackStream,

+

+    kEmptyStream,

+    kEmptyFile,

+    kAnti,

+

+    kName,

+    kCTime,

+    kATime,

+    kMTime,

+    kWinAttributes,

+    kComment,

+

+    kEncodedHeader,

+

+    kStartPos,

+    kDummy

+  };

+}

+

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
new file mode 100755
index 0000000..f418bb1
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -0,0 +1,1276 @@
+// 7zIn.cpp

+

+#include "StdAfx.h"

+

+#include "../../../../C/7zCrc.h"

+#include "../../../../C/CpuArch.h"

+

+#include "../../Common/StreamObjects.h"

+#include "../../Common/StreamUtils.h"

+

+#include "7zDecode.h"

+#include "7zIn.h"

+

+#define Get16(p) GetUi16(p)

+#define Get32(p) GetUi32(p)

+#define Get64(p) GetUi64(p)

+

+// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader

+#ifndef _SFX

+#define FORMAT_7Z_RECOVERY

+#endif

+

+namespace NArchive {

+namespace N7z {

+

+static void BoolVector_Fill_False(CBoolVector &v, int size)

+{

+  v.Clear();

+  v.Reserve(size);

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

+    v.Add(false);

+}

+

+static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index)

+{

+  if (index >= (UInt32)v.Size())

+    return true;

+  bool res = v[index];

+  v[index] = true;

+  return res;

+}

+

+bool CFolder::CheckStructure() const

+{

+  const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it

+  const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax

+  const int kNumBindsMax = 32;

+

+  if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax)

+    return false;

+

+  {

+    CBoolVector v;

+    BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size());

+    

+    int i;

+    for (i = 0; i < BindPairs.Size(); i++)

+      if (BoolVector_GetAndSet(v, BindPairs[i].InIndex))

+        return false;

+    for (i = 0; i < PackStreams.Size(); i++)

+      if (BoolVector_GetAndSet(v, PackStreams[i]))

+        return false;

+    

+    BoolVector_Fill_False(v, UnpackSizes.Size());

+    for (i = 0; i < BindPairs.Size(); i++)

+      if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex))

+        return false;

+  }

+  

+  UInt32 mask[kMaskSize];

+  int i;

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

+    mask[i] = 0;

+

+  {

+    CIntVector inStreamToCoder, outStreamToCoder;

+    for (i = 0; i < Coders.Size(); i++)

+    {

+      CNum j;

+      const CCoderInfo &coder = Coders[i];

+      for (j = 0; j < coder.NumInStreams; j++)

+        inStreamToCoder.Add(i);

+      for (j = 0; j < coder.NumOutStreams; j++)

+        outStreamToCoder.Add(i);

+    }

+    

+    for (i = 0; i < BindPairs.Size(); i++)

+    {

+      const CBindPair &bp = BindPairs[i];

+      mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]);

+    }

+  }

+  

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

+    for (int j = 0; j < kMaskSize; j++)

+      if (((1 << j) & mask[i]) != 0)

+        mask[i] |= mask[j];

+

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

+    if (((1 << i) & mask[i]) != 0)

+      return false;

+

+  return true;

+}

+

+class CInArchiveException {};

+

+static void ThrowException() { throw CInArchiveException(); }

+static inline void ThrowEndOfData()   { ThrowException(); }

+static inline void ThrowUnsupported() { ThrowException(); }

+static inline void ThrowIncorrect()   { ThrowException(); }

+static inline void ThrowUnsupportedVersion() { ThrowException(); }

+

+/*

+class CInArchiveException

+{

+public:

+  enum CCauseType

+  {

+    kUnsupportedVersion = 0,

+    kUnsupported,

+    kIncorrect,

+    kEndOfData

+  } Cause;

+  CInArchiveException(CCauseType cause): Cause(cause) {};

+};

+

+static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); }

+static void ThrowEndOfData()   { ThrowException(CInArchiveException::kEndOfData); }

+static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); }

+static void ThrowIncorrect()   { ThrowException(CInArchiveException::kIncorrect); }

+static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); }

+*/

+

+class CStreamSwitch

+{

+  CInArchive *_archive;

+  bool _needRemove;

+public:

+  CStreamSwitch(): _needRemove(false) {}

+  ~CStreamSwitch() { Remove(); }

+  void Remove();

+  void Set(CInArchive *archive, const Byte *data, size_t size);

+  void Set(CInArchive *archive, const CByteBuffer &byteBuffer);

+  void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector);

+};

+

+void CStreamSwitch::Remove()

+{

+  if (_needRemove)

+  {

+    _archive->DeleteByteStream();

+    _needRemove = false;

+  }

+}

+

+void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size)

+{

+  Remove();

+  _archive = archive;

+  _archive->AddByteStream(data, size);

+  _needRemove = true;

+}

+

+void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)

+{

+  Set(archive, byteBuffer, byteBuffer.GetCapacity());

+}

+

+void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector)

+{

+  Remove();

+  Byte external = archive->ReadByte();

+  if (external != 0)

+  {

+    int dataIndex = (int)archive->ReadNum();

+    if (dataIndex < 0 || dataIndex >= dataVector->Size())

+      ThrowIncorrect();

+    Set(archive, (*dataVector)[dataIndex]);

+  }

+}

+

+Byte CInByte2::ReadByte()

+{

+  if (_pos >= _size)

+    ThrowEndOfData();

+  return _buffer[_pos++];

+}

+

+void CInByte2::ReadBytes(Byte *data, size_t size)

+{

+  if (size > _size - _pos)

+    ThrowEndOfData();

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

+    data[i] = _buffer[_pos++];

+}

+

+void CInByte2::SkipData(UInt64 size)

+{

+  if (size > _size - _pos)

+    ThrowEndOfData();

+  _pos += (size_t)size;

+}

+

+void CInByte2::SkipData()

+{

+  SkipData(ReadNumber());

+}

+

+UInt64 CInByte2::ReadNumber()

+{

+  if (_pos >= _size)

+    ThrowEndOfData();

+  Byte firstByte = _buffer[_pos++];

+  Byte mask = 0x80;

+  UInt64 value = 0;

+  for (int i = 0; i < 8; i++)

+  {

+    if ((firstByte & mask) == 0)

+    {

+      UInt64 highPart = firstByte & (mask - 1);

+      value += (highPart << (i * 8));

+      return value;

+    }

+    if (_pos >= _size)

+      ThrowEndOfData();

+    value |= ((UInt64)_buffer[_pos++] << (8 * i));

+    mask >>= 1;

+  }

+  return value;

+}

+

+CNum CInByte2::ReadNum()

+{

+  UInt64 value = ReadNumber();

+  if (value > kNumMax)

+    ThrowUnsupported();

+  return (CNum)value;

+}

+

+UInt32 CInByte2::ReadUInt32()

+{

+  if (_pos + 4 > _size)

+    ThrowEndOfData();

+  UInt32 res = Get32(_buffer + _pos);

+  _pos += 4;

+  return res;

+}

+

+UInt64 CInByte2::ReadUInt64()

+{

+  if (_pos + 8 > _size)

+    ThrowEndOfData();

+  UInt64 res = Get64(_buffer + _pos);

+  _pos += 8;

+  return res;

+}

+

+void CInByte2::ReadString(UString &s)

+{

+  const Byte *buf = _buffer + _pos;

+  size_t rem = (_size - _pos) / 2 * 2;

+  {

+    size_t i;

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

+      if (buf[i] == 0 && buf[i + 1] == 0)

+        break;

+    if (i == rem)

+      ThrowEndOfData();

+    rem = i;

+  }

+  int len = (int)(rem / 2);

+  if (len < 0 || (size_t)len * 2 != rem)

+    ThrowUnsupported();

+  wchar_t *p = s.GetBuffer(len);

+  int i;

+  for (i = 0; i < len; i++, buf += 2)

+    p[i] = (wchar_t)Get16(buf);

+  s.ReleaseBuffer(len);

+  _pos += rem + 2;

+}

+

+static inline bool TestSignature(const Byte *p)

+{

+  for (int i = 0; i < kSignatureSize; i++)

+    if (p[i] != kSignature[i])

+      return false;

+  return CrcCalc(p + 12, 20) == GetUi32(p + 8);

+}

+

+#ifdef FORMAT_7Z_RECOVERY

+static inline bool TestSignature2(const Byte *p)

+{

+  int i;

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

+    if (p[i] != kSignature[i])

+      return false;

+  if (CrcCalc(p + 12, 20) == GetUi32(p + 8))

+    return true;

+  for (i = 8; i < kHeaderSize; i++)

+    if (p[i] != 0)

+      return false;

+  return (p[6] != 0 || p[7] != 0);

+}

+#else

+#define TestSignature2(p) TestSignature(p)

+#endif

+

+HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)

+{

+  RINOK(ReadStream_FALSE(stream, _header, kHeaderSize));

+

+  if (TestSignature2(_header))

+    return S_OK;

+

+  CByteBuffer byteBuffer;

+  const UInt32 kBufferSize = (1 << 16);

+  byteBuffer.SetCapacity(kBufferSize);

+  Byte *buffer = byteBuffer;

+  UInt32 numPrevBytes = kHeaderSize;

+  memcpy(buffer, _header, kHeaderSize);

+  UInt64 curTestPos = _arhiveBeginStreamPosition;

+  for (;;)

+  {

+    if (searchHeaderSizeLimit != NULL)

+      if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit)

+        break;

+    do

+    {

+      UInt32 numReadBytes = kBufferSize - numPrevBytes;

+      UInt32 processedSize;

+      RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize));

+      numPrevBytes += processedSize;

+      if (processedSize == 0)

+        return S_FALSE;

+    }

+    while (numPrevBytes <= kHeaderSize);

+    UInt32 numTests = numPrevBytes - kHeaderSize;

+    for (UInt32 pos = 0; pos < numTests; pos++)

+    {

+      for (; buffer[pos] != '7' && pos < numTests; pos++);

+      if (pos == numTests)

+        break;

+      if (TestSignature(buffer + pos))

+      {

+        memcpy(_header, buffer + pos, kHeaderSize);

+        curTestPos += pos;

+        _arhiveBeginStreamPosition = curTestPos;

+        return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL);

+      }

+    }

+    curTestPos += numTests;

+    numPrevBytes -= numTests;

+    memmove(buffer, buffer + numTests, numPrevBytes);

+  }

+  return S_FALSE;

+}

+

+// S_FALSE means that file is not archive

+HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)

+{

+  HeadersSize = 0;

+  Close();

+  RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition))

+  RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));

+  _stream = stream;

+  return S_OK;

+}

+  

+void CInArchive::Close()

+{

+  _stream.Release();

+}

+

+void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)

+{

+  for (;;)

+  {

+    if (ReadID() == NID::kEnd)

+      break;

+    SkipData();

+  }

+}

+

+void CInArchive::GetNextFolderItem(CFolder &folder)

+{

+  CNum numCoders = ReadNum();

+

+  folder.Coders.Clear();

+  folder.Coders.Reserve((int)numCoders);

+  CNum numInStreams = 0;

+  CNum numOutStreams = 0;

+  CNum i;

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

+  {

+    folder.Coders.Add(CCoderInfo());

+    CCoderInfo &coder = folder.Coders.Back();

+

+    {

+      Byte mainByte = ReadByte();

+      int idSize = (mainByte & 0xF);

+      Byte longID[15];

+      ReadBytes(longID, idSize);

+      if (idSize > 8)

+        ThrowUnsupported();

+      UInt64 id = 0;

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

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

+      coder.MethodID = id;

+

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

+      {

+        coder.NumInStreams = ReadNum();

+        coder.NumOutStreams = ReadNum();

+      }

+      else

+      {

+        coder.NumInStreams = 1;

+        coder.NumOutStreams = 1;

+      }

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

+      {

+        CNum propsSize = ReadNum();

+        coder.Props.SetCapacity((size_t)propsSize);

+        ReadBytes((Byte *)coder.Props, (size_t)propsSize);

+      }

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

+        ThrowUnsupported();

+    }

+    numInStreams += coder.NumInStreams;

+    numOutStreams += coder.NumOutStreams;

+  }

+

+  CNum numBindPairs = numOutStreams - 1;

+  folder.BindPairs.Clear();

+  folder.BindPairs.Reserve(numBindPairs);

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

+  {

+    CBindPair bp;

+    bp.InIndex = ReadNum();

+    bp.OutIndex = ReadNum();

+    folder.BindPairs.Add(bp);

+  }

+

+  if (numInStreams < numBindPairs)

+    ThrowUnsupported();

+  CNum numPackStreams = numInStreams - numBindPairs;

+  folder.PackStreams.Reserve(numPackStreams);

+  if (numPackStreams == 1)

+  {

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

+      if (folder.FindBindPairForInStream(i) < 0)

+      {

+        folder.PackStreams.Add(i);

+        break;

+      }

+    if (folder.PackStreams.Size() != 1)

+      ThrowUnsupported();

+  }

+  else

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

+      folder.PackStreams.Add(ReadNum());

+}

+

+void CInArchive::WaitAttribute(UInt64 attribute)

+{

+  for (;;)

+  {

+    UInt64 type = ReadID();

+    if (type == attribute)

+      return;

+    if (type == NID::kEnd)

+      ThrowIncorrect();

+    SkipData();

+  }

+}

+

+void CInArchive::ReadHashDigests(int numItems,

+    CBoolVector &digestsDefined,

+    CRecordVector<UInt32> &digests)

+{

+  ReadBoolVector2(numItems, digestsDefined);

+  digests.Clear();

+  digests.Reserve(numItems);

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

+  {

+    UInt32 crc = 0;

+    if (digestsDefined[i])

+      crc = ReadUInt32();

+    digests.Add(crc);

+  }

+}

+

+void CInArchive::ReadPackInfo(

+    UInt64 &dataOffset,

+    CRecordVector<UInt64> &packSizes,

+    CBoolVector &packCRCsDefined,

+    CRecordVector<UInt32> &packCRCs)

+{

+  dataOffset = ReadNumber();

+  CNum numPackStreams = ReadNum();

+

+  WaitAttribute(NID::kSize);

+  packSizes.Clear();

+  packSizes.Reserve(numPackStreams);

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

+    packSizes.Add(ReadNumber());

+

+  UInt64 type;

+  for (;;)

+  {

+    type = ReadID();

+    if (type == NID::kEnd)

+      break;

+    if (type == NID::kCRC)

+    {

+      ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs);

+      continue;

+    }

+    SkipData();

+  }

+  if (packCRCsDefined.IsEmpty())

+  {

+    BoolVector_Fill_False(packCRCsDefined, numPackStreams);

+    packCRCs.Reserve(numPackStreams);

+    packCRCs.Clear();

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

+      packCRCs.Add(0);

+  }

+}

+

+void CInArchive::ReadUnpackInfo(

+    const CObjectVector<CByteBuffer> *dataVector,

+    CObjectVector<CFolder> &folders)

+{

+  WaitAttribute(NID::kFolder);

+  CNum numFolders = ReadNum();

+

+  {

+    CStreamSwitch streamSwitch;

+    streamSwitch.Set(this, dataVector);

+    folders.Clear();

+    folders.Reserve(numFolders);

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

+    {

+      folders.Add(CFolder());

+      GetNextFolderItem(folders.Back());

+    }

+  }

+

+  WaitAttribute(NID::kCodersUnpackSize);

+

+  CNum i;

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

+  {

+    CFolder &folder = folders[i];

+    CNum numOutStreams = folder.GetNumOutStreams();

+    folder.UnpackSizes.Reserve(numOutStreams);

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

+      folder.UnpackSizes.Add(ReadNumber());

+  }

+

+  for (;;)

+  {

+    UInt64 type = ReadID();

+    if (type == NID::kEnd)

+      return;

+    if (type == NID::kCRC)

+    {

+      CBoolVector crcsDefined;

+      CRecordVector<UInt32> crcs;

+      ReadHashDigests(numFolders, crcsDefined, crcs);

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

+      {

+        CFolder &folder = folders[i];

+        folder.UnpackCRCDefined = crcsDefined[i];

+        folder.UnpackCRC = crcs[i];

+      }

+      continue;

+    }

+    SkipData();

+  }

+}

+

+void CInArchive::ReadSubStreamsInfo(

+    const CObjectVector<CFolder> &folders,

+    CRecordVector<CNum> &numUnpackStreamsInFolders,

+    CRecordVector<UInt64> &unpackSizes,

+    CBoolVector &digestsDefined,

+    CRecordVector<UInt32> &digests)

+{

+  numUnpackStreamsInFolders.Clear();

+  numUnpackStreamsInFolders.Reserve(folders.Size());

+  UInt64 type;

+  for (;;)

+  {

+    type = ReadID();

+    if (type == NID::kNumUnpackStream)

+    {

+      for (int i = 0; i < folders.Size(); i++)

+        numUnpackStreamsInFolders.Add(ReadNum());

+      continue;

+    }

+    if (type == NID::kCRC || type == NID::kSize)

+      break;

+    if (type == NID::kEnd)

+      break;

+    SkipData();

+  }

+

+  if (numUnpackStreamsInFolders.IsEmpty())

+    for (int i = 0; i < folders.Size(); i++)

+      numUnpackStreamsInFolders.Add(1);

+

+  int i;

+  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)

+  {

+    // v3.13 incorrectly worked with empty folders

+    // v4.07: we check that folder is empty

+    CNum numSubstreams = numUnpackStreamsInFolders[i];

+    if (numSubstreams == 0)

+      continue;

+    UInt64 sum = 0;

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

+      if (type == NID::kSize)

+      {

+        UInt64 size = ReadNumber();

+        unpackSizes.Add(size);

+        sum += size;

+      }

+    unpackSizes.Add(folders[i].GetUnpackSize() - sum);

+  }

+  if (type == NID::kSize)

+    type = ReadID();

+

+  int numDigests = 0;

+  int numDigestsTotal = 0;

+  for (i = 0; i < folders.Size(); i++)

+  {

+    CNum numSubstreams = numUnpackStreamsInFolders[i];

+    if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)

+      numDigests += numSubstreams;

+    numDigestsTotal += numSubstreams;

+  }

+

+  for (;;)

+  {

+    if (type == NID::kCRC)

+    {

+      CBoolVector digestsDefined2;

+      CRecordVector<UInt32> digests2;

+      ReadHashDigests(numDigests, digestsDefined2, digests2);

+      int digestIndex = 0;

+      for (i = 0; i < folders.Size(); i++)

+      {

+        CNum numSubstreams = numUnpackStreamsInFolders[i];

+        const CFolder &folder = folders[i];

+        if (numSubstreams == 1 && folder.UnpackCRCDefined)

+        {

+          digestsDefined.Add(true);

+          digests.Add(folder.UnpackCRC);

+        }

+        else

+          for (CNum j = 0; j < numSubstreams; j++, digestIndex++)

+          {

+            digestsDefined.Add(digestsDefined2[digestIndex]);

+            digests.Add(digests2[digestIndex]);

+          }

+      }

+    }

+    else if (type == NID::kEnd)

+    {

+      if (digestsDefined.IsEmpty())

+      {

+        BoolVector_Fill_False(digestsDefined, numDigestsTotal);

+        digests.Clear();

+        for (int i = 0; i < numDigestsTotal; i++)

+          digests.Add(0);

+      }

+      return;

+    }

+    else

+      SkipData();

+    type = ReadID();

+  }

+}

+

+void CInArchive::ReadStreamsInfo(

+    const CObjectVector<CByteBuffer> *dataVector,

+    UInt64 &dataOffset,

+    CRecordVector<UInt64> &packSizes,

+    CBoolVector &packCRCsDefined,

+    CRecordVector<UInt32> &packCRCs,

+    CObjectVector<CFolder> &folders,

+    CRecordVector<CNum> &numUnpackStreamsInFolders,

+    CRecordVector<UInt64> &unpackSizes,

+    CBoolVector &digestsDefined,

+    CRecordVector<UInt32> &digests)

+{

+  for (;;)

+  {

+    UInt64 type = ReadID();

+    if (type > ((UInt32)1 << 30))

+      ThrowIncorrect();

+    switch((UInt32)type)

+    {

+      case NID::kEnd:

+        return;

+      case NID::kPackInfo:

+      {

+        ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs);

+        break;

+      }

+      case NID::kUnpackInfo:

+      {

+        ReadUnpackInfo(dataVector, folders);

+        break;

+      }

+      case NID::kSubStreamsInfo:

+      {

+        ReadSubStreamsInfo(folders, numUnpackStreamsInFolders,

+            unpackSizes, digestsDefined, digests);

+        break;

+      }

+      default:

+        ThrowIncorrect();

+    }

+  }

+}

+

+void CInArchive::ReadBoolVector(int numItems, CBoolVector &v)

+{

+  v.Clear();

+  v.Reserve(numItems);

+  Byte b = 0;

+  Byte mask = 0;

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

+  {

+    if (mask == 0)

+    {

+      b = ReadByte();

+      mask = 0x80;

+    }

+    v.Add((b & mask) != 0);

+    mask >>= 1;

+  }

+}

+

+void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v)

+{

+  Byte allAreDefined = ReadByte();

+  if (allAreDefined == 0)

+  {

+    ReadBoolVector(numItems, v);

+    return;

+  }

+  v.Clear();

+  v.Reserve(numItems);

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

+    v.Add(true);

+}

+

+void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,

+    CUInt64DefVector &v, int numFiles)

+{

+  ReadBoolVector2(numFiles, v.Defined);

+

+  CStreamSwitch streamSwitch;

+  streamSwitch.Set(this, &dataVector);

+  v.Values.Reserve(numFiles);

+

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

+  {

+    UInt64 t = 0;

+    if (v.Defined[i])

+      t = ReadUInt64();

+    v.Values.Add(t);

+  }

+}

+

+HRESULT CInArchive::ReadAndDecodePackedStreams(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    UInt64 baseOffset,

+    UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector

+    #ifndef _NO_CRYPTO

+    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

+    #endif

+    )

+{

+  CRecordVector<UInt64> packSizes;

+  CBoolVector packCRCsDefined;

+  CRecordVector<UInt32> packCRCs;

+  CObjectVector<CFolder> folders;

+  

+  CRecordVector<CNum> numUnpackStreamsInFolders;

+  CRecordVector<UInt64> unpackSizes;

+  CBoolVector digestsDefined;

+  CRecordVector<UInt32> digests;

+  

+  ReadStreamsInfo(NULL,

+    dataOffset,

+    packSizes,

+    packCRCsDefined,

+    packCRCs,

+    folders,

+    numUnpackStreamsInFolders,

+    unpackSizes,

+    digestsDefined,

+    digests);

+  

+  // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader;

+  

+  CNum packIndex = 0;

+  CDecoder decoder(

+    #ifdef _ST_MODE

+    false

+    #else

+    true

+    #endif

+    );

+  UInt64 dataStartPos = baseOffset + dataOffset;

+  for (int i = 0; i < folders.Size(); i++)

+  {

+    const CFolder &folder = folders[i];

+    dataVector.Add(CByteBuffer());

+    CByteBuffer &data = dataVector.Back();

+    UInt64 unpackSize64 = folder.GetUnpackSize();

+    size_t unpackSize = (size_t)unpackSize64;

+    if (unpackSize != unpackSize64)

+      ThrowUnsupported();

+    data.SetCapacity(unpackSize);

+    

+    CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;

+    CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;

+    outStreamSpec->Init(data, unpackSize);

+    

+    HRESULT result = decoder.Decode(

+      EXTERNAL_CODECS_LOC_VARS

+      _stream, dataStartPos,

+      &packSizes[packIndex], folder, outStream, NULL

+      #ifndef _NO_CRYPTO

+      , getTextPassword, passwordIsDefined

+      #endif

+      #if !defined(_7ZIP_ST) && !defined(_SFX)

+      , false, 1

+      #endif

+      );

+    RINOK(result);

+    

+    if (folder.UnpackCRCDefined)

+      if (CrcCalc(data, unpackSize) != folder.UnpackCRC)

+        ThrowIncorrect();

+    for (int j = 0; j < folder.PackStreams.Size(); j++)

+    {

+      UInt64 packSize = packSizes[packIndex++];

+      dataStartPos += packSize;

+      HeadersSize += packSize;

+    }

+  }

+  return S_OK;

+}

+

+HRESULT CInArchive::ReadHeader(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CArchiveDatabaseEx &db

+    #ifndef _NO_CRYPTO

+    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

+    #endif

+    )

+{

+  UInt64 type = ReadID();

+

+  if (type == NID::kArchiveProperties)

+  {

+    ReadArchiveProperties(db.ArchiveInfo);

+    type = ReadID();

+  }

+ 

+  CObjectVector<CByteBuffer> dataVector;

+  

+  if (type == NID::kAdditionalStreamsInfo)

+  {

+    HRESULT result = ReadAndDecodePackedStreams(

+        EXTERNAL_CODECS_LOC_VARS

+        db.ArchiveInfo.StartPositionAfterHeader,

+        db.ArchiveInfo.DataStartPosition2,

+        dataVector

+        #ifndef _NO_CRYPTO

+        , getTextPassword, passwordIsDefined

+        #endif

+        );

+    RINOK(result);

+    db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader;

+    type = ReadID();

+  }

+

+  CRecordVector<UInt64> unpackSizes;

+  CBoolVector digestsDefined;

+  CRecordVector<UInt32> digests;

+  

+  if (type == NID::kMainStreamsInfo)

+  {

+    ReadStreamsInfo(&dataVector,

+        db.ArchiveInfo.DataStartPosition,

+        db.PackSizes,

+        db.PackCRCsDefined,

+        db.PackCRCs,

+        db.Folders,

+        db.NumUnpackStreamsVector,

+        unpackSizes,

+        digestsDefined,

+        digests);

+    db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader;

+    type = ReadID();

+  }

+  else

+  {

+    for (int i = 0; i < db.Folders.Size(); i++)

+    {

+      db.NumUnpackStreamsVector.Add(1);

+      CFolder &folder = db.Folders[i];

+      unpackSizes.Add(folder.GetUnpackSize());

+      digestsDefined.Add(folder.UnpackCRCDefined);

+      digests.Add(folder.UnpackCRC);

+    }

+  }

+

+  db.Files.Clear();

+

+  if (type == NID::kEnd)

+    return S_OK;

+  if (type != NID::kFilesInfo)

+    ThrowIncorrect();

+  

+  CNum numFiles = ReadNum();

+  db.Files.Reserve(numFiles);

+  CNum i;

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

+    db.Files.Add(CFileItem());

+

+  db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize);

+  if (!db.PackSizes.IsEmpty())

+    db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo);

+  if (numFiles > 0  && !digests.IsEmpty())

+    db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC);

+

+  CBoolVector emptyStreamVector;

+  BoolVector_Fill_False(emptyStreamVector, (int)numFiles);

+  CBoolVector emptyFileVector;

+  CBoolVector antiFileVector;

+  CNum numEmptyStreams = 0;

+

+  for (;;)

+  {

+    UInt64 type = ReadID();

+    if (type == NID::kEnd)

+      break;

+    UInt64 size = ReadNumber();

+    size_t ppp = _inByteBack->_pos;

+    bool addPropIdToList = true;

+    bool isKnownType = true;

+    if (type > ((UInt32)1 << 30))

+      isKnownType = false;

+    else switch((UInt32)type)

+    {

+      case NID::kName:

+      {

+        CStreamSwitch streamSwitch;

+        streamSwitch.Set(this, &dataVector);

+        for (int i = 0; i < db.Files.Size(); i++)

+          _inByteBack->ReadString(db.Files[i].Name);

+        break;

+      }

+      case NID::kWinAttributes:

+      {

+        CBoolVector boolVector;

+        ReadBoolVector2(db.Files.Size(), boolVector);

+        CStreamSwitch streamSwitch;

+        streamSwitch.Set(this, &dataVector);

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

+        {

+          CFileItem &file = db.Files[i];

+          file.AttribDefined = boolVector[i];

+          if (file.AttribDefined)

+            file.Attrib = ReadUInt32();

+        }

+        break;

+      }

+      case NID::kEmptyStream:

+      {

+        ReadBoolVector(numFiles, emptyStreamVector);

+        for (i = 0; i < (CNum)emptyStreamVector.Size(); i++)

+          if (emptyStreamVector[i])

+            numEmptyStreams++;

+

+        BoolVector_Fill_False(emptyFileVector, numEmptyStreams);

+        BoolVector_Fill_False(antiFileVector, numEmptyStreams);

+

+        break;

+      }

+      case NID::kEmptyFile:  ReadBoolVector(numEmptyStreams, emptyFileVector); break;

+      case NID::kAnti:  ReadBoolVector(numEmptyStreams, antiFileVector); break;

+      case NID::kStartPos:  ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break;

+      case NID::kCTime:  ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break;

+      case NID::kATime:  ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break;

+      case NID::kMTime:  ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break;

+      case NID::kDummy:

+      {

+        for (UInt64 j = 0; j < size; j++)

+          if (ReadByte() != 0)

+            ThrowIncorrect();

+        addPropIdToList = false;

+        break;

+      }

+      default:

+        addPropIdToList = isKnownType = false;

+    }

+    if (isKnownType)

+    {

+      if(addPropIdToList)

+        db.ArchiveInfo.FileInfoPopIDs.Add(type);

+    }

+    else

+      SkipData(size);

+    bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 ||

+        db.ArchiveInfo.Version.Minor > 2);

+    if (checkRecordsSize && _inByteBack->_pos - ppp != size)

+      ThrowIncorrect();

+  }

+

+  CNum emptyFileIndex = 0;

+  CNum sizeIndex = 0;

+

+  CNum numAntiItems = 0;

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

+    if (antiFileVector[i])

+      numAntiItems++;

+    

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

+  {

+    CFileItem &file = db.Files[i];

+    bool isAnti;

+    file.HasStream = !emptyStreamVector[i];

+    if (file.HasStream)

+    {

+      file.IsDir = false;

+      isAnti = false;

+      file.Size = unpackSizes[sizeIndex];

+      file.Crc = digests[sizeIndex];

+      file.CrcDefined = digestsDefined[sizeIndex];

+      sizeIndex++;

+    }

+    else

+    {

+      file.IsDir = !emptyFileVector[emptyFileIndex];

+      isAnti = antiFileVector[emptyFileIndex];

+      emptyFileIndex++;

+      file.Size = 0;

+      file.CrcDefined = false;

+    }

+    if (numAntiItems != 0)

+      db.IsAnti.Add(isAnti);

+  }

+  return S_OK;

+}

+

+

+void CArchiveDatabaseEx::FillFolderStartPackStream()

+{

+  FolderStartPackStreamIndex.Clear();

+  FolderStartPackStreamIndex.Reserve(Folders.Size());

+  CNum startPos = 0;

+  for (int i = 0; i < Folders.Size(); i++)

+  {

+    FolderStartPackStreamIndex.Add(startPos);

+    startPos += (CNum)Folders[i].PackStreams.Size();

+  }

+}

+

+void CArchiveDatabaseEx::FillStartPos()

+{

+  PackStreamStartPositions.Clear();

+  PackStreamStartPositions.Reserve(PackSizes.Size());

+  UInt64 startPos = 0;

+  for (int i = 0; i < PackSizes.Size(); i++)

+  {

+    PackStreamStartPositions.Add(startPos);

+    startPos += PackSizes[i];

+  }

+}

+

+void CArchiveDatabaseEx::FillFolderStartFileIndex()

+{

+  FolderStartFileIndex.Clear();

+  FolderStartFileIndex.Reserve(Folders.Size());

+  FileIndexToFolderIndexMap.Clear();

+  FileIndexToFolderIndexMap.Reserve(Files.Size());

+  

+  int folderIndex = 0;

+  CNum indexInFolder = 0;

+  for (int i = 0; i < Files.Size(); i++)

+  {

+    const CFileItem &file = Files[i];

+    bool emptyStream = !file.HasStream;

+    if (emptyStream && indexInFolder == 0)

+    {

+      FileIndexToFolderIndexMap.Add(kNumNoIndex);

+      continue;

+    }

+    if (indexInFolder == 0)

+    {

+      // v3.13 incorrectly worked with empty folders

+      // v4.07: Loop for skipping empty folders

+      for (;;)

+      {

+        if (folderIndex >= Folders.Size())

+          ThrowIncorrect();

+        FolderStartFileIndex.Add(i); // check it

+        if (NumUnpackStreamsVector[folderIndex] != 0)

+          break;

+        folderIndex++;

+      }

+    }

+    FileIndexToFolderIndexMap.Add(folderIndex);

+    if (emptyStream)

+      continue;

+    indexInFolder++;

+    if (indexInFolder >= NumUnpackStreamsVector[folderIndex])

+    {

+      folderIndex++;

+      indexInFolder = 0;

+    }

+  }

+}

+

+HRESULT CInArchive::ReadDatabase2(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CArchiveDatabaseEx &db

+    #ifndef _NO_CRYPTO

+    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

+    #endif

+    )

+{

+  db.Clear();

+  db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;

+

+  db.ArchiveInfo.Version.Major = _header[6];

+  db.ArchiveInfo.Version.Minor = _header[7];

+

+  if (db.ArchiveInfo.Version.Major != kMajorVersion)

+    ThrowUnsupportedVersion();

+

+  UInt32 crcFromArchive = Get32(_header + 8);

+  UInt64 nextHeaderOffset = Get64(_header + 0xC);

+  UInt64 nextHeaderSize = Get64(_header + 0x14);

+  UInt32 nextHeaderCRC = Get32(_header + 0x1C);

+  UInt32 crc = CrcCalc(_header + 0xC, 20);

+

+  #ifdef FORMAT_7Z_RECOVERY

+  if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)

+  {

+    UInt64 cur, cur2;

+    RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur));

+    const int kCheckSize = 500;

+    Byte buf[kCheckSize];

+    RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2));

+    int checkSize = kCheckSize;

+    if (cur2 - cur < kCheckSize)

+      checkSize = (int)(cur2 - cur);

+    RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2));

+    

+    RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize));

+

+    int i;

+    for (i = (int)checkSize - 2; i >= 0; i--)

+      if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04)

+        break;

+    if (i < 0)

+      return S_FALSE;

+    nextHeaderSize = checkSize - i;

+    nextHeaderOffset = cur2 - cur + i;

+    nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);

+    RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL));

+  }

+  else

+  #endif

+  {

+    if (crc != crcFromArchive)

+      ThrowIncorrect();

+  }

+

+  db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;

+

+  if (nextHeaderSize == 0)

+    return S_OK;

+

+  if (nextHeaderSize > (UInt64)0xFFFFFFFF)

+    return S_FALSE;

+

+  if ((Int64)nextHeaderOffset < 0)

+    return S_FALSE;

+

+  RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));

+

+  CByteBuffer buffer2;

+  buffer2.SetCapacity((size_t)nextHeaderSize);

+

+  RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize));

+  HeadersSize += kHeaderSize + nextHeaderSize;

+  db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize;

+

+  if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC)

+    ThrowIncorrect();

+  

+  CStreamSwitch streamSwitch;

+  streamSwitch.Set(this, buffer2);

+  

+  CObjectVector<CByteBuffer> dataVector;

+  

+  UInt64 type = ReadID();

+  if (type != NID::kHeader)

+  {

+    if (type != NID::kEncodedHeader)

+      ThrowIncorrect();

+    HRESULT result = ReadAndDecodePackedStreams(

+        EXTERNAL_CODECS_LOC_VARS

+        db.ArchiveInfo.StartPositionAfterHeader,

+        db.ArchiveInfo.DataStartPosition2,

+        dataVector

+        #ifndef _NO_CRYPTO

+        , getTextPassword, passwordIsDefined

+        #endif

+        );

+    RINOK(result);

+    if (dataVector.Size() == 0)

+      return S_OK;

+    if (dataVector.Size() > 1)

+      ThrowIncorrect();

+    streamSwitch.Remove();

+    streamSwitch.Set(this, dataVector.Front());

+    if (ReadID() != NID::kHeader)

+      ThrowIncorrect();

+  }

+

+  db.HeadersSize = HeadersSize;

+

+  return ReadHeader(

+    EXTERNAL_CODECS_LOC_VARS

+    db

+    #ifndef _NO_CRYPTO

+    , getTextPassword, passwordIsDefined

+    #endif

+    );

+}

+

+HRESULT CInArchive::ReadDatabase(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CArchiveDatabaseEx &db

+    #ifndef _NO_CRYPTO

+    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

+    #endif

+    )

+{

+  try

+  {

+    return ReadDatabase2(

+      EXTERNAL_CODECS_LOC_VARS db

+      #ifndef _NO_CRYPTO

+      , getTextPassword, passwordIsDefined

+      #endif

+      );

+  }

+  catch(CInArchiveException &) { return S_FALSE; }

+}

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
new file mode 100755
index 0000000..b82a020
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zIn.h
@@ -0,0 +1,245 @@
+// 7zIn.h

+

+#ifndef __7Z_IN_H

+#define __7Z_IN_H

+

+#include "../../../Common/MyCom.h"

+

+#include "../../IPassword.h"

+#include "../../IStream.h"

+

+#include "../../Common/CreateCoder.h"

+#include "../../Common/InBuffer.h"

+

+#include "7zItem.h"

+ 

+namespace NArchive {

+namespace N7z {

+  

+struct CInArchiveInfo

+{

+  CArchiveVersion Version;

+  UInt64 StartPosition;

+  UInt64 StartPositionAfterHeader;

+  UInt64 DataStartPosition;

+  UInt64 DataStartPosition2;

+  CRecordVector<UInt64> FileInfoPopIDs;

+  void Clear()

+  {

+    FileInfoPopIDs.Clear();

+  }

+};

+

+struct CArchiveDatabaseEx: public CArchiveDatabase

+{

+  CInArchiveInfo ArchiveInfo;

+  CRecordVector<UInt64> PackStreamStartPositions;

+  CRecordVector<CNum> FolderStartPackStreamIndex;

+  CRecordVector<CNum> FolderStartFileIndex;

+  CRecordVector<CNum> FileIndexToFolderIndexMap;

+

+  UInt64 HeadersSize;

+  UInt64 PhySize;

+

+  void Clear()

+  {

+    CArchiveDatabase::Clear();

+    ArchiveInfo.Clear();

+    PackStreamStartPositions.Clear();

+    FolderStartPackStreamIndex.Clear();

+    FolderStartFileIndex.Clear();

+    FileIndexToFolderIndexMap.Clear();

+

+    HeadersSize = 0;

+    PhySize = 0;

+  }

+

+  void FillFolderStartPackStream();

+  void FillStartPos();

+  void FillFolderStartFileIndex();

+

+  void Fill()

+  {

+    FillFolderStartPackStream();

+    FillStartPos();

+    FillFolderStartFileIndex();

+  }

+  

+  UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const

+  {

+    return ArchiveInfo.DataStartPosition +

+        PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder];

+  }

+  

+  UInt64 GetFolderFullPackSize(int folderIndex) const

+  {

+    CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex];

+    const CFolder &folder = Folders[folderIndex];

+    UInt64 size = 0;

+    for (int i = 0; i < folder.PackStreams.Size(); i++)

+      size += PackSizes[packStreamIndex + i];

+    return size;

+  }

+  

+  UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const

+  {

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

+  }

+

+  UInt64 GetFilePackSize(CNum fileIndex) const

+  {

+    CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];

+    if (folderIndex != kNumNoIndex)

+      if (FolderStartFileIndex[folderIndex] == fileIndex)

+        return GetFolderFullPackSize(folderIndex);

+    return 0;

+  }

+};

+

+class CInByte2

+{

+  const Byte *_buffer;

+  size_t _size;

+public:

+  size_t _pos;

+  void Init(const Byte *buffer, size_t size)

+  {

+    _buffer = buffer;

+    _size = size;

+    _pos = 0;

+  }

+  Byte ReadByte();

+  void ReadBytes(Byte *data, size_t size);

+  void SkipData(UInt64 size);

+  void SkipData();

+  UInt64 ReadNumber();

+  CNum ReadNum();

+  UInt32 ReadUInt32();

+  UInt64 ReadUInt64();

+  void ReadString(UString &s);

+};

+

+class CStreamSwitch;

+

+const UInt32 kHeaderSize = 32;

+

+class CInArchive

+{

+  friend class CStreamSwitch;

+

+  CMyComPtr<IInStream> _stream;

+

+  CObjectVector<CInByte2> _inByteVector;

+  CInByte2 *_inByteBack;

+ 

+  UInt64 _arhiveBeginStreamPosition;

+

+  Byte _header[kHeaderSize];

+

+  UInt64 HeadersSize;

+

+  void AddByteStream(const Byte *buffer, size_t size)

+  {

+    _inByteVector.Add(CInByte2());

+    _inByteBack = &_inByteVector.Back();

+    _inByteBack->Init(buffer, size);

+  }

+  

+  void DeleteByteStream()

+  {

+    _inByteVector.DeleteBack();

+    if (!_inByteVector.IsEmpty())

+      _inByteBack = &_inByteVector.Back();

+  }

+

+private:

+  HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);

+  

+  void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }

+  Byte ReadByte() { return _inByteBack->ReadByte(); }

+  UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }

+  CNum ReadNum() { return _inByteBack->ReadNum(); }

+  UInt64 ReadID() { return _inByteBack->ReadNumber(); }

+  UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }

+  UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }

+  void SkipData(UInt64 size) { _inByteBack->SkipData(size); }

+  void SkipData() { _inByteBack->SkipData(); }

+  void WaitAttribute(UInt64 attribute);

+

+  void ReadArchiveProperties(CInArchiveInfo &archiveInfo);

+  void GetNextFolderItem(CFolder &itemInfo);

+  void ReadHashDigests(int numItems,

+      CBoolVector &digestsDefined, CRecordVector<UInt32> &digests);

+  

+  void ReadPackInfo(

+      UInt64 &dataOffset,

+      CRecordVector<UInt64> &packSizes,

+      CBoolVector &packCRCsDefined,

+      CRecordVector<UInt32> &packCRCs);

+  

+  void ReadUnpackInfo(

+      const CObjectVector<CByteBuffer> *dataVector,

+      CObjectVector<CFolder> &folders);

+  

+  void ReadSubStreamsInfo(

+      const CObjectVector<CFolder> &folders,

+      CRecordVector<CNum> &numUnpackStreamsInFolders,

+      CRecordVector<UInt64> &unpackSizes,

+      CBoolVector &digestsDefined,

+      CRecordVector<UInt32> &digests);

+

+  void ReadStreamsInfo(

+      const CObjectVector<CByteBuffer> *dataVector,

+      UInt64 &dataOffset,

+      CRecordVector<UInt64> &packSizes,

+      CBoolVector &packCRCsDefined,

+      CRecordVector<UInt32> &packCRCs,

+      CObjectVector<CFolder> &folders,

+      CRecordVector<CNum> &numUnpackStreamsInFolders,

+      CRecordVector<UInt64> &unpackSizes,

+      CBoolVector &digestsDefined,

+      CRecordVector<UInt32> &digests);

+

+

+  void ReadBoolVector(int numItems, CBoolVector &v);

+  void ReadBoolVector2(int numItems, CBoolVector &v);

+  void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,

+      CUInt64DefVector &v, int numFiles);

+  HRESULT ReadAndDecodePackedStreams(

+      DECL_EXTERNAL_CODECS_LOC_VARS

+      UInt64 baseOffset, UInt64 &dataOffset,

+      CObjectVector<CByteBuffer> &dataVector

+      #ifndef _NO_CRYPTO

+      , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

+      #endif

+      );

+  HRESULT ReadHeader(

+      DECL_EXTERNAL_CODECS_LOC_VARS

+      CArchiveDatabaseEx &db

+      #ifndef _NO_CRYPTO

+      ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

+      #endif

+      );

+  HRESULT ReadDatabase2(

+      DECL_EXTERNAL_CODECS_LOC_VARS

+      CArchiveDatabaseEx &db

+      #ifndef _NO_CRYPTO

+      ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

+      #endif

+      );

+public:

+  HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive

+  void Close();

+

+  HRESULT ReadDatabase(

+      DECL_EXTERNAL_CODECS_LOC_VARS

+      CArchiveDatabaseEx &db

+      #ifndef _NO_CRYPTO

+      ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined

+      #endif

+      );

+};

+  

+}}

+  

+#endif

diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h
new file mode 100755
index 0000000..3b01a8d
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zItem.h
@@ -0,0 +1,268 @@
+// 7zItem.h

+

+#ifndef __7Z_ITEM_H

+#define __7Z_ITEM_H

+

+#include "../../../Common/Buffer.h"

+#include "../../../Common/MyString.h"

+

+#include "../../Common/MethodId.h"

+

+#include "7zHeader.h"

+

+namespace NArchive {

+namespace N7z {

+

+const UInt64 k_AES = 0x06F10701;

+

+typedef UInt32 CNum;

+const CNum kNumMax     = 0x7FFFFFFF;

+const CNum kNumNoIndex = 0xFFFFFFFF;

+

+struct CCoderInfo

+{

+  CMethodId MethodID;

+  CByteBuffer Props;

+  CNum NumInStreams;

+  CNum NumOutStreams;

+  bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }

+};

+

+struct CBindPair

+{

+  CNum InIndex;

+  CNum OutIndex;

+};

+

+struct CFolder

+{

+  CObjectVector<CCoderInfo> Coders;

+  CRecordVector<CBindPair> BindPairs;

+  CRecordVector<CNum> PackStreams;

+  CRecordVector<UInt64> UnpackSizes;

+  UInt32 UnpackCRC;

+  bool UnpackCRCDefined;

+

+  CFolder(): UnpackCRCDefined(false) {}

+

+  UInt64 GetUnpackSize() const // test it

+  {

+    if (UnpackSizes.IsEmpty())

+      return 0;

+    for (int i = UnpackSizes.Size() - 1; i >= 0; i--)

+      if (FindBindPairForOutStream(i) < 0)

+        return UnpackSizes[i];

+    throw 1;

+  }

+

+  CNum GetNumOutStreams() const

+  {

+    CNum result = 0;

+    for (int i = 0; i < Coders.Size(); i++)

+      result += Coders[i].NumOutStreams;

+    return result;

+  }

+

+  int FindBindPairForInStream(CNum inStreamIndex) const

+  {

+    for(int i = 0; i < BindPairs.Size(); i++)

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

+        return i;

+    return -1;

+  }

+  int FindBindPairForOutStream(CNum outStreamIndex) const

+  {

+    for(int i = 0; i < BindPairs.Size(); i++)

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

+        return i;

+    return -1;

+  }

+  int FindPackStreamArrayIndex(CNum inStreamIndex) const

+  {

+    for(int i = 0; i < PackStreams.Size(); i++)

+      if (PackStreams[i] == inStreamIndex)

+        return i;

+    return -1;

+  }

+

+  bool IsEncrypted() const

+  {

+    for (int i = Coders.Size() - 1; i >= 0; i--)

+      if (Coders[i].MethodID == k_AES)

+        return true;

+    return false;

+  }

+

+  bool CheckStructure() const;

+};

+

+struct CUInt64DefVector

+{

+  CRecordVector<UInt64> Values;

+  CRecordVector<bool> Defined;

+  

+  void Clear()

+  {

+    Values.Clear();

+    Defined.Clear();

+  }

+  

+  void ReserveDown()

+  {

+    Values.ReserveDown();

+    Values.ReserveDown();

+  }

+

+  bool GetItem(int index, UInt64 &value) const

+  {

+    if (index < Defined.Size() && Defined[index])

+    {

+      value = Values[index];

+      return true;

+    }

+    value = 0;

+    return false;

+  }

+  

+  void SetItem(int index, bool defined, UInt64 value)

+  {

+    while (index >= Defined.Size())

+      Defined.Add(false);

+    Defined[index] = defined;

+    if (!defined)

+      return;

+    while (index >= Values.Size())

+      Values.Add(0);

+    Values[index] = value;

+  }

+

+  bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; }

+};

+

+struct CFileItem

+{

+  UInt64 Size;

+  UInt32 Attrib;

+  UInt32 Crc;

+  UString Name;

+

+  bool HasStream; // Test it !!! it means that there is

+                  // stream in some folder. It can be empty stream

+  bool IsDir;

+  bool CrcDefined;

+  bool AttribDefined;

+

+  CFileItem():

+    HasStream(true),

+    IsDir(false),

+    CrcDefined(false),

+    AttribDefined(false)

+      {}

+  void SetAttrib(UInt32 attrib)

+  {

+    AttribDefined = true;

+    Attrib = attrib;

+  }

+};

+

+struct CFileItem2

+{

+  UInt64 CTime;

+  UInt64 ATime;

+  UInt64 MTime;

+  UInt64 StartPos;

+  bool CTimeDefined;

+  bool ATimeDefined;

+  bool MTimeDefined;

+  bool StartPosDefined;

+  bool IsAnti;

+};

+

+struct CArchiveDatabase

+{

+  CRecordVector<UInt64> PackSizes;

+  CRecordVector<bool> PackCRCsDefined;

+  CRecordVector<UInt32> PackCRCs;

+  CObjectVector<CFolder> Folders;

+  CRecordVector<CNum> NumUnpackStreamsVector;

+  CObjectVector<CFileItem> Files;

+

+  CUInt64DefVector CTime;

+  CUInt64DefVector ATime;

+  CUInt64DefVector MTime;

+  CUInt64DefVector StartPos;

+  CRecordVector<bool> IsAnti;

+

+  void Clear()

+  {

+    PackSizes.Clear();

+    PackCRCsDefined.Clear();

+    PackCRCs.Clear();

+    Folders.Clear();

+    NumUnpackStreamsVector.Clear();

+    Files.Clear();

+    CTime.Clear();

+    ATime.Clear();

+    MTime.Clear();

+    StartPos.Clear();

+    IsAnti.Clear();

+  }

+

+  void ReserveDown()

+  {

+    PackSizes.ReserveDown();

+    PackCRCsDefined.ReserveDown();

+    PackCRCs.ReserveDown();

+    Folders.ReserveDown();

+    NumUnpackStreamsVector.ReserveDown();

+    Files.ReserveDown();

+    CTime.ReserveDown();

+    ATime.ReserveDown();

+    MTime.ReserveDown();

+    StartPos.ReserveDown();

+    IsAnti.ReserveDown();

+  }

+

+  bool IsEmpty() const

+  {

+    return (PackSizes.IsEmpty() &&

+      PackCRCsDefined.IsEmpty() &&

+      PackCRCs.IsEmpty() &&

+      Folders.IsEmpty() &&

+      NumUnpackStreamsVector.IsEmpty() &&

+      Files.IsEmpty());

+  }

+

+  bool CheckNumFiles() const

+  {

+    int size = Files.Size();

+    return (

+      CTime.CheckSize(size) &&

+      ATime.CheckSize(size) &&

+      MTime.CheckSize(size) &&

+      StartPos.CheckSize(size) &&

+      (size == IsAnti.Size() || IsAnti.Size() == 0));

+  }

+

+  bool IsSolid() const

+  {

+    for (int i = 0; i < NumUnpackStreamsVector.Size(); i++)

+      if (NumUnpackStreamsVector[i] > 1)

+        return true;

+    return false;

+  }

+  bool IsItemAnti(int index) const { return (index < IsAnti.Size() && IsAnti[index]); }

+  void SetItemAnti(int index, bool isAnti)

+  {

+    while (index >= IsAnti.Size())

+      IsAnti.Add(false);

+    IsAnti[index] = isAnti;

+  }

+

+  void GetFile(int index, CFileItem &file, CFileItem2 &file2) const;

+  void AddFile(const CFileItem &file, const CFileItem2 &file2);

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
new file mode 100755
index 0000000..b34a2c9
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zOut.cpp
@@ -0,0 +1,866 @@
+// 7zOut.cpp

+

+#include "StdAfx.h"

+

+#include "../../../../C/7zCrc.h"

+

+#include "../../../Common/AutoPtr.h"

+

+#include "../../Common/StreamObjects.h"

+

+#include "7zOut.h"

+

+static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)

+{

+  while (size > 0)

+  {

+    UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF);

+    UInt32 processedSize;

+    RINOK(stream->Write(data, curSize, &processedSize));

+    if (processedSize == 0)

+      return E_FAIL;

+    data = (const void *)((const Byte *)data + processedSize);

+    size -= processedSize;

+  }

+  return S_OK;

+}

+

+namespace NArchive {

+namespace N7z {

+

+HRESULT COutArchive::WriteDirect(const void *data, UInt32 size)

+{

+  return ::WriteBytes(SeqStream, data, size);

+}

+

+HRESULT COutArchive::WriteSignature()

+{

+  Byte buf[8];

+  memcpy(buf, kSignature, kSignatureSize);

+  buf[kSignatureSize] = kMajorVersion;

+  buf[kSignatureSize + 1] = 3;

+  return WriteDirect(buf, 8);

+}

+

+#ifdef _7Z_VOL

+HRESULT COutArchive::WriteFinishSignature()

+{

+  RINOK(WriteDirect(kFinishSignature, kSignatureSize));

+  CArchiveVersion av;

+  av.Major = kMajorVersion;

+  av.Minor = 2;

+  RINOK(WriteDirectByte(av.Major));

+  return WriteDirectByte(av.Minor);

+}

+#endif

+

+static void SetUInt32(Byte *p, UInt32 d)

+{

+  for (int i = 0; i < 4; i++, d >>= 8)

+    p[i] = (Byte)d;

+}

+

+static void SetUInt64(Byte *p, UInt64 d)

+{

+  for (int i = 0; i < 8; i++, d >>= 8)

+    p[i] = (Byte)d;

+}

+

+HRESULT COutArchive::WriteStartHeader(const CStartHeader &h)

+{

+  Byte buf[24];

+  SetUInt64(buf + 4, h.NextHeaderOffset);

+  SetUInt64(buf + 12, h.NextHeaderSize);

+  SetUInt32(buf + 20, h.NextHeaderCRC);

+  SetUInt32(buf, CrcCalc(buf + 4, 20));

+  return WriteDirect(buf, 24);

+}

+

+#ifdef _7Z_VOL

+HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)

+{

+  CCRC crc;

+  crc.UpdateUInt64(h.NextHeaderOffset);

+  crc.UpdateUInt64(h.NextHeaderSize);

+  crc.UpdateUInt32(h.NextHeaderCRC);

+  crc.UpdateUInt64(h.ArchiveStartOffset);

+  crc.UpdateUInt64(h.AdditionalStartBlockSize);

+  RINOK(WriteDirectUInt32(crc.GetDigest()));

+  RINOK(WriteDirectUInt64(h.NextHeaderOffset));

+  RINOK(WriteDirectUInt64(h.NextHeaderSize));

+  RINOK(WriteDirectUInt32(h.NextHeaderCRC));

+  RINOK(WriteDirectUInt64(h.ArchiveStartOffset));

+  return WriteDirectUInt64(h.AdditionalStartBlockSize);

+}

+#endif

+

+HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker)

+{

+  Close();

+  #ifdef _7Z_VOL

+  // endMarker = false;

+  _endMarker = endMarker;

+  #endif

+  SeqStream = stream;

+  if (!endMarker)

+  {

+    SeqStream.QueryInterface(IID_IOutStream, &Stream);

+    if (!Stream)

+    {

+      return E_NOTIMPL;

+      // endMarker = true;

+    }

+  }

+  #ifdef _7Z_VOL

+  if (endMarker)

+  {

+    /*

+    CStartHeader sh;

+    sh.NextHeaderOffset = (UInt32)(Int32)-1;

+    sh.NextHeaderSize = (UInt32)(Int32)-1;

+    sh.NextHeaderCRC = 0;

+    WriteStartHeader(sh);

+    */

+  }

+  else

+  #endif

+  {

+    if (!Stream)

+      return E_FAIL;

+    RINOK(WriteSignature());

+    RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos));

+  }

+  return S_OK;

+}

+

+void COutArchive::Close()

+{

+  SeqStream.Release();

+  Stream.Release();

+}

+

+HRESULT COutArchive::SkipPrefixArchiveHeader()

+{

+  #ifdef _7Z_VOL

+  if (_endMarker)

+    return S_OK;

+  #endif

+  return Stream->Seek(24, STREAM_SEEK_CUR, NULL);

+}

+

+UInt64 COutArchive::GetPos() const

+{

+  if (_countMode)

+    return _countSize;

+  if (_writeToStream)

+    return _outByte.GetProcessedSize();

+  return _outByte2.GetPos();

+}

+

+void COutArchive::WriteBytes(const void *data, size_t size)

+{

+  if (_countMode)

+    _countSize += size;

+  else if (_writeToStream)

+  {

+    _outByte.WriteBytes(data, size);

+    _crc = CrcUpdate(_crc, data, size);

+  }

+  else

+    _outByte2.WriteBytes(data, size);

+}

+

+void COutArchive::WriteByte(Byte b)

+{

+  if (_countMode)

+    _countSize++;

+  else if (_writeToStream)

+  {

+    _outByte.WriteByte(b);

+    _crc = CRC_UPDATE_BYTE(_crc, b);

+  }

+  else

+    _outByte2.WriteByte(b);

+}

+

+void COutArchive::WriteUInt32(UInt32 value)

+{

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

+  {

+    WriteByte((Byte)value);

+    value >>= 8;

+  }

+}

+

+void COutArchive::WriteUInt64(UInt64 value)

+{

+  for (int i = 0; i < 8; i++)

+  {

+    WriteByte((Byte)value);

+    value >>= 8;

+  }

+}

+

+void COutArchive::WriteNumber(UInt64 value)

+{

+  Byte firstByte = 0;

+  Byte mask = 0x80;

+  int i;

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

+  {

+    if (value < ((UInt64(1) << ( 7  * (i + 1)))))

+    {

+      firstByte |= Byte(value >> (8 * i));

+      break;

+    }

+    firstByte |= mask;

+    mask >>= 1;

+  }

+  WriteByte(firstByte);

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

+  {

+    WriteByte((Byte)value);

+    value >>= 8;

+  }

+}

+

+static UInt32 GetBigNumberSize(UInt64 value)

+{

+  int i;

+  for (i = 1; i < 9; i++)

+    if (value < (((UInt64)1 << (i * 7))))

+      break;

+  return i;

+}

+

+#ifdef _7Z_VOL

+UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)

+{

+  UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;

+  if (nameLength != 0)

+  {

+    nameLength = (nameLength + 1) * 2;

+    result += nameLength + GetBigNumberSize(nameLength) + 2;

+  }

+  if (props)

+  {

+    result += 20;

+  }

+  if (result >= 128)

+    result++;

+  result += kSignatureSize + 2 + kFinishHeaderSize;

+  return result;

+}

+

+UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)

+{

+  UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);

+  int testSize;

+  if (volSize > headersSizeBase)

+    testSize = volSize - headersSizeBase;

+  else

+    testSize = 1;

+  UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);

+  UInt64 pureSize = 1;

+  if (volSize > headersSize)

+    pureSize = volSize - headersSize;

+  return pureSize;

+}

+#endif

+

+void COutArchive::WriteFolder(const CFolder &folder)

+{

+  WriteNumber(folder.Coders.Size());

+  int i;

+  for (i = 0; i < folder.Coders.Size(); i++)

+  {

+    const CCoderInfo &coder = folder.Coders[i];

+    {

+      size_t propsSize = coder.Props.GetCapacity();

+      

+      UInt64 id = coder.MethodID;

+      int idSize;

+      for (idSize = 1; idSize < sizeof(id); idSize++)

+        if ((id >> (8 * idSize)) == 0)

+          break;

+      BYTE longID[15];

+      for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)

+        longID[t] = (Byte)(id & 0xFF);

+      Byte b;

+      b = (Byte)(idSize & 0xF);

+      bool isComplex = !coder.IsSimpleCoder();

+      b |= (isComplex ? 0x10 : 0);

+      b |= ((propsSize != 0) ? 0x20 : 0 );

+      WriteByte(b);

+      WriteBytes(longID, idSize);

+      if (isComplex)

+      {

+        WriteNumber(coder.NumInStreams);

+        WriteNumber(coder.NumOutStreams);

+      }

+      if (propsSize == 0)

+        continue;

+      WriteNumber(propsSize);

+      WriteBytes(coder.Props, propsSize);

+    }

+  }

+  for (i = 0; i < folder.BindPairs.Size(); i++)

+  {

+    const CBindPair &bindPair = folder.BindPairs[i];

+    WriteNumber(bindPair.InIndex);

+    WriteNumber(bindPair.OutIndex);

+  }

+  if (folder.PackStreams.Size() > 1)

+    for (i = 0; i < folder.PackStreams.Size(); i++)

+    {

+      WriteNumber(folder.PackStreams[i]);

+    }

+}

+

+void COutArchive::WriteBoolVector(const CBoolVector &boolVector)

+{

+  Byte b = 0;

+  Byte mask = 0x80;

+  for (int i = 0; i < boolVector.Size(); i++)

+  {

+    if (boolVector[i])

+      b |= mask;

+    mask >>= 1;

+    if (mask == 0)

+    {

+      WriteByte(b);

+      mask = 0x80;

+      b = 0;

+    }

+  }

+  if (mask != 0x80)

+    WriteByte(b);

+}

+

+

+void COutArchive::WriteHashDigests(

+    const CRecordVector<bool> &digestsDefined,

+    const CRecordVector<UInt32> &digests)

+{

+  int numDefined = 0;

+  int i;

+  for (i = 0; i < digestsDefined.Size(); i++)

+    if (digestsDefined[i])

+      numDefined++;

+  if (numDefined == 0)

+    return;

+

+  WriteByte(NID::kCRC);

+  if (numDefined == digestsDefined.Size())

+    WriteByte(1);

+  else

+  {

+    WriteByte(0);

+    WriteBoolVector(digestsDefined);

+  }

+  for (i = 0; i < digests.Size(); i++)

+    if (digestsDefined[i])

+      WriteUInt32(digests[i]);

+}

+

+void COutArchive::WritePackInfo(

+    UInt64 dataOffset,

+    const CRecordVector<UInt64> &packSizes,

+    const CRecordVector<bool> &packCRCsDefined,

+    const CRecordVector<UInt32> &packCRCs)

+{

+  if (packSizes.IsEmpty())

+    return;

+  WriteByte(NID::kPackInfo);

+  WriteNumber(dataOffset);

+  WriteNumber(packSizes.Size());

+  WriteByte(NID::kSize);

+  for (int i = 0; i < packSizes.Size(); i++)

+    WriteNumber(packSizes[i]);

+

+  WriteHashDigests(packCRCsDefined, packCRCs);

+  

+  WriteByte(NID::kEnd);

+}

+

+void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders)

+{

+  if (folders.IsEmpty())

+    return;

+

+  WriteByte(NID::kUnpackInfo);

+

+  WriteByte(NID::kFolder);

+  WriteNumber(folders.Size());

+  {

+    WriteByte(0);

+    for (int i = 0; i < folders.Size(); i++)

+      WriteFolder(folders[i]);

+  }

+  

+  WriteByte(NID::kCodersUnpackSize);

+  int i;

+  for (i = 0; i < folders.Size(); i++)

+  {

+    const CFolder &folder = folders[i];

+    for (int j = 0; j < folder.UnpackSizes.Size(); j++)

+      WriteNumber(folder.UnpackSizes[j]);

+  }

+

+  CRecordVector<bool> unpackCRCsDefined;

+  CRecordVector<UInt32> unpackCRCs;

+  for (i = 0; i < folders.Size(); i++)

+  {

+    const CFolder &folder = folders[i];

+    unpackCRCsDefined.Add(folder.UnpackCRCDefined);

+    unpackCRCs.Add(folder.UnpackCRC);

+  }

+  WriteHashDigests(unpackCRCsDefined, unpackCRCs);

+

+  WriteByte(NID::kEnd);

+}

+

+void COutArchive::WriteSubStreamsInfo(

+    const CObjectVector<CFolder> &folders,

+    const CRecordVector<CNum> &numUnpackStreamsInFolders,

+    const CRecordVector<UInt64> &unpackSizes,

+    const CRecordVector<bool> &digestsDefined,

+    const CRecordVector<UInt32> &digests)

+{

+  WriteByte(NID::kSubStreamsInfo);

+

+  int i;

+  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)

+  {

+    if (numUnpackStreamsInFolders[i] != 1)

+    {

+      WriteByte(NID::kNumUnpackStream);

+      for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)

+        WriteNumber(numUnpackStreamsInFolders[i]);

+      break;

+    }

+  }

+ 

+

+  bool needFlag = true;

+  CNum index = 0;

+  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)

+    for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++)

+    {

+      if (j + 1 != numUnpackStreamsInFolders[i])

+      {

+        if (needFlag)

+          WriteByte(NID::kSize);

+        needFlag = false;

+        WriteNumber(unpackSizes[index]);

+      }

+      index++;

+    }

+

+  CRecordVector<bool> digestsDefined2;

+  CRecordVector<UInt32> digests2;

+

+  int digestIndex = 0;

+  for (i = 0; i < folders.Size(); i++)

+  {

+    int numSubStreams = (int)numUnpackStreamsInFolders[i];

+    if (numSubStreams == 1 && folders[i].UnpackCRCDefined)

+      digestIndex++;

+    else

+      for (int j = 0; j < numSubStreams; j++, digestIndex++)

+      {

+        digestsDefined2.Add(digestsDefined[digestIndex]);

+        digests2.Add(digests[digestIndex]);

+      }

+  }

+  WriteHashDigests(digestsDefined2, digests2);

+  WriteByte(NID::kEnd);

+}

+

+void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */)

+{

+  return;

+}

+

+/*

+7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.

+

+void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)

+{

+  pos += (unsigned)GetPos();

+  pos &= (alignSize - 1);

+  if (pos == 0)

+    return;

+  unsigned skip = alignSize - pos;

+  if (skip < 2)

+    skip += alignSize;

+  skip -= 2;

+  WriteByte(NID::kDummy);

+  WriteByte((Byte)skip);

+  for (unsigned i = 0; i < skip; i++)

+    WriteByte(0);

+}

+*/

+

+static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }

+

+void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize)

+{

+  const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);

+  const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2;

+  SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize);

+

+  WriteByte(type);

+  WriteNumber(dataSize);

+  if (numDefined == v.Size())

+    WriteByte(1);

+  else

+  {

+    WriteByte(0);

+    WriteBoolVector(v);

+  }

+  WriteByte(0);

+}

+

+void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)

+{

+  int numDefined = 0;

+

+  int i;

+  for (i = 0; i < v.Defined.Size(); i++)

+    if (v.Defined[i])

+      numDefined++;

+

+  if (numDefined == 0)

+    return;

+

+  WriteAlignedBoolHeader(v.Defined, numDefined, type, 8);

+  

+  for (i = 0; i < v.Defined.Size(); i++)

+    if (v.Defined[i])

+      WriteUInt64(v.Values[i]);

+}

+

+HRESULT COutArchive::EncodeStream(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    CEncoder &encoder, const CByteBuffer &data,

+    CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)

+{

+  CBufInStream *streamSpec = new CBufInStream;

+  CMyComPtr<ISequentialInStream> stream = streamSpec;

+  streamSpec->Init(data, data.GetCapacity());

+  CFolder folderItem;

+  folderItem.UnpackCRCDefined = true;

+  folderItem.UnpackCRC = CrcCalc(data, data.GetCapacity());

+  UInt64 dataSize64 = data.GetCapacity();

+  RINOK(encoder.Encode(

+      EXTERNAL_CODECS_LOC_VARS

+      stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL))

+  folders.Add(folderItem);

+  return S_OK;

+}

+

+void COutArchive::WriteHeader(

+    const CArchiveDatabase &db,

+    const CHeaderOptions &headerOptions,

+    UInt64 &headerOffset)

+{

+  int i;

+  

+  UInt64 packedSize = 0;

+  for (i = 0; i < db.PackSizes.Size(); i++)

+    packedSize += db.PackSizes[i];

+

+  headerOffset = packedSize;

+

+  WriteByte(NID::kHeader);

+

+  // Archive Properties

+

+  if (db.Folders.Size() > 0)

+  {

+    WriteByte(NID::kMainStreamsInfo);

+    WritePackInfo(0, db.PackSizes,

+        db.PackCRCsDefined,

+        db.PackCRCs);

+

+    WriteUnpackInfo(db.Folders);

+

+    CRecordVector<UInt64> unpackSizes;

+    CRecordVector<bool> digestsDefined;

+    CRecordVector<UInt32> digests;

+    for (i = 0; i < db.Files.Size(); i++)

+    {

+      const CFileItem &file = db.Files[i];

+      if (!file.HasStream)

+        continue;

+      unpackSizes.Add(file.Size);

+      digestsDefined.Add(file.CrcDefined);

+      digests.Add(file.Crc);

+    }

+

+    WriteSubStreamsInfo(

+        db.Folders,

+        db.NumUnpackStreamsVector,

+        unpackSizes,

+        digestsDefined,

+        digests);

+    WriteByte(NID::kEnd);

+  }

+

+  if (db.Files.IsEmpty())

+  {

+    WriteByte(NID::kEnd);

+    return;

+  }

+

+  WriteByte(NID::kFilesInfo);

+  WriteNumber(db.Files.Size());

+

+  {

+  /* ---------- Empty Streams ---------- */

+  CBoolVector emptyStreamVector;

+  emptyStreamVector.Reserve(db.Files.Size());

+  int numEmptyStreams = 0;

+  for (i = 0; i < db.Files.Size(); i++)

+    if (db.Files[i].HasStream)

+      emptyStreamVector.Add(false);

+    else

+    {

+      emptyStreamVector.Add(true);

+      numEmptyStreams++;

+    }

+  if (numEmptyStreams > 0)

+  {

+    WriteByte(NID::kEmptyStream);

+    WriteNumber(Bv_GetSizeInBytes(emptyStreamVector));

+    WriteBoolVector(emptyStreamVector);

+

+    CBoolVector emptyFileVector, antiVector;

+    emptyFileVector.Reserve(numEmptyStreams);

+    antiVector.Reserve(numEmptyStreams);

+    CNum numEmptyFiles = 0, numAntiItems = 0;

+    for (i = 0; i < db.Files.Size(); i++)

+    {

+      const CFileItem &file = db.Files[i];

+      if (!file.HasStream)

+      {

+        emptyFileVector.Add(!file.IsDir);

+        if (!file.IsDir)

+          numEmptyFiles++;

+        bool isAnti = db.IsItemAnti(i);

+        antiVector.Add(isAnti);

+        if (isAnti)

+          numAntiItems++;

+      }

+    }

+

+    if (numEmptyFiles > 0)

+    {

+      WriteByte(NID::kEmptyFile);

+      WriteNumber(Bv_GetSizeInBytes(emptyFileVector));

+      WriteBoolVector(emptyFileVector);

+    }

+

+    if (numAntiItems > 0)

+    {

+      WriteByte(NID::kAnti);

+      WriteNumber(Bv_GetSizeInBytes(antiVector));

+      WriteBoolVector(antiVector);

+    }

+  }

+  }

+

+

+  {

+    /* ---------- Names ---------- */

+    

+    int numDefined = 0;

+    size_t namesDataSize = 0;

+    for (int i = 0; i < db.Files.Size(); i++)

+    {

+      const UString &name = db.Files[i].Name;

+      if (!name.IsEmpty())

+        numDefined++;

+      namesDataSize += (name.Length() + 1) * 2;

+    }

+    

+    if (numDefined > 0)

+    {

+      namesDataSize++;

+      SkipAlign(2 + GetBigNumberSize(namesDataSize), 2);

+

+      WriteByte(NID::kName);

+      WriteNumber(namesDataSize);

+      WriteByte(0);

+      for (int i = 0; i < db.Files.Size(); i++)

+      {

+        const UString &name = db.Files[i].Name;

+        for (int t = 0; t <= name.Length(); t++)

+        {

+          wchar_t c = name[t];

+          WriteByte((Byte)c);

+          WriteByte((Byte)(c >> 8));

+        }

+      }

+    }

+  }

+

+  if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime);

+  if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime);

+  if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime);

+  WriteUInt64DefVector(db.StartPos, NID::kStartPos);

+  

+  {

+    /* ---------- Write Attrib ---------- */

+    CBoolVector boolVector;

+    boolVector.Reserve(db.Files.Size());

+    int numDefined = 0;

+    for (i = 0; i < db.Files.Size(); i++)

+    {

+      bool defined = db.Files[i].AttribDefined;

+      boolVector.Add(defined);

+      if (defined)

+        numDefined++;

+    }

+    if (numDefined > 0)

+    {

+      WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4);

+      for (i = 0; i < db.Files.Size(); i++)

+      {

+        const CFileItem &file = db.Files[i];

+        if (file.AttribDefined)

+          WriteUInt32(file.Attrib);

+      }

+    }

+  }

+

+  WriteByte(NID::kEnd); // for files

+  WriteByte(NID::kEnd); // for headers

+}

+

+HRESULT COutArchive::WriteDatabase(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    const CArchiveDatabase &db,

+    const CCompressionMethodMode *options,

+    const CHeaderOptions &headerOptions)

+{

+  if (!db.CheckNumFiles())

+    return E_FAIL;

+

+  UInt64 headerOffset;

+  UInt32 headerCRC;

+  UInt64 headerSize;

+  if (db.IsEmpty())

+  {

+    headerSize = 0;

+    headerOffset = 0;

+    headerCRC = CrcCalc(0, 0);

+  }

+  else

+  {

+    bool encodeHeaders = false;

+    if (options != 0)

+      if (options->IsEmpty())

+        options = 0;

+    if (options != 0)

+      if (options->PasswordIsDefined || headerOptions.CompressMainHeader)

+        encodeHeaders = true;

+

+    _outByte.SetStream(SeqStream);

+    _outByte.Init();

+    _crc = CRC_INIT_VAL;

+    _countMode = encodeHeaders;

+    _writeToStream = true;

+    _countSize = 0;

+    WriteHeader(db, headerOptions, headerOffset);

+

+    if (encodeHeaders)

+    {

+      CByteBuffer buf;

+      buf.SetCapacity(_countSize);

+      _outByte2.Init((Byte *)buf, _countSize);

+      

+      _countMode = false;

+      _writeToStream = false;

+      WriteHeader(db, headerOptions, headerOffset);

+      

+      if (_countSize != _outByte2.GetPos())

+        return E_FAIL;

+

+      CCompressionMethodMode encryptOptions;

+      encryptOptions.PasswordIsDefined = options->PasswordIsDefined;

+      encryptOptions.Password = options->Password;

+      CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);

+      CRecordVector<UInt64> packSizes;

+      CObjectVector<CFolder> folders;

+      RINOK(EncodeStream(

+          EXTERNAL_CODECS_LOC_VARS

+          encoder, buf,

+          packSizes, folders));

+

+      _writeToStream = true;

+      

+      if (folders.Size() == 0)

+        throw 1;

+

+      WriteID(NID::kEncodedHeader);

+      WritePackInfo(headerOffset, packSizes,

+        CRecordVector<bool>(), CRecordVector<UInt32>());

+      WriteUnpackInfo(folders);

+      WriteByte(NID::kEnd);

+      for (int i = 0; i < packSizes.Size(); i++)

+        headerOffset += packSizes[i];

+    }

+    RINOK(_outByte.Flush());

+    headerCRC = CRC_GET_DIGEST(_crc);

+    headerSize = _outByte.GetProcessedSize();

+  }

+  #ifdef _7Z_VOL

+  if (_endMarker)

+  {

+    CFinishHeader h;

+    h.NextHeaderSize = headerSize;

+    h.NextHeaderCRC = headerCRC;

+    h.NextHeaderOffset =

+        UInt64(0) - (headerSize +

+        4 + kFinishHeaderSize);

+    h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;

+    h.AdditionalStartBlockSize = 0;

+    RINOK(WriteFinishHeader(h));

+    return WriteFinishSignature();

+  }

+  else

+  #endif

+  {

+    CStartHeader h;

+    h.NextHeaderSize = headerSize;

+    h.NextHeaderCRC = headerCRC;

+    h.NextHeaderOffset = headerOffset;

+    RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));

+    return WriteStartHeader(h);

+  }

+}

+

+void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const

+{

+  file = Files[index];

+  file2.CTimeDefined = CTime.GetItem(index, file2.CTime);

+  file2.ATimeDefined = ATime.GetItem(index, file2.ATime);

+  file2.MTimeDefined = MTime.GetItem(index, file2.MTime);

+  file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos);

+  file2.IsAnti = IsItemAnti(index);

+}

+

+void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2)

+{

+  int index = Files.Size();

+  CTime.SetItem(index, file2.CTimeDefined, file2.CTime);

+  ATime.SetItem(index, file2.ATimeDefined, file2.ATime);

+  MTime.SetItem(index, file2.MTimeDefined, file2.MTime);

+  StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);

+  SetItemAnti(index, file2.IsAnti);

+  Files.Add(file);

+}

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h
new file mode 100755
index 0000000..bdd465c
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zOut.h
@@ -0,0 +1,152 @@
+// 7zOut.h

+

+#ifndef __7Z_OUT_H

+#define __7Z_OUT_H

+

+#include "7zCompressionMode.h"

+#include "7zEncode.h"

+#include "7zHeader.h"

+#include "7zItem.h"

+

+#include "../../Common/OutBuffer.h"

+

+namespace NArchive {

+namespace N7z {

+

+class CWriteBufferLoc

+{

+  Byte *_data;

+  size_t _size;

+  size_t _pos;

+public:

+  CWriteBufferLoc(): _size(0), _pos(0) {}

+  void Init(Byte *data, size_t size)

+  {

+    _data = data;

+    _size = size;

+    _pos = 0;

+  }

+  void WriteBytes(const void *data, size_t size)

+  {

+    if (size > _size - _pos)

+      throw 1;

+    memcpy(_data + _pos, data, size);

+    _pos += size;

+  }

+  void WriteByte(Byte b)

+  {

+    if (_size == _pos)

+      throw 1;

+    _data[_pos++] = b;

+  }

+  size_t GetPos() const { return _pos; }

+};

+

+struct CHeaderOptions

+{

+  bool CompressMainHeader;

+  bool WriteCTime;

+  bool WriteATime;

+  bool WriteMTime;

+

+  CHeaderOptions():

+      CompressMainHeader(true),

+      WriteCTime(false),

+      WriteATime(false),

+      WriteMTime(true)

+      {}

+};

+

+class COutArchive

+{

+  UInt64 _prefixHeaderPos;

+

+  HRESULT WriteDirect(const void *data, UInt32 size);

+  

+  UInt64 GetPos() const;

+  void WriteBytes(const void *data, size_t size);

+  void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); }

+  void WriteByte(Byte b);

+  void WriteUInt32(UInt32 value);

+  void WriteUInt64(UInt64 value);

+  void WriteNumber(UInt64 value);

+  void WriteID(UInt64 value) { WriteNumber(value); }

+

+  void WriteFolder(const CFolder &folder);

+  HRESULT WriteFileHeader(const CFileItem &itemInfo);

+  void WriteBoolVector(const CBoolVector &boolVector);

+  void WriteHashDigests(

+      const CRecordVector<bool> &digestsDefined,

+      const CRecordVector<UInt32> &hashDigests);

+

+  void WritePackInfo(

+      UInt64 dataOffset,

+      const CRecordVector<UInt64> &packSizes,

+      const CRecordVector<bool> &packCRCsDefined,

+      const CRecordVector<UInt32> &packCRCs);

+

+  void WriteUnpackInfo(const CObjectVector<CFolder> &folders);

+

+  void WriteSubStreamsInfo(

+      const CObjectVector<CFolder> &folders,

+      const CRecordVector<CNum> &numUnpackStreamsInFolders,

+      const CRecordVector<UInt64> &unpackSizes,

+      const CRecordVector<bool> &digestsDefined,

+      const CRecordVector<UInt32> &hashDigests);

+

+  void SkipAlign(unsigned pos, unsigned alignSize);

+  void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize);

+  void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type);

+

+  HRESULT EncodeStream(

+      DECL_EXTERNAL_CODECS_LOC_VARS

+      CEncoder &encoder, const CByteBuffer &data,

+      CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);

+  void WriteHeader(

+      const CArchiveDatabase &db,

+      const CHeaderOptions &headerOptions,

+      UInt64 &headerOffset);

+  

+  bool _countMode;

+  bool _writeToStream;

+  size_t _countSize;

+  UInt32 _crc;

+  COutBuffer _outByte;

+  CWriteBufferLoc _outByte2;

+

+  #ifdef _7Z_VOL

+  bool _endMarker;

+  #endif

+

+  HRESULT WriteSignature();

+  #ifdef _7Z_VOL

+  HRESULT WriteFinishSignature();

+  #endif

+  HRESULT WriteStartHeader(const CStartHeader &h);

+  #ifdef _7Z_VOL

+  HRESULT WriteFinishHeader(const CFinishHeader &h);

+  #endif

+  CMyComPtr<IOutStream> Stream;

+public:

+

+  COutArchive() { _outByte.Create(1 << 16); }

+  CMyComPtr<ISequentialOutStream> SeqStream;

+  HRESULT Create(ISequentialOutStream *stream, bool endMarker);

+  void Close();

+  HRESULT SkipPrefixArchiveHeader();

+  HRESULT WriteDatabase(

+      DECL_EXTERNAL_CODECS_LOC_VARS

+      const CArchiveDatabase &db,

+      const CCompressionMethodMode *options,

+      const CHeaderOptions &headerOptions);

+

+  #ifdef _7Z_VOL

+  static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false);

+  static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false);

+  #endif

+

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/7z/7zProperties.cpp b/CPP/7zip/Archive/7z/7zProperties.cpp
new file mode 100755
index 0000000..432da23
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zProperties.cpp
@@ -0,0 +1,164 @@
+// 7zProperties.cpp

+

+#include "StdAfx.h"

+

+#include "7zProperties.h"

+#include "7zHeader.h"

+#include "7zHandler.h"

+

+// #define _MULTI_PACK

+

+namespace NArchive {

+namespace N7z {

+

+struct CPropMap

+{

+  UInt64 FilePropID;

+  STATPROPSTG StatPROPSTG;

+};

+

+CPropMap kPropMap[] =

+{

+  { NID::kName, { NULL, kpidPath, VT_BSTR } },

+  { NID::kSize, { NULL, kpidSize, VT_UI8 } },

+  { NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } },

+  

+  #ifdef _MULTI_PACK

+  { 100, { L"Pack0", kpidPackedSize0, VT_UI8 } },

+  { 101, { L"Pack1", kpidPackedSize1, VT_UI8 } },

+  { 102, { L"Pack2", kpidPackedSize2, VT_UI8 } },

+  { 103, { L"Pack3", kpidPackedSize3, VT_UI8 } },

+  { 104, { L"Pack4", kpidPackedSize4, VT_UI8 } },

+  #endif

+

+  { NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },

+  { NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },

+  { NID::kATime, { NULL, kpidATime, VT_FILETIME } },

+  { NID::kWinAttributes, { NULL, kpidAttrib, VT_UI4 } },

+  { NID::kStartPos, { NULL, kpidPosition, VT_UI4 } },

+

+  { NID::kCRC, { NULL, kpidCRC, VT_UI4 } },

+  

+  { NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } }

+

+  #ifndef _SFX

+  ,

+  { 97, { NULL,kpidEncrypted, VT_BOOL } },

+  { 98, { NULL,kpidMethod, VT_BSTR } },

+  { 99, { NULL,kpidBlock, VT_UI4 } }

+  #endif

+};

+

+static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]);

+

+static int FindPropInMap(UInt64 filePropID)

+{

+  for (int i = 0; i < kPropMapSize; i++)

+    if (kPropMap[i].FilePropID == filePropID)

+      return i;

+  return -1;

+}

+

+static void CopyOneItem(CRecordVector<UInt64> &src,

+    CRecordVector<UInt64> &dest, UInt32 item)

+{

+  for (int i = 0; i < src.Size(); i++)

+    if (src[i] == item)

+    {

+      dest.Add(item);

+      src.Delete(i);

+      return;

+    }

+}

+

+static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)

+{

+  for (int i = 0; i < src.Size(); i++)

+    if (src[i] == item)

+    {

+      src.Delete(i);

+      return;

+    }

+}

+

+static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item)

+{

+  for (int i = 0; i < dest.Size(); i++)

+    if (dest[i] == item)

+    {

+      dest.Delete(i);

+      break;

+    }

+  dest.Insert(0, item);

+}

+

+void CHandler::FillPopIDs()

+{

+  _fileInfoPopIDs.Clear();

+

+  #ifdef _7Z_VOL

+  if(_volumes.Size() < 1)

+    return;

+  const CVolume &volume = _volumes.Front();

+  const CArchiveDatabaseEx &_db = volume.Database;

+  #endif

+

+  CRecordVector<UInt64> fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs;

+

+  RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);

+  RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);

+

+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName);

+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti);

+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize);

+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo);

+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCTime);

+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kMTime);

+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kATime);

+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes);

+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC);

+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment);

+  _fileInfoPopIDs += fileInfoPopIDs;

+ 

+  #ifndef _SFX

+  _fileInfoPopIDs.Add(97);

+  _fileInfoPopIDs.Add(98);

+  _fileInfoPopIDs.Add(99);

+  #endif

+  #ifdef _MULTI_PACK

+  _fileInfoPopIDs.Add(100);

+  _fileInfoPopIDs.Add(101);

+  _fileInfoPopIDs.Add(102);

+  _fileInfoPopIDs.Add(103);

+  _fileInfoPopIDs.Add(104);

+  #endif

+

+  #ifndef _SFX

+  InsertToHead(_fileInfoPopIDs, NID::kMTime);

+  InsertToHead(_fileInfoPopIDs, NID::kPackInfo);

+  InsertToHead(_fileInfoPopIDs, NID::kSize);

+  InsertToHead(_fileInfoPopIDs, NID::kName);

+  #endif

+}

+

+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties)

+{

+  *numProperties = _fileInfoPopIDs.Size();

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)

+{

+  if ((int)index >= _fileInfoPopIDs.Size())

+    return E_INVALIDARG;

+  int indexInMap = FindPropInMap(_fileInfoPopIDs[index]);

+  if (indexInMap == -1)

+    return E_INVALIDARG;

+  const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG;

+  *propID = srcItem.propid;

+  *varType = srcItem.vt;

+  *name = 0;

+  return S_OK;

+}

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zProperties.h b/CPP/7zip/Archive/7z/7zProperties.h
new file mode 100755
index 0000000..7b78130
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zProperties.h
@@ -0,0 +1,22 @@
+// 7zProperties.h

+

+#ifndef __7Z_PROPERTIES_H

+#define __7Z_PROPERTIES_H

+

+#include "../../PropID.h"

+

+namespace NArchive {

+namespace N7z {

+

+enum

+{

+  kpidPackedSize0 = kpidUserDefined,

+  kpidPackedSize1,

+  kpidPackedSize2,

+  kpidPackedSize3,

+  kpidPackedSize4

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp
new file mode 100755
index 0000000..ac3d133
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zRegister.cpp
@@ -0,0 +1,18 @@
+// 7zRegister.cpp

+

+#include "StdAfx.h"

+

+#include "../../Common/RegisterArc.h"

+

+#include "7zHandler.h"

+static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; }

+#ifndef EXTRACT_ONLY

+static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; }

+#else

+#define CreateArcOut 0

+#endif

+

+static CArcInfo g_ArcInfo =

+  { L"7z", L"7z", 0, 7, {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut };

+

+REGISTER_ARC(7z)

diff --git a/CPP/7zip/Archive/7z/7zSpecStream.cpp b/CPP/7zip/Archive/7z/7zSpecStream.cpp
new file mode 100755
index 0000000..58f2ec4
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zSpecStream.cpp
@@ -0,0 +1,24 @@
+// 7zSpecStream.cpp

+

+#include "StdAfx.h"

+

+#include "7zSpecStream.h"

+

+STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  UInt32 realProcessedSize;

+  HRESULT result = _stream->Read(data, size, &realProcessedSize);

+  _size += realProcessedSize;

+  if (processedSize != 0)

+    *processedSize = realProcessedSize;

+  return result;

+}

+

+STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(

+    UInt64 subStream, UInt64 *value)

+{

+  if (_getSubStreamSize == NULL)

+    return E_NOTIMPL;

+  return  _getSubStreamSize->GetSubStreamSize(subStream, value);

+}

+

diff --git a/CPP/7zip/Archive/7z/7zSpecStream.h b/CPP/7zip/Archive/7z/7zSpecStream.h
new file mode 100755
index 0000000..0058ac2
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zSpecStream.h
@@ -0,0 +1,35 @@
+// 7zSpecStream.h

+

+#ifndef __7Z_SPEC_STREAM_H

+#define __7Z_SPEC_STREAM_H

+

+#include "../../IStream.h"

+#include "../../ICoder.h"

+#include "../../../Common/MyCom.h"

+

+class CSequentialInStreamSizeCount2:

+  public ISequentialInStream,

+  public ICompressGetSubStreamSize,

+  public CMyUnknownImp

+{

+  CMyComPtr<ISequentialInStream> _stream;

+  CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize;

+  UInt64 _size;

+public:

+  void Init(ISequentialInStream *stream)

+  {

+    _stream = stream;

+    _getSubStreamSize = 0;

+    _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);

+    _size = 0;

+  }

+  UInt64 GetSize() const { return _size; }

+

+  MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+

+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);

+};

+

+#endif

diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
new file mode 100755
index 0000000..4b4db06
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -0,0 +1,1177 @@
+// 7zUpdate.cpp

+

+#include "StdAfx.h"

+

+#include "../../../../C/CpuArch.h"

+

+#include "../../Common/LimitedStreams.h"

+#include "../../Common/ProgressUtils.h"

+

+#include "../../Common/CreateCoder.h"

+

+#include "../../Compress/CopyCoder.h"

+

+#include "../Common/ItemNameUtils.h"

+#include "../Common/OutStreamWithCRC.h"

+

+#include "7zDecode.h"

+#include "7zEncode.h"

+#include "7zFolderInStream.h"

+#include "7zHandler.h"

+#include "7zOut.h"

+#include "7zUpdate.h"

+

+namespace NArchive {

+namespace N7z {

+

+static const UInt64 k_LZMA = 0x030101;

+static const UInt64 k_BCJ  = 0x03030103;

+static const UInt64 k_BCJ2 = 0x0303011B;

+

+static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2";

+static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20;

+static const UInt32 kAlgorithmForBCJ2_LZMA = 1;

+static const UInt32 kNumFastBytesForBCJ2_LZMA = 64;

+

+#ifdef MY_CPU_X86_OR_AMD64

+#define USE_86_FILTER

+#endif

+

+static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,

+    UInt64 position, UInt64 size, ICompressProgressInfo *progress)

+{

+  RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0));

+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;

+  CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);

+  streamSpec->SetStream(inStream);

+  streamSpec->Init(size);

+

+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;

+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;

+  RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));

+  return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);

+}

+

+static int GetReverseSlashPos(const UString &name)

+{

+  int slashPos = name.ReverseFind(L'/');

+  #ifdef _WIN32

+  int slash1Pos = name.ReverseFind(L'\\');

+  slashPos = MyMax(slashPos, slash1Pos);

+  #endif

+  return slashPos;

+}

+

+int CUpdateItem::GetExtensionPos() const

+{

+  int slashPos = GetReverseSlashPos(Name);

+  int dotPos = Name.ReverseFind(L'.');

+  if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))

+    return Name.Length();

+  return dotPos + 1;

+}

+

+UString CUpdateItem::GetExtension() const

+{

+  return Name.Mid(GetExtensionPos());

+}

+

+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }

+

+#define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b))

+

+static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)

+{

+  size_t c1 = a1.GetCapacity();

+  size_t c2 = a2.GetCapacity();

+  RINOZ_COMP(c1, c2);

+  for (size_t i = 0; i < c1; i++)

+    RINOZ_COMP(a1[i], a2[i]);

+  return 0;

+}

+

+static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)

+{

+  RINOZ_COMP(c1.NumInStreams, c2.NumInStreams);

+  RINOZ_COMP(c1.NumOutStreams, c2.NumOutStreams);

+  RINOZ_COMP(c1.MethodID, c2.MethodID);

+  return CompareBuffers(c1.Props, c2.Props);

+}

+

+static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)

+{

+  RINOZ_COMP(b1.InIndex, b2.InIndex);

+  return MyCompare(b1.OutIndex, b2.OutIndex);

+}

+

+static int CompareFolders(const CFolder &f1, const CFolder &f2)

+{

+  int s1 = f1.Coders.Size();

+  int s2 = f2.Coders.Size();

+  RINOZ_COMP(s1, s2);

+  int i;

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

+    RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));

+  s1 = f1.BindPairs.Size();

+  s2 = f2.BindPairs.Size();

+  RINOZ_COMP(s1, s2);

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

+    RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));

+  return 0;

+}

+

+/*

+static int CompareFiles(const CFileItem &f1, const CFileItem &f2)

+{

+  return MyStringCompareNoCase(f1.Name, f2.Name);

+}

+*/

+

+struct CFolderRepack

+{

+  int FolderIndex;

+  int Group;

+  CNum NumCopyFiles;

+};

+

+static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *param)

+{

+  RINOZ_COMP(p1->Group, p2->Group);

+  int i1 = p1->FolderIndex;

+  int i2 = p2->FolderIndex;

+  const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param;

+  RINOZ(CompareFolders(

+      db.Folders[i1],

+      db.Folders[i2]));

+  return MyCompare(i1, i2);

+  /*

+  RINOZ_COMP(

+      db.NumUnpackStreamsVector[i1],

+      db.NumUnpackStreamsVector[i2]);

+  if (db.NumUnpackStreamsVector[i1] == 0)

+    return 0;

+  return CompareFiles(

+      db.Files[db.FolderStartFileIndex[i1]],

+      db.Files[db.FolderStartFileIndex[i2]]);

+  */

+}

+

+////////////////////////////////////////////////////////////

+

+static int CompareEmptyItems(const int *p1, const int *p2, void *param)

+{

+  const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;

+  const CUpdateItem &u1 = updateItems[*p1];

+  const CUpdateItem &u2 = updateItems[*p2];

+  if (u1.IsDir != u2.IsDir)

+    return (u1.IsDir) ? 1 : -1;

+  if (u1.IsDir)

+  {

+    if (u1.IsAnti != u2.IsAnti)

+      return (u1.IsAnti ? 1 : -1);

+    int n = MyStringCompareNoCase(u1.Name, u2.Name);

+    return -n;

+  }

+  if (u1.IsAnti != u2.IsAnti)

+    return (u1.IsAnti ? 1 : -1);

+  return MyStringCompareNoCase(u1.Name, u2.Name);

+}

+

+static const char *g_Exts =

+  " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo"

+  " zip jar ear war msi"

+  " 3gp avi mov mpeg mpg mpe wmv"

+  " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav"

+  " swf "

+  " chm hxi hxs"

+  " gif jpeg jpg jp2 png tiff  bmp ico psd psp"

+  " awg ps eps cgm dxf svg vrml wmf emf ai md"

+  " cad dwg pps key sxi"

+  " max 3ds"

+  " iso bin nrg mdf img pdi tar cpio xpi"

+  " vfd vhd vud vmc vsv"

+  " vmdk dsk nvram vmem vmsd vmsn vmss vmtm"

+  " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def"

+  " f77 f f90 f95"

+  " asm sql manifest dep "

+  " mak clw csproj vcproj sln dsp dsw "

+  " class "

+  " bat cmd"

+  " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"

+  " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs"

+  " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf"

+  " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf"

+  " abw afp cwk lwp wpd wps wpt wrf wri"

+  " abf afm bdf fon mgf otf pcf pfa snf ttf"

+  " dbf mdb nsf ntf wdb db fdb gdb"

+  " exe dll ocx vbx sfx sys tlb awx com obj lib out o so "

+  " pdb pch idb ncb opt";

+

+int GetExtIndex(const char *ext)

+{

+  int extIndex = 1;

+  const char *p = g_Exts;

+  for (;;)

+  {

+    char c = *p++;

+    if (c == 0)

+      return extIndex;

+    if (c == ' ')

+      continue;

+    int pos = 0;

+    for (;;)

+    {

+      char c2 = ext[pos++];

+      if (c2 == 0 && (c == 0 || c == ' '))

+        return extIndex;

+      if (c != c2)

+        break;

+      c = *p++;

+    }

+    extIndex++;

+    for (;;)

+    {

+      if (c == 0)

+        return extIndex;

+      if (c == ' ')

+        break;

+      c = *p++;

+    }

+  }

+}

+

+struct CRefItem

+{

+  const CUpdateItem *UpdateItem;

+  UInt32 Index;

+  UInt32 ExtensionPos;

+  UInt32 NamePos;

+  int ExtensionIndex;

+  CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType):

+    UpdateItem(&ui),

+    Index(index),

+    ExtensionPos(0),

+    NamePos(0),

+    ExtensionIndex(0)

+  {

+    if (sortByType)

+    {

+      int slashPos = GetReverseSlashPos(ui.Name);

+      NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0);

+      int dotPos = ui.Name.ReverseFind(L'.');

+      if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))

+        ExtensionPos = ui.Name.Length();

+      else

+      {

+        ExtensionPos = dotPos + 1;

+        UString us = ui.Name.Mid(ExtensionPos);

+        if (!us.IsEmpty())

+        {

+          us.MakeLower();

+          int i;

+          AString s;

+          for (i = 0; i < us.Length(); i++)

+          {

+            wchar_t c = us[i];

+            if (c >= 0x80)

+              break;

+            s += (char)c;

+          }

+          if (i == us.Length())

+            ExtensionIndex = GetExtIndex(s);

+          else

+            ExtensionIndex = 0;

+        }

+      }

+    }

+  }

+};

+

+static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param)

+{

+  const CRefItem &a1 = *p1;

+  const CRefItem &a2 = *p2;

+  const CUpdateItem &u1 = *a1.UpdateItem;

+  const CUpdateItem &u2 = *a2.UpdateItem;

+  int n;

+  if (u1.IsDir != u2.IsDir)

+    return (u1.IsDir) ? 1 : -1;

+  if (u1.IsDir)

+  {

+    if (u1.IsAnti != u2.IsAnti)

+      return (u1.IsAnti ? 1 : -1);

+    n = MyStringCompareNoCase(u1.Name, u2.Name);

+    return -n;

+  }

+  bool sortByType = *(bool *)param;

+  if (sortByType)

+  {

+    RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex);

+    RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos));

+    RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos));

+    if (!u1.MTimeDefined && u2.MTimeDefined) return 1;

+    if (u1.MTimeDefined && !u2.MTimeDefined) return -1;

+    if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime);

+    RINOZ_COMP(u1.Size, u2.Size);

+  }

+  return MyStringCompareNoCase(u1.Name, u2.Name);

+}

+

+struct CSolidGroup

+{

+  CRecordVector<UInt32> Indices;

+};

+

+static wchar_t *g_ExeExts[] =

+{

+  L"dll",

+  L"exe",

+  L"ocx",

+  L"sfx",

+  L"sys"

+};

+

+static bool IsExeExt(const UString &ext)

+{

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

+    if (ext.CompareNoCase(g_ExeExts[i]) == 0)

+      return true;

+  return false;

+}

+

+#ifdef USE_86_FILTER

+

+static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult)

+{

+  methodResult.Id = methodID;

+  methodResult.NumInStreams = numInStreams;

+  methodResult.NumOutStreams = 1;

+}

+

+static void MakeExeMethod(const CCompressionMethodMode &method,

+    bool bcj2Filter, CCompressionMethodMode &exeMethod)

+{

+  exeMethod = method;

+  if (bcj2Filter)

+  {

+    CMethodFull methodFull;

+    GetMethodFull(k_BCJ2, 4, methodFull);

+    exeMethod.Methods.Insert(0, methodFull);

+    GetMethodFull(k_LZMA, 1, methodFull);

+    {

+      CProp prop;

+      prop.Id = NCoderPropID::kAlgorithm;

+      prop.Value = kAlgorithmForBCJ2_LZMA;

+      methodFull.Props.Add(prop);

+    }

+    {

+      CProp prop;

+      prop.Id = NCoderPropID::kMatchFinder;

+      prop.Value = kMatchFinderForBCJ2_LZMA;

+      methodFull.Props.Add(prop);

+    }

+    {

+      CProp prop;

+      prop.Id = NCoderPropID::kDictionarySize;

+      prop.Value = kDictionaryForBCJ2_LZMA;

+      methodFull.Props.Add(prop);

+    }

+    {

+      CProp prop;

+      prop.Id = NCoderPropID::kNumFastBytes;

+      prop.Value = kNumFastBytesForBCJ2_LZMA;

+      methodFull.Props.Add(prop);

+    }

+    {

+      CProp prop;

+      prop.Id = NCoderPropID::kNumThreads;

+      prop.Value = (UInt32)1;

+      methodFull.Props.Add(prop);

+    }

+

+    exeMethod.Methods.Add(methodFull);

+    exeMethod.Methods.Add(methodFull);

+    CBind bind;

+

+    bind.OutCoder = 0;

+    bind.InStream = 0;

+

+    bind.InCoder = 1;

+    bind.OutStream = 0;

+    exeMethod.Binds.Add(bind);

+

+    bind.InCoder = 2;

+    bind.OutStream = 1;

+    exeMethod.Binds.Add(bind);

+

+    bind.InCoder = 3;

+    bind.OutStream = 2;

+    exeMethod.Binds.Add(bind);

+  }

+  else

+  {

+    CMethodFull methodFull;

+    GetMethodFull(k_BCJ, 1, methodFull);

+    exeMethod.Methods.Insert(0, methodFull);

+    CBind bind;

+    bind.OutCoder = 0;

+    bind.InStream = 0;

+    bind.InCoder = 1;

+    bind.OutStream = 0;

+    exeMethod.Binds.Add(bind);

+  }

+}

+

+#endif

+

+static void FromUpdateItemToFileItem(const CUpdateItem &ui,

+    CFileItem &file, CFileItem2 &file2)

+{

+  file.Name = NItemName::MakeLegalName(ui.Name);

+  if (ui.AttribDefined)

+    file.SetAttrib(ui.Attrib);

+  

+  file2.CTime = ui.CTime;  file2.CTimeDefined = ui.CTimeDefined;

+  file2.ATime = ui.ATime;  file2.ATimeDefined = ui.ATimeDefined;

+  file2.MTime = ui.MTime;  file2.MTimeDefined = ui.MTimeDefined;

+  file2.IsAnti = ui.IsAnti;

+  file2.StartPosDefined = false;

+

+  file.Size = ui.Size;

+  file.IsDir = ui.IsDir;

+  file.HasStream = ui.HasStream();

+}

+

+class CFolderOutStream2:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  COutStreamWithCRC *_crcStreamSpec;

+  CMyComPtr<ISequentialOutStream> _crcStream;

+  const CArchiveDatabaseEx *_db;

+  const CBoolVector *_extractStatuses;

+  CMyComPtr<ISequentialOutStream> _outStream;

+  UInt32 _startIndex;

+  int _currentIndex;

+  bool _fileIsOpen;

+  UInt64 _rem;

+

+  void OpenFile();

+  void CloseFile();

+  HRESULT CloseFileAndSetResult();

+  HRESULT ProcessEmptyFiles();

+public:

+  MY_UNKNOWN_IMP

+  

+  CFolderOutStream2()

+  {

+    _crcStreamSpec = new COutStreamWithCRC;

+    _crcStream = _crcStreamSpec;

+  }

+

+  HRESULT Init(const CArchiveDatabaseEx *db, UInt32 startIndex,

+      const CBoolVector *extractStatuses, ISequentialOutStream *outStream);

+  void ReleaseOutStream();

+  HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+HRESULT CFolderOutStream2::Init(const CArchiveDatabaseEx *db, UInt32 startIndex,

+    const CBoolVector *extractStatuses, ISequentialOutStream *outStream)

+{

+  _db = db;

+  _startIndex = startIndex;

+  _extractStatuses = extractStatuses;

+  _outStream = outStream;

+

+  _currentIndex = 0;

+  _fileIsOpen = false;

+  return ProcessEmptyFiles();

+}

+

+void CFolderOutStream2::ReleaseOutStream()

+{

+  _outStream.Release();

+  _crcStreamSpec->ReleaseStream();

+}

+

+void CFolderOutStream2::OpenFile()

+{

+  _crcStreamSpec->SetStream((*_extractStatuses)[_currentIndex] ? _outStream : NULL);

+  _crcStreamSpec->Init(true);

+  _fileIsOpen = true;

+  _rem = _db->Files[_startIndex + _currentIndex].Size;

+}

+

+void CFolderOutStream2::CloseFile()

+{

+  _crcStreamSpec->ReleaseStream();

+  _fileIsOpen = false;

+  _currentIndex++;

+}

+

+HRESULT CFolderOutStream2::CloseFileAndSetResult()

+{

+  const CFileItem &file = _db->Files[_startIndex + _currentIndex];

+  CloseFile();

+  return (file.IsDir || !file.CrcDefined || file.Crc == _crcStreamSpec->GetCRC()) ? S_OK: S_FALSE;

+}

+

+HRESULT CFolderOutStream2::ProcessEmptyFiles()

+{

+  while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)

+  {

+    OpenFile();

+    RINOK(CloseFileAndSetResult());

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize != NULL)

+    *processedSize = 0;

+  while (size != 0)

+  {

+    if (_fileIsOpen)

+    {

+      UInt32 cur = size < _rem ? size : (UInt32)_rem;

+      RINOK(_crcStream->Write(data, cur, &cur));

+      if (cur == 0)

+        break;

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

+      size -= cur;

+      _rem -= cur;

+      if (processedSize != NULL)

+        *processedSize += cur;

+      if (_rem == 0)

+      {

+        RINOK(CloseFileAndSetResult());

+        RINOK(ProcessEmptyFiles());

+        continue;

+      }

+    }

+    else

+    {

+      RINOK(ProcessEmptyFiles());

+      if (_currentIndex == _extractStatuses->Size())

+      {

+        // we don't support partial extracting

+        return E_FAIL;

+      }

+      OpenFile();

+    }

+  }

+  return S_OK;

+}

+

+class CThreadDecoder: public CVirtThread

+{

+public:

+  HRESULT Result;

+  CMyComPtr<IInStream> InStream;

+

+  CFolderOutStream2 *FosSpec;

+  CMyComPtr<ISequentialOutStream> Fos;

+

+  UInt64 StartPos;

+  const UInt64 *PackSizes;

+  const CFolder *Folder;

+  #ifndef _NO_CRYPTO

+  CMyComPtr<ICryptoGetTextPassword> GetTextPassword;

+  #endif

+

+  DECL_EXTERNAL_CODECS_VARS

+  CDecoder Decoder;

+

+  #ifndef _7ZIP_ST

+  bool MtMode;

+  UInt32 NumThreads;

+  #endif

+

+  CThreadDecoder():

+    Decoder(true)

+  {

+    #ifndef _7ZIP_ST

+    MtMode = false;

+    NumThreads = 1;

+    #endif

+    FosSpec = new CFolderOutStream2;

+    Fos = FosSpec;

+    Result = E_FAIL;

+  }

+  virtual void Execute();

+};

+

+void CThreadDecoder::Execute()

+{

+  try

+  {

+    #ifndef _NO_CRYPTO

+    bool passwordIsDefined;

+    #endif

+    Result = Decoder.Decode(

+      EXTERNAL_CODECS_VARS

+      InStream,

+      StartPos,

+      PackSizes,

+      *Folder,

+      Fos,

+      NULL

+      #ifndef _NO_CRYPTO

+      , GetTextPassword, passwordIsDefined

+      #endif

+      #ifndef _7ZIP_ST

+      , MtMode, NumThreads

+      #endif

+      );

+  }

+  catch(...)

+  {

+    Result = E_FAIL;

+  }

+  if (Result == S_OK)

+    Result = FosSpec->CheckFinishedState();

+  FosSpec->ReleaseOutStream();

+}

+

+bool static Is86FilteredFolder(const CFolder &f)

+{

+  for (int i = 0; i < f.Coders.Size(); i++)

+  {

+    CMethodId m = f.Coders[i].MethodID;

+    if (m == k_BCJ || m == k_BCJ2)

+      return true;

+  }

+  return false;

+}

+

+#ifndef _NO_CRYPTO

+

+class CCryptoGetTextPassword:

+  public ICryptoGetTextPassword,

+  public CMyUnknownImp

+{

+public:

+  UString Password;

+

+  MY_UNKNOWN_IMP

+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);

+};

+

+STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)

+{

+  return StringToBstr(Password, password);

+}

+

+#endif

+

+static const int kNumGroupsMax = 4;

+

+#ifdef USE_86_FILTER

+static bool Is86Group(int group) { return (group & 1) != 0; }

+#endif

+static bool IsEncryptedGroup(int group) { return (group & 2) != 0; }

+static int GetGroupIndex(bool encrypted, int bcjFiltered)

+  { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); }

+

+HRESULT Update(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    IInStream *inStream,

+    const CArchiveDatabaseEx *db,

+    const CObjectVector<CUpdateItem> &updateItems,

+    COutArchive &archive,

+    CArchiveDatabase &newDatabase,

+    ISequentialOutStream *seqOutStream,

+    IArchiveUpdateCallback *updateCallback,

+    const CUpdateOptions &options

+    #ifndef _NO_CRYPTO

+    , ICryptoGetTextPassword *getDecoderPassword

+    #endif

+    )

+{

+  UInt64 numSolidFiles = options.NumSolidFiles;

+  if (numSolidFiles == 0)

+    numSolidFiles = 1;

+  /*

+  CMyComPtr<IOutStream> outStream;

+  RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));

+  if (!outStream)

+    return E_NOTIMPL;

+  */

+

+  UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0;

+  if (startBlockSize > 0 && !options.RemoveSfxBlock)

+  {

+    RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));

+  }

+

+  CRecordVector<int> fileIndexToUpdateIndexMap;

+  CRecordVector<CFolderRepack> folderRefs;

+  UInt64 complexity = 0;

+  UInt64 inSizeForReduce2 = 0;

+  bool needEncryptedRepack = false;

+  if (db != 0)

+  {

+    fileIndexToUpdateIndexMap.Reserve(db->Files.Size());

+    int i;

+    for (i = 0; i < db->Files.Size(); i++)

+      fileIndexToUpdateIndexMap.Add(-1);

+

+    for (i = 0; i < updateItems.Size(); i++)

+    {

+      int index = updateItems[i].IndexInArchive;

+      if (index != -1)

+        fileIndexToUpdateIndexMap[index] = i;

+    }

+

+    for (i = 0; i < db->Folders.Size(); i++)

+    {

+      CNum indexInFolder = 0;

+      CNum numCopyItems = 0;

+      CNum numUnpackStreams = db->NumUnpackStreamsVector[i];

+      UInt64 repackSize = 0;

+      for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++)

+      {

+        const CFileItem &file = db->Files[fi];

+        if (file.HasStream)

+        {

+          indexInFolder++;

+          int updateIndex = fileIndexToUpdateIndexMap[fi];

+          if (updateIndex >= 0 && !updateItems[updateIndex].NewData)

+          {

+            numCopyItems++;

+            repackSize += file.Size;

+          }

+        }

+      }

+

+      if (numCopyItems == 0)

+        continue;

+

+      CFolderRepack rep;

+      rep.FolderIndex = i;

+      rep.NumCopyFiles = numCopyItems;

+      const CFolder &f = db->Folders[i];

+      bool isEncrypted = f.IsEncrypted();

+      rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f));

+      folderRefs.Add(rep);

+      if (numCopyItems == numUnpackStreams)

+        complexity += db->GetFolderFullPackSize(i);

+      else

+      {

+        complexity += repackSize;

+        if (repackSize > inSizeForReduce2)

+          inSizeForReduce2 = repackSize;

+        if (isEncrypted)

+          needEncryptedRepack = true;

+      }

+    }

+    folderRefs.Sort(CompareFolderRepacks, (void *)db);

+  }

+

+  UInt64 inSizeForReduce = 0;

+  int i;

+  for (i = 0; i < updateItems.Size(); i++)

+  {

+    const CUpdateItem &ui = updateItems[i];

+    if (ui.NewData)

+    {

+      complexity += ui.Size;

+      if (numSolidFiles != 1)

+        inSizeForReduce += ui.Size;

+      else if (ui.Size > inSizeForReduce)

+        inSizeForReduce = ui.Size;

+    }

+  }

+

+  if (inSizeForReduce2 > inSizeForReduce)

+    inSizeForReduce = inSizeForReduce2;

+

+  const UInt32 kMinReduceSize = (1 << 16);

+  if (inSizeForReduce < kMinReduceSize)

+    inSizeForReduce = kMinReduceSize;

+

+  RINOK(updateCallback->SetTotal(complexity));

+

+  CLocalProgress *lps = new CLocalProgress;

+  CMyComPtr<ICompressProgressInfo> progress = lps;

+  lps->Init(updateCallback, true);

+

+  CThreadDecoder threadDecoder;

+  if (!folderRefs.IsEmpty())

+  {

+    #ifdef EXTERNAL_CODECS

+    threadDecoder._codecsInfo = codecsInfo;

+    threadDecoder._externalCodecs = *externalCodecs;

+    #endif

+    RINOK(threadDecoder.Create());

+  }

+

+  CObjectVector<CSolidGroup> groups;

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

+    groups.Add(CSolidGroup());

+

+  {

+    // ---------- Split files to 2 groups ----------

+

+    bool useFilters = options.UseFilters;

+    const CCompressionMethodMode &method = *options.Method;

+    if (method.Methods.Size() != 1 || method.Binds.Size() != 0)

+      useFilters = false;

+    for (i = 0; i < updateItems.Size(); i++)

+    {

+      const CUpdateItem &ui = updateItems[i];

+      if (!ui.NewData || !ui.HasStream())

+        continue;

+      bool filteredGroup = false;

+      if (useFilters)

+      {

+        int dotPos = ui.Name.ReverseFind(L'.');

+        if (dotPos >= 0)

+          filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1));

+      }

+      groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i);

+    }

+  }

+

+  #ifndef _NO_CRYPTO

+

+  CCryptoGetTextPassword *getPasswordSpec = NULL;

+  if (needEncryptedRepack)

+  {

+    getPasswordSpec = new CCryptoGetTextPassword;

+    threadDecoder.GetTextPassword = getPasswordSpec;

+

+    if (options.Method->PasswordIsDefined)

+      getPasswordSpec->Password = options.Method->Password;

+    else

+    {

+      if (!getDecoderPassword)

+        return E_NOTIMPL;

+      CMyComBSTR password;

+      RINOK(getDecoderPassword->CryptoGetTextPassword(&password));

+      getPasswordSpec->Password = password;

+    }

+  }

+

+  #endif

+

+  // ---------- Compress ----------

+

+  RINOK(archive.Create(seqOutStream, false));

+  RINOK(archive.SkipPrefixArchiveHeader());

+

+  int folderRefIndex = 0;

+  lps->ProgressOffset = 0;

+

+  for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++)

+  {

+    const CSolidGroup &group = groups[groupIndex];

+

+    CCompressionMethodMode method;

+    #ifdef USE_86_FILTER

+    if (Is86Group(groupIndex))

+      MakeExeMethod(*options.Method, options.MaxFilter, method);

+    else

+    #endif

+      method = *options.Method;

+

+    if (IsEncryptedGroup(groupIndex))

+    {

+      if (!method.PasswordIsDefined)

+      {

+        #ifndef _NO_CRYPTO

+        if (getPasswordSpec)

+          method.Password = getPasswordSpec->Password;

+        #endif

+        method.PasswordIsDefined = true;

+      }

+    }

+    else

+    {

+      method.PasswordIsDefined = false;

+      method.Password.Empty();

+    }

+

+    CEncoder encoder(method);

+

+    for (; folderRefIndex < folderRefs.Size(); folderRefIndex++)

+    {

+      const CFolderRepack &rep = folderRefs[folderRefIndex];

+      if (rep.Group != groupIndex)

+        break;

+      int folderIndex = rep.FolderIndex;

+      

+      if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex])

+      {

+        UInt64 packSize = db->GetFolderFullPackSize(folderIndex);

+        RINOK(WriteRange(inStream, archive.SeqStream,

+          db->GetFolderStreamPos(folderIndex, 0), packSize, progress));

+        lps->ProgressOffset += packSize;

+        

+        const CFolder &folder = db->Folders[folderIndex];

+        CNum startIndex = db->FolderStartPackStreamIndex[folderIndex];

+        for (int j = 0; j < folder.PackStreams.Size(); j++)

+        {

+          newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]);

+          // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);

+          // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);

+        }

+        newDatabase.Folders.Add(folder);

+      }

+      else

+      {

+        CStreamBinder sb;

+        RINOK(sb.CreateEvents());

+        CMyComPtr<ISequentialOutStream> sbOutStream;

+        CMyComPtr<ISequentialInStream> sbInStream;

+        sb.CreateStreams(&sbInStream, &sbOutStream);

+        CBoolVector extractStatuses;

+        

+        CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];

+        CNum indexInFolder = 0;

+        

+        for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)

+        {

+          bool needExtract = false;

+          if (db->Files[fi].HasStream)

+          {

+            indexInFolder++;

+            int updateIndex = fileIndexToUpdateIndexMap[fi];

+            if (updateIndex >= 0 && !updateItems[updateIndex].NewData)

+              needExtract = true;

+          }

+          extractStatuses.Add(needExtract);

+        }

+

+        RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream));

+        sbOutStream.Release();

+        

+        threadDecoder.InStream = inStream;

+        threadDecoder.Folder = &db->Folders[folderIndex];

+        threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0);

+        threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]];

+        

+        threadDecoder.Start();

+        

+        int startPackIndex = newDatabase.PackSizes.Size();

+        CFolder newFolder;

+        RINOK(encoder.Encode(

+          EXTERNAL_CODECS_LOC_VARS

+          sbInStream, NULL, &inSizeForReduce, newFolder,

+          archive.SeqStream, newDatabase.PackSizes, progress));

+        

+        threadDecoder.WaitFinish();

+

+        RINOK(threadDecoder.Result);

+

+        for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)

+          lps->OutSize += newDatabase.PackSizes[startPackIndex];

+        lps->InSize += newFolder.GetUnpackSize();

+        

+        newDatabase.Folders.Add(newFolder);

+      }

+      

+      newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);

+      

+      CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];

+      

+      CNum indexInFolder = 0;

+      for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)

+      {

+        CFileItem file;

+        CFileItem2 file2;

+        db->GetFile(fi, file, file2);

+        if (file.HasStream)

+        {

+          indexInFolder++;

+          int updateIndex = fileIndexToUpdateIndexMap[fi];

+          if (updateIndex >= 0)

+          {

+            const CUpdateItem &ui = updateItems[updateIndex];

+            if (ui.NewData)

+              continue;

+            if (ui.NewProps)

+            {

+              CFileItem uf;

+              FromUpdateItemToFileItem(ui, uf, file2);

+              uf.Size = file.Size;

+              uf.Crc = file.Crc;

+              uf.CrcDefined = file.CrcDefined;

+              uf.HasStream = file.HasStream;

+              file = uf;

+            }

+            newDatabase.AddFile(file, file2);

+          }

+        }

+      }

+    }

+

+    int numFiles = group.Indices.Size();

+    if (numFiles == 0)

+      continue;

+    CRecordVector<CRefItem> refItems;

+    refItems.Reserve(numFiles);

+    bool sortByType = (numSolidFiles > 1);

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

+      refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType));

+    refItems.Sort(CompareUpdateItems, (void *)&sortByType);

+    

+    CRecordVector<UInt32> indices;

+    indices.Reserve(numFiles);

+

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

+    {

+      UInt32 index = refItems[i].Index;

+      indices.Add(index);

+      /*

+      const CUpdateItem &ui = updateItems[index];

+      CFileItem file;

+      if (ui.NewProps)

+        FromUpdateItemToFileItem(ui, file);

+      else

+        file = db.Files[ui.IndexInArchive];

+      if (file.IsAnti || file.IsDir)

+        return E_FAIL;

+      newDatabase.Files.Add(file);

+      */

+    }

+    

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

+    {

+      UInt64 totalSize = 0;

+      int numSubFiles;

+      UString prevExtension;

+      for (numSubFiles = 0; i + numSubFiles < numFiles &&

+          numSubFiles < numSolidFiles; numSubFiles++)

+      {

+        const CUpdateItem &ui = updateItems[indices[i + numSubFiles]];

+        totalSize += ui.Size;

+        if (totalSize > options.NumSolidBytes)

+          break;

+        if (options.SolidExtension)

+        {

+          UString ext = ui.GetExtension();

+          if (numSubFiles == 0)

+            prevExtension = ext;

+          else

+            if (ext.CompareNoCase(prevExtension) != 0)

+              break;

+        }

+      }

+      if (numSubFiles < 1)

+        numSubFiles = 1;

+

+      CFolderInStream *inStreamSpec = new CFolderInStream;

+      CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);

+      inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);

+      

+      CFolder folderItem;

+

+      int startPackIndex = newDatabase.PackSizes.Size();

+      RINOK(encoder.Encode(

+          EXTERNAL_CODECS_LOC_VARS

+          solidInStream, NULL, &inSizeForReduce, folderItem,

+          archive.SeqStream, newDatabase.PackSizes, progress));

+

+      for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)

+        lps->OutSize += newDatabase.PackSizes[startPackIndex];

+

+      lps->InSize += folderItem.GetUnpackSize();

+      // for ()

+      // newDatabase.PackCRCsDefined.Add(false);

+      // newDatabase.PackCRCs.Add(0);

+      

+      newDatabase.Folders.Add(folderItem);

+      

+      CNum numUnpackStreams = 0;

+      for (int subIndex = 0; subIndex < numSubFiles; subIndex++)

+      {

+        const CUpdateItem &ui = updateItems[indices[i + subIndex]];

+        CFileItem file;

+        CFileItem2 file2;

+        if (ui.NewProps)

+          FromUpdateItemToFileItem(ui, file, file2);

+        else

+          db->GetFile(ui.IndexInArchive, file, file2);

+        if (file2.IsAnti || file.IsDir)

+          return E_FAIL;

+        

+        /*

+        CFileItem &file = newDatabase.Files[

+              startFileIndexInDatabase + i + subIndex];

+        */

+        if (!inStreamSpec->Processed[subIndex])

+        {

+          continue;

+          // file.Name += L".locked";

+        }

+

+        file.Crc = inStreamSpec->CRCs[subIndex];

+        file.Size = inStreamSpec->Sizes[subIndex];

+        if (file.Size != 0)

+        {

+          file.CrcDefined = true;

+          file.HasStream = true;

+          numUnpackStreams++;

+        }

+        else

+        {

+          file.CrcDefined = false;

+          file.HasStream = false;

+        }

+        newDatabase.AddFile(file, file2);

+      }

+      // numUnpackStreams = 0 is very bad case for locked files

+      // v3.13 doesn't understand it.

+      newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);

+      i += numSubFiles;

+    }

+  }

+

+  if (folderRefIndex != folderRefs.Size())

+    return E_FAIL;

+

+  /*

+  folderRefs.ClearAndFree();

+  fileIndexToUpdateIndexMap.ClearAndFree();

+  groups.ClearAndFree();

+  */

+

+  {

+    // ---------- Write Folders & Empty Files ----------

+    

+    CRecordVector<int> emptyRefs;

+    for (i = 0; i < updateItems.Size(); i++)

+    {

+      const CUpdateItem &ui = updateItems[i];

+      if (ui.NewData)

+      {

+        if (ui.HasStream())

+          continue;

+      }

+      else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream)

+        continue;

+      emptyRefs.Add(i);

+    }

+    emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);

+    for (i = 0; i < emptyRefs.Size(); i++)

+    {

+      const CUpdateItem &ui = updateItems[emptyRefs[i]];

+      CFileItem file;

+      CFileItem2 file2;

+      if (ui.NewProps)

+        FromUpdateItemToFileItem(ui, file, file2);

+      else

+        db->GetFile(ui.IndexInArchive, file, file2);

+      newDatabase.AddFile(file, file2);

+    }

+  }

+    

+  newDatabase.ReserveDown();

+  return S_OK;

+}

+

+}}

diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h
new file mode 100755
index 0000000..f3dc885
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zUpdate.h
@@ -0,0 +1,88 @@
+// 7zUpdate.h

+

+#ifndef __7Z_UPDATE_H

+#define __7Z_UPDATE_H

+

+#include "7zCompressionMode.h"

+#include "7zIn.h"

+#include "7zOut.h"

+

+#include "../IArchive.h"

+

+namespace NArchive {

+namespace N7z {

+

+struct CUpdateItem

+{

+  int IndexInArchive;

+  int IndexInClient;

+  

+  UInt64 CTime;

+  UInt64 ATime;

+  UInt64 MTime;

+

+  UInt64 Size;

+  UString Name;

+

+  UInt32 Attrib;

+  

+  bool NewData;

+  bool NewProps;

+

+  bool IsAnti;

+  bool IsDir;

+

+  bool AttribDefined;

+  bool CTimeDefined;

+  bool ATimeDefined;

+  bool MTimeDefined;

+

+  bool HasStream() const { return !IsDir && !IsAnti && Size != 0; }

+

+  CUpdateItem():

+      IsAnti(false),

+      IsDir(false),

+      AttribDefined(false),

+      CTimeDefined(false),

+      ATimeDefined(false),

+      MTimeDefined(false)

+      {}

+  void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); };

+

+  int GetExtensionPos() const;

+  UString GetExtension() const;

+};

+

+struct CUpdateOptions

+{

+  const CCompressionMethodMode *Method;

+  const CCompressionMethodMode *HeaderMethod;

+  bool UseFilters;

+  bool MaxFilter;

+

+  CHeaderOptions HeaderOptions;

+

+  UInt64 NumSolidFiles;

+  UInt64 NumSolidBytes;

+  bool SolidExtension;

+  bool RemoveSfxBlock;

+  bool VolumeMode;

+};

+

+HRESULT Update(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    IInStream *inStream,

+    const CArchiveDatabaseEx *db,

+    const CObjectVector<CUpdateItem> &updateItems,

+    COutArchive &archive,

+    CArchiveDatabase &newDatabase,

+    ISequentialOutStream *seqOutStream,

+    IArchiveUpdateCallback *updateCallback,

+    const CUpdateOptions &options

+    #ifndef _NO_CRYPTO

+    , ICryptoGetTextPassword *getDecoderPassword

+    #endif

+    );

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/7z/StdAfx.cpp b/CPP/7zip/Archive/7z/StdAfx.cpp
new file mode 100755
index 0000000..c6d3b1f
--- /dev/null
+++ b/CPP/7zip/Archive/7z/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp

+

+#include "StdAfx.h"

diff --git a/CPP/7zip/Archive/7z/StdAfx.h b/CPP/7zip/Archive/7z/StdAfx.h
new file mode 100755
index 0000000..a4e6173
--- /dev/null
+++ b/CPP/7zip/Archive/7z/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../../Common/MyWindows.h"

+#include "../../../Common/NewHandler.h"

+

+#endif

diff --git a/CPP/7zip/Archive/Archive.def b/CPP/7zip/Archive/Archive.def
new file mode 100755
index 0000000..839245e
--- /dev/null
+++ b/CPP/7zip/Archive/Archive.def
@@ -0,0 +1,6 @@
+EXPORTS

+  CreateObject PRIVATE

+  GetHandlerProperty PRIVATE

+  GetNumberOfFormats PRIVATE

+  GetHandlerProperty2 PRIVATE

+  CreateObject PRIVATE

diff --git a/CPP/7zip/Archive/Archive2.def b/CPP/7zip/Archive/Archive2.def
new file mode 100755
index 0000000..190fbd8
--- /dev/null
+++ b/CPP/7zip/Archive/Archive2.def
@@ -0,0 +1,9 @@
+EXPORTS

+  CreateObject PRIVATE

+  GetHandlerProperty PRIVATE

+  GetNumberOfFormats PRIVATE

+  GetHandlerProperty2 PRIVATE

+  CreateObject PRIVATE

+  GetNumberOfMethods PRIVATE

+  GetMethodProperty PRIVATE

+  SetLargePageMode PRIVATE

diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp
new file mode 100755
index 0000000..5d6cf92
--- /dev/null
+++ b/CPP/7zip/Archive/ArchiveExports.cpp
@@ -0,0 +1,135 @@
+// ArchiveExports.cpp

+

+#include "StdAfx.h"

+

+#include "../../Common/ComTry.h"

+

+#include "../../Windows/PropVariant.h"

+

+#include "../Common/RegisterArc.h"

+

+static const unsigned int kNumArcsMax = 48;

+static unsigned int g_NumArcs = 0;

+static unsigned int g_DefaultArcIndex = 0;

+static const CArcInfo *g_Arcs[kNumArcsMax];

+void RegisterArc(const CArcInfo *arcInfo)

+{

+  if (g_NumArcs < kNumArcsMax)

+  {

+    const wchar_t *p = arcInfo->Name;

+    if (p[0] == '7' && p[1] == 'z' && p[2] == 0)

+      g_DefaultArcIndex = g_NumArcs;

+    g_Arcs[g_NumArcs++] = arcInfo;

+  }

+}

+

+DEFINE_GUID(CLSID_CArchiveHandler,

+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);

+

+#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])

+

+static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)

+{

+  if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)

+    value->vt = VT_BSTR;

+  return S_OK;

+}

+

+static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)

+{

+  return SetPropString((const char *)&guid, sizeof(GUID), value);

+}

+

+int FindFormatCalssId(const GUID *clsID)

+{

+  GUID cls = *clsID;

+  CLS_ARC_ID_ITEM(cls) = 0;

+  if (cls != CLSID_CArchiveHandler)

+    return -1;

+  Byte id = CLS_ARC_ID_ITEM(*clsID);

+  for (unsigned i = 0; i < g_NumArcs; i++)

+    if (g_Arcs[i]->ClassId == id)

+      return (int)i;

+  return -1;

+}

+

+STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)

+{

+  COM_TRY_BEGIN

+  {

+    int needIn = (*iid == IID_IInArchive);

+    int needOut = (*iid == IID_IOutArchive);

+    if (!needIn && !needOut)

+      return E_NOINTERFACE;

+    int formatIndex = FindFormatCalssId(clsid);

+    if (formatIndex < 0)

+      return CLASS_E_CLASSNOTAVAILABLE;

+    

+    const CArcInfo &arc = *g_Arcs[formatIndex];

+    if (needIn)

+    {

+      *outObject = arc.CreateInArchive();

+      ((IInArchive *)*outObject)->AddRef();

+    }

+    else

+    {

+      if (!arc.CreateOutArchive)

+        return CLASS_E_CLASSNOTAVAILABLE;

+      *outObject = arc.CreateOutArchive();

+      ((IOutArchive *)*outObject)->AddRef();

+    }

+  }

+  COM_TRY_END

+  return S_OK;

+}

+

+STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)

+{

+  COM_TRY_BEGIN

+  if (formatIndex >= g_NumArcs)

+    return E_INVALIDARG;

+  const CArcInfo &arc = *g_Arcs[formatIndex];

+  NWindows::NCOM::CPropVariant prop;

+  switch(propID)

+  {

+    case NArchive::kName:

+      prop = arc.Name;

+      break;

+    case NArchive::kClassID:

+    {

+      GUID clsId = CLSID_CArchiveHandler;

+      CLS_ARC_ID_ITEM(clsId) = arc.ClassId;

+      return SetPropGUID(clsId, value);

+    }

+    case NArchive::kExtension:

+      if (arc.Ext != 0)

+        prop = arc.Ext;

+      break;

+    case NArchive::kAddExtension:

+      if (arc.AddExt != 0)

+        prop = arc.AddExt;

+      break;

+    case NArchive::kUpdate:

+      prop = (bool)(arc.CreateOutArchive != 0);

+      break;

+    case NArchive::kKeepName:

+      prop = arc.KeepName;

+      break;

+    case NArchive::kStartSignature:

+      return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);

+  }

+  prop.Detach(value);

+  return S_OK;

+  COM_TRY_END

+}

+

+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)

+{

+  return GetHandlerProperty2(g_DefaultArcIndex, propID, value);

+}

+

+STDAPI GetNumberOfFormats(UINT32 *numFormats)

+{

+  *numFormats = g_NumArcs;

+  return S_OK;

+}

diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
new file mode 100755
index 0000000..417e8a7
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp
@@ -0,0 +1,121 @@
+// CoderMixer2.cpp

+

+#include "StdAfx.h"

+

+#include "CoderMixer2.h"

+

+namespace NCoderMixer {

+

+CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):

+  _srcBindInfo(srcBindInfo)

+{

+  srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);

+

+  UInt32  j;

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

+  {

+    _srcInToDestOutMap.Add(0);

+    DestOutToSrcInMap.Add(0);

+  }

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

+  {

+    _srcOutToDestInMap.Add(0);

+    _destInToSrcOutMap.Add(0);

+  }

+

+  UInt32 destInOffset = 0;

+  UInt32 destOutOffset = 0;

+  UInt32 srcInOffset = NumSrcInStreams;

+  UInt32 srcOutOffset = _numSrcOutStreams;

+

+  for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--)

+  {

+    const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i];

+

+    srcInOffset -= srcCoderInfo.NumInStreams;

+    srcOutOffset -= srcCoderInfo.NumOutStreams;

+    

+    UInt32 j;

+    for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++)

+    {

+      UInt32 index = srcInOffset + j;

+      _srcInToDestOutMap[index] = destOutOffset;

+      DestOutToSrcInMap[destOutOffset] = index;

+    }

+    for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++)

+    {

+      UInt32 index = srcOutOffset + j;

+      _srcOutToDestInMap[index] = destInOffset;

+      _destInToSrcOutMap[destInOffset] = index;

+    }

+  }

+}

+

+void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)

+{

+  destBindInfo.Coders.Clear();

+  destBindInfo.BindPairs.Clear();

+  destBindInfo.InStreams.Clear();

+  destBindInfo.OutStreams.Clear();

+

+  int i;

+  for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--)

+  {

+    const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i];

+    CCoderStreamsInfo destCoderInfo;

+    destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams;

+    destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams;

+    destBindInfo.Coders.Add(destCoderInfo);

+  }

+  for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--)

+  {

+    const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i];

+    CBindPair destBindPair;

+    destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex];

+    destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex];

+    destBindInfo.BindPairs.Add(destBindPair);

+  }

+  for (i = 0; i < _srcBindInfo.InStreams.Size(); i++)

+    destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);

+  for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++)

+    destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);

+}

+

+CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):

+    NumInStreams(numInStreams),

+    NumOutStreams(numOutStreams)

+{

+  InSizes.Reserve(NumInStreams);

+  InSizePointers.Reserve(NumInStreams);

+  OutSizes.Reserve(NumOutStreams);

+  OutSizePointers.Reserve(NumOutStreams);

+}

+

+static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,

+    CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)

+{

+  sizes.Clear();

+  sizePointers.Clear();

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

+  {

+    if (srcSizes == 0 || srcSizes[i] == NULL)

+    {

+      sizes.Add(0);

+      sizePointers.Add(NULL);

+    }

+    else

+    {

+      sizes.Add(*srcSizes[i]);

+      sizePointers.Add(&sizes.Back());

+    }

+  }

+}

+

+void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes,

+      const UInt64 **outSizes)

+{

+  SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);

+  SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);

+}

+

+}

diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h
new file mode 100755
index 0000000..b1893b2
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderMixer2.h
@@ -0,0 +1,174 @@
+// CoderMixer2.h

+

+#ifndef __CODER_MIXER2_H

+#define __CODER_MIXER2_H

+

+#include "../../../Common/MyVector.h"

+#include "../../../Common/Types.h"

+#include "../../../Common/MyCom.h"

+#include "../../ICoder.h"

+

+namespace NCoderMixer {

+

+struct CBindPair

+{

+  UInt32 InIndex;

+  UInt32 OutIndex;

+};

+

+struct CCoderStreamsInfo

+{

+  UInt32 NumInStreams;

+  UInt32 NumOutStreams;

+};

+

+struct CBindInfo

+{

+  CRecordVector<CCoderStreamsInfo> Coders;

+  CRecordVector<CBindPair> BindPairs;

+  CRecordVector<UInt32> InStreams;

+  CRecordVector<UInt32> OutStreams;

+

+  void Clear()

+  {

+    Coders.Clear();

+    BindPairs.Clear();

+    InStreams.Clear();

+    OutStreams.Clear();

+  }

+

+  /*

+  UInt32 GetCoderStartOutStream(UInt32 coderIndex) const

+  {

+    UInt32 numOutStreams = 0;

+    for (UInt32 i = 0; i < coderIndex; i++)

+      numOutStreams += Coders[i].NumOutStreams;

+    return numOutStreams;

+  }

+  */

+

+

+  void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const

+  {

+    numInStreams = 0;

+    numOutStreams = 0;

+    for (int i = 0; i < Coders.Size(); i++)

+    {

+      const CCoderStreamsInfo &coderStreamsInfo = Coders[i];

+      numInStreams += coderStreamsInfo.NumInStreams;

+      numOutStreams += coderStreamsInfo.NumOutStreams;

+    }

+  }

+

+  int FindBinderForInStream(UInt32 inStream) const

+  {

+    for (int i = 0; i < BindPairs.Size(); i++)

+      if (BindPairs[i].InIndex == inStream)

+        return i;

+    return -1;

+  }

+  int FindBinderForOutStream(UInt32 outStream) const

+  {

+    for (int i = 0; i < BindPairs.Size(); i++)

+      if (BindPairs[i].OutIndex == outStream)

+        return i;

+    return -1;

+  }

+

+  UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const

+  {

+    UInt32 streamIndex = 0;

+    for (UInt32 i = 0; i < coderIndex; i++)

+      streamIndex += Coders[i].NumInStreams;

+    return streamIndex;

+  }

+

+  UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const

+  {

+    UInt32 streamIndex = 0;

+    for (UInt32 i = 0; i < coderIndex; i++)

+      streamIndex += Coders[i].NumOutStreams;

+    return streamIndex;

+  }

+

+

+  void FindInStream(UInt32 streamIndex, UInt32 &coderIndex,

+      UInt32 &coderStreamIndex) const

+  {

+    for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)

+    {

+      UInt32 curSize = Coders[coderIndex].NumInStreams;

+      if (streamIndex < curSize)

+      {

+        coderStreamIndex = streamIndex;

+        return;

+      }

+      streamIndex -= curSize;

+    }

+    throw 1;

+  }

+  void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex,

+      UInt32 &coderStreamIndex) const

+  {

+    for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)

+    {

+      UInt32 curSize = Coders[coderIndex].NumOutStreams;

+      if (streamIndex < curSize)

+      {

+        coderStreamIndex = streamIndex;

+        return;

+      }

+      streamIndex -= curSize;

+    }

+    throw 1;

+  }

+};

+

+class CBindReverseConverter

+{

+  UInt32 _numSrcOutStreams;

+  NCoderMixer::CBindInfo _srcBindInfo;

+  CRecordVector<UInt32> _srcInToDestOutMap;

+  CRecordVector<UInt32> _srcOutToDestInMap;

+  CRecordVector<UInt32> _destInToSrcOutMap;

+public:

+  UInt32 NumSrcInStreams;

+  CRecordVector<UInt32> DestOutToSrcInMap;

+

+  CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo);

+  void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo);

+};

+

+struct CCoderInfo2

+{

+  CMyComPtr<ICompressCoder> Coder;

+  CMyComPtr<ICompressCoder2> Coder2;

+  UInt32 NumInStreams;

+  UInt32 NumOutStreams;

+

+  CRecordVector<UInt64> InSizes;

+  CRecordVector<UInt64> OutSizes;

+  CRecordVector<const UInt64 *> InSizePointers;

+  CRecordVector<const UInt64 *> OutSizePointers;

+

+  CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams);

+  void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);

+

+  HRESULT QueryInterface(REFGUID iid, void** pp) const

+  {

+    IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;

+    return p->QueryInterface(iid, pp);

+  }

+};

+

+class CCoderMixer2

+{

+public:

+  virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0;

+  virtual void ReInit() = 0;

+  virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;

+};

+

+}

+#endif

+

diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
new file mode 100755
index 0000000..3047b13
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
@@ -0,0 +1,240 @@
+// CoderMixer2MT.cpp

+

+#include "StdAfx.h"

+

+#include "CoderMixer2MT.h"

+

+namespace NCoderMixer {

+

+CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):

+    CCoderInfo2(numInStreams, numOutStreams)

+{

+  InStreams.Reserve(NumInStreams);

+  InStreamPointers.Reserve(NumInStreams);

+  OutStreams.Reserve(NumOutStreams);

+  OutStreamPointers.Reserve(NumOutStreams);

+}

+

+void CCoder2::Execute() { Code(NULL); }

+

+void CCoder2::Code(ICompressProgressInfo *progress)

+{

+  InStreamPointers.Clear();

+  OutStreamPointers.Clear();

+  UInt32 i;

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

+  {

+    if (InSizePointers[i] != NULL)

+      InSizePointers[i] = &InSizes[i];

+    InStreamPointers.Add((ISequentialInStream *)InStreams[i]);

+  }

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

+  {

+    if (OutSizePointers[i] != NULL)

+      OutSizePointers[i] = &OutSizes[i];

+    OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]);

+  }

+  if (Coder)

+    Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],

+        InSizePointers[0], OutSizePointers[0], progress);

+  else

+    Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,

+      &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);

+  {

+    int i;

+    for (i = 0; i < InStreams.Size(); i++)

+      InStreams[i].Release();

+    for (i = 0; i < OutStreams.Size(); i++)

+      OutStreams[i].Release();

+  }

+}

+

+static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,

+    CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)

+{

+  sizes.Clear();

+  sizePointers.Clear();

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

+  {

+    if (srcSizes == 0 || srcSizes[i] == NULL)

+    {

+      sizes.Add(0);

+      sizePointers.Add(NULL);

+    }

+    else

+    {

+      sizes.Add(*srcSizes[i]);

+      sizePointers.Add(&sizes.Back());

+    }

+  }

+}

+

+

+void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)

+{

+  SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);

+  SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);

+}

+

+//////////////////////////////////////

+// CCoderMixer2MT

+

+HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)

+{

+  _bindInfo = bindInfo;

+  _streamBinders.Clear();

+  for (int i = 0; i < _bindInfo.BindPairs.Size(); i++)

+  {

+    _streamBinders.Add(CStreamBinder());

+    RINOK(_streamBinders.Back().CreateEvents());

+  }

+  return S_OK;

+}

+

+void CCoderMixer2MT::AddCoderCommon()

+{

+  const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];

+  CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);

+  _coders.Add(threadCoderInfo);

+}

+

+void CCoderMixer2MT::AddCoder(ICompressCoder *coder)

+{

+  AddCoderCommon();

+  _coders.Back().Coder = coder;

+}

+

+void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)

+{

+  AddCoderCommon();

+  _coders.Back().Coder2 = coder;

+}

+

+

+void CCoderMixer2MT::ReInit()

+{

+  for (int i = 0; i < _streamBinders.Size(); i++)

+    _streamBinders[i].ReInit();

+}

+

+

+HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams)

+{

+  /*

+  if (_coders.Size() != _bindInfo.Coders.Size())

+    throw 0;

+  */

+  int i;

+  for (i = 0; i < _coders.Size(); i++)

+  {

+    CCoder2 &coderInfo = _coders[i];

+    const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];

+    coderInfo.InStreams.Clear();

+    UInt32 j;

+    for (j = 0; j < coderStreamsInfo.NumInStreams; j++)

+      coderInfo.InStreams.Add(NULL);

+    coderInfo.OutStreams.Clear();

+    for (j = 0; j < coderStreamsInfo.NumOutStreams; j++)

+      coderInfo.OutStreams.Add(NULL);

+  }

+

+  for (i = 0; i < _bindInfo.BindPairs.Size(); i++)

+  {

+    const CBindPair &bindPair = _bindInfo.BindPairs[i];

+    UInt32 inCoderIndex, inCoderStreamIndex;

+    UInt32 outCoderIndex, outCoderStreamIndex;

+    _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);

+    _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);

+

+    _streamBinders[i].CreateStreams(

+        &_coders[inCoderIndex].InStreams[inCoderStreamIndex],

+        &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);

+

+    CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;

+    _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);

+    _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);

+    if (inSetSize && outSetSize)

+    {

+      const UInt32 kBufSize = 1 << 19;

+      inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);

+      outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);

+    }

+  }

+

+  for (i = 0; i < _bindInfo.InStreams.Size(); i++)

+  {

+    UInt32 inCoderIndex, inCoderStreamIndex;

+    _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);

+    _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];

+  }

+  

+  for (i = 0; i < _bindInfo.OutStreams.Size(); i++)

+  {

+    UInt32 outCoderIndex, outCoderStreamIndex;

+    _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);

+    _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];

+  }

+  return S_OK;

+}

+

+HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)

+{

+  for (int i = 0; i < _coders.Size(); i++)

+    if (_coders[i].Result == code)

+      return code;

+  return S_OK;

+}

+

+STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,

+      const UInt64 ** /* inSizes */,

+      UInt32 numInStreams,

+      ISequentialOutStream **outStreams,

+      const UInt64 ** /* outSizes */,

+      UInt32 numOutStreams,

+      ICompressProgressInfo *progress)

+{

+  if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||

+      numOutStreams != (UInt32)_bindInfo.OutStreams.Size())

+    return E_INVALIDARG;

+

+  Init(inStreams, outStreams);

+

+  int i;

+  for (i = 0; i < _coders.Size(); i++)

+    if (i != _progressCoderIndex)

+    {

+      RINOK(_coders[i].Create());

+    }

+

+  for (i = 0; i < _coders.Size(); i++)

+    if (i != _progressCoderIndex)

+      _coders[i].Start();

+

+  _coders[_progressCoderIndex].Code(progress);

+

+  for (i = 0; i < _coders.Size(); i++)

+    if (i != _progressCoderIndex)

+      _coders[i].WaitFinish();

+

+  RINOK(ReturnIfError(E_ABORT));

+  RINOK(ReturnIfError(E_OUTOFMEMORY));

+

+  for (i = 0; i < _coders.Size(); i++)

+  {

+    HRESULT result = _coders[i].Result;

+    if (result != S_OK && result != E_FAIL && result != S_FALSE)

+      return result;

+  }

+

+  RINOK(ReturnIfError(S_FALSE));

+

+  for (i = 0; i < _coders.Size(); i++)

+  {

+    HRESULT result = _coders[i].Result;

+    if (result != S_OK)

+      return result;

+  }

+  return S_OK;

+}

+

+}

diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h
new file mode 100755
index 0000000..acecc39
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h
@@ -0,0 +1,80 @@
+// CoderMixer2MT.h

+

+#ifndef __CODER_MIXER2_MT_H

+#define __CODER_MIXER2_MT_H

+

+#include "CoderMixer2.h"

+#include "../../../Common/MyCom.h"

+#include "../../Common/StreamBinder.h"

+#include "../../Common/VirtThread.h"

+

+namespace NCoderMixer {

+

+struct CCoder2: public CCoderInfo2, public CVirtThread

+{

+  HRESULT Result;

+  CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;

+  CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;

+  CRecordVector<ISequentialInStream*> InStreamPointers;

+  CRecordVector<ISequentialOutStream*> OutStreamPointers;

+

+  CCoder2(UInt32 numInStreams, UInt32 numOutStreams);

+  void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);

+  virtual void Execute();

+  void Code(ICompressProgressInfo *progress);

+};

+

+

+/*

+  SetBindInfo()

+  for each coder

+    AddCoder[2]()

+  SetProgressIndex(UInt32 coderIndex);

+ 

+  for each file

+  {

+    ReInit()

+    for each coder

+      SetCoderInfo

+    Code

+  }

+*/

+

+class CCoderMixer2MT:

+  public ICompressCoder2,

+  public CCoderMixer2,

+  public CMyUnknownImp

+{

+  CBindInfo _bindInfo;

+  CObjectVector<CStreamBinder> _streamBinders;

+  int _progressCoderIndex;

+

+  void AddCoderCommon();

+  HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams);

+  HRESULT ReturnIfError(HRESULT code);

+public:

+  CObjectVector<CCoder2> _coders;

+  MY_UNKNOWN_IMP

+

+  STDMETHOD(Code)(ISequentialInStream **inStreams,

+      const UInt64 **inSizes,

+      UInt32 numInStreams,

+      ISequentialOutStream **outStreams,

+      const UInt64 **outSizes,

+      UInt32 numOutStreams,

+      ICompressProgressInfo *progress);

+

+  HRESULT SetBindInfo(const CBindInfo &bindInfo);

+  void AddCoder(ICompressCoder *coder);

+  void AddCoder2(ICompressCoder2 *coder);

+  void SetProgressCoderIndex(int coderIndex) {  _progressCoderIndex = coderIndex; }

+

+  void ReInit();

+  void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)

+    {  _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }

+  UInt64 GetWriteProcessedSize(UInt32 binderIndex) const

+    {  return _streamBinders[binderIndex].ProcessedSize; }

+};

+

+}

+#endif

diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
new file mode 100755
index 0000000..62d05af
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
@@ -0,0 +1,15 @@
+// CrossThreadProgress.cpp

+

+#include "StdAfx.h"

+

+#include "CrossThreadProgress.h"

+

+STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)

+{

+  InSize = inSize;

+  OutSize = outSize;

+  ProgressEvent.Set();

+  WaitEvent.Lock();

+  return Result;

+}

+

diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.h b/CPP/7zip/Archive/Common/CrossThreadProgress.h
new file mode 100755
index 0000000..d414958
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CrossThreadProgress.h
@@ -0,0 +1,37 @@
+// CrossThreadProgress.h

+

+#ifndef __CROSSTHREADPROGRESS_H

+#define __CROSSTHREADPROGRESS_H

+

+#include "../../ICoder.h"

+#include "../../../Windows/Synchronization.h"

+#include "../../../Common/MyCom.h"

+

+class CCrossThreadProgress:

+  public ICompressProgressInfo,

+  public CMyUnknownImp

+{

+public:

+  const UInt64 *InSize;

+  const UInt64 *OutSize;

+  HRESULT Result;

+  NWindows::NSynchronization::CAutoResetEvent ProgressEvent;

+  NWindows::NSynchronization::CAutoResetEvent WaitEvent;

+

+  HRes Create()

+  {

+    RINOK(ProgressEvent.CreateIfNotCreated());

+    return WaitEvent.CreateIfNotCreated();

+  }

+  void Init()

+  {

+    ProgressEvent.Reset();

+    WaitEvent.Reset();

+  }

+

+  MY_UNKNOWN_IMP

+

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

+};

+

+#endif

diff --git a/CPP/7zip/Archive/Common/DummyOutStream.cpp b/CPP/7zip/Archive/Common/DummyOutStream.cpp
new file mode 100755
index 0000000..237e01e
--- /dev/null
+++ b/CPP/7zip/Archive/Common/DummyOutStream.cpp
@@ -0,0 +1,22 @@
+// DummyOutStream.cpp

+

+#include "StdAfx.h"

+

+#include "DummyOutStream.h"

+

+STDMETHODIMP CDummyOutStream::Write(const void *data,  UInt32 size, UInt32 *processedSize)

+{

+  UInt32 realProcessedSize;

+  HRESULT result;

+  if(!_stream)

+  {

+    realProcessedSize = size;

+    result = S_OK;

+  }

+  else

+    result = _stream->Write(data, size, &realProcessedSize);

+  _size += realProcessedSize;

+  if(processedSize != NULL)

+    *processedSize = realProcessedSize;

+  return result;

+}

diff --git a/CPP/7zip/Archive/Common/DummyOutStream.h b/CPP/7zip/Archive/Common/DummyOutStream.h
new file mode 100755
index 0000000..c993bb3
--- /dev/null
+++ b/CPP/7zip/Archive/Common/DummyOutStream.h
@@ -0,0 +1,24 @@
+// DummyOutStream.h

+

+#ifndef __DUMMYOUTSTREAM_H

+#define __DUMMYOUTSTREAM_H

+

+#include "../../IStream.h"

+#include "Common/MyCom.h"

+

+class CDummyOutStream:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  CMyComPtr<ISequentialOutStream> _stream;

+  UInt64 _size;

+public:

+  void SetStream(ISequentialOutStream *outStream) { _stream = outStream; }

+  void ReleaseStream() { _stream.Release(); }

+  void Init() { _size = 0; }

+  MY_UNKNOWN_IMP

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  UInt64 GetSize() const { return _size; }

+};

+

+#endif

diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
new file mode 100755
index 0000000..c2254a7
--- /dev/null
+++ b/CPP/7zip/Archive/Common/HandlerOut.cpp
@@ -0,0 +1,623 @@
+// HandlerOut.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/StringToInt.h"

+

+#include "../../../Windows/PropVariant.h"

+

+#ifndef _7ZIP_ST

+#include "../../../Windows/System.h"

+#endif

+

+#include "../../ICoder.h"

+

+#include "../Common/ParseProperties.h"

+

+#include "HandlerOut.h"

+

+using namespace NWindows;

+

+namespace NArchive {

+

+static const wchar_t *kCopyMethod = L"Copy";

+static const wchar_t *kLZMAMethodName = L"LZMA";

+static const wchar_t *kLZMA2MethodName = L"LZMA2";

+static const wchar_t *kBZip2MethodName = L"BZip2";

+static const wchar_t *kPpmdMethodName = L"PPMd";

+static const wchar_t *kDeflateMethodName = L"Deflate";

+static const wchar_t *kDeflate64MethodName = L"Deflate64";

+

+static const wchar_t *kLzmaMatchFinderX1 = L"HC4";

+static const wchar_t *kLzmaMatchFinderX5 = L"BT4";

+

+static const UInt32 kLzmaAlgoX1 = 0;

+static const UInt32 kLzmaAlgoX5 = 1;

+

+static const UInt32 kLzmaDicSizeX1 = 1 << 16;

+static const UInt32 kLzmaDicSizeX3 = 1 << 20;

+static const UInt32 kLzmaDicSizeX5 = 1 << 24;

+static const UInt32 kLzmaDicSizeX7 = 1 << 25;

+static const UInt32 kLzmaDicSizeX9 = 1 << 26;

+

+static const UInt32 kLzmaFastBytesX1 = 32;

+static const UInt32 kLzmaFastBytesX7 = 64;

+

+static const UInt32 kPpmdMemSizeX1 = (1 << 22);

+static const UInt32 kPpmdMemSizeX5 = (1 << 24);

+static const UInt32 kPpmdMemSizeX7 = (1 << 26);

+static const UInt32 kPpmdMemSizeX9 = (192 << 20);

+

+static const UInt32 kPpmdOrderX1 = 4;

+static const UInt32 kPpmdOrderX5 = 6;

+static const UInt32 kPpmdOrderX7 = 16;

+static const UInt32 kPpmdOrderX9 = 32;

+

+static const UInt32 kDeflateAlgoX1 = 0;

+static const UInt32 kDeflateAlgoX5 = 1;

+

+static const UInt32 kDeflateFastBytesX1 = 32;

+static const UInt32 kDeflateFastBytesX7 = 64;

+static const UInt32 kDeflateFastBytesX9 = 128;

+

+static const UInt32 kDeflatePassesX1 = 1;

+static const UInt32 kDeflatePassesX7 = 3;

+static const UInt32 kDeflatePassesX9 = 10;

+

+static const UInt32 kBZip2NumPassesX1 = 1;

+static const UInt32 kBZip2NumPassesX7 = 2;

+static const UInt32 kBZip2NumPassesX9 = 7;

+

+static const UInt32 kBZip2DicSizeX1 = 100000;

+static const UInt32 kBZip2DicSizeX3 = 500000;

+static const UInt32 kBZip2DicSizeX5 = 900000;

+

+static const wchar_t *kDefaultMethodName = kLZMAMethodName;

+

+static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";

+static const UInt32 kDictionaryForHeaders = 1 << 20;

+static const UInt32 kNumFastBytesForHeaders = 273;

+static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;

+

+static bool AreEqual(const UString &methodName, const wchar_t *s)

+  { return (methodName.CompareNoCase(s) == 0); }

+

+bool COneMethodInfo::IsLzma() const

+{

+  return

+    AreEqual(MethodName, kLZMAMethodName) ||

+    AreEqual(MethodName, kLZMA2MethodName);

+}

+

+static inline bool IsBZip2Method(const UString &methodName)

+  { return AreEqual(methodName, kBZip2MethodName); }

+

+static inline bool IsPpmdMethod(const UString &methodName)

+  { return AreEqual(methodName, kPpmdMethodName); }

+

+static inline bool IsDeflateMethod(const UString &methodName)

+{

+  return

+    AreEqual(methodName, kDeflateMethodName) ||

+    AreEqual(methodName, kDeflate64MethodName);

+}

+

+struct CNameToPropID

+{

+  PROPID PropID;

+  VARTYPE VarType;

+  const wchar_t *Name;

+};

+

+static CNameToPropID g_NameToPropID[] =

+{

+  { NCoderPropID::kBlockSize, VT_UI4, L"C" },

+  { NCoderPropID::kDictionarySize, VT_UI4, L"D" },

+  { NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" },

+

+  { NCoderPropID::kOrder, VT_UI4, L"O" },

+  { NCoderPropID::kPosStateBits, VT_UI4, L"PB" },

+  { NCoderPropID::kLitContextBits, VT_UI4, L"LC" },

+  { NCoderPropID::kLitPosBits, VT_UI4, L"LP" },

+  { NCoderPropID::kEndMarker, VT_BOOL, L"eos" },

+

+  { NCoderPropID::kNumPasses, VT_UI4, L"Pass" },

+  { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },

+  { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },

+  { NCoderPropID::kAlgorithm, VT_UI4, L"a" },

+  { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },

+  { NCoderPropID::kNumThreads, VT_UI4, L"mt" },

+  { NCoderPropID::kDefaultProp, VT_UI4, L"" }

+};

+

+static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)

+{

+  if (varType == srcProp.vt)

+  {

+    destProp = srcProp;

+    return true;

+  }

+  if (varType == VT_UI1)

+  {

+    if (srcProp.vt == VT_UI4)

+    {

+      UInt32 value = srcProp.ulVal;

+      if (value > 0xFF)

+        return false;

+      destProp = (Byte)value;

+      return true;

+    }

+  }

+  else if (varType == VT_BOOL)

+  {

+    bool res;

+    if (SetBoolProperty(res, srcProp) != S_OK)

+      return false;

+    destProp = res;

+    return true;

+  }

+  return false;

+}

+    

+static int FindPropIdExact(const UString &name)

+{

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

+    if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)

+      return i;

+  return -1;

+}

+

+static int FindPropIdStart(const UString &name)

+{

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

+  {

+    UString t = g_NameToPropID[i].Name;

+    if (t.CompareNoCase(name.Left(t.Length())) == 0)

+      return i;

+  }

+  return -1;

+}

+

+static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value)

+{

+  for (int j = 0; j < m.Props.Size(); j++)

+    if (m.Props[j].Id == propID)

+      return;

+  CProp prop;

+  prop.Id = propID;

+  prop.Value = value;

+  m.Props.Add(prop);

+}

+

+void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo

+    #ifndef _7ZIP_ST

+    , UInt32 numThreads

+    #endif

+    )

+{

+  UInt32 level = _level;

+  if (oneMethodInfo.MethodName.IsEmpty())

+    oneMethodInfo.MethodName = kDefaultMethodName;

+  

+  if (oneMethodInfo.IsLzma())

+  {

+    UInt32 dicSize =

+      (level >= 9 ? kLzmaDicSizeX9 :

+      (level >= 7 ? kLzmaDicSizeX7 :

+      (level >= 5 ? kLzmaDicSizeX5 :

+      (level >= 3 ? kLzmaDicSizeX3 :

+                    kLzmaDicSizeX1))));

+    

+    UInt32 algo =

+      (level >= 5 ? kLzmaAlgoX5 :

+                    kLzmaAlgoX1);

+    

+    UInt32 fastBytes =

+      (level >= 7 ? kLzmaFastBytesX7 :

+                    kLzmaFastBytesX1);

+    

+    const wchar_t *matchFinder =

+      (level >= 5 ? kLzmaMatchFinderX5 :

+                    kLzmaMatchFinderX1);

+    

+    SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);

+    SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);

+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);

+    SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);

+    #ifndef _7ZIP_ST

+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);

+    #endif

+  }

+  else if (IsDeflateMethod(oneMethodInfo.MethodName))

+  {

+    UInt32 fastBytes =

+      (level >= 9 ? kDeflateFastBytesX9 :

+      (level >= 7 ? kDeflateFastBytesX7 :

+                    kDeflateFastBytesX1));

+    

+    UInt32 numPasses =

+      (level >= 9 ? kDeflatePassesX9 :

+      (level >= 7 ? kDeflatePassesX7 :

+                    kDeflatePassesX1));

+    

+    UInt32 algo =

+      (level >= 5 ? kDeflateAlgoX5 :

+                    kDeflateAlgoX1);

+    

+    SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);

+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);

+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);

+  }

+  else if (IsBZip2Method(oneMethodInfo.MethodName))

+  {

+    UInt32 numPasses =

+      (level >= 9 ? kBZip2NumPassesX9 :

+      (level >= 7 ? kBZip2NumPassesX7 :

+                    kBZip2NumPassesX1));

+    

+    UInt32 dicSize =

+      (level >= 5 ? kBZip2DicSizeX5 :

+      (level >= 3 ? kBZip2DicSizeX3 :

+                    kBZip2DicSizeX1));

+    

+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);

+    SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);

+    #ifndef _7ZIP_ST

+    SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);

+    #endif

+  }

+  else if (IsPpmdMethod(oneMethodInfo.MethodName))

+  {

+    UInt32 useMemSize =

+      (level >= 9 ? kPpmdMemSizeX9 :

+      (level >= 7 ? kPpmdMemSizeX7 :

+      (level >= 5 ? kPpmdMemSizeX5 :

+                    kPpmdMemSizeX1)));

+    

+    UInt32 order =

+      (level >= 9 ? kPpmdOrderX9 :

+      (level >= 7 ? kPpmdOrderX7 :

+      (level >= 5 ? kPpmdOrderX5 :

+                    kPpmdOrderX1)));

+    

+    SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);

+    SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);

+  }

+}

+

+static void SplitParams(const UString &srcString, UStringVector &subStrings)

+{

+  subStrings.Clear();

+  UString name;

+  int len = srcString.Length();

+  if (len == 0)

+    return;

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

+  {

+    wchar_t c = srcString[i];

+    if (c == L':')

+    {

+      subStrings.Add(name);

+      name.Empty();

+    }

+    else

+      name += c;

+  }

+  subStrings.Add(name);

+}

+

+static void SplitParam(const UString &param, UString &name, UString &value)

+{

+  int eqPos = param.Find(L'=');

+  if (eqPos >= 0)

+  {

+    name = param.Left(eqPos);

+    value = param.Mid(eqPos + 1);

+    return;

+  }

+  for(int i = 0; i < param.Length(); i++)

+  {

+    wchar_t c = param[i];

+    if (c >= L'0' && c <= L'9')

+    {

+      name = param.Left(i);

+      value = param.Mid(i);

+      return;

+    }

+  }

+  name = param;

+}

+

+HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)

+{

+  CProp prop;

+  int index = FindPropIdExact(name);

+  if (index < 0)

+    return E_INVALIDARG;

+  const CNameToPropID &nameToPropID = g_NameToPropID[index];

+  prop.Id = nameToPropID.PropID;

+

+  if (prop.Id == NCoderPropID::kBlockSize ||

+      prop.Id == NCoderPropID::kDictionarySize ||

+      prop.Id == NCoderPropID::kUsedMemorySize)

+  {

+    UInt32 dicSize;

+    RINOK(ParsePropDictionaryValue(value, dicSize));

+    prop.Value = dicSize;

+  }

+  else

+  {

+    NCOM::CPropVariant propValue;

+    

+    if (nameToPropID.VarType == VT_BSTR)

+      propValue = value;

+    else if (nameToPropID.VarType == VT_BOOL)

+    {

+      bool res;

+      if (!StringToBool(value, res))

+        return E_INVALIDARG;

+      propValue = res;

+    }

+    else

+    {

+      UInt32 number;

+      if (ParseStringToUInt32(value, number) == value.Length())

+        propValue = number;

+      else

+        propValue = value;

+    }

+    

+    if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))

+      return E_INVALIDARG;

+  }

+  oneMethodInfo.Props.Add(prop);

+  return S_OK;

+}

+

+HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)

+{

+  UStringVector params;

+  SplitParams(srcString, params);

+  if (params.Size() > 0)

+    oneMethodInfo.MethodName = params[0];

+  for (int i = 1; i < params.Size(); i++)

+  {

+    const UString &param = params[i];

+    UString name, value;

+    SplitParam(param, name, value);

+    RINOK(SetParam(oneMethodInfo, name, value));

+  }

+  return S_OK;

+}

+

+HRESULT COutHandler::SetSolidSettings(const UString &s)

+{

+  UString s2 = s;

+  s2.MakeUpper();

+  for (int i = 0; i < s2.Length();)

+  {

+    const wchar_t *start = ((const wchar_t *)s2) + i;

+    const wchar_t *end;

+    UInt64 v = ConvertStringToUInt64(start, &end);

+    if (start == end)

+    {

+      if (s2[i++] != 'E')

+        return E_INVALIDARG;

+      _solidExtension = true;

+      continue;

+    }

+    i += (int)(end - start);

+    if (i == s2.Length())

+      return E_INVALIDARG;

+    wchar_t c = s2[i++];

+    switch(c)

+    {

+      case 'F':

+        if (v < 1)

+          v = 1;

+        _numSolidFiles = v;

+        break;

+      case 'B':

+        _numSolidBytes = v;

+        _numSolidBytesDefined = true;

+        break;

+      case 'K':

+        _numSolidBytes = (v << 10);

+        _numSolidBytesDefined = true;

+        break;

+      case 'M':

+        _numSolidBytes = (v << 20);

+        _numSolidBytesDefined = true;

+        break;

+      case 'G':

+        _numSolidBytes = (v << 30);

+        _numSolidBytesDefined = true;

+        break;

+      default:

+        return E_INVALIDARG;

+    }

+  }

+  return S_OK;

+}

+

+HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value)

+{

+  bool isSolid;

+  switch(value.vt)

+  {

+    case VT_EMPTY:

+      isSolid = true;

+      break;

+    case VT_BOOL:

+      isSolid = (value.boolVal != VARIANT_FALSE);

+      break;

+    case VT_BSTR:

+      if (StringToBool(value.bstrVal, isSolid))

+        break;

+      return SetSolidSettings(value.bstrVal);

+    default:

+      return E_INVALIDARG;

+  }

+  if (isSolid)

+    InitSolid();

+  else

+    _numSolidFiles = 1;

+  return S_OK;

+}

+

+void COutHandler::Init()

+{

+  _removeSfxBlock = false;

+  _compressHeaders = true;

+  _encryptHeadersSpecified = false;

+  _encryptHeaders = false;

+  

+  WriteCTime = false;

+  WriteATime = false;

+  WriteMTime = true;

+  

+  #ifndef _7ZIP_ST

+  _numThreads = NSystem::GetNumberOfProcessors();

+  #endif

+  

+  _level = 5;

+  _autoFilter = true;

+  _volumeMode = false;

+  _crcSize = 4;

+  InitSolid();

+}

+

+void COutHandler::BeforeSetProperty()

+{

+  Init();

+  #ifndef _7ZIP_ST

+  numProcessors = NSystem::GetNumberOfProcessors();

+  #endif

+

+  mainDicSize = 0xFFFFFFFF;

+  mainDicMethodIndex = 0xFFFFFFFF;

+  minNumber = 0;

+  _crcSize = 4;

+}

+

+HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)

+{

+  UString name = nameSpec;

+  name.MakeUpper();

+  if (name.IsEmpty())

+    return E_INVALIDARG;

+  

+  if (name[0] == 'X')

+  {

+    name.Delete(0);

+    _level = 9;

+    return ParsePropValue(name, value, _level);

+  }

+  

+  if (name[0] == L'S')

+  {

+    name.Delete(0);

+    if (name.IsEmpty())

+      return SetSolidSettings(value);

+    if (value.vt != VT_EMPTY)

+      return E_INVALIDARG;

+    return SetSolidSettings(name);

+  }

+  

+  if (name == L"CRC")

+  {

+    _crcSize = 4;

+    name.Delete(0, 3);

+    return ParsePropValue(name, value, _crcSize);

+  }

+  

+  UInt32 number;

+  int index = ParseStringToUInt32(name, number);

+  UString realName = name.Mid(index);

+  if (index == 0)

+  {

+    if(name.Left(2).CompareNoCase(L"MT") == 0)

+    {

+      #ifndef _7ZIP_ST

+      RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));

+      #endif

+      return S_OK;

+    }

+    if (name.CompareNoCase(L"RSFX") == 0)  return SetBoolProperty(_removeSfxBlock, value);

+    if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value);

+    if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value);

+    if (name.CompareNoCase(L"HCF") == 0)

+    {

+      bool compressHeadersFull = true;

+      RINOK(SetBoolProperty(compressHeadersFull, value));

+      if (!compressHeadersFull)

+        return E_INVALIDARG;

+      return S_OK;

+    }

+    if (name.CompareNoCase(L"HE") == 0)

+    {

+      RINOK(SetBoolProperty(_encryptHeaders, value));

+      _encryptHeadersSpecified = true;

+      return S_OK;

+    }

+    if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value);

+    if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value);

+    if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value);

+    if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value);

+    number = 0;

+  }

+  if (number > 10000)

+    return E_FAIL;

+  if (number < minNumber)

+    return E_INVALIDARG;

+  number -= minNumber;

+  for(int j = _methods.Size(); j <= (int)number; j++)

+  {

+    COneMethodInfo oneMethodInfo;

+    _methods.Add(oneMethodInfo);

+  }

+  

+  COneMethodInfo &oneMethodInfo = _methods[number];

+  

+  if (realName.Length() == 0)

+  {

+    if (value.vt != VT_BSTR)

+      return E_INVALIDARG;

+    

+    RINOK(SetParams(oneMethodInfo, value.bstrVal));

+  }

+  else

+  {

+    int index = FindPropIdStart(realName);

+    if (index < 0)

+      return E_INVALIDARG;

+    const CNameToPropID &nameToPropID = g_NameToPropID[index];

+    CProp prop;

+    prop.Id = nameToPropID.PropID;

+

+    if (prop.Id == NCoderPropID::kBlockSize ||

+        prop.Id == NCoderPropID::kDictionarySize ||

+        prop.Id == NCoderPropID::kUsedMemorySize)

+    {

+      UInt32 dicSize;

+      RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize));

+      prop.Value = dicSize;

+      if (number <= mainDicMethodIndex)

+        mainDicSize = dicSize;

+    }

+    else

+    {

+      int index = FindPropIdExact(realName);

+      if (index < 0)

+        return E_INVALIDARG;

+      const CNameToPropID &nameToPropID = g_NameToPropID[index];

+      prop.Id = nameToPropID.PropID;

+      if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))

+        return E_INVALIDARG;

+    }

+    oneMethodInfo.Props.Add(prop);

+  }

+  return S_OK;

+}

+

+}

diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h
new file mode 100755
index 0000000..c4ccf37
--- /dev/null
+++ b/CPP/7zip/Archive/Common/HandlerOut.h
@@ -0,0 +1,87 @@
+// HandlerOut.h

+

+#ifndef __HANDLER_OUT_H

+#define __HANDLER_OUT_H

+

+#include "../../../Common/MyString.h"

+#include "../../Common/MethodProps.h"

+

+namespace NArchive {

+

+struct COneMethodInfo

+{

+  CObjectVector<CProp> Props;

+  UString MethodName;

+

+  bool IsLzma() const;

+};

+

+class COutHandler

+{

+public:

+  HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);

+  

+  HRESULT SetSolidSettings(const UString &s);

+  HRESULT SetSolidSettings(const PROPVARIANT &value);

+

+  #ifndef _7ZIP_ST

+  UInt32 _numThreads;

+  #endif

+

+  UInt32 _crcSize;

+

+  CObjectVector<COneMethodInfo> _methods;

+  bool _removeSfxBlock;

+  

+  UInt64 _numSolidFiles;

+  UInt64 _numSolidBytes;

+  bool _numSolidBytesDefined;

+  bool _solidExtension;

+

+  bool _compressHeaders;

+  bool _encryptHeadersSpecified;

+  bool _encryptHeaders;

+

+  bool WriteCTime;

+  bool WriteATime;

+  bool WriteMTime;

+

+  bool _autoFilter;

+  UInt32 _level;

+

+  bool _volumeMode;

+

+  HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value);

+  HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString);

+

+  void SetCompressionMethod2(COneMethodInfo &oneMethodInfo

+      #ifndef _7ZIP_ST

+      , UInt32 numThreads

+      #endif

+      );

+

+  void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }

+  void InitSolidSize()  { _numSolidBytes = (UInt64)(Int64)(-1); }

+  void InitSolid()

+  {

+    InitSolidFiles();

+    InitSolidSize();

+    _solidExtension = false;

+    _numSolidBytesDefined = false;

+  }

+

+  void Init();

+

+  COutHandler() { Init(); }

+

+  void BeforeSetProperty();

+

+  UInt32 minNumber;

+  UInt32 numProcessors;

+  UInt32 mainDicSize;

+  UInt32 mainDicMethodIndex;

+};

+

+}

+

+#endif

diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
new file mode 100755
index 0000000..6338d0a
--- /dev/null
+++ b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
@@ -0,0 +1,42 @@
+// InStreamWithCRC.cpp

+

+#include "StdAfx.h"

+

+#include "InStreamWithCRC.h"

+

+STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  UInt32 realProcessedSize;

+  HRESULT result = _stream->Read(data, size, &realProcessedSize);

+  _size += realProcessedSize;

+  if (size > 0 && realProcessedSize == 0)

+    _wasFinished = true;

+  _crc = CrcUpdate(_crc, data, realProcessedSize);

+  if(processedSize != NULL)

+    *processedSize = realProcessedSize;

+  return result;

+}

+

+STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  UInt32 realProcessedSize;

+  HRESULT result = _stream->Read(data, size, &realProcessedSize);

+  /*

+  if (size > 0 && realProcessedSize == 0)

+    _wasFinished = true;

+  */

+  _size += realProcessedSize;

+  _crc = CrcUpdate(_crc, data, realProcessedSize);

+  if(processedSize != NULL)

+    *processedSize = realProcessedSize;

+  return result;

+}

+

+STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  if (seekOrigin != STREAM_SEEK_SET || offset != 0)

+    return E_FAIL;

+  _size = 0;

+  _crc = CRC_INIT_VAL;

+  return _stream->Seek(offset, seekOrigin, newPosition);

+}

diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.h b/CPP/7zip/Archive/Common/InStreamWithCRC.h
new file mode 100755
index 0000000..1a4b2c9
--- /dev/null
+++ b/CPP/7zip/Archive/Common/InStreamWithCRC.h
@@ -0,0 +1,67 @@
+// InStreamWithCRC.h

+

+#ifndef __IN_STREAM_WITH_CRC_H

+#define __IN_STREAM_WITH_CRC_H

+

+#include "../../../../C/7zCrc.h"

+

+#include "../../../Common/MyCom.h"

+

+#include "../../IStream.h"

+

+class CSequentialInStreamWithCRC:

+  public ISequentialInStream,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+private:

+  CMyComPtr<ISequentialInStream> _stream;

+  UInt64 _size;

+  UInt32 _crc;

+  bool _wasFinished;

+public:

+  void SetStream(ISequentialInStream *stream) { _stream = stream;  }

+  void Init()

+  {

+    _size = 0;

+    _wasFinished = false;

+    _crc = CRC_INIT_VAL;

+  }

+  void ReleaseStream() { _stream.Release(); }

+  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }

+  UInt64 GetSize() const { return _size; }

+  bool WasFinished() const { return _wasFinished; }

+};

+

+class CInStreamWithCRC:

+  public IInStream,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP1(IInStream)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+private:

+  CMyComPtr<IInStream> _stream;

+  UInt64 _size;

+  UInt32 _crc;

+  // bool _wasFinished;

+public:

+  void SetStream(IInStream *stream) { _stream = stream;  }

+  void Init()

+  {

+    _size = 0;

+    // _wasFinished = false;

+    _crc = CRC_INIT_VAL;

+  }

+  void ReleaseStream() { _stream.Release(); }

+  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }

+  UInt64 GetSize() const { return _size; }

+  // bool WasFinished() const { return _wasFinished; }

+};

+

+#endif

diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
new file mode 100755
index 0000000..287ddce
--- /dev/null
+++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
@@ -0,0 +1,61 @@
+// Archive/Common/ItemNameUtils.cpp

+

+#include "StdAfx.h"

+

+#include "../../../../C/Types.h"

+

+#include "ItemNameUtils.h"

+

+namespace NArchive {

+namespace NItemName {

+

+static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR;

+static const wchar_t kDirDelimiter = L'/';

+

+UString MakeLegalName(const UString &name)

+{

+  UString zipName = name;

+  zipName.Replace(kOSDirDelimiter, kDirDelimiter);

+  return zipName;

+}

+

+UString GetOSName(const UString &name)

+{

+  UString newName = name;

+  newName.Replace(kDirDelimiter, kOSDirDelimiter);

+  return newName;

+}

+

+UString GetOSName2(const UString &name)

+{

+  if (name.IsEmpty())

+    return UString();

+  UString newName = GetOSName(name);

+  if (newName[newName.Length() - 1] == kOSDirDelimiter)

+    newName.Delete(newName.Length() - 1);

+  return newName;

+}

+

+bool HasTailSlash(const AString &name, UINT codePage)

+{

+  if (name.IsEmpty())

+    return false;

+  LPCSTR prev =

+  #if defined(_WIN32) && !defined(UNDER_CE)

+    CharPrevExA((WORD)codePage, name, &name[name.Length()], 0);

+  #else

+    (LPCSTR)(name) + (name.Length() - 1);

+  #endif

+  return (*prev == '/');

+}

+

+#ifndef _WIN32

+UString WinNameToOSName(const UString &name)

+{

+  UString newName = name;

+  newName.Replace(L'\\', kOSDirDelimiter);

+  return newName;

+}

+#endif

+

+}}

diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h
new file mode 100755
index 0000000..8b91d1c
--- /dev/null
+++ b/CPP/7zip/Archive/Common/ItemNameUtils.h
@@ -0,0 +1,24 @@
+// Archive/Common/ItemNameUtils.h

+

+#ifndef __ARCHIVE_ITEMNAMEUTILS_H

+#define __ARCHIVE_ITEMNAMEUTILS_H

+

+#include "../../../Common/MyString.h"

+

+namespace NArchive {

+namespace NItemName {

+

+  UString MakeLegalName(const UString &name);

+  UString GetOSName(const UString &name);

+  UString GetOSName2(const UString &name);

+  bool HasTailSlash(const AString &name, UINT codePage);

+

+  #ifdef _WIN32

+  inline UString WinNameToOSName(const UString &name)  { return name; }

+  #else

+  UString WinNameToOSName(const UString &name);

+  #endif

+

+}}

+

+#endif

diff --git a/CPP/7zip/Archive/Common/MultiStream.cpp b/CPP/7zip/Archive/Common/MultiStream.cpp
new file mode 100755
index 0000000..83b3da1
--- /dev/null
+++ b/CPP/7zip/Archive/Common/MultiStream.cpp
@@ -0,0 +1,190 @@
+// MultiStream.cpp

+

+#include "StdAfx.h"

+

+#include "MultiStream.h"

+

+STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+  if (size == 0)

+    return S_OK;

+  if (_pos >= _totalLength)

+    return (_pos == _totalLength) ? S_OK : E_FAIL;

+

+  {

+    int left = 0, mid = _streamIndex, right = Streams.Size();

+    for (;;)

+    {

+      CSubStreamInfo &m = Streams[mid];

+      if (_pos < m.GlobalOffset)

+        right = mid;

+      else if (_pos >= m.GlobalOffset + m.Size)

+        left = mid + 1;

+      else

+      {

+        _streamIndex = mid;

+        break;

+      }

+      mid = (left + right) / 2;

+    }

+    _streamIndex = mid;

+  }

+  

+  CSubStreamInfo &s = Streams[_streamIndex];

+  UInt64 localPos = _pos - s.GlobalOffset;

+  if (localPos != s.LocalPos)

+  {

+    RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos));

+  }

+  UInt64 rem = s.Size - localPos;

+  if (size > rem)

+    size = (UInt32)rem;

+  HRESULT result = s.Stream->Read(data, size, &size);

+  _pos += size;

+  s.LocalPos += size;

+  if (processedSize)

+    *processedSize = size;

+  return result;

+}

+  

+STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  switch(seekOrigin)

+  {

+    case STREAM_SEEK_SET: _pos = offset; break;

+    case STREAM_SEEK_CUR: _pos = _pos + offset; break;

+    case STREAM_SEEK_END: _pos = _totalLength + offset; break;

+    default: return STG_E_INVALIDFUNCTION;

+  }

+  if (newPosition != 0)

+    *newPosition = _pos;

+  return S_OK;

+}

+

+

+/*

+class COutVolumeStream:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  int _volIndex;

+  UInt64 _volSize;

+  UInt64 _curPos;

+  CMyComPtr<ISequentialOutStream> _volumeStream;

+  COutArchive _archive;

+  CCRC _crc;

+

+public:

+  MY_UNKNOWN_IMP

+

+  CFileItem _file;

+  CUpdateOptions _options;

+  CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;

+  void Init(IArchiveUpdateCallback2 *volumeCallback,

+      const UString &name)

+  {

+    _file.Name = name;

+    _file.IsStartPosDefined = true;

+    _file.StartPos = 0;

+    

+    VolumeCallback = volumeCallback;

+    _volIndex = 0;

+    _volSize = 0;

+  }

+  

+  HRESULT Flush();

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+HRESULT COutVolumeStream::Flush()

+{

+  if (_volumeStream)

+  {

+    _file.UnPackSize = _curPos;

+    _file.FileCRC = _crc.GetDigest();

+    RINOK(WriteVolumeHeader(_archive, _file, _options));

+    _archive.Close();

+    _volumeStream.Release();

+    _file.StartPos += _file.UnPackSize;

+  }

+  return S_OK;

+}

+*/

+

+/*

+STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  if(processedSize != NULL)

+    *processedSize = 0;

+  while(size > 0)

+  {

+    if (_streamIndex >= Streams.Size())

+    {

+      CSubStreamInfo subStream;

+      RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));

+      RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));

+      subStream.Pos = 0;

+      Streams.Add(subStream);

+      continue;

+    }

+    CSubStreamInfo &subStream = Streams[_streamIndex];

+    if (_offsetPos >= subStream.Size)

+    {

+      _offsetPos -= subStream.Size;

+      _streamIndex++;

+      continue;

+    }

+    if (_offsetPos != subStream.Pos)

+    {

+      CMyComPtr<IOutStream> outStream;

+      RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));

+      RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));

+      subStream.Pos = _offsetPos;

+    }

+

+    UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);

+    UInt32 realProcessed;

+    RINOK(subStream.Stream->Write(data, curSize, &realProcessed));

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

+    size -= realProcessed;

+    subStream.Pos += realProcessed;

+    _offsetPos += realProcessed;

+    _absPos += realProcessed;

+    if (_absPos > _length)

+      _length = _absPos;

+    if(processedSize != NULL)

+      *processedSize += realProcessed;

+    if (subStream.Pos == subStream.Size)

+    {

+      _streamIndex++;

+      _offsetPos = 0;

+    }

+    if (realProcessed != curSize && realProcessed == 0)

+      return E_FAIL;

+  }

+  return S_OK;

+}

+

+STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  if(seekOrigin >= 3)

+    return STG_E_INVALIDFUNCTION;

+  switch(seekOrigin)

+  {

+    case STREAM_SEEK_SET:

+      _absPos = offset;

+      break;

+    case STREAM_SEEK_CUR:

+      _absPos += offset;

+      break;

+    case STREAM_SEEK_END:

+      _absPos = _length + offset;

+      break;

+  }

+  _offsetPos = _absPos;

+  _streamIndex = 0;

+  return S_OK;

+}

+*/

diff --git a/CPP/7zip/Archive/Common/MultiStream.h b/CPP/7zip/Archive/Common/MultiStream.h
new file mode 100755
index 0000000..74ec6ad
--- /dev/null
+++ b/CPP/7zip/Archive/Common/MultiStream.h
@@ -0,0 +1,84 @@
+// MultiStream.h

+

+#ifndef __MULTI_STREAM_H

+#define __MULTI_STREAM_H

+

+#include "../../../Common/MyCom.h"

+#include "../../../Common/MyVector.h"

+

+#include "../../IStream.h"

+

+class CMultiStream:

+  public IInStream,

+  public CMyUnknownImp

+{

+  UInt64 _pos;

+  UInt64 _totalLength;

+  int _streamIndex;

+public:

+  struct CSubStreamInfo

+  {

+    CMyComPtr<IInStream> Stream;

+    UInt64 Size;

+    UInt64 GlobalOffset;

+    UInt64 LocalPos;

+  };

+  CObjectVector<CSubStreamInfo> Streams;

+  

+  HRESULT Init()

+  {

+    UInt64 total = 0;

+    for (int i = 0; i < Streams.Size(); i++)

+    {

+      CSubStreamInfo &s = Streams[i];

+      s.GlobalOffset = total;

+      total += Streams[i].Size;

+      RINOK(s.Stream->Seek(0, STREAM_SEEK_CUR, &s.LocalPos));

+    }

+    _totalLength = total;

+    _pos = 0;

+    _streamIndex = 0;

+    return S_OK;

+  }

+

+  MY_UNKNOWN_IMP1(IInStream)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+};

+

+/*

+class COutMultiStream:

+  public IOutStream,

+  public CMyUnknownImp

+{

+  int _streamIndex; // required stream

+  UInt64 _offsetPos; // offset from start of _streamIndex index

+  UInt64 _absPos;

+  UInt64 _length;

+

+  struct CSubStreamInfo

+  {

+    CMyComPtr<ISequentialOutStream> Stream;

+    UInt64 Size;

+    UInt64 Pos;

+ };

+  CObjectVector<CSubStreamInfo> Streams;

+public:

+  CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;

+  void Init()

+  {

+    _streamIndex = 0;

+    _offsetPos = 0;

+    _absPos = 0;

+    _length = 0;

+  }

+

+  MY_UNKNOWN_IMP1(IOutStream)

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+};

+*/

+

+#endif

diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
new file mode 100755
index 0000000..e0d3894
--- /dev/null
+++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
@@ -0,0 +1,18 @@
+// OutStreamWithCRC.cpp

+

+#include "StdAfx.h"

+

+#include "OutStreamWithCRC.h"

+

+STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  HRESULT result = S_OK;

+  if (_stream)

+    result = _stream->Write(data, size, &size);

+  if (_calculate)

+    _crc = CrcUpdate(_crc, data, size);

+  _size += size;

+  if (processedSize != NULL)

+    *processedSize = size;

+  return result;

+}

diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h
new file mode 100755
index 0000000..d9eb646
--- /dev/null
+++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.h
@@ -0,0 +1,36 @@
+// OutStreamWithCRC.h

+

+#ifndef __OUT_STREAM_WITH_CRC_H

+#define __OUT_STREAM_WITH_CRC_H

+

+#include "../../../../C/7zCrc.h"

+

+#include "../../../Common/MyCom.h"

+

+#include "../../IStream.h"

+

+class COutStreamWithCRC:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  CMyComPtr<ISequentialOutStream> _stream;

+  UInt64 _size;

+  UInt32 _crc;

+  bool _calculate;

+public:

+  MY_UNKNOWN_IMP

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }

+  void ReleaseStream() { _stream.Release(); }

+  void Init(bool calculate = true)

+  {

+    _size = 0;

+    _calculate = calculate;

+    _crc = CRC_INIT_VAL;

+  }

+  void InitCRC() { _crc = CRC_INIT_VAL; }

+  UInt64 GetSize() const { return _size; }

+  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }

+};

+

+#endif

diff --git a/CPP/7zip/Archive/Common/ParseProperties.cpp b/CPP/7zip/Archive/Common/ParseProperties.cpp
new file mode 100755
index 0000000..5550a23
--- /dev/null
+++ b/CPP/7zip/Archive/Common/ParseProperties.cpp
@@ -0,0 +1,177 @@
+// ParseProperties.cpp

+

+#include "StdAfx.h"

+

+#include "ParseProperties.h"

+

+#include "Common/StringToInt.h"

+#include "Common/MyCom.h"

+

+HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)

+{

+  if (prop.vt == VT_UI4)

+  {

+    if (!name.IsEmpty())

+      return E_INVALIDARG;

+    resValue = prop.ulVal;

+  }

+  else if (prop.vt == VT_EMPTY)

+  {

+    if(!name.IsEmpty())

+    {

+      const wchar_t *start = name;

+      const wchar_t *end;

+      UInt64 v = ConvertStringToUInt64(start, &end);

+      if (end - start != name.Length())

+        return E_INVALIDARG;

+      resValue = (UInt32)v;

+    }

+  }

+  else

+    return E_INVALIDARG;

+  return S_OK;

+}

+

+static const int kLogarithmicSizeLimit = 32;

+static const wchar_t kByteSymbol = L'B';

+static const wchar_t kKiloByteSymbol = L'K';

+static const wchar_t kMegaByteSymbol = L'M';

+

+HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize)

+{

+  UString srcString = srcStringSpec;

+  srcString.MakeUpper();

+

+  const wchar_t *start = srcString;

+  const wchar_t *end;

+  UInt64 number = ConvertStringToUInt64(start, &end);

+  int numDigits = (int)(end - start);

+  if (numDigits == 0 || srcString.Length() > numDigits + 1)

+    return E_INVALIDARG;

+  if (srcString.Length() == numDigits)

+  {

+    if (number >= kLogarithmicSizeLimit)

+      return E_INVALIDARG;

+    dicSize = (UInt32)1 << (int)number;

+    return S_OK;

+  }

+  switch (srcString[numDigits])

+  {

+    case kByteSymbol:

+      if (number >= ((UInt64)1 << kLogarithmicSizeLimit))

+        return E_INVALIDARG;

+      dicSize = (UInt32)number;

+      break;

+    case kKiloByteSymbol:

+      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))

+        return E_INVALIDARG;

+      dicSize = (UInt32)(number << 10);

+      break;

+    case kMegaByteSymbol:

+      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))

+        return E_INVALIDARG;

+      dicSize = (UInt32)(number << 20);

+      break;

+    default:

+      return E_INVALIDARG;

+  }

+  return S_OK;

+}

+

+HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)

+{

+  if (name.IsEmpty())

+  {

+    if (prop.vt == VT_UI4)

+    {

+      UInt32 logDicSize = prop.ulVal;

+      if (logDicSize >= 32)

+        return E_INVALIDARG;

+      resValue = (UInt32)1 << logDicSize;

+      return S_OK;

+    }

+    if (prop.vt == VT_BSTR)

+      return ParsePropDictionaryValue(prop.bstrVal, resValue);

+    return E_INVALIDARG;

+  }

+  return ParsePropDictionaryValue(name, resValue);

+}

+

+bool StringToBool(const UString &s, bool &res)

+{

+  if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0)

+  {

+    res = true;

+    return true;

+  }

+  if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0)

+  {

+    res = false;

+    return true;

+  }

+  return false;

+}

+

+HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)

+{

+  switch(value.vt)

+  {

+    case VT_EMPTY:

+      dest = true;

+      return S_OK;

+    case VT_BOOL:

+      dest = (value.boolVal != VARIANT_FALSE);

+      return S_OK;

+    /*

+    case VT_UI4:

+      dest = (value.ulVal != 0);

+      break;

+    */

+    case VT_BSTR:

+      return StringToBool(value.bstrVal, dest) ?  S_OK : E_INVALIDARG;

+  }

+  return E_INVALIDARG;

+}

+

+int ParseStringToUInt32(const UString &srcString, UInt32 &number)

+{

+  const wchar_t *start = srcString;

+  const wchar_t *end;

+  UInt64 number64 = ConvertStringToUInt64(start, &end);

+  if (number64 > 0xFFFFFFFF)

+  {

+    number = 0;

+    return 0;

+  }

+  number = (UInt32)number64;

+  return (int)(end - start);

+}

+

+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)

+{

+  if (name.IsEmpty())

+  {

+    switch(prop.vt)

+    {

+      case VT_UI4:

+        numThreads = prop.ulVal;

+        break;

+      default:

+      {

+        bool val;

+        RINOK(SetBoolProperty(val, prop));

+        numThreads = (val ? defaultNumThreads : 1);

+        break;

+      }

+    }

+  }

+  else

+  {

+    UInt32 number;

+    int index = ParseStringToUInt32(name, number);

+    if (index != name.Length())

+      return E_INVALIDARG;

+    numThreads = number;

+  }

+  return S_OK;

+}

diff --git a/CPP/7zip/Archive/Common/ParseProperties.h b/CPP/7zip/Archive/Common/ParseProperties.h
new file mode 100755
index 0000000..c64fc1e
--- /dev/null
+++ b/CPP/7zip/Archive/Common/ParseProperties.h
@@ -0,0 +1,18 @@
+// ParseProperties.h

+

+#ifndef __PARSEPROPERTIES_H

+#define __PARSEPROPERTIES_H

+

+#include "Common/MyString.h"

+#include "Common/Types.h"

+

+HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);

+HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize);

+HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);

+

+bool StringToBool(const UString &s, bool &res);

+HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value);

+int ParseStringToUInt32(const UString &srcString, UInt32 &number);

+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);

+

+#endif

diff --git a/CPP/7zip/Archive/Common/StdAfx.h b/CPP/7zip/Archive/Common/StdAfx.h
new file mode 100755
index 0000000..a4e6173
--- /dev/null
+++ b/CPP/7zip/Archive/Common/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../../Common/MyWindows.h"

+#include "../../../Common/NewHandler.h"

+

+#endif

diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp
new file mode 100755
index 0000000..a45b5c9
--- /dev/null
+++ b/CPP/7zip/Archive/DllExports2.cpp
@@ -0,0 +1,74 @@
+// DLLExports.cpp

+

+#include "StdAfx.h"

+

+#include "../../Common/MyInitGuid.h"

+

+#if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)

+#include "../../../C/Alloc.h"

+#endif

+

+#include "../../Common/ComTry.h"

+

+#include "../../Windows/NtCheck.h"

+#include "../../Windows/PropVariant.h"

+

+#include "../ICoder.h"

+#include "../IPassword.h"

+

+#include "IArchive.h"

+

+HINSTANCE g_hInstance;

+

+#define NT_CHECK_FAIL_ACTION return FALSE;

+

+extern "C"

+BOOL WINAPI DllMain(

+  #ifdef UNDER_CE

+  HANDLE

+  #else

+  HINSTANCE

+  #endif

+  hInstance, DWORD dwReason, LPVOID /*lpReserved*/)

+{

+  if (dwReason == DLL_PROCESS_ATTACH)

+  {

+    g_hInstance = (HINSTANCE)hInstance;

+    NT_CHECK;

+  }

+  return TRUE;

+}

+

+DEFINE_GUID(CLSID_CArchiveHandler,

+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);

+

+static const UInt16 kDecodeId = 0x2790;

+

+DEFINE_GUID(CLSID_CCodec,

+0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);

+

+STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);

+STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);

+

+STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)

+{

+  // COM_TRY_BEGIN

+  *outObject = 0;

+  if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter)

+  {

+    return CreateCoder(clsid, iid, outObject);

+  }

+  else

+  {

+    return CreateArchiver(clsid, iid, outObject);

+  }

+  // COM_TRY_END

+}

+

+STDAPI SetLargePageMode()

+{

+  #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)

+  SetLargePageSize();

+  #endif

+  return S_OK;

+}

diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h
new file mode 100755
index 0000000..e4101cc
--- /dev/null
+++ b/CPP/7zip/Archive/IArchive.h
@@ -0,0 +1,234 @@
+// IArchive.h

+

+#ifndef __IARCHIVE_H

+#define __IARCHIVE_H

+

+#include "../IProgress.h"

+#include "../IStream.h"

+#include "../PropID.h"

+

+#define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x)

+#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x)

+

+namespace NFileTimeType

+{

+  enum EEnum

+  {

+    kWindows,

+    kUnix,

+    kDOS

+  };

+}

+

+namespace NArchive

+{

+  enum

+  {

+    kName = 0,

+    kClassID,

+    kExtension,

+    kAddExtension,

+    kUpdate,

+    kKeepName,

+    kStartSignature,

+    kFinishSignature,

+    kAssociate

+  };

+

+  namespace NExtract

+  {

+    namespace NAskMode

+    {

+      enum

+      {

+        kExtract = 0,

+        kTest,

+        kSkip

+      };

+    }

+    namespace NOperationResult

+    {

+      enum

+      {

+        kOK = 0,

+        kUnSupportedMethod,

+        kDataError,

+        kCRCError

+      };

+    }

+  }

+  namespace NUpdate

+  {

+    namespace NOperationResult

+    {

+      enum

+      {

+        kOK = 0,

+        kError

+      };

+    }

+  }

+}

+

+#define INTERFACE_IArchiveOpenCallback(x) \

+  STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \

+  STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \

+

+ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)

+{

+  INTERFACE_IArchiveOpenCallback(PURE);

+};

+

+

+#define INTERFACE_IArchiveExtractCallback(x) \

+  INTERFACE_IProgress(x) \

+  STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream,  Int32 askExtractMode) x; \

+  STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \

+  STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \

+

+ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)

+{

+  INTERFACE_IArchiveExtractCallback(PURE)

+};

+

+

+#define INTERFACE_IArchiveOpenVolumeCallback(x) \

+  STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \

+  STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \

+

+ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30)

+{

+  INTERFACE_IArchiveOpenVolumeCallback(PURE);

+};

+

+

+ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40)

+{

+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;

+};

+

+

+ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50)

+{

+  STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;

+};

+

+

+/*

+IInArchive::Extract:

+  indices must be sorted

+  numItems = 0xFFFFFFFF means "all files"

+  testMode != 0 means "test files without writing to outStream"

+*/

+

+#define INTERFACE_IInArchive(x) \

+  STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \

+  STDMETHOD(Close)() x; \

+  STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \

+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \

+  STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \

+  STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \

+  STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \

+  STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \

+  STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \

+  STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x;

+

+ARCHIVE_INTERFACE(IInArchive, 0x60)

+{

+  INTERFACE_IInArchive(PURE)

+};

+

+ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61)

+{

+  STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE;

+};

+

+#define INTERFACE_IArchiveUpdateCallback(x) \

+  INTERFACE_IProgress(x); \

+  STDMETHOD(GetUpdateItemInfo)(UInt32 index,  \

+      Int32 *newData, /*1 - new data, 0 - old data */ \

+      Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \

+      UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \

+      )  x; \

+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \

+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \

+  STDMETHOD(SetOperationResult)(Int32 operationResult) x; \

+

+ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80)

+{

+  INTERFACE_IArchiveUpdateCallback(PURE);

+};

+

+#define INTERFACE_IArchiveUpdateCallback2(x) \

+  INTERFACE_IArchiveUpdateCallback(x) \

+  STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \

+  STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \

+

+ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)

+{

+  INTERFACE_IArchiveUpdateCallback2(PURE);

+};

+

+

+#define INTERFACE_IOutArchive(x) \

+  STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \

+  STDMETHOD(GetFileTimeType)(UInt32 *type) x;

+

+ARCHIVE_INTERFACE(IOutArchive, 0xA0)

+{

+  INTERFACE_IOutArchive(PURE)

+};

+

+

+ARCHIVE_INTERFACE(ISetProperties, 0x03)

+{

+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE;

+};

+

+

+#define IMP_IInArchive_GetProp(k) \

+  (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \

+    { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \

+    const STATPROPSTG &srcItem = k[index]; \

+    *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \

+

+#define IMP_IInArchive_GetProp_WITH_NAME(k) \

+  (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \

+    { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \

+    const STATPROPSTG &srcItem = k[index]; \

+    *propID = srcItem.propid; *varType = srcItem.vt; \

+    if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \

+

+#define IMP_IInArchive_Props \

+  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \

+    { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \

+  STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps)

+

+#define IMP_IInArchive_Props_WITH_NAME \

+  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \

+    { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \

+  STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps)

+

+

+#define IMP_IInArchive_ArcProps \

+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \

+    { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \

+  STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps)

+

+#define IMP_IInArchive_ArcProps_WITH_NAME \

+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \

+    { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \

+  STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps)

+

+#define IMP_IInArchive_ArcProps_NO_Table \

+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \

+    { *numProperties = 0; return S_OK; } \

+  STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \

+    { return E_NOTIMPL; } \

+

+#define IMP_IInArchive_ArcProps_NO \

+  IMP_IInArchive_ArcProps_NO_Table \

+  STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \

+    { value->vt = VT_EMPTY; return S_OK; }

+

+#endif

diff --git a/CPP/7zip/Archive/Icons/7z.ico b/CPP/7zip/Archive/Icons/7z.ico
new file mode 100755
index 0000000..319753a
--- /dev/null
+++ b/CPP/7zip/Archive/Icons/7z.ico
Binary files differ
diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp
new file mode 100755
index 0000000..9b8db45
--- /dev/null
+++ b/CPP/7zip/Archive/LzmaHandler.cpp
@@ -0,0 +1,430 @@
+// LzmaHandler.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/CpuArch.h"

+

+#include "Common/ComTry.h"

+#include "Common/IntToString.h"

+

+#include "Windows/PropVariant.h"

+

+#include "../Common/CreateCoder.h"

+#include "../Common/ProgressUtils.h"

+#include "../Common/RegisterArc.h"

+#include "../Common/StreamUtils.h"

+

+#include "../Compress/LzmaDecoder.h"

+

+#include "Common/DummyOutStream.h"

+

+using namespace NWindows;

+

+namespace NArchive {

+namespace NLzma {

+

+static bool CheckDicSize(const Byte *p)

+{

+  UInt32 dicSize = GetUi32(p);

+  for (int i = 1; i <= 30; i++)

+    if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i))

+      return true;

+  return (dicSize == 0xFFFFFFFF);

+}

+

+STATPROPSTG kProps[] =

+{

+  { NULL, kpidSize, VT_UI8},

+  { NULL, kpidPackSize, VT_UI8},

+  { NULL, kpidMethod, VT_BSTR}

+};

+

+struct CHeader

+{

+  UInt64 Size;

+  Byte FilterID;

+  Byte LzmaProps[5];

+

+  UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); }

+  bool HasSize() const { return (Size != (UInt64)(Int64)-1); }

+  bool Parse(const Byte *buf, bool isThereFilter);

+};

+

+bool CHeader::Parse(const Byte *buf, bool isThereFilter)

+{

+  FilterID = 0;

+  if (isThereFilter)

+    FilterID = buf[0];

+  const Byte *sig = buf + (isThereFilter ? 1 : 0);

+  for (int i = 0; i < 5; i++)

+    LzmaProps[i] = sig[i];

+  Size = GetUi64(sig + 5);

+  return

+    LzmaProps[0] < 5 * 5 * 9 &&

+    FilterID < 2 &&

+    (!HasSize() || Size < ((UInt64)1 << 56)) &&

+    CheckDicSize(LzmaProps + 1);

+}

+

+class CDecoder

+{

+  NCompress::NLzma::CDecoder *_lzmaDecoderSpec;

+  CMyComPtr<ICompressCoder> _lzmaDecoder;

+  CMyComPtr<ISequentialOutStream> _bcjStream;

+public:

+  ~CDecoder();

+  HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS

+      bool filtered, ISequentialInStream *inStream);

+

+  HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);

+

+  UInt64 GetInputProcessedSize() const { return _lzmaDecoderSpec->GetInputProcessedSize(); }

+

+  void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoderSpec->ReleaseInStream(); }

+

+  HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize)

+    { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); }

+};

+

+static const UInt64 k_BCJ = 0x03030103;

+  

+HRESULT CDecoder::Create(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    bool filteredMode, ISequentialInStream *inStream)

+{

+  if (!_lzmaDecoder)

+  {

+    _lzmaDecoderSpec = new NCompress::NLzma::CDecoder;

+    _lzmaDecoder = _lzmaDecoderSpec;

+  }

+

+  if (filteredMode)

+  {

+    if (!_bcjStream)

+    {

+      CMyComPtr<ICompressCoder> coder;

+      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false));

+      if (!coder)

+        return E_NOTIMPL;

+      coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream);

+      if (!_bcjStream)

+        return E_NOTIMPL;

+    }

+  }

+

+  return _lzmaDecoderSpec->SetInStream(inStream);

+}

+

+CDecoder::~CDecoder()

+{

+  ReleaseInStream();

+}

+

+HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,

+    ICompressProgressInfo *progress)

+{

+  if (header.FilterID > 1)

+    return E_NOTIMPL;

+

+  {

+    CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;

+    _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);

+    if (!setDecoderProperties)

+      return E_NOTIMPL;

+    RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5));

+  }

+

+  CMyComPtr<ICompressSetOutStream> setOutStream;

+

+  bool filteredMode = (header.FilterID == 1);

+

+  if (filteredMode)

+  {

+    _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream);

+    if (!setOutStream)

+      return E_NOTIMPL;

+    RINOK(setOutStream->SetOutStream(outStream));

+    outStream = _bcjStream;

+  }

+

+  const UInt64 *Size = header.HasSize() ? &header.Size : NULL;

+  HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress);

+

+  if (filteredMode)

+  {

+    CMyComPtr<IOutStreamFlush> flush;

+    _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush);

+    if (flush)

+    {

+      HRESULT res2 = flush->Flush();

+      if (res == S_OK)

+        res = res2;

+    }

+    HRESULT res2 = setOutStream->ReleaseOutStream();

+    if (res == S_OK)

+      res = res2;

+  }

+  RINOK(res);

+

+  return S_OK;

+}

+

+

+class CHandler:

+  public IInArchive,

+  public IArchiveOpenSeq,

+  PUBLIC_ISetCompressCodecsInfo

+  public CMyUnknownImp

+{

+  CHeader _header;

+  bool _lzma86;

+  UInt64 _startPosition;

+  UInt64 _packSize;

+  bool _packSizeDefined;

+  CMyComPtr<IInStream> _stream;

+  CMyComPtr<ISequentialInStream> _seqStream;

+

+  DECL_EXTERNAL_CODECS_VARS

+  DECL_ISetCompressCodecsInfo

+

+public:

+  MY_QUERYINTERFACE_BEGIN2(IInArchive)

+  MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)

+  QUERY_ENTRY_ISetCompressCodecsInfo

+  MY_QUERYINTERFACE_END

+  MY_ADDREF_RELEASE

+

+  INTERFACE_IInArchive(;)

+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);

+

+  CHandler(bool lzma86) { _lzma86 = lzma86; }

+

+  unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); }

+

+};

+

+IMP_IInArchive_Props

+IMP_IInArchive_ArcProps_NO_Table

+

+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)

+{

+  NCOM::CPropVariant prop;

+  switch(propID)

+  {

+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;

+  }

+  prop.Detach(value);

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)

+{

+  *numItems = 1;

+  return S_OK;

+}

+

+static void DictSizeToString(UInt32 value, char *s)

+{

+  for (int i = 0; i <= 31; i++)

+    if ((UInt32(1) << i) == value)

+    {

+      ::ConvertUInt32ToString(i, s);

+      return;

+    }

+  char c = 'b';

+  if ((value & ((1 << 20) - 1)) == 0)

+  {

+    value >>= 20;

+    c = 'm';

+  }

+  else if ((value & ((1 << 10) - 1)) == 0)

+  {

+    value >>= 10;

+    c = 'k';

+  }

+  ::ConvertUInt32ToString(value, s);

+  int p = MyStringLen(s);

+  s[p++] = c;

+  s[p++] = '\0';

+}

+

+static void MyStrCat(char *d, const char *s)

+{

+  MyStringCopy(d + MyStringLen(d), s);

+}

+

+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID,  PROPVARIANT *value)

+{

+  NCOM::CPropVariant prop;

+  switch(propID)

+  {

+    case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break;

+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;

+    case kpidMethod:

+      if (_stream)

+      {

+        char s[64];

+        s[0] = '\0';

+        if (_header.FilterID != 0)

+          MyStrCat(s, "BCJ ");

+        MyStrCat(s, "LZMA:");

+        DictSizeToString(_header.GetDicSize(), s + MyStringLen(s));

+        prop = s;

+      }

+      break;

+  }

+  prop.Detach(value);

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *)

+{

+  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition));

+  

+  const UInt32 kBufSize = 1 + 5 + 8 + 1;

+  Byte buf[kBufSize];

+  

+  RINOK(ReadStream_FALSE(inStream, buf, kBufSize));

+  

+  if (!_header.Parse(buf, _lzma86))

+    return S_FALSE;

+  const Byte *start = buf + GetHeaderSize();

+  if (start[0] != 0)

+    return S_FALSE;

+  

+  UInt64 endPos;

+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));

+  _packSize = endPos - _startPosition;

+  _packSizeDefined = true;

+  

+  _stream = inStream;

+  _seqStream = inStream;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)

+{

+  Close();

+  _seqStream = stream;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::Close()

+{

+  _packSizeDefined = false;

+  _stream.Release();

+  _seqStream.Release();

+   return S_OK;

+}

+

+

+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,

+    Int32 testMode, IArchiveExtractCallback *extractCallback)

+{

+  COM_TRY_BEGIN

+  if (numItems == 0)

+    return S_OK;

+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))

+    return E_INVALIDARG;

+

+  if (_stream)

+    extractCallback->SetTotal(_packSize);

+    

+  

+  CMyComPtr<ISequentialOutStream> realOutStream;

+  Int32 askMode = testMode ?

+      NExtract::NAskMode::kTest :

+      NExtract::NAskMode::kExtract;

+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));

+  if (!testMode && !realOutStream)

+    return S_OK;

+  

+  extractCallback->PrepareOperation(askMode);

+

+  CDummyOutStream *outStreamSpec = new CDummyOutStream;

+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);

+  outStreamSpec->SetStream(realOutStream);

+  outStreamSpec->Init();

+  realOutStream.Release();

+

+  CLocalProgress *lps = new CLocalProgress;

+  CMyComPtr<ICompressProgressInfo> progress = lps;

+  lps->Init(extractCallback, true);

+

+  if (_stream)

+  {

+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));

+  }

+

+  CDecoder decoder;

+  HRESULT result = decoder.Create(

+      EXTERNAL_CODECS_VARS

+      _lzma86, _seqStream);

+  RINOK(result);

+ 

+  Int32 opRes = NExtract::NOperationResult::kOK;

+  bool firstItem = true;

+

+  for (;;)

+  {

+    lps->OutSize = outStreamSpec->GetSize();

+    lps->InSize = _packSize = decoder.GetInputProcessedSize();

+    _packSizeDefined = true;

+    RINOK(lps->SetCur());

+

+    CHeader st;

+

+    const UInt32 kBufSize = 1 + 5 + 8;

+    Byte buf[kBufSize];

+    const UInt32 headerSize = GetHeaderSize();

+    UInt32 processed;

+    RINOK(decoder.ReadInput(buf, headerSize, &processed));

+    if (processed != headerSize)

+      break;

+  

+    if (!st.Parse(buf, _lzma86))

+      break;

+    firstItem = false;

+

+    result = decoder.Code(st, outStream, progress);

+    if (result == E_NOTIMPL)

+    {

+      opRes = NExtract::NOperationResult::kUnSupportedMethod;

+      break;

+    }

+    if (result == S_FALSE)

+    {

+      opRes = NExtract::NOperationResult::kDataError;

+      break;

+    }

+    RINOK(result);

+  }

+  if (firstItem)

+    return E_FAIL;

+  outStream.Release();

+  return extractCallback->SetOperationResult(opRes);

+  COM_TRY_END

+}

+

+IMPL_ISetCompressCodecsInfo

+

+static IInArchive *CreateArc() { return new CHandler(false); }

+static IInArchive *CreateArc86() { return new CHandler(true); }

+

+namespace NLzmaAr {

+  

+static CArcInfo g_ArcInfo =

+  { L"lzma", L"lzma", 0, 0xA, { 0 }, 0, true, CreateArc, NULL };

+REGISTER_ARC(Lzma)

+

+}

+

+namespace NLzma86Ar {

+

+static CArcInfo g_ArcInfo =

+  { L"lzma86", L"lzma86", 0, 0xB, { 0 }, 0, true, CreateArc86, NULL };

+REGISTER_ARC(Lzma86)

+

+}

+

+}}

diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp
new file mode 100755
index 0000000..cb98a77
--- /dev/null
+++ b/CPP/7zip/Archive/SplitHandler.cpp
@@ -0,0 +1,366 @@
+// SplitHandler.cpp

+

+#include "StdAfx.h"

+

+#include "Common/ComTry.h"

+#include "Common/MyString.h"

+

+#include "Windows/PropVariant.h"

+

+#include "../Common/ProgressUtils.h"

+#include "../Common/RegisterArc.h"

+

+#include "../Compress/CopyCoder.h"

+

+#include "Common/MultiStream.h"

+

+using namespace NWindows;

+

+namespace NArchive {

+namespace NSplit {

+

+STATPROPSTG kProps[] =

+{

+  { NULL, kpidPath, VT_BSTR},

+  { NULL, kpidSize, VT_UI8}

+};

+

+STATPROPSTG kArcProps[] =

+{

+  { NULL, kpidNumVolumes, VT_UI4}

+};

+

+class CHandler:

+  public IInArchive,

+  public IInArchiveGetStream,

+  public CMyUnknownImp

+{

+  UString _subName;

+  CObjectVector<CMyComPtr<IInStream> > _streams;

+  CRecordVector<UInt64> _sizes;

+  UInt64 _totalSize;

+public:

+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)

+  INTERFACE_IInArchive(;)

+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);

+};

+

+IMP_IInArchive_Props

+IMP_IInArchive_ArcProps

+

+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)

+{

+  NCOM::CPropVariant prop;

+  switch(propID)

+  {

+    case kpidMainSubfile: prop = (UInt32)0; break;

+    case kpidNumVolumes: prop = (UInt32)_streams.Size(); break;

+  }

+  prop.Detach(value);

+  return S_OK;

+}

+

+struct CSeqName

+{

+  UString _unchangedPart;

+  UString _changedPart;

+  bool _splitStyle;

+  

+  UString GetNextName()

+  {

+    UString newName;

+    if (_splitStyle)

+    {

+      int i;

+      int numLetters = _changedPart.Length();

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

+      {

+        wchar_t c = _changedPart[i];

+        if (c == 'z')

+        {

+          c = 'a';

+          newName = c + newName;

+          continue;

+        }

+        else if (c == 'Z')

+        {

+          c = 'A';

+          newName = c + newName;

+          continue;

+        }

+        c++;

+        if ((c == 'z' || c == 'Z') && i == 0)

+        {

+          _unchangedPart += c;

+          wchar_t newChar = (c == 'z') ? L'a' : L'A';

+          newName.Empty();

+          numLetters++;

+          for (int k = 0; k < numLetters; k++)

+            newName += newChar;

+          break;

+        }

+        newName = c + newName;

+        i--;

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

+          newName = _changedPart[i] + newName;

+        break;

+      }

+    }

+    else

+    {

+      int i;

+      int numLetters = _changedPart.Length();

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

+      {

+        wchar_t c = _changedPart[i];

+        if (c == L'9')

+        {

+          c = L'0';

+          newName = c + newName;

+          if (i == 0)

+            newName = UString(L'1') + newName;

+          continue;

+        }

+        c++;

+        newName = c + newName;

+        i--;

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

+          newName = _changedPart[i] + newName;

+        break;

+      }

+    }

+    _changedPart = newName;

+    return _unchangedPart + _changedPart;

+  }

+};

+

+STDMETHODIMP CHandler::Open(IInStream *stream,

+    const UInt64 * /* maxCheckStartPosition */,

+    IArchiveOpenCallback *openArchiveCallback)

+{

+  COM_TRY_BEGIN

+  Close();

+  if (openArchiveCallback == 0)

+    return S_FALSE;

+  // try

+  {

+    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;

+    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;

+    if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback,

+        &openVolumeCallback) != S_OK)

+      return S_FALSE;

+    

+    UString name;

+    {

+      NCOM::CPropVariant prop;

+      RINOK(openVolumeCallback->GetProperty(kpidName, &prop));

+      if (prop.vt != VT_BSTR)

+        return S_FALSE;

+      name = prop.bstrVal;

+    }

+    

+    int dotPos = name.ReverseFind('.');

+    UString prefix, ext;

+    if (dotPos >= 0)

+    {

+      prefix = name.Left(dotPos + 1);

+      ext = name.Mid(dotPos + 1);

+    }

+    else

+      ext = name;

+    UString extBig = ext;

+    extBig.MakeUpper();

+

+    CSeqName seqName;

+

+    int numLetters = 2;

+    bool splitStyle = false;

+    if (extBig.Right(2) == L"AA")

+    {

+      splitStyle = true;

+      while (numLetters < extBig.Length())

+      {

+        if (extBig[extBig.Length() - numLetters - 1] != 'A')

+          break;

+        numLetters++;

+      }

+    }

+    else if (ext.Right(2) == L"01")

+    {

+      while (numLetters < extBig.Length())

+      {

+        if (extBig[extBig.Length() - numLetters - 1] != '0')

+          break;

+        numLetters++;

+      }

+      if (numLetters != ext.Length())

+        return S_FALSE;

+    }

+    else

+      return S_FALSE;

+

+    _streams.Add(stream);

+

+    seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters);

+    seqName._changedPart = ext.Right(numLetters);

+    seqName._splitStyle = splitStyle;

+

+    if (prefix.Length() < 1)

+      _subName = L"file";

+    else

+      _subName = prefix.Left(prefix.Length() - 1);

+

+    _totalSize = 0;

+    UInt64 size;

+    {

+      NCOM::CPropVariant prop;

+      RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));

+      if (prop.vt != VT_UI8)

+        return E_INVALIDARG;

+      size = prop.uhVal.QuadPart;

+    }

+    _totalSize += size;

+    _sizes.Add(size);

+    

+    if (openArchiveCallback != NULL)

+    {

+      UInt64 numFiles = _streams.Size();

+      RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));

+    }

+

+    for (;;)

+    {

+      UString fullName = seqName.GetNextName();

+      CMyComPtr<IInStream> nextStream;

+      HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);

+      if (result == S_FALSE)

+        break;

+      if (result != S_OK)

+        return result;

+      if (!stream)

+        break;

+      {

+        NCOM::CPropVariant prop;

+        RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));

+        if (prop.vt != VT_UI8)

+          return E_INVALIDARG;

+        size = prop.uhVal.QuadPart;

+      }

+      _totalSize += size;

+      _sizes.Add(size);

+      _streams.Add(nextStream);

+      if (openArchiveCallback != NULL)

+      {

+        UInt64 numFiles = _streams.Size();

+        RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));

+      }

+    }

+  }

+  /*

+  catch(...)

+  {

+    return S_FALSE;

+  }

+  */

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP CHandler::Close()

+{

+  _sizes.Clear();

+  _streams.Clear();

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)

+{

+  *numItems = _streams.IsEmpty() ? 0 : 1;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)

+{

+  NWindows::NCOM::CPropVariant prop;

+  switch(propID)

+  {

+    case kpidPath: prop = _subName; break;

+    case kpidSize:

+    case kpidPackSize:

+      prop = _totalSize;

+      break;

+  }

+  prop.Detach(value);

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,

+    Int32 testMode, IArchiveExtractCallback *extractCallback)

+{

+  COM_TRY_BEGIN

+  if (numItems == 0)

+    return S_OK;

+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))

+    return E_INVALIDARG;

+

+  UInt64 currentTotalSize = 0;

+  RINOK(extractCallback->SetTotal(_totalSize));

+  CMyComPtr<ISequentialOutStream> outStream;

+  Int32 askMode = testMode ?

+      NExtract::NAskMode::kTest :

+      NExtract::NAskMode::kExtract;

+  RINOK(extractCallback->GetStream(0, &outStream, askMode));

+  if (!testMode && !outStream)

+    return S_OK;

+  RINOK(extractCallback->PrepareOperation(askMode));

+  

+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;

+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;

+

+  CLocalProgress *lps = new CLocalProgress;

+  CMyComPtr<ICompressProgressInfo> progress = lps;

+  lps->Init(extractCallback, false);

+

+  for (int i = 0; i < _streams.Size(); i++)

+  {

+    lps->InSize = lps->OutSize = currentTotalSize;

+    RINOK(lps->SetCur());

+    IInStream *inStream = _streams[i];

+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));

+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));

+    currentTotalSize += copyCoderSpec->TotalSize;

+  }

+  outStream.Release();

+  return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);

+  COM_TRY_END

+}

+

+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)

+{

+  COM_TRY_BEGIN

+  if (index != 0)

+    return E_INVALIDARG;

+  *stream = 0;

+  CMultiStream *streamSpec = new CMultiStream;

+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;

+  for (int i = 0; i < _streams.Size(); i++)

+  {

+    CMultiStream::CSubStreamInfo subStreamInfo;

+    subStreamInfo.Stream = _streams[i];

+    subStreamInfo.Size = _sizes[i];

+    streamSpec->Streams.Add(subStreamInfo);

+  }

+  streamSpec->Init();

+  *stream = streamTemp.Detach();

+  return S_OK;

+  COM_TRY_END

+}

+

+static IInArchive *CreateArc() { return new CHandler; }

+

+static CArcInfo g_ArcInfo =

+{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 };

+

+REGISTER_ARC(Split)

+

+}}

diff --git a/CPP/7zip/Archive/StdAfx.h b/CPP/7zip/Archive/StdAfx.h
new file mode 100755
index 0000000..f56e92f
--- /dev/null
+++ b/CPP/7zip/Archive/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../Common/MyWindows.h"

+#include "../../Common/NewHandler.h"

+

+#endif

diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
new file mode 100755
index 0000000..e4029e0
--- /dev/null
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -0,0 +1,707 @@
+// XzHandler.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+#include "../../../C/XzCrc64.h"

+#include "../../../C/XzEnc.h"

+

+#include "../../Common/ComTry.h"

+#include "../../Common/IntToString.h"

+

+#include "../ICoder.h"

+

+#include "../Common/CWrappers.h"

+#include "../Common/ProgressUtils.h"

+#include "../Common/RegisterArc.h"

+#include "../Common/StreamUtils.h"

+

+#include "../Compress/CopyCoder.h"

+

+#include "IArchive.h"

+

+#include "Common/HandlerOut.h"

+

+using namespace NWindows;

+

+namespace NCompress {

+namespace NLzma2 {

+

+HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);

+

+}}

+

+static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }

+static void SzFree(void *, void *address) { MyFree(address); }

+static ISzAlloc g_Alloc = { SzAlloc, SzFree };

+

+namespace NArchive {

+namespace NXz {

+

+struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;

+

+class CHandler:

+  public IInArchive,

+  public IArchiveOpenSeq,

+  #ifndef EXTRACT_ONLY

+  public IOutArchive,

+  public ISetProperties,

+  public COutHandler,

+  #endif

+  public CMyUnknownImp

+{

+  Int64 _startPosition;

+  UInt64 _packSize;

+  UInt64 _unpackSize;

+  UInt64 _numBlocks;

+  AString _methodsString;

+  bool _useSeq;

+  UInt64 _unpackSizeDefined;

+  UInt64 _packSizeDefined;

+  

+  CMyComPtr<IInStream> _stream;

+  CMyComPtr<ISequentialInStream> _seqStream;

+

+  UInt32 _crcSize;

+

+  void Init()

+  {

+    _crcSize = 4;

+    COutHandler::Init();

+  }

+

+  HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback);

+

+public:

+  MY_QUERYINTERFACE_BEGIN2(IInArchive)

+  MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)

+  #ifndef EXTRACT_ONLY

+  MY_QUERYINTERFACE_ENTRY(IOutArchive)

+  MY_QUERYINTERFACE_ENTRY(ISetProperties)

+  #endif

+  MY_QUERYINTERFACE_END

+  MY_ADDREF_RELEASE

+

+  INTERFACE_IInArchive(;)

+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);

+

+  #ifndef EXTRACT_ONLY

+  INTERFACE_IOutArchive(;)

+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);

+  #endif

+

+  CHandler();

+};

+

+CHandler::CHandler()

+{

+  Init();

+}

+

+STATPROPSTG kProps[] =

+{

+  { NULL, kpidSize, VT_UI8},

+  { NULL, kpidPackSize, VT_UI8},

+  { NULL, kpidMethod, VT_BSTR}

+};

+

+STATPROPSTG kArcProps[] =

+{

+  { NULL, kpidMethod, VT_BSTR},

+  { NULL, kpidNumBlocks, VT_UI4}

+};

+

+IMP_IInArchive_Props

+IMP_IInArchive_ArcProps

+

+static char GetHex(Byte value)

+{

+  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

+}

+

+static inline void AddHexToString(AString &res, Byte value)

+{

+  res += GetHex((Byte)(value >> 4));

+  res += GetHex((Byte)(value & 0xF));

+}

+

+static AString ConvertUInt32ToString(UInt32 value)

+{

+  char temp[32];

+  ::ConvertUInt32ToString(value, temp);

+  return temp;

+}

+

+static AString Lzma2PropToString(int prop)

+{

+  if ((prop & 1) == 0)

+    return ConvertUInt32ToString(prop / 2 + 12);

+  AString res;

+  char c;

+

+  UInt32 size = (2 | ((prop) & 1)) << ((prop) / 2 + 1);

+

+  if (prop > 17)

+  {

+    res = ConvertUInt32ToString(size >> 10);

+    c = 'm';

+  }

+  else

+  {

+    res = ConvertUInt32ToString(size);

+    c = 'k';

+  }

+  return res + c;

+}

+

+struct CMethodNamePair

+{

+  UInt32 Id;

+  const char *Name;

+};

+

+static CMethodNamePair g_NamePairs[] =

+{

+  { XZ_ID_Subblock, "SB" },

+  { XZ_ID_Delta, "Delta" },

+  { XZ_ID_X86, "x86" },

+  { XZ_ID_PPC, "PPC" },

+  { XZ_ID_IA64, "IA64" },

+  { XZ_ID_ARM, "ARM" },

+  { XZ_ID_ARMT, "ARMT" },

+  { XZ_ID_SPARC, "SPARC" },

+  { XZ_ID_LZMA2, "LZMA2" }

+};

+

+static AString GetMethodString(const CXzFilter &f)

+{

+  AString s;

+

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

+    if (g_NamePairs[i].Id == f.id)

+      s = g_NamePairs[i].Name;

+  if (s.IsEmpty())

+  {

+    char temp[32];

+    ::ConvertUInt64ToString(f.id, temp);

+    s = temp;

+  }

+

+  if (f.propsSize > 0)

+  {

+    s += ':';

+    if (f.id == XZ_ID_LZMA2 && f.propsSize == 1)

+      s += Lzma2PropToString(f.props[0]);

+    else if (f.id == XZ_ID_Delta && f.propsSize == 1)

+      s += ConvertUInt32ToString((UInt32)f.props[0] + 1);

+    else

+    {

+      s += '[';

+      for (UInt32 bi = 0; bi < f.propsSize; bi++)

+        AddHexToString(s, f.props[bi]);

+      s += ']';

+    }

+  }

+  return s;

+}

+

+static void AddString(AString &dest, const AString &src)

+{

+  if (!dest.IsEmpty())

+    dest += ' ';

+  dest += src;

+}

+

+static const char *kChecks[] =

+{

+  "NoCheck",

+  "CRC32",

+  NULL,

+  NULL,

+  "CRC64",

+  NULL,

+  NULL,

+  NULL,

+  NULL,

+  NULL,

+  "SHA256",

+  NULL,

+  NULL,

+  NULL,

+  NULL,

+  NULL

+};

+

+static AString GetCheckString(const CXzs &xzs)

+{

+  size_t i;

+  UInt32 mask = 0;

+  for (i = 0; i < xzs.num; i++)

+    mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags));

+  AString s;

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

+    if (((mask >> i) & 1) != 0)

+    {

+      AString s2;

+      if (kChecks[i])

+        s2 = kChecks[i];

+      else

+        s2 = "Check-" + ConvertUInt32ToString((UInt32)i);

+      AddString(s, s2);

+    }

+  return s;

+}

+

+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)

+{

+  COM_TRY_BEGIN

+  NWindows::NCOM::CPropVariant prop;

+  switch(propID)

+  {

+    case kpidNumBlocks: if (!_useSeq) prop = _numBlocks; break;

+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;

+    case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;

+  }

+  prop.Detach(value);

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)

+{

+  *numItems = 1;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID,  PROPVARIANT *value)

+{

+  COM_TRY_BEGIN

+  NWindows::NCOM::CPropVariant prop;

+  switch(propID)

+  {

+    case kpidSize: if (_unpackSizeDefined) prop = _unpackSize; break;

+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;

+    case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;

+  }

+  prop.Detach(value);

+  return S_OK;

+  COM_TRY_END

+}

+

+

+struct COpenCallbackWrap

+{

+  ICompressProgress p;

+  IArchiveOpenCallback *OpenCallback;

+  HRESULT Res;

+  COpenCallbackWrap(IArchiveOpenCallback *progress);

+};

+

+static SRes OpenCallbackProgress(void *pp, UInt64 inSize, UInt64 /* outSize */)

+{

+  COpenCallbackWrap *p = (COpenCallbackWrap *)pp;

+  p->Res = p->OpenCallback->SetCompleted(NULL, &inSize);

+  return (SRes)p->Res;

+}

+

+COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback)

+{

+  p.Progress = OpenCallbackProgress;

+  OpenCallback = callback;

+  Res = SZ_OK;

+}

+

+struct CXzsCPP

+{

+  CXzs p;

+  CXzsCPP() { Xzs_Construct(&p); }

+  ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }

+};

+

+HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback)

+{

+  CSeekInStreamWrap inStreamImp(inStream);

+

+  CLookToRead lookStream;

+  LookToRead_CreateVTable(&lookStream, True);

+  lookStream.realStream = &inStreamImp.p;

+  LookToRead_Init(&lookStream);

+

+  COpenCallbackWrap openWrap(callback);

+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize));

+  RINOK(callback->SetTotal(NULL, &_packSize));

+

+  CXzsCPP xzs;

+  SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &_startPosition, &openWrap.p, &g_Alloc);

+  if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0)

+    res = SZ_OK;

+  if (res == SZ_OK)

+  {

+    _packSize -= _startPosition;

+    _unpackSize = Xzs_GetUnpackSize(&xzs.p);

+    _unpackSizeDefined = _packSizeDefined = true;

+    _numBlocks = (UInt64)Xzs_GetNumBlocks(&xzs.p);

+

+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));

+    CXzStreamFlags st;

+    CSeqInStreamWrap inStreamWrap(inStream);

+    SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p);

+

+    if (res2 == SZ_OK)

+    {

+      CXzBlock block;

+      Bool isIndex;

+      UInt32 headerSizeRes;

+      res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes);

+      if (res2 == SZ_OK && !isIndex)

+      {

+        int numFilters = XzBlock_GetNumFilters(&block);

+        for (int i = 0; i < numFilters; i++)

+          AddString(_methodsString, GetMethodString(block.filters[i]));

+      }

+    }

+    AddString(_methodsString, GetCheckString(xzs.p));

+  }

+

+  if (res != SZ_OK || _startPosition != 0)

+  {

+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));

+    CXzStreamFlags st;

+    CSeqInStreamWrap inStreamWrap(inStream);

+    SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p);

+    if (res2 == SZ_OK)

+    {

+      res = res2;

+      _startPosition = 0;

+      _useSeq = True;

+      _unpackSizeDefined = _packSizeDefined = false;

+    }

+  }

+  if (res == SZ_ERROR_NO_ARCHIVE)

+    return S_FALSE;

+  RINOK(SResToHRESULT(res));

+  _stream = inStream;

+  _seqStream = inStream;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)

+{

+  COM_TRY_BEGIN

+  try

+  {

+    Close();

+    return Open2(inStream, callback);

+  }

+  catch(...) { return S_FALSE; }

+  COM_TRY_END

+}

+

+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)

+{

+  Close();

+  _seqStream = stream;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::Close()

+{

+  _numBlocks = 0;

+  _useSeq = true;

+  _unpackSizeDefined = _packSizeDefined = false;

+  _methodsString.Empty();

+  _stream.Release();

+  _seqStream.Release();

+  return S_OK;

+}

+

+class CSeekToSeqStream:

+  public IInStream,

+  public CMyUnknownImp

+{

+public:

+  CMyComPtr<ISequentialInStream> Stream;

+  MY_UNKNOWN_IMP1(IInStream)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+};

+

+STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  return Stream->Read(data, size, processedSize);

+}

+

+STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; }

+

+struct CXzUnpackerCPP

+{

+  Byte *InBuf;

+  Byte *OutBuf;

+  CXzUnpacker p;

+  CXzUnpackerCPP(): InBuf(0), OutBuf(0) {}

+  ~CXzUnpackerCPP()

+  {

+    XzUnpacker_Free(&p);

+    MyFree(InBuf);

+    MyFree(OutBuf);

+  }

+};

+

+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,

+    Int32 testMode, IArchiveExtractCallback *extractCallback)

+{

+  COM_TRY_BEGIN

+  if (numItems == 0)

+    return S_OK;

+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))

+    return E_INVALIDARG;

+

+  extractCallback->SetTotal(_packSize);

+  UInt64 currentTotalPacked = 0;

+  RINOK(extractCallback->SetCompleted(&currentTotalPacked));

+  CMyComPtr<ISequentialOutStream> realOutStream;

+  Int32 askMode = testMode ?

+      NExtract::NAskMode::kTest :

+      NExtract::NAskMode::kExtract;

+  

+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));

+  

+  if (!testMode && !realOutStream)

+    return S_OK;

+

+  extractCallback->PrepareOperation(askMode);

+

+  if (_stream)

+  {

+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));

+  }

+

+  CLocalProgress *lps = new CLocalProgress;

+  CMyComPtr<ICompressProgressInfo> progress = lps;

+  lps->Init(extractCallback, true);

+

+  CCompressProgressWrap progressWrap(progress);

+

+  SRes res;

+

+  const UInt32 kInBufSize = 1 << 15;

+  const UInt32 kOutBufSize = 1 << 21;

+

+  UInt32 inPos = 0;

+  UInt32 inSize = 0;

+  UInt32 outPos = 0;

+  CXzUnpackerCPP xzu;

+  res = XzUnpacker_Create(&xzu.p, &g_Alloc);

+  if (res == SZ_OK)

+  {

+    xzu.InBuf = (Byte *)MyAlloc(kInBufSize);

+    xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);

+    if (xzu.InBuf == 0 || xzu.OutBuf == 0)

+      res = SZ_ERROR_MEM;

+  }

+  if (res == SZ_OK)

+  for (;;)

+  {

+    if (inPos == inSize)

+    {

+      inPos = inSize = 0;

+      RINOK(_seqStream->Read(xzu.InBuf, kInBufSize, &inSize));

+    }

+

+    SizeT inLen = inSize - inPos;

+    SizeT outLen = kOutBufSize - outPos;

+    ECoderStatus status;

+    res = XzUnpacker_Code(&xzu.p,

+        xzu.OutBuf + outPos, &outLen,

+        xzu.InBuf + inPos, &inLen,

+        (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status);

+

+    // printf("\n_inPos = %6d  inLen = %5d, outLen = %5d", inPos, inLen, outLen);

+

+    inPos += (UInt32)inLen;

+    outPos += (UInt32)outLen;

+    lps->InSize += inLen;

+    lps->OutSize += outLen;

+

+    bool finished = (((inLen == 0) && (outLen == 0)) || res != SZ_OK);

+

+    if (outPos == kOutBufSize || finished)

+    {

+      if (realOutStream && outPos > 0)

+      {

+        RINOK(WriteStream(realOutStream, xzu.OutBuf, outPos));

+      }

+      outPos = 0;

+    }

+    if (finished)

+    {

+      _packSize = lps->InSize;

+      _unpackSize = lps->OutSize;

+      _packSizeDefined = _unpackSizeDefined = true;

+      if (res == SZ_OK)

+      {

+        if (status == CODER_STATUS_NEEDS_MORE_INPUT)

+        {

+          if (XzUnpacker_IsStreamWasFinished(&xzu.p))

+            _packSize -= xzu.p.padSize;

+          else

+            res = SZ_ERROR_DATA;

+        }

+        else

+          res = SZ_ERROR_DATA;

+      }

+      break;

+    }

+    RINOK(lps->SetCur());

+  }

+

+  Int32 opRes;

+  switch(res)

+  {

+    case SZ_OK:

+      opRes = NExtract::NOperationResult::kOK; break;

+    case SZ_ERROR_UNSUPPORTED:

+      opRes = NExtract::NOperationResult::kUnSupportedMethod; break;

+    case SZ_ERROR_CRC:

+      opRes = NExtract::NOperationResult::kCRCError; break;

+    case SZ_ERROR_DATA:

+    case SZ_ERROR_ARCHIVE:

+    case SZ_ERROR_NO_ARCHIVE:

+      opRes = NExtract::NOperationResult::kDataError; break;

+    default:

+      return SResToHRESULT(res);

+  }

+  realOutStream.Release();

+  RINOK(extractCallback->SetOperationResult(opRes));

+  return S_OK;

+  COM_TRY_END

+}

+

+#ifndef EXTRACT_ONLY

+

+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)

+{

+  *timeType = NFileTimeType::kUnix;

+  return S_OK;

+}

+

+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,

+    IArchiveUpdateCallback *updateCallback)

+{

+  CSeqOutStreamWrap seqOutStream(outStream);

+  

+  if (numItems == 0)

+  {

+    SRes res = Xz_EncodeEmpty(&seqOutStream.p);

+    return SResToHRESULT(res);

+  }

+  

+  if (numItems != 1)

+    return E_INVALIDARG;

+

+  Int32 newData, newProps;

+  UInt32 indexInArchive;

+  if (!updateCallback)

+    return E_FAIL;

+  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));

+

+  if (IntToBool(newProps))

+  {

+    {

+      NCOM::CPropVariant prop;

+      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));

+      if (prop.vt != VT_EMPTY)

+        if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)

+          return E_INVALIDARG;

+    }

+  }

+

+  if (IntToBool(newData))

+  {

+    {

+      UInt64 size;

+      NCOM::CPropVariant prop;

+      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));

+      if (prop.vt != VT_UI8)

+        return E_INVALIDARG;

+      size = prop.uhVal.QuadPart;

+      RINOK(updateCallback->SetTotal(size));

+    }

+

+    CLzma2EncProps lzma2Props;

+    Lzma2EncProps_Init(&lzma2Props);

+

+    lzma2Props.lzmaProps.level = _level;

+

+    CMyComPtr<ISequentialInStream> fileInStream;

+    RINOK(updateCallback->GetStream(0, &fileInStream));

+

+    CSeqInStreamWrap seqInStream(fileInStream);

+

+    for (int i = 0; i < _methods.Size(); i++)

+    {

+      COneMethodInfo &m = _methods[i];

+      SetCompressionMethod2(m

+      #ifndef _7ZIP_ST

+      , _numThreads

+      #endif

+      );

+      if (m.IsLzma())

+      {

+        for (int j = 0; j < m.Props.Size(); j++)

+        {

+          const CProp &prop = m.Props[j];

+          RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props));

+        }

+      }

+    }

+

+    #ifndef _7ZIP_ST

+    lzma2Props.numTotalThreads = _numThreads;

+    #endif

+

+    CLocalProgress *lps = new CLocalProgress;

+    CMyComPtr<ICompressProgressInfo> progress = lps;

+    lps->Init(updateCallback, true);

+

+    CCompressProgressWrap progressWrap(progress);

+    SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p);

+    if (res == SZ_OK)

+      return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);

+    return SResToHRESULT(res);

+  }

+  if (indexInArchive != 0)

+    return E_INVALIDARG;

+  if (_stream)

+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));

+  return NCompress::CopyStream(_stream, outStream, 0);

+}

+

+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)

+{

+  COM_TRY_BEGIN

+  BeforeSetProperty();

+  for (int i = 0; i < numProps; i++)

+  {

+    RINOK(SetProperty(names[i], values[i]));

+  }

+  return S_OK;

+  COM_TRY_END

+}

+

+#endif

+

+static IInArchive *CreateArc() { return new NArchive::NXz::CHandler; }

+#ifndef EXTRACT_ONLY

+static IOutArchive *CreateArcOut() { return new NArchive::NXz::CHandler; }

+#else

+#define CreateArcOut 0

+#endif

+

+static CArcInfo g_ArcInfo =

+  { L"xz", L"xz txz", L"* .tar", 0xC, {0xFD, '7' , 'z', 'X', 'Z', '\0'}, 6, true, CreateArc, CreateArcOut };

+

+REGISTER_ARC(xz)

+

+}}

diff --git a/CPP/7zip/Asm.mak b/CPP/7zip/Asm.mak
new file mode 100755
index 0000000..0284903
--- /dev/null
+++ b/CPP/7zip/Asm.mak
@@ -0,0 +1,7 @@
+!IF "$(CPU)" == "ARM"

+$(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm

+	$(COMPL_ASM)

+!ELSEIF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS"

+$(ASM_OBJS): ../../../../Asm/x86/$(*B).asm

+	$(COMPL_ASM)

+!ENDIF

diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsp b/CPP/7zip/Bundles/Alone7z/Alone.dsp
new file mode 100755
index 0000000..2b9543f
--- /dev/null
+++ b/CPP/7zip/Bundles/Alone7z/Alone.dsp
@@ -0,0 +1,1664 @@
+# Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Console Application" 0x0103

+

+CFG=Alone - Win32 DebugU

+!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 "Alone.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 "Alone.mak" CFG="Alone - Win32 DebugU"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application")

+!MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application")

+!MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application")

+!MESSAGE "Alone - Win32 DebugU" (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)" == "Alone - 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 /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_NO_CRYPTO" /Yu"StdAfx.h" /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:"c:\UTIL\7zr.exe" /opt:NOWIN98

+# SUBTRACT LINK32 /pdb:none

+

+!ELSEIF  "$(CFG)" == "Alone - 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 /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_NO_CRYPTO" /Yu"StdAfx.h" /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:"c:\UTIL\7zr.exe" /pdbtype:sept

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir "ReleaseU"

+# PROP BASE Intermediate_Dir "ReleaseU"

+# PROP BASE Ignore_Export_Lib 0

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir "ReleaseU"

+# PROP Intermediate_Dir "ReleaseU"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /Yu"StdAfx.h" /FD /c

+# ADD CPP /nologo /Gz /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "_NO_CRYPTO" /Yu"StdAfx.h" /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 /out:"c:\UTIL\7za.exe" /opt:NOWIN98

+# SUBTRACT BASE LINK32 /pdb:none

+# 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\7zr.exe" /opt:NOWIN98

+# SUBTRACT LINK32 /pdb:none

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 1

+# PROP BASE Output_Dir "DebugU"

+# PROP BASE Intermediate_Dir "DebugU"

+# PROP BASE Ignore_Export_Lib 0

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 1

+# PROP Output_Dir "DebugU"

+# PROP Intermediate_Dir "DebugU"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c

+# ADD CPP /nologo /Gz /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "_NO_CRYPTO" /Yu"StdAfx.h" /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 /out:"c:\UTIL\7za.exe" /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\7zr.exe" /pdbtype:sept

+

+!ENDIF 

+

+# Begin Target

+

+# Name "Alone - Win32 Release"

+# Name "Alone - Win32 Debug"

+# Name "Alone - Win32 ReleaseU"

+# Name "Alone - Win32 DebugU"

+# Begin Group "Console"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\Console\ArError.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\BenchCon.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\BenchCon.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\CompressionMode.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\ConsoleClose.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\ConsoleClose.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\ExtractCallbackConsole.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\List.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\List.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\Main.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\MainAr.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\OpenCallbackConsole.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\PercentPrinter.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\PercentPrinter.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\UpdateCallbackConsole.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\UserInputUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\UserInputUtils.h

+# End Source File

+# End Group

+# Begin Group "Spec"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=.\resource.rc

+# End Source File

+# Begin Source File

+

+SOURCE=.\StdAfx.cpp

+# ADD CPP /Yc"StdAfx.h"

+# End Source File

+# Begin Source File

+

+SOURCE=.\StdAfx.h

+# End Source File

+# End Group

+# Begin Group "Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Common\AutoPtr.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Buffer.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CommandLineParser.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CommandLineParser.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\ComTry.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CRC.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Defs.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\DynamicBuffer.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\ListFileUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\ListFileUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyCom.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyException.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyGuidDef.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyInitGuid.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyUnknown.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StdInStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StdInStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StdOutStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StdOutStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringToInt.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringToInt.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Types.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\UTFConvert.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\UTFConvert.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Wildcard.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Wildcard.h

+# End Source File

+# End Group

+# Begin Group "Windows"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Defs.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Device.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\DLL.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\DLL.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Error.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Error.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileDir.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileDir.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileFind.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileFind.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileMapping.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileName.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileName.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Handle.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\MemoryLock.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\MemoryLock.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariant.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariant.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariantConversions.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariantConversions.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Synchronization.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Synchronization.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\System.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\System.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Thread.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Time.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Time.h

+# End Source File

+# End Group

+# Begin Group "7zip Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Common\CreateCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CreateCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CrossThreadProgress.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CWrappers.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CWrappers.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilePathAutoRename.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilePathAutoRename.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilterCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilterCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\InBuffer.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\InBuffer.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\InOutTempBuffer.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\InOutTempBuffer.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\LimitedStreams.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\LimitedStreams.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\LockedStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\LockedStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\MethodId.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\MethodId.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\MethodProps.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\MethodProps.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\OffsetStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\OffsetStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\OutBuffer.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\OutBuffer.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\ProgressUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\ProgressUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\RegisterArc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\RegisterCodec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamBinder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamBinder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamObjects.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamObjects.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\VirtThread.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\VirtThread.h

+# End Source File

+# End Group

+# Begin Group "Compress"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Compress\Bcj2Coder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Bcj2Coder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Bcj2Register.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BcjCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BcjCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BcjRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchMisc.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchMisc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\BranchRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\ByteSwap.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\ByteSwap.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\CopyCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\CopyCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\CopyRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\DeltaFilter.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Decoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Decoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Encoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Encoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\Lzma2Register.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaDecoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaDecoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaEncoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaEncoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\RangeCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\RangeCoderBit.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\RangeCoderBitTree.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\RangeCoderOpt.h

+# End Source File

+# End Group

+# Begin Group "Archive"

+

+# PROP Default_Filter ""

+# Begin Group "7z"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zCompressionMode.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zCompressionMode.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zDecode.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zDecode.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zEncode.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zEncode.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zExtract.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zFolderInStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zFolderInStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zFolderOutStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zHandler.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zHandler.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zHandlerOut.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zHeader.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zHeader.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zIn.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zIn.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zItem.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zOut.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zOut.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zProperties.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zProperties.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zRegister.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zSpecStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zSpecStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zUpdate.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\7z\7zUpdate.h

+# End Source File

+# End Group

+# Begin Group "Archive Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CoderMixer2.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CoderMixer2.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\CoderMixer2MT.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\DummyOutStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\DummyOutStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\HandlerOut.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\HandlerOut.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\InStreamWithCRC.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\ItemNameUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\MultiStream.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\MultiStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\ParseProperties.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\Common\ParseProperties.h

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=..\..\Archive\LzmaHandler.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\SplitHandler.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Archive\XzHandler.cpp

+# End Source File

+# End Group

+# Begin Group "UI Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveCommandLine.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveExtractCallback.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Bench.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Bench.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\DefaultName.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\DefaultName.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\EnumDirItems.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\EnumDirItems.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Extract.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Extract.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ExtractingFilePath.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\ExtractingFilePath.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\LoadCodecs.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\LoadCodecs.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\OpenArchive.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\OpenArchive.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Property.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\PropIDUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\PropIDUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\SetProperties.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\SetProperties.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\SortUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\SortUtils.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\TempFiles.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\TempFiles.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Update.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Update.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\UpdateAction.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\UpdateAction.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\UpdateCallback.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\UpdateCallback.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\UpdatePair.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\UpdatePair.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\UpdateProduce.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\UpdateProduce.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\WorkDir.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\WorkDir.h

+# End Source File

+# End Group

+# Begin Group "7-zip"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\ICoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\IMyUnknown.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\IPassword.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\IProgress.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\IStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\PropID.h

+# End Source File

+# End Group

+# Begin Group "C"

+

+# PROP Default_Filter ""

+# Begin Group "Xz"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Sha256.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Sha256.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Xz.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Xz.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\XzCrc64.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\XzCrc64.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\XzDec.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\XzEnc.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\XzEnc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\XzIn.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrcOpt.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zStream.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Alloc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Alloc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra86.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\BraIA64.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\CpuArch.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\CpuArch.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Delta.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Delta.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\IStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzFind.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzFind.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzFindMt.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzFindMt.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzHash.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Lzma2Dec.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Lzma2Dec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Lzma2Enc.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Lzma2Enc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaDec.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaDec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaEnc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaEnc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\MtCoder.c

+

+!IF  "$(CFG)" == "Alone - Win32 Release"

+

+# ADD CPP /O2

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"

+

+# SUBTRACT CPP /YX /Yc /Yu

+

+!ENDIF 

+

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\MtCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Threads.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Threads.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Types.h

+# End Source File

+# End Group

+# End Target

+# End Project

diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsw b/CPP/7zip/Bundles/Alone7z/Alone.dsw
new file mode 100755
index 0000000..036aab4
--- /dev/null
+++ b/CPP/7zip/Bundles/Alone7z/Alone.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00

+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

+

+###############################################################################

+

+Project: "Alone"=.\Alone.dsp - Package Owner=<4>

+

+Package=<5>

+{{{

+}}}

+

+Package=<4>

+{{{

+}}}

+

+###############################################################################

+

+Global:

+

+Package=<5>

+{{{

+}}}

+

+Package=<3>

+{{{

+}}}

+

+###############################################################################

+

diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.cpp b/CPP/7zip/Bundles/Alone7z/StdAfx.cpp
new file mode 100755
index 0000000..c6d3b1f
--- /dev/null
+++ b/CPP/7zip/Bundles/Alone7z/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp

+

+#include "StdAfx.h"

diff --git a/CPP/7zip/Bundles/Alone7z/StdAfx.h b/CPP/7zip/Bundles/Alone7z/StdAfx.h
new file mode 100755
index 0000000..a4e6173
--- /dev/null
+++ b/CPP/7zip/Bundles/Alone7z/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../../Common/MyWindows.h"

+#include "../../../Common/NewHandler.h"

+

+#endif

diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile
new file mode 100755
index 0000000..3132895
--- /dev/null
+++ b/CPP/7zip/Bundles/Alone7z/makefile
@@ -0,0 +1,213 @@
+PROG = 7zr.exe

+MY_CONSOLE = 1

+CFLAGS = $(CFLAGS) -I ../../../ \

+  -D_NO_CRYPTO \

+

+!IFNDEF UNDER_CE

+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH

+!ENDIF

+

+CONSOLE_OBJS = \

+  $O\BenchCon.obj \

+  $O\ConsoleClose.obj \

+  $O\ExtractCallbackConsole.obj \

+  $O\List.obj \

+  $O\Main.obj \

+  $O\MainAr.obj \

+  $O\OpenCallbackConsole.obj \

+  $O\PercentPrinter.obj \

+  $O\UpdateCallbackConsole.obj \

+  $O\UserInputUtils.obj \

+

+COMMON_OBJS = \

+  $O\CommandLineParser.obj \

+  $O\CRC.obj \

+  $O\IntToString.obj \

+  $O\ListFileUtils.obj \

+  $O\NewHandler.obj \

+  $O\StdInStream.obj \

+  $O\StdOutStream.obj \

+  $O\MyString.obj \

+  $O\StringConvert.obj \

+  $O\StringToInt.obj \

+  $O\UTFConvert.obj \

+  $O\MyVector.obj \

+  $O\Wildcard.obj \

+

+WIN_OBJS = \

+  $O\DLL.obj \

+  $O\Error.obj \

+  $O\FileDir.obj \

+  $O\FileFind.obj \

+  $O\FileIO.obj \

+  $O\FileName.obj \

+  $O\MemoryLock.obj \

+  $O\PropVariant.obj \

+  $O\PropVariantConversions.obj \

+  $O\Synchronization.obj \

+  $O\System.obj \

+  $O\Time.obj \

+

+7ZIP_COMMON_OBJS = \

+  $O\CreateCoder.obj \

+  $O\CWrappers.obj \

+  $O\FilePathAutoRename.obj \

+  $O\FileStreams.obj \

+  $O\InBuffer.obj \

+  $O\InOutTempBuffer.obj \

+  $O\FilterCoder.obj \

+  $O\LimitedStreams.obj \

+  $O\LockedStream.obj \

+  $O\MethodId.obj \

+  $O\MethodProps.obj \

+  $O\OffsetStream.obj \

+  $O\OutBuffer.obj \

+  $O\ProgressUtils.obj \

+  $O\StreamBinder.obj \

+  $O\StreamObjects.obj \

+  $O\StreamUtils.obj \

+  $O\VirtThread.obj \

+

+UI_COMMON_OBJS = \

+  $O\ArchiveCommandLine.obj \

+  $O\ArchiveExtractCallback.obj \

+  $O\ArchiveOpenCallback.obj \

+  $O\Bench.obj \

+  $O\DefaultName.obj \

+  $O\EnumDirItems.obj \

+  $O\Extract.obj \

+  $O\ExtractingFilePath.obj \

+  $O\LoadCodecs.obj \

+  $O\OpenArchive.obj \

+  $O\PropIDUtils.obj \

+  $O\SetProperties.obj \

+  $O\SortUtils.obj \

+  $O\TempFiles.obj \

+  $O\Update.obj \

+  $O\UpdateAction.obj \

+  $O\UpdateCallback.obj \

+  $O\UpdatePair.obj \

+  $O\UpdateProduce.obj \

+  $O\WorkDir.obj \

+

+AR_OBJS = \

+  $O\LzmaHandler.obj \

+  $O\SplitHandler.obj \

+  $O\XzHandler.obj \

+

+AR_COMMON_OBJS = \

+  $O\CoderMixer2.obj \

+  $O\CoderMixer2MT.obj \

+  $O\CrossThreadProgress.obj \

+  $O\DummyOutStream.obj \

+  $O\HandlerOut.obj \

+  $O\InStreamWithCRC.obj \

+  $O\ItemNameUtils.obj \

+  $O\MultiStream.obj \

+  $O\OutStreamWithCRC.obj \

+  $O\ParseProperties.obj \

+

+

+7Z_OBJS = \

+  $O\7zCompressionMode.obj \

+  $O\7zDecode.obj \

+  $O\7zEncode.obj \

+  $O\7zExtract.obj \

+  $O\7zFolderInStream.obj \

+  $O\7zFolderOutStream.obj \

+  $O\7zHandler.obj \

+  $O\7zHandlerOut.obj \

+  $O\7zHeader.obj \

+  $O\7zIn.obj \

+  $O\7zOut.obj \

+  $O\7zProperties.obj \

+  $O\7zRegister.obj \

+  $O\7zSpecStream.obj \

+  $O\7zUpdate.obj \

+

+COMPRESS_OBJS = \

+  $O\Bcj2Coder.obj \

+  $O\Bcj2Register.obj \

+  $O\BcjCoder.obj \

+  $O\BcjRegister.obj \

+  $O\BranchCoder.obj \

+  $O\BranchMisc.obj \

+  $O\BranchRegister.obj \

+  $O\ByteSwap.obj \

+  $O\CopyCoder.obj \

+  $O\CopyRegister.obj \

+  $O\DeltaFilter.obj \

+  $O\Lzma2Decoder.obj \

+  $O\Lzma2Encoder.obj \

+  $O\Lzma2Register.obj \

+  $O\LzmaDecoder.obj \

+  $O\LzmaEncoder.obj \

+  $O\LzmaRegister.obj \

+

+C_OBJS = \

+  $O\7zStream.obj \

+  $O\Alloc.obj \

+  $O\Bra.obj \

+  $O\Bra86.obj \

+  $O\BraIA64.obj \

+  $O\CpuArch.obj \

+  $O\Delta.obj \

+  $O\LzFind.obj \

+  $O\LzFindMt.obj \

+  $O\Lzma2Dec.obj \

+  $O\Lzma2Enc.obj \

+  $O\LzmaDec.obj \

+  $O\LzmaEnc.obj \

+  $O\MtCoder.obj \

+  $O\Sha256.obj \

+  $O\Threads.obj \

+  $O\Xz.obj \

+  $O\XzCrc64.obj \

+  $O\XzDec.obj \

+  $O\XzEnc.obj \

+  $O\XzIn.obj \

+

+!include "../../Crc.mak"

+

+OBJS = \

+  $O\StdAfx.obj \

+  $(CONSOLE_OBJS) \

+  $(COMMON_OBJS) \

+  $(WIN_OBJS) \

+  $(7ZIP_COMMON_OBJS) \

+  $(UI_COMMON_OBJS) \

+  $(AR_OBJS) \

+  $(AR_COMMON_OBJS) \

+  $(7Z_OBJS) \

+  $(COMPRESS_OBJS) \

+  $(C_OBJS) \

+  $(ASM_OBJS) \

+  $O\resource.res

+

+

+!include "../../../Build.mak"

+

+$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp

+	$(COMPL)

+

+$(COMMON_OBJS): ../../../Common/$(*B).cpp

+	$(COMPL)

+$(WIN_OBJS): ../../../Windows/$(*B).cpp

+	$(COMPL)

+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

+	$(COMPL)

+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp

+	$(COMPL)

+$(AR_OBJS): ../../Archive/$(*B).cpp

+	$(COMPL)

+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp

+	$(COMPL)

+

+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp

+	$(COMPL)

+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp

+	$(COMPL_O2)

+$(C_OBJS): ../../../../C/$(*B).c

+	$(COMPL_O2)

+

+!include "../../Asm.mak"

diff --git a/CPP/7zip/Bundles/Alone7z/resource.rc b/CPP/7zip/Bundles/Alone7z/resource.rc
new file mode 100755
index 0000000..0f90dfb
--- /dev/null
+++ b/CPP/7zip/Bundles/Alone7z/resource.rc
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"

+

+MY_VERSION_INFO_APP("7-Zip Standalone Console", "7zr")

diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp
new file mode 100755
index 0000000..c6d3b1f
--- /dev/null
+++ b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp

+

+#include "StdAfx.h"

diff --git a/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h
new file mode 100755
index 0000000..a4e6173
--- /dev/null
+++ b/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../../Common/MyWindows.h"

+#include "../../../Common/NewHandler.h"

+

+#endif

diff --git a/CPP/7zip/Bundles/Format7zExtractR/makefile b/CPP/7zip/Bundles/Format7zExtractR/makefile
new file mode 100755
index 0000000..34a9bb3
--- /dev/null
+++ b/CPP/7zip/Bundles/Format7zExtractR/makefile
@@ -0,0 +1,132 @@
+PROG = 7zxr.dll

+DEF_FILE = ../../Archive/Archive2.def

+CFLAGS = $(CFLAGS) -I ../../../ \

+  -DEXTRACT_ONLY \

+  -D_NO_CRYPTO

+

+COMMON_OBJS = \

+  $O\CRC.obj \

+  $O\IntToString.obj \

+  $O\NewHandler.obj \

+  $O\MyString.obj \

+  $O\StringConvert.obj \

+  $O\StringToInt.obj \

+  $O\MyVector.obj \

+  $O\Wildcard.obj \

+

+WIN_OBJS = \

+  $O\PropVariant.obj \

+  $O\Synchronization.obj \

+  $O\System.obj \

+

+7ZIP_COMMON_OBJS = \

+  $O\CreateCoder.obj \

+  $O\CWrappers.obj \

+  $O\InBuffer.obj \

+  $O\FilterCoder.obj \

+  $O\LimitedStreams.obj \

+  $O\LockedStream.obj \

+  $O\MethodId.obj \

+  $O\MethodProps.obj \

+  $O\OutBuffer.obj \

+  $O\ProgressUtils.obj \

+  $O\StreamBinder.obj \

+  $O\StreamObjects.obj \

+  $O\StreamUtils.obj \

+  $O\VirtThread.obj \

+

+AR_OBJS = \

+  $O\ArchiveExports.obj \

+  $O\DllExports2.obj \

+

+AR_COMMON_OBJS = \

+  $O\CoderMixer2.obj \

+  $O\CoderMixer2MT.obj \

+  $O\CrossThreadProgress.obj \

+  $O\HandlerOut.obj \

+  $O\ItemNameUtils.obj \

+  $O\OutStreamWithCRC.obj \

+  $O\ParseProperties.obj \

+

+

+7Z_OBJS = \

+  $O\7zCompressionMode.obj \

+  $O\7zDecode.obj \

+  $O\7zExtract.obj \

+  $O\7zFolderOutStream.obj \

+  $O\7zHandler.obj \

+  $O\7zHeader.obj \

+  $O\7zIn.obj \

+  $O\7zProperties.obj \

+  $O\7zRegister.obj \

+

+

+COMPRESS_OBJS = \

+  $O\CodecExports.obj \

+  $O\Bcj2Coder.obj \

+  $O\Bcj2Register.obj \

+  $O\BcjCoder.obj \

+  $O\BcjRegister.obj \

+  $O\BranchCoder.obj \

+  $O\BranchMisc.obj \

+  $O\BranchRegister.obj \

+  $O\ByteSwap.obj \

+  $O\CopyCoder.obj \

+  $O\CopyRegister.obj \

+  $O\DeltaFilter.obj \

+  $O\Lzma2Decoder.obj \

+  $O\Lzma2Register.obj \

+  $O\LzmaDecoder.obj \

+  $O\LzmaRegister.obj \

+

+C_OBJS = \

+  $O\Alloc.obj \

+  $O\Bra.obj \

+  $O\Bra86.obj \

+  $O\BraIA64.obj \

+  $O\CpuArch.obj \

+  $O\Delta.obj \

+  $O\Lzma2Dec.obj \

+  $O\LzmaDec.obj \

+  $O\Threads.obj \

+

+!include "../../Crc.mak"

+

+OBJS = \

+  $O\StdAfx.obj \

+  $(CONSOLE_OBJS) \

+  $(COMMON_OBJS) \

+  $(WIN_OBJS) \

+  $(7ZIP_COMMON_OBJS) \

+  $(AR_OBJS) \

+  $(AR_COMMON_OBJS) \

+  $(7Z_OBJS) \

+  $(COMPRESS_OBJS) \

+  $(C_OBJS) \

+  $(ASM_OBJS) \

+  $O\resource.res

+

+

+!include "../../../Build.mak"

+

+$(COMMON_OBJS): ../../../Common/$(*B).cpp

+	$(COMPL)

+$(WIN_OBJS): ../../../Windows/$(*B).cpp

+	$(COMPL)

+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

+	$(COMPL)

+$(AR_OBJS): ../../Archive/$(*B).cpp

+	$(COMPL)

+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp

+	$(COMPL)

+

+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp

+	$(COMPL)

+

+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp

+	$(COMPL_O2)

+

+$(C_OBJS): ../../../../C/$(*B).c

+	$(COMPL_O2)

+

+!include "../../Asm.mak"

diff --git a/CPP/7zip/Bundles/Format7zExtractR/resource.rc b/CPP/7zip/Bundles/Format7zExtractR/resource.rc
new file mode 100755
index 0000000..652c4a1
--- /dev/null
+++ b/CPP/7zip/Bundles/Format7zExtractR/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"

+

+MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr")

+

+101  ICON  "../../Archive/Icons/7z.ico"

diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.cpp b/CPP/7zip/Bundles/Format7zR/StdAfx.cpp
new file mode 100755
index 0000000..c6d3b1f
--- /dev/null
+++ b/CPP/7zip/Bundles/Format7zR/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp

+

+#include "StdAfx.h"

diff --git a/CPP/7zip/Bundles/Format7zR/StdAfx.h b/CPP/7zip/Bundles/Format7zR/StdAfx.h
new file mode 100755
index 0000000..a4e6173
--- /dev/null
+++ b/CPP/7zip/Bundles/Format7zR/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../../Common/MyWindows.h"

+#include "../../../Common/NewHandler.h"

+

+#endif

diff --git a/CPP/7zip/Bundles/Format7zR/makefile b/CPP/7zip/Bundles/Format7zR/makefile
new file mode 100755
index 0000000..65d1f65
--- /dev/null
+++ b/CPP/7zip/Bundles/Format7zR/makefile
@@ -0,0 +1,149 @@
+PROG = 7zra.dll

+DEF_FILE = ../../Archive/Archive2.def

+CFLAGS = $(CFLAGS) -I ../../../ \

+  -D_NO_CRYPTO

+

+COMMON_OBJS = \

+  $O\CRC.obj \

+  $O\IntToString.obj \

+  $O\NewHandler.obj \

+  $O\MyString.obj \

+  $O\StringConvert.obj \

+  $O\StringToInt.obj \

+  $O\MyVector.obj \

+  $O\Wildcard.obj \

+

+WIN_OBJS = \

+  $O\FileDir.obj \

+  $O\FileFind.obj \

+  $O\FileIO.obj \

+  $O\PropVariant.obj \

+  $O\Synchronization.obj \

+  $O\System.obj \

+

+7ZIP_COMMON_OBJS = \

+  $O\CreateCoder.obj \

+  $O\CWrappers.obj \

+  $O\InBuffer.obj \

+  $O\InOutTempBuffer.obj \

+  $O\FilterCoder.obj \

+  $O\LimitedStreams.obj \

+  $O\LockedStream.obj \

+  $O\MethodId.obj \

+  $O\MethodProps.obj \

+  $O\OutBuffer.obj \

+  $O\ProgressUtils.obj \

+  $O\StreamBinder.obj \

+  $O\StreamObjects.obj \

+  $O\StreamUtils.obj \

+  $O\VirtThread.obj \

+

+AR_OBJS = \

+  $O\ArchiveExports.obj \

+  $O\DllExports2.obj \

+

+AR_COMMON_OBJS = \

+  $O\CoderMixer2.obj \

+  $O\CoderMixer2MT.obj \

+  $O\CrossThreadProgress.obj \

+  $O\HandlerOut.obj \

+  $O\InStreamWithCRC.obj \

+  $O\ItemNameUtils.obj \

+  $O\OutStreamWithCRC.obj \

+  $O\ParseProperties.obj \

+

+

+7Z_OBJS = \

+  $O\7zCompressionMode.obj \

+  $O\7zDecode.obj \

+  $O\7zEncode.obj \

+  $O\7zExtract.obj \

+  $O\7zFolderInStream.obj \

+  $O\7zFolderOutStream.obj \

+  $O\7zHandler.obj \

+  $O\7zHandlerOut.obj \

+  $O\7zHeader.obj \

+  $O\7zIn.obj \

+  $O\7zOut.obj \

+  $O\7zProperties.obj \

+  $O\7zSpecStream.obj \

+  $O\7zUpdate.obj \

+  $O\7zRegister.obj \

+

+

+COMPRESS_OBJS = \

+  $O\CodecExports.obj \

+  $O\Bcj2Coder.obj \

+  $O\Bcj2Register.obj \

+  $O\BcjCoder.obj \

+  $O\BcjRegister.obj \

+  $O\BranchCoder.obj \

+  $O\BranchMisc.obj \

+  $O\BranchRegister.obj \

+  $O\ByteSwap.obj \

+  $O\CopyCoder.obj \

+  $O\CopyRegister.obj \

+  $O\DeltaFilter.obj \

+  $O\Lzma2Decoder.obj \

+  $O\Lzma2Encoder.obj \

+  $O\Lzma2Register.obj \

+  $O\LzmaDecoder.obj \

+  $O\LzmaEncoder.obj \

+  $O\LzmaRegister.obj \

+

+C_OBJS = \

+  $O\Alloc.obj \

+  $O\Bra.obj \

+  $O\Bra86.obj \

+  $O\BraIA64.obj \

+  $O\CpuArch.obj \

+  $O\Delta.obj \

+  $O\LzFind.obj \

+  $O\LzFindMt.obj \

+  $O\Lzma2Dec.obj \

+  $O\Lzma2Enc.obj \

+  $O\LzmaDec.obj \

+  $O\LzmaEnc.obj \

+  $O\MtCoder.obj \

+  $O\Threads.obj \

+

+!include "../../Crc.mak"

+

+OBJS = \

+  $O\StdAfx.obj \

+  $(CONSOLE_OBJS) \

+  $(COMMON_OBJS) \

+  $(WIN_OBJS) \

+  $(7ZIP_COMMON_OBJS) \

+  $(AR_OBJS) \

+  $(AR_COMMON_OBJS) \

+  $(7Z_OBJS) \

+  $(COMPRESS_OBJS) \

+  $(C_OBJS) \

+  $(ASM_OBJS) \

+  $O\resource.res

+

+

+!include "../../../Build.mak"

+

+$(COMMON_OBJS): ../../../Common/$(*B).cpp

+	$(COMPL)

+$(WIN_OBJS): ../../../Windows/$(*B).cpp

+	$(COMPL)

+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

+	$(COMPL)

+$(AR_OBJS): ../../Archive/$(*B).cpp

+	$(COMPL)

+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp

+	$(COMPL)

+

+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp

+	$(COMPL)

+

+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp

+	$(COMPL_O2)

+

+$(C_OBJS): ../../../../C/$(*B).c

+	$(COMPL_O2)

+

+!include "../../Asm.mak"

diff --git a/CPP/7zip/Bundles/Format7zR/resource.rc b/CPP/7zip/Bundles/Format7zR/resource.rc
new file mode 100755
index 0000000..b67ef0c
--- /dev/null
+++ b/CPP/7zip/Bundles/Format7zR/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"

+

+MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr")

+

+101  ICON  "../../Archive/Icons/7z.ico"

diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
new file mode 100755
index 0000000..1f759b4
--- /dev/null
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
@@ -0,0 +1,525 @@
+// LzmaAlone.cpp

+

+#include "StdAfx.h"

+

+#include <stdio.h>

+

+#if (defined(_WIN32) || defined(OS2) || defined(MSDOS)) && !defined(UNDER_CE)

+#include <fcntl.h>

+#include <io.h>

+#define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY)

+#else

+#define MY_SET_BINARY_MODE(file)

+#endif

+

+// #include "../../../Common/MyWindows.h"

+#include "../../../Common/MyInitGuid.h"

+

+#include "../../../../C/7zVersion.h"

+#include "../../../../C/Alloc.h"

+#include "../../../../C/Lzma86.h"

+

+#include "../../../Windows/NtCheck.h"

+

+#ifndef _7ZIP_ST

+#include "../../../Windows/System.h"

+#endif

+

+#include "../../../Common/CommandLineParser.h"

+#include "../../../Common/StringConvert.h"

+#include "../../../Common/StringToInt.h"

+

+#include "../../Common/FileStreams.h"

+#include "../../Common/StreamUtils.h"

+

+#include "../../Compress/LzmaDecoder.h"

+#include "../../Compress/LzmaEncoder.h"

+

+#include "../../UI/Console/BenchCon.h"

+

+

+using namespace NCommandLineParser;

+

+static const char *kCantAllocate = "Can not allocate memory";

+static const char *kReadError = "Read error";

+static const char *kWriteError = "Write error";

+

+namespace NKey {

+enum Enum

+{

+  kHelp1 = 0,

+  kHelp2,

+  kAlgo,

+  kDict,

+  kFb,

+  kMc,

+  kLc,

+  kLp,

+  kPb,

+  kMatchFinder,

+  kMultiThread,

+  kEOS,

+  kStdIn,

+  kStdOut,

+  kFilter86

+};

+}

+

+static const CSwitchForm kSwitchForms[] =

+{

+  { L"?",  NSwitchType::kSimple, false },

+  { L"H",  NSwitchType::kSimple, false },

+  { L"A", NSwitchType::kUnLimitedPostString, false, 1 },

+  { L"D", NSwitchType::kUnLimitedPostString, false, 1 },

+  { L"FB", NSwitchType::kUnLimitedPostString, false, 1 },

+  { L"MC", NSwitchType::kUnLimitedPostString, false, 1 },

+  { L"LC", NSwitchType::kUnLimitedPostString, false, 1 },

+  { L"LP", NSwitchType::kUnLimitedPostString, false, 1 },

+  { L"PB", NSwitchType::kUnLimitedPostString, false, 1 },

+  { L"MF", NSwitchType::kUnLimitedPostString, false, 1 },

+  { L"MT", NSwitchType::kUnLimitedPostString, false, 0 },

+  { L"EOS", NSwitchType::kSimple, false },

+  { L"SI",  NSwitchType::kSimple, false },

+  { L"SO",  NSwitchType::kSimple, false },

+  { L"F86",  NSwitchType::kPostChar, false, 0, 0, L"+" }

+};

+

+static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]);

+

+static void PrintMessage(const char *s)

+{

+  fputs(s, stderr);

+}

+

+static void PrintHelp()

+{

+  PrintMessage("\nUsage:  LZMA <e|d> inputFile outputFile [<switches>...]\n"

+             "  e: encode file\n"

+             "  d: decode file\n"

+             "  b: Benchmark\n"

+    "<Switches>\n"

+    "  -a{N}:  set compression mode - [0, 1], default: 1 (max)\n"

+    "  -d{N}:  set dictionary size - [12, 30], default: 23 (8MB)\n"

+    "  -fb{N}: set number of fast bytes - [5, 273], default: 128\n"

+    "  -mc{N}: set number of cycles for match finder\n"

+    "  -lc{N}: set number of literal context bits - [0, 8], default: 3\n"

+    "  -lp{N}: set number of literal pos bits - [0, 4], default: 0\n"

+    "  -pb{N}: set number of pos bits - [0, 4], default: 2\n"

+    "  -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n"

+    "  -mt{N}: set number of CPU threads\n"

+    "  -eos:   write End Of Stream marker\n"

+    "  -si:    read data from stdin\n"

+    "  -so:    write data to stdout\n"

+    );

+}

+

+static void PrintHelpAndExit(const char *s)

+{

+  fprintf(stderr, "\nError: %s\n\n", s);

+  PrintHelp();

+  throw -1;

+}

+

+static void IncorrectCommand()

+{

+  PrintHelpAndExit("Incorrect command");

+}

+

+static void WriteArgumentsToStringList(int numArgs, const char *args[], UStringVector &strings)

+{

+  for (int i = 1; i < numArgs; i++)

+    strings.Add(MultiByteToUnicodeString(args[i]));

+}

+

+static bool GetNumber(const wchar_t *s, UInt32 &value)

+{

+  value = 0;

+  if (MyStringLen(s) == 0)

+    return false;

+  const wchar_t *end;

+  UInt64 res = ConvertStringToUInt64(s, &end);

+  if (*end != L'\0')

+    return false;

+  if (res > 0xFFFFFFFF)

+    return false;

+  value = UInt32(res);

+  return true;

+}

+

+static void ParseUInt32(const CParser &parser, int index, UInt32 &res)

+{

+  if (parser[index].ThereIs)

+    if (!GetNumber(parser[index].PostStrings[0], res))

+      IncorrectCommand();

+}

+

+#define NT_CHECK_FAIL_ACTION PrintMessage("Unsupported Windows version"); return 1;

+

+int main2(int numArgs, const char *args[])

+{

+  NT_CHECK

+

+  PrintMessage("\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n");

+

+  if (numArgs == 1)

+  {

+    PrintHelp();

+    return 0;

+  }

+

+  bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4);

+  if (unsupportedTypes)

+  {

+    PrintMessage("Unsupported base types. Edit Common/Types.h and recompile");

+    return 1;

+  }

+

+  UStringVector commandStrings;

+  WriteArgumentsToStringList(numArgs, args, commandStrings);

+  CParser parser(kNumSwitches);

+  try

+  {

+    parser.ParseStrings(kSwitchForms, commandStrings);

+  }

+  catch(...)

+  {

+    IncorrectCommand();

+  }

+

+  if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)

+  {

+    PrintHelp();

+    return 0;

+  }

+  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;

+

+  int paramIndex = 0;

+  if (paramIndex >= nonSwitchStrings.Size())

+    IncorrectCommand();

+  const UString &command = nonSwitchStrings[paramIndex++];

+

+  bool dictDefined = false;

+  UInt32 dict = (UInt32)-1;

+  if(parser[NKey::kDict].ThereIs)

+  {

+    UInt32 dicLog;

+    if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog))

+      IncorrectCommand();

+    dict = 1 << dicLog;

+    dictDefined = true;

+  }

+  UString mf = L"BT4";

+  if (parser[NKey::kMatchFinder].ThereIs)

+    mf = parser[NKey::kMatchFinder].PostStrings[0];

+

+  UInt32 numThreads = (UInt32)-1;

+

+  #ifndef _7ZIP_ST

+  if (parser[NKey::kMultiThread].ThereIs)

+  {

+    UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();

+    const UString &s = parser[NKey::kMultiThread].PostStrings[0];

+    if (s.IsEmpty())

+      numThreads = numCPUs;

+    else

+      if (!GetNumber(s, numThreads))

+        IncorrectCommand();

+  }

+  #endif

+

+  if (command.CompareNoCase(L"b") == 0)

+  {

+    const UInt32 kNumDefaultItereations = 1;

+    UInt32 numIterations = kNumDefaultItereations;

+    {

+      if (paramIndex < nonSwitchStrings.Size())

+        if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))

+          numIterations = kNumDefaultItereations;

+    }

+    return LzmaBenchCon(stderr, numIterations, numThreads, dict);

+  }

+

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

+    numThreads = 1;

+

+  bool encodeMode = false;

+  if (command.CompareNoCase(L"e") == 0)

+    encodeMode = true;

+  else if (command.CompareNoCase(L"d") == 0)

+    encodeMode = false;

+  else

+    IncorrectCommand();

+

+  bool stdInMode = parser[NKey::kStdIn].ThereIs;

+  bool stdOutMode = parser[NKey::kStdOut].ThereIs;

+

+  CMyComPtr<ISequentialInStream> inStream;

+  CInFileStream *inStreamSpec = 0;

+  if (stdInMode)

+  {

+    inStream = new CStdInFileStream;

+    MY_SET_BINARY_MODE(stdin);

+  }

+  else

+  {

+    if (paramIndex >= nonSwitchStrings.Size())

+      IncorrectCommand();

+    const UString &inputName = nonSwitchStrings[paramIndex++];

+    inStreamSpec = new CInFileStream;

+    inStream = inStreamSpec;

+    if (!inStreamSpec->Open(GetSystemString(inputName)))

+    {

+      fprintf(stderr, "\nError: can not open input file %s\n",

+          (const char *)GetOemString(inputName));

+      return 1;

+    }

+  }

+

+  CMyComPtr<ISequentialOutStream> outStream;

+  COutFileStream *outStreamSpec = NULL;

+  if (stdOutMode)

+  {

+    outStream = new CStdOutFileStream;

+    MY_SET_BINARY_MODE(stdout);

+  }

+  else

+  {

+    if (paramIndex >= nonSwitchStrings.Size())

+      IncorrectCommand();

+    const UString &outputName = nonSwitchStrings[paramIndex++];

+    outStreamSpec = new COutFileStream;

+    outStream = outStreamSpec;

+    if (!outStreamSpec->Create(GetSystemString(outputName), true))

+    {

+      fprintf(stderr, "\nError: can not open output file %s\n",

+        (const char *)GetOemString(outputName));

+      return 1;

+    }

+  }

+

+  if (parser[NKey::kFilter86].ThereIs)

+  {

+    // -f86 switch is for x86 filtered mode: BCJ + LZMA.

+    if (parser[NKey::kEOS].ThereIs || stdInMode)

+      throw "Can not use stdin in this mode";

+    UInt64 fileSize;

+    inStreamSpec->File.GetLength(fileSize);

+    if (fileSize > 0xF0000000)

+      throw "File is too big";

+    size_t inSize = (size_t)fileSize;

+    Byte *inBuffer = 0;

+    if (inSize != 0)

+    {

+      inBuffer = (Byte *)MyAlloc((size_t)inSize);

+      if (inBuffer == 0)

+        throw kCantAllocate;

+    }

+    

+    if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK)

+      throw "Can not read";

+

+    Byte *outBuffer = 0;

+    size_t outSize;

+    if (encodeMode)

+    {

+      // we allocate 105% of original size for output buffer

+      outSize = (size_t)fileSize / 20 * 21 + (1 << 16);

+      if (outSize != 0)

+      {

+        outBuffer = (Byte *)MyAlloc((size_t)outSize);

+        if (outBuffer == 0)

+          throw kCantAllocate;

+      }

+      if (!dictDefined)

+        dict = 1 << 23;

+      int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize,

+          5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO);

+      if (res != 0)

+      {

+        fprintf(stderr, "\nEncoder error = %d\n", (int)res);

+        return 1;

+      }

+    }

+    else

+    {

+      UInt64 outSize64;

+      if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0)

+        throw "data error";

+      outSize = (size_t)outSize64;

+      if (outSize != outSize64)

+        throw "too big";

+      if (outSize != 0)

+      {

+        outBuffer = (Byte *)MyAlloc(outSize);

+        if (outBuffer == 0)

+          throw kCantAllocate;

+      }

+      int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize);

+      if (inSize != (size_t)fileSize)

+        throw "incorrect processed size";

+      if (res != 0)

+        throw "LzmaDecoder error";

+    }

+    if (WriteStream(outStream, outBuffer, outSize) != S_OK)

+      throw kWriteError;

+    MyFree(outBuffer);

+    MyFree(inBuffer);

+    return 0;

+  }

+

+

+  UInt64 fileSize;

+  if (encodeMode)

+  {

+    NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder;

+    CMyComPtr<ICompressCoder> encoder = encoderSpec;

+

+    if (!dictDefined)

+      dict = 1 << 23;

+

+    UInt32 pb = 2;

+    UInt32 lc = 3; // = 0; for 32-bit data

+    UInt32 lp = 0; // = 2; for 32-bit data

+    UInt32 algo = 1;

+    UInt32 fb = 128;

+    UInt32 mc = 16 + fb / 2;

+    bool mcDefined = false;

+

+    bool eos = parser[NKey::kEOS].ThereIs || stdInMode;

+ 

+    ParseUInt32(parser, NKey::kAlgo, algo);

+    ParseUInt32(parser, NKey::kFb, fb);

+    ParseUInt32(parser, NKey::kLc, lc);

+    ParseUInt32(parser, NKey::kLp, lp);

+    ParseUInt32(parser, NKey::kPb, pb);

+

+    mcDefined = parser[NKey::kMc].ThereIs;

+    if (mcDefined)

+      if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc))

+        IncorrectCommand();

+    

+    PROPID propIDs[] =

+    {

+      NCoderPropID::kDictionarySize,

+      NCoderPropID::kPosStateBits,

+      NCoderPropID::kLitContextBits,

+      NCoderPropID::kLitPosBits,

+      NCoderPropID::kAlgorithm,

+      NCoderPropID::kNumFastBytes,

+      NCoderPropID::kMatchFinder,

+      NCoderPropID::kEndMarker,

+      NCoderPropID::kNumThreads,

+      NCoderPropID::kMatchFinderCycles,

+    };

+    const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]);

+

+    PROPVARIANT props[kNumPropsMax];

+    for (int p = 0; p < 6; p++)

+      props[p].vt = VT_UI4;

+

+    props[0].ulVal = (UInt32)dict;

+    props[1].ulVal = (UInt32)pb;

+    props[2].ulVal = (UInt32)lc;

+    props[3].ulVal = (UInt32)lp;

+    props[4].ulVal = (UInt32)algo;

+    props[5].ulVal = (UInt32)fb;

+

+    props[6].vt = VT_BSTR;

+    props[6].bstrVal = const_cast<BSTR>((const wchar_t *)mf);

+

+    props[7].vt = VT_BOOL;

+    props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE;

+

+    props[8].vt = VT_UI4;

+    props[8].ulVal = (UInt32)numThreads;

+

+    // it must be last in property list

+    props[9].vt = VT_UI4;

+    props[9].ulVal = (UInt32)mc;

+

+    int numProps = kNumPropsMax;

+    if (!mcDefined)

+      numProps--;

+

+    if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK)

+      IncorrectCommand();

+    encoderSpec->WriteCoderProperties(outStream);

+

+    if (eos || stdInMode)

+      fileSize = (UInt64)(Int64)-1;

+    else

+      inStreamSpec->File.GetLength(fileSize);

+

+    for (int i = 0; i < 8; i++)

+    {

+      Byte b = Byte(fileSize >> (8 * i));

+      if (outStream->Write(&b, 1, 0) != S_OK)

+      {

+        PrintMessage(kWriteError);

+        return 1;

+      }

+    }

+    HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);

+    if (result == E_OUTOFMEMORY)

+    {

+      PrintMessage("\nError: Can not allocate memory\n");

+      return 1;

+    }

+    else if (result != S_OK)

+    {

+      fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result);

+      return 1;

+    }

+  }

+  else

+  {

+    NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder;

+    CMyComPtr<ICompressCoder> decoder = decoderSpec;

+    decoderSpec->FinishStream = true;

+    const UInt32 kPropertiesSize = 5;

+    Byte header[kPropertiesSize + 8];

+    if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK)

+    {

+      PrintMessage(kReadError);

+      return 1;

+    }

+    if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK)

+    {

+      PrintMessage("SetDecoderProperties error");

+      return 1;

+    }

+    fileSize = 0;

+    for (int i = 0; i < 8; i++)

+      fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);

+

+    if (decoder->Code(inStream, outStream, 0, (fileSize == (UInt64)(Int64)-1) ? 0 : &fileSize, 0) != S_OK)

+    {

+      PrintMessage("Decoder error");

+      return 1;

+    }

+  }

+  if (outStreamSpec != NULL)

+  {

+    if (outStreamSpec->Close() != S_OK)

+    {

+      PrintMessage("File closing error");

+      return 1;

+    }

+  }

+  return 0;

+}

+

+int MY_CDECL main(int numArgs, const char *args[])

+{

+  try { return main2(numArgs, args); }

+  catch(const char *s)

+  {

+    fprintf(stderr, "\nError: %s\n", s);

+    return 1;

+  }

+  catch(...)

+  {

+    PrintMessage("\nError\n");

+    return 1;

+  }

+}

diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
new file mode 100755
index 0000000..edac514
--- /dev/null
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
@@ -0,0 +1,457 @@
+# Microsoft Developer Studio Project File - Name="LzmaCon" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Console Application" 0x0103

+

+CFG=LzmaCon - 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 "LzmaCon.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 "LzmaCon.mak" CFG="LzmaCon - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "LzmaCon - Win32 Release" (based on "Win32 (x86) Console Application")

+!MESSAGE "LzmaCon - 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)" == "LzmaCon - 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 /Gr /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /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:"C:\Util\lzma.exe"

+

+!ELSEIF  "$(CFG)" == "LzmaCon - 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 /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /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:"C:\Util\lzma.exe" /pdbtype:sept

+

+!ENDIF 

+

+# Begin Target

+

+# Name "LzmaCon - Win32 Release"

+# Name "LzmaCon - Win32 Debug"

+# Begin Group "Spec"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=.\StdAfx.cpp

+# ADD CPP /Yc"StdAfx.h"

+# End Source File

+# Begin Source File

+

+SOURCE=.\StdAfx.h

+# End Source File

+# End Group

+# Begin Group "Compress"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaDecoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaDecoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaEncoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaEncoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Compress\LzmaRegister.cpp

+# End Source File

+# End Group

+# Begin Group "Windows"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Synchronization.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Synchronization.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\System.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\System.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\Thread.h

+# End Source File

+# End Group

+# Begin Group "Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Common\CommandLineParser.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CommandLineParser.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\ComTry.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\CRC.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Defs.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyCom.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyUnknown.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyWindows.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyWindows.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringToInt.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringToInt.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Types.h

+# End Source File

+# End Group

+# Begin Group "7zip Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Common\CreateCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CreateCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CWrappers.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\CWrappers.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilterCoder.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FilterCoder.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamUtils.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\StreamUtils.h

+# End Source File

+# End Group

+# Begin Group "UI Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Bench.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\Bench.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\LoadCodecs.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Common\LoadCodecs.h

+# End Source File

+# End Group

+# Begin Group "Console"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\UI\Console\BenchCon.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\BenchCon.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\ConsoleClose.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\UI\Console\ConsoleClose.h

+# End Source File

+# End Group

+# Begin Group "C"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\7zCrcOpt.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Alloc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Alloc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Bra86.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\BraIA64.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\CpuArch.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\CpuArch.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzFind.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzFind.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzFindMt.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzFindMt.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzHash.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Lzma86.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Lzma86Dec.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Lzma86Enc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaDec.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaDec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaEnc.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\LzmaEnc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Threads.c

+# SUBTRACT CPP /YX /Yc /Yu

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Threads.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\..\C\Types.h

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=.\LzmaAlone.cpp

+# End Source File

+# End Target

+# End Project

diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw
new file mode 100755
index 0000000..c6a6662
--- /dev/null
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00

+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

+

+###############################################################################

+

+Project: "LzmaCon"=.\LzmaCon.dsp - Package Owner=<4>

+

+Package=<5>

+{{{

+}}}

+

+Package=<4>

+{{{

+}}}

+

+###############################################################################

+

+Global:

+

+Package=<5>

+{{{

+}}}

+

+Package=<3>

+{{{

+}}}

+

+###############################################################################

+

diff --git a/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp b/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp
new file mode 100755
index 0000000..c6d3b1f
--- /dev/null
+++ b/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp

+

+#include "StdAfx.h"

diff --git a/CPP/7zip/Bundles/LzmaCon/StdAfx.h b/CPP/7zip/Bundles/LzmaCon/StdAfx.h
new file mode 100755
index 0000000..83fdd22
--- /dev/null
+++ b/CPP/7zip/Bundles/LzmaCon/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../../Common/MyWindows.h"

+

+#endif

diff --git a/CPP/7zip/Bundles/LzmaCon/makefile b/CPP/7zip/Bundles/LzmaCon/makefile
new file mode 100755
index 0000000..b0b84f1
--- /dev/null
+++ b/CPP/7zip/Bundles/LzmaCon/makefile
@@ -0,0 +1,87 @@
+PROG = lzma.exe

+MY_CONSOLE = 1

+CFLAGS = $(CFLAGS)

+

+LZMA_OBJS = \

+  $O\LzmaAlone.obj \

+

+COMPRESS_OBJS = \

+  $O\LzmaDecoder.obj \

+  $O\LzmaEncoder.obj \

+  $O\LzmaRegister.obj \

+

+COMMON_OBJS = \

+  $O\CommandLineParser.obj \

+  $O\CRC.obj \

+  $O\IntToString.obj \

+  $O\MyString.obj \

+  $O\StringConvert.obj \

+  $O\StringToInt.obj \

+  $O\MyVector.obj

+

+WIN_OBJS = \

+  $O\FileIO.obj \

+  $O\System.obj

+

+7ZIP_COMMON_OBJS = \

+  $O\CWrappers.obj \

+  $O\CreateCoder.obj \

+  $O\FileStreams.obj \

+  $O\FilterCoder.obj \

+  $O\OutBuffer.obj \

+  $O\StreamUtils.obj \

+

+UI_COMMON_OBJS = \

+  $O\Bench.obj \

+

+CONSOLE_OBJS = \

+  $O\ConsoleClose.obj \

+  $O\BenchCon.obj \

+

+C_OBJS = \

+  $O\Alloc.obj \

+  $O\Bra86.obj \

+  $O\CpuArch.obj \

+  $O\LzFind.obj \

+  $O\LzFindMt.obj \

+  $O\Lzma86Dec.obj \

+  $O\Lzma86Enc.obj \

+  $O\LzmaDec.obj \

+  $O\LzmaEnc.obj \

+  $O\Threads.obj \

+

+!include "../../Crc.mak"

+

+OBJS = \

+  $O\StdAfx.obj \

+  $(LZMA_OBJS) \

+  $(COMPRESS_OBJS) \

+  $(COMMON_OBJS) \

+  $(WIN_OBJS) \

+  $(7ZIP_COMMON_OBJS) \

+  $(UI_COMMON_OBJS) \

+  $(CONSOLE_OBJS) \

+  $(C_OBJS) \

+  $(ASM_OBJS) \

+

+!include "../../../Build.mak"

+

+

+$(LZMA_OBJS): $(*B).cpp

+	$(COMPL)

+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp

+	$(COMPL_O2)

+$(COMMON_OBJS): ../../../Common/$(*B).cpp

+	$(COMPL)

+$(WIN_OBJS): ../../../Windows/$(*B).cpp

+	$(COMPL)

+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

+	$(COMPL)

+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp

+	$(COMPL)

+$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp

+	$(COMPL)

+$(C_OBJS): ../../../../C/$(*B).c

+	$(COMPL_O2)

+

+!include "../../Asm.mak"

diff --git a/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/CPP/7zip/Bundles/LzmaCon/makefile.gcc
new file mode 100755
index 0000000..59a70de
--- /dev/null
+++ b/CPP/7zip/Bundles/LzmaCon/makefile.gcc
@@ -0,0 +1,155 @@
+PROG = lzma

+CXX = g++ -O2 -Wall

+CXX_C = gcc -O2 -Wall

+LIB = -lm

+RM = rm -f

+CFLAGS = -c -D_7ZIP_ST

+

+ifdef SystemDrive

+IS_MINGW = 1

+endif

+

+ifdef IS_MINGW

+FILE_IO =FileIO

+FILE_IO_2 =Windows/$(FILE_IO)

+LIB2 = -luuid

+else

+FILE_IO =C_FileIO

+FILE_IO_2 =Common/$(FILE_IO)

+endif

+

+OBJS = \

+  LzmaAlone.o \

+  Bench.o \

+  BenchCon.o \

+  ConsoleClose.o \

+  LzmaDecoder.o \

+  LzmaEncoder.o \

+  LzmaRegister.o \

+  CreateCoder.o \

+  CWrappers.o \

+  FileStreams.o \

+  FilterCoder.o \

+  StreamUtils.o \

+  $(FILE_IO).o \

+  CommandLineParser.o \

+  CRC.o \

+  IntToString.o \

+  MyString.o \

+  StringConvert.o \

+  StringToInt.o \

+  MyVector.o \

+  7zCrc.o \

+  7zCrcOpt.o \

+  Alloc.o \

+  Bra86.o \

+  CpuArch.o \

+  LzFind.o \

+  LzmaDec.o \

+  LzmaEnc.o \

+  Lzma86Dec.o \

+  Lzma86Enc.o \

+

+

+all: $(PROG)

+

+$(PROG): $(OBJS)

+	$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)

+

+LzmaAlone.o: LzmaAlone.cpp

+	$(CXX) $(CFLAGS) LzmaAlone.cpp

+

+Bench.o: ../../UI/Common/Bench.cpp

+	$(CXX) $(CFLAGS) ../../UI/Common/Bench.cpp

+

+BenchCon.o: ../../UI/Console/BenchCon.cpp

+	$(CXX) $(CFLAGS) ../../UI/Console/BenchCon.cpp

+

+ConsoleClose.o: ../../UI/Console/ConsoleClose.cpp

+	$(CXX) $(CFLAGS) ../../UI/Console/ConsoleClose.cpp

+

+LzmaDecoder.o: ../../Compress/LzmaDecoder.cpp

+	$(CXX) $(CFLAGS) ../../Compress/LzmaDecoder.cpp

+

+LzmaEncoder.o: ../../Compress/LzmaEncoder.cpp

+	$(CXX) $(CFLAGS) ../../Compress/LzmaEncoder.cpp

+

+LzmaRegister.o: ../../Compress/LzmaRegister.cpp

+	$(CXX) $(CFLAGS) ../../Compress/LzmaRegister.cpp

+

+CreateCoder.o: ../../Common/CreateCoder.cpp

+	$(CXX) $(CFLAGS) ../../Common/CreateCoder.cpp

+

+CWrappers.o: ../../Common/CWrappers.cpp

+	$(CXX) $(CFLAGS) ../../Common/CWrappers.cpp

+

+FileStreams.o: ../../Common/FileStreams.cpp

+	$(CXX) $(CFLAGS) ../../Common/FileStreams.cpp

+

+FilterCoder.o: ../../Common/FilterCoder.cpp

+	$(CXX) $(CFLAGS) ../../Common/FilterCoder.cpp

+

+StreamUtils.o: ../../Common/StreamUtils.cpp

+	$(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp

+

+$(FILE_IO).o: ../../../$(FILE_IO_2).cpp

+	$(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp

+

+

+CommandLineParser.o: ../../../Common/CommandLineParser.cpp

+	$(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp

+

+CRC.o: ../../../Common/CRC.cpp

+	$(CXX) $(CFLAGS) ../../../Common/CRC.cpp

+

+MyWindows.o: ../../../Common/MyWindows.cpp

+	$(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp

+

+IntToString.o: ../../../Common/IntToString.cpp

+	$(CXX) $(CFLAGS) ../../../Common/IntToString.cpp

+

+MyString.o: ../../../Common/MyString.cpp

+	$(CXX) $(CFLAGS) ../../../Common/MyString.cpp

+

+StringConvert.o: ../../../Common/StringConvert.cpp

+	$(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp

+

+StringToInt.o: ../../../Common/StringToInt.cpp

+	$(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp

+

+MyVector.o: ../../../Common/MyVector.cpp

+	$(CXX) $(CFLAGS) ../../../Common/MyVector.cpp

+

+7zCrc.o: ../../../../C/7zCrc.c

+	$(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c

+

+7zCrcOpt.o: ../../../../C/7zCrcOpt.c

+	$(CXX_C) $(CFLAGS) ../../../../C/7zCrcOpt.c

+

+Alloc.o: ../../../../C/Alloc.c

+	$(CXX_C) $(CFLAGS) ../../../../C/Alloc.c

+

+Bra86.o: ../../../../C/Bra86.c

+	$(CXX_C) $(CFLAGS) ../../../../C/Bra86.c

+

+CpuArch.o: ../../../../C/CpuArch.c

+	$(CXX_C) $(CFLAGS) ../../../../C/CpuArch.c

+

+LzFind.o: ../../../../C/LzFind.c

+	$(CXX_C) $(CFLAGS) ../../../../C/LzFind.c

+

+LzmaDec.o: ../../../../C/LzmaDec.c

+	$(CXX_C) $(CFLAGS) ../../../../C/LzmaDec.c

+

+LzmaEnc.o: ../../../../C/LzmaEnc.c

+	$(CXX_C) $(CFLAGS) ../../../../C/LzmaEnc.c

+

+Lzma86Dec.o: ../../../../C/Lzma86Dec.c

+	$(CXX_C) $(CFLAGS) ../../../../C/Lzma86Dec.c

+

+Lzma86Enc.o: ../../../../C/Lzma86Enc.c

+	$(CXX_C) $(CFLAGS) ../../../../C/Lzma86Enc.c

+

+clean:

+	-$(RM) $(PROG) $(OBJS)

+

diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp
new file mode 100755
index 0000000..66b8449
--- /dev/null
+++ b/CPP/7zip/Common/CWrappers.cpp
@@ -0,0 +1,226 @@
+// CWrappers.h

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+

+#include "CWrappers.h"

+

+#include "StreamUtils.h"

+

+#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1)

+

+#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x)

+

+static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize)

+{

+  CCompressProgressWrap *p = (CCompressProgressWrap *)pp;

+  p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize));

+  return (SRes)p->Res;

+}

+

+CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress)

+{

+  p.Progress = CompressProgress;

+  Progress = progress;

+  Res = SZ_OK;

+}

+

+static const UInt32 kStreamStepSize = (UInt32)1 << 31;

+

+SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes)

+{

+  switch(res)

+  {

+    case S_OK: return SZ_OK;

+    case E_OUTOFMEMORY: return SZ_ERROR_MEM;

+    case E_INVALIDARG: return SZ_ERROR_PARAM;

+    case E_ABORT: return SZ_ERROR_PROGRESS;

+    case S_FALSE: return SZ_ERROR_DATA;

+  }

+  return defaultRes;

+}

+

+static SRes MyRead(void *object, void *data, size_t *size)

+{

+  CSeqInStreamWrap *p = (CSeqInStreamWrap *)object;

+  UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);

+  p->Res = (p->Stream->Read(data, curSize, &curSize));

+  *size = curSize;

+  if (p->Res == S_OK)

+    return SZ_OK;

+  return HRESULT_To_SRes(p->Res, SZ_ERROR_READ);

+}

+

+static size_t MyWrite(void *object, const void *data, size_t size)

+{

+  CSeqOutStreamWrap *p = (CSeqOutStreamWrap *)object;

+  if (p->Stream)

+  {

+    p->Res = WriteStream(p->Stream, data, size);

+    if (p->Res != 0)

+      return 0;

+  }

+  else

+    p->Res = S_OK;

+  p->Processed += size;

+  return size;

+}

+

+CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream)

+{

+  p.Read = MyRead;

+  Stream = stream;

+}

+

+CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream)

+{

+  p.Write = MyWrite;

+  Stream = stream;

+  Res = SZ_OK;

+  Processed = 0;

+}

+

+HRESULT SResToHRESULT(SRes res)

+{

+  switch(res)

+  {

+    case SZ_OK: return S_OK;

+    case SZ_ERROR_MEM: return E_OUTOFMEMORY;

+    case SZ_ERROR_PARAM: return E_INVALIDARG;

+    case SZ_ERROR_PROGRESS: return E_ABORT;

+    case SZ_ERROR_DATA: return S_FALSE;

+  }

+  return E_FAIL;

+}

+

+static SRes InStreamWrap_Read(void *pp, void *data, size_t *size)

+{

+  CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp;

+  UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);

+  p->Res = p->Stream->Read(data, curSize, &curSize);

+  *size = curSize;

+  return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;

+}

+

+static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin)

+{

+  CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp;

+  UInt32 moveMethod;

+  switch(origin)

+  {

+    case SZ_SEEK_SET: moveMethod = STREAM_SEEK_SET; break;

+    case SZ_SEEK_CUR: moveMethod = STREAM_SEEK_CUR; break;

+    case SZ_SEEK_END: moveMethod = STREAM_SEEK_END; break;

+    default: return SZ_ERROR_PARAM;

+  }

+  UInt64 newPosition;

+  p->Res = p->Stream->Seek(*offset, moveMethod, &newPosition);

+  *offset = (Int64)newPosition;

+  return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;

+}

+

+CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream)

+{

+  Stream = stream;

+  p.Read = InStreamWrap_Read;

+  p.Seek = InStreamWrap_Seek;

+  Res = S_OK;

+}

+

+

+/* ---------- CByteInBufWrap ---------- */

+

+void CByteInBufWrap::Free()

+{

+  ::MidFree(Buf);

+  Buf = 0;

+}

+

+bool CByteInBufWrap::Alloc(UInt32 size)

+{

+  if (Buf == 0 || size != Size)

+  {

+    Free();

+    Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size);

+    Size = size;

+  }

+  return (Buf != 0);

+}

+

+Byte CByteInBufWrap::ReadByteFromNewBlock()

+{

+  if (Res == S_OK)

+  {

+    UInt32 avail;

+    Processed += (Cur - Buf);

+    Res = Stream->Read(Buf, Size, &avail);

+    Cur = Buf;

+    Lim = Buf + avail;

+    if (avail != 0)

+      return *Cur++;

+  }

+  Extra = true;

+  return 0;

+}

+

+static Byte Wrap_ReadByte(void *pp)

+{

+  CByteInBufWrap *p = (CByteInBufWrap *)pp;

+  if (p->Cur != p->Lim)

+    return *p->Cur++;

+  return p->ReadByteFromNewBlock();

+}

+

+CByteInBufWrap::CByteInBufWrap(): Buf(0)

+{

+  p.Read = Wrap_ReadByte;

+}

+

+

+/* ---------- CByteOutBufWrap ---------- */

+

+void CByteOutBufWrap::Free()

+{

+  ::MidFree(Buf);

+  Buf = 0;

+}

+

+bool CByteOutBufWrap::Alloc(size_t size)

+{

+  if (Buf == 0 || size != Size)

+  {

+    Free();

+    Buf = (Byte *)::MidAlloc(size);

+    Size = size;

+  }

+  return (Buf != 0);

+}

+

+HRESULT CByteOutBufWrap::Flush()

+{

+  if (Res == S_OK)

+  {

+    size_t size = (Cur - Buf);

+    Res = WriteStream(Stream, Buf, size);

+    if (Res == S_OK)

+      Processed += size;

+    Cur = Buf;

+  }

+  return Res;

+}

+

+static void Wrap_WriteByte(void *pp, Byte b)

+{

+  CByteOutBufWrap *p = (CByteOutBufWrap *)pp;

+  Byte *dest = p->Cur;

+  *dest = b;

+  p->Cur = ++dest;

+  if (dest == p->Lim)

+    p->Flush();

+}

+

+CByteOutBufWrap::CByteOutBufWrap(): Buf(0)

+{

+  p.Write = Wrap_WriteByte;

+}

diff --git a/CPP/7zip/Common/CWrappers.h b/CPP/7zip/Common/CWrappers.h
new file mode 100755
index 0000000..dd4197c
--- /dev/null
+++ b/CPP/7zip/Common/CWrappers.h
@@ -0,0 +1,109 @@
+// CWrappers.h

+

+#ifndef __C_WRAPPERS_H

+#define __C_WRAPPERS_H

+

+#include "../ICoder.h"

+#include "../../Common/MyCom.h"

+

+struct CCompressProgressWrap

+{

+  ICompressProgress p;

+  ICompressProgressInfo *Progress;

+  HRESULT Res;

+  CCompressProgressWrap(ICompressProgressInfo *progress);

+};

+

+struct CSeqInStreamWrap

+{

+  ISeqInStream p;

+  ISequentialInStream *Stream;

+  HRESULT Res;

+  CSeqInStreamWrap(ISequentialInStream *stream);

+};

+

+struct CSeekInStreamWrap

+{

+  ISeekInStream p;

+  IInStream *Stream;

+  HRESULT Res;

+  CSeekInStreamWrap(IInStream *stream);

+};

+

+struct CSeqOutStreamWrap

+{

+  ISeqOutStream p;

+  ISequentialOutStream *Stream;

+  HRESULT Res;

+  UInt64 Processed;

+  CSeqOutStreamWrap(ISequentialOutStream *stream);

+};

+

+HRESULT SResToHRESULT(SRes res);

+

+struct CByteInBufWrap

+{

+  IByteIn p;

+  const Byte *Cur;

+  const Byte *Lim;

+  Byte *Buf;

+  UInt32 Size;

+  ISequentialInStream *Stream;

+  UInt64 Processed;

+  bool Extra;

+  HRESULT Res;

+  

+  CByteInBufWrap();

+  ~CByteInBufWrap() { Free();  }

+  void Free();

+  bool Alloc(UInt32 size);

+  void Init()

+  {

+    Lim = Cur = Buf;

+    Processed = 0;

+    Extra = false;

+    Res = S_OK;

+  }

+  UInt64 GetProcessed() const { return Processed + (Cur - Buf); }

+  Byte ReadByteFromNewBlock();

+  Byte ReadByte()

+  {

+    if (Cur != Lim)

+      return *Cur++;

+    return ReadByteFromNewBlock();

+  }

+};

+

+struct CByteOutBufWrap

+{

+  IByteOut p;

+  Byte *Cur;

+  const Byte *Lim;

+  Byte *Buf;

+  size_t Size;

+  ISequentialOutStream *Stream;

+  UInt64 Processed;

+  HRESULT Res;

+  

+  CByteOutBufWrap();

+  ~CByteOutBufWrap() { Free();  }

+  void Free();

+  bool Alloc(size_t size);

+  void Init()

+  {

+    Cur = Buf;

+    Lim = Buf + Size;

+    Processed = 0;

+    Res = S_OK;

+  }

+  UInt64 GetProcessed() const { return Processed + (Cur - Buf); }

+  HRESULT Flush();

+  void WriteByte(Byte b)

+  {

+    *Cur++ = b;

+    if (Cur == Lim)

+      Flush();

+  }

+};

+

+#endif

diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp
new file mode 100755
index 0000000..55bad3c
--- /dev/null
+++ b/CPP/7zip/Common/CreateCoder.cpp
@@ -0,0 +1,293 @@
+// CreateCoder.cpp

+

+#include "StdAfx.h"

+

+#include "../../Windows/Defs.h"

+#include "../../Windows/PropVariant.h"

+

+#include "CreateCoder.h"

+

+#include "FilterCoder.h"

+#include "RegisterCodec.h"

+

+static const unsigned int kNumCodecsMax = 64;

+unsigned int g_NumCodecs = 0;

+const CCodecInfo *g_Codecs[kNumCodecsMax];

+void RegisterCodec(const CCodecInfo *codecInfo)

+{

+  if (g_NumCodecs < kNumCodecsMax)

+    g_Codecs[g_NumCodecs++] = codecInfo;

+}

+

+#ifdef EXTERNAL_CODECS

+static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)

+{

+  NWindows::NCOM::CPropVariant prop;

+  RINOK(codecsInfo->GetProperty(index, propID, &prop));

+  if (prop.vt == VT_EMPTY)

+    res = 1;

+  else if (prop.vt == VT_UI4)

+    res = prop.ulVal;

+  else

+    return E_INVALIDARG;

+  return S_OK;

+}

+

+static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)

+{

+  NWindows::NCOM::CPropVariant prop;

+  RINOK(codecsInfo->GetProperty(index, propID, &prop));

+  if (prop.vt == VT_EMPTY)

+    res = true;

+  else if (prop.vt == VT_BOOL)

+    res = VARIANT_BOOLToBool(prop.boolVal);

+  else

+    return E_INVALIDARG;

+  return S_OK;

+}

+

+HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs)

+{

+  UInt32 num;

+  RINOK(codecsInfo->GetNumberOfMethods(&num));

+  for (UInt32 i = 0; i < num; i++)

+  {

+    CCodecInfoEx info;

+    NWindows::NCOM::CPropVariant prop;

+    RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop));

+    // if (prop.vt != VT_BSTR)

+    // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal);

+    // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize);

+    if (prop.vt != VT_UI8)

+    {

+      continue; // old Interface

+      // return E_INVALIDARG;

+    }

+    info.Id = prop.uhVal.QuadPart;

+    prop.Clear();

+    

+    RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop));

+    if (prop.vt == VT_BSTR)

+      info.Name = prop.bstrVal;

+    else if (prop.vt != VT_EMPTY)

+      return E_INVALIDARG;;

+    

+    RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams));

+    RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams));

+    RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));

+    RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));

+    

+    externalCodecs.Add(info);

+  }

+  return S_OK;

+}

+

+#endif

+

+bool FindMethod(

+  #ifdef EXTERNAL_CODECS

+  ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,

+  #endif

+  const UString &name,

+  CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams)

+{

+  UInt32 i;

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

+  {

+    const CCodecInfo &codec = *g_Codecs[i];

+    if (name.CompareNoCase(codec.Name) == 0)

+    {

+      methodId = codec.Id;

+      numInStreams = codec.NumInStreams;

+      numOutStreams = 1;

+      return true;

+    }

+  }

+  #ifdef EXTERNAL_CODECS

+  if (externalCodecs)

+    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)

+    {

+      const CCodecInfoEx &codec = (*externalCodecs)[i];

+      if (codec.Name.CompareNoCase(name) == 0)

+      {

+        methodId = codec.Id;

+        numInStreams = codec.NumInStreams;

+        numOutStreams = codec.NumOutStreams;

+        return true;

+      }

+    }

+  #endif

+  return false;

+}

+

+bool FindMethod(

+  #ifdef EXTERNAL_CODECS

+  ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,

+  #endif

+  CMethodId methodId, UString &name)

+{

+  UInt32 i;

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

+  {

+    const CCodecInfo &codec = *g_Codecs[i];

+    if (methodId == codec.Id)

+    {

+      name = codec.Name;

+      return true;

+    }

+  }

+  #ifdef EXTERNAL_CODECS

+  if (externalCodecs)

+    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)

+    {

+      const CCodecInfoEx &codec = (*externalCodecs)[i];

+      if (methodId == codec.Id)

+      {

+        name = codec.Name;

+        return true;

+      }

+    }

+  #endif

+  return false;

+}

+

+HRESULT CreateCoder(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CMethodId methodId,

+  CMyComPtr<ICompressFilter> &filter,

+  CMyComPtr<ICompressCoder> &coder,

+  CMyComPtr<ICompressCoder2> &coder2,

+  bool encode, bool onlyCoder)

+{

+  bool created = false;

+  UInt32 i;

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

+  {

+    const CCodecInfo &codec = *g_Codecs[i];

+    if (codec.Id == methodId)

+    {

+      if (encode)

+      {

+        if (codec.CreateEncoder)

+        {

+          void *p = codec.CreateEncoder();

+          if (codec.IsFilter) filter = (ICompressFilter *)p;

+          else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;

+          else coder2 = (ICompressCoder2 *)p;

+          created = (p != 0);

+          break;

+        }

+      }

+      else

+        if (codec.CreateDecoder)

+        {

+          void *p = codec.CreateDecoder();

+          if (codec.IsFilter) filter = (ICompressFilter *)p;

+          else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;

+          else coder2 = (ICompressCoder2 *)p;

+          created = (p != 0);

+          break;

+        }

+    }

+  }

+

+  #ifdef EXTERNAL_CODECS

+  if (!created && externalCodecs)

+    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)

+    {

+      const CCodecInfoEx &codec = (*externalCodecs)[i];

+      if (codec.Id == methodId)

+      {

+        if (encode)

+        {

+          if (codec.EncoderIsAssigned)

+          {

+            if (codec.IsSimpleCodec())

+            {

+              HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder);

+              if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE)

+                return result;

+              if (!coder)

+              {

+                RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter));

+              }

+            }

+            else

+            {

+              RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2));

+            }

+            break;

+          }

+        }

+        else

+          if (codec.DecoderIsAssigned)

+          {

+            if (codec.IsSimpleCodec())

+            {

+              HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder);

+              if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE)

+                return result;

+              if (!coder)

+              {

+                RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter));

+              }

+            }

+            else

+            {

+              RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2));

+            }

+            break;

+          }

+      }

+    }

+  #endif

+

+  if (onlyCoder && filter)

+  {

+    CFilterCoder *coderSpec = new CFilterCoder;

+    coder = coderSpec;

+    coderSpec->Filter = filter;

+  }

+  return S_OK;

+}

+

+HRESULT CreateCoder(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CMethodId methodId,

+  CMyComPtr<ICompressCoder> &coder,

+  CMyComPtr<ICompressCoder2> &coder2,

+  bool encode)

+{

+  CMyComPtr<ICompressFilter> filter;

+  return CreateCoder(

+    EXTERNAL_CODECS_LOC_VARS

+    methodId,

+    filter, coder, coder2, encode, true);

+}

+

+HRESULT CreateCoder(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CMethodId methodId,

+  CMyComPtr<ICompressCoder> &coder, bool encode)

+{

+  CMyComPtr<ICompressFilter> filter;

+  CMyComPtr<ICompressCoder2> coder2;

+  return CreateCoder(

+    EXTERNAL_CODECS_LOC_VARS

+    methodId,

+    coder, coder2, encode);

+}

+

+HRESULT CreateFilter(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CMethodId methodId,

+  CMyComPtr<ICompressFilter> &filter,

+  bool encode)

+{

+  CMyComPtr<ICompressCoder> coder;

+  CMyComPtr<ICompressCoder2> coder2;

+  return CreateCoder(

+    EXTERNAL_CODECS_LOC_VARS

+    methodId,

+    filter, coder, coder2, encode, false);

+}

diff --git a/CPP/7zip/Common/CreateCoder.h b/CPP/7zip/Common/CreateCoder.h
new file mode 100755
index 0000000..9a59d45
--- /dev/null
+++ b/CPP/7zip/Common/CreateCoder.h
@@ -0,0 +1,98 @@
+// CreateCoder.h

+

+#ifndef __CREATE_CODER_H

+#define __CREATE_CODER_H

+

+#include "../../Common/MyCom.h"

+#include "../../Common/MyString.h"

+#include "../ICoder.h"

+

+#include "MethodId.h"

+

+#ifdef EXTERNAL_CODECS

+

+struct CCodecInfoEx

+{

+  UString Name;

+  CMethodId Id;

+  UInt32 NumInStreams;

+  UInt32 NumOutStreams;

+  bool EncoderIsAssigned;

+  bool DecoderIsAssigned;

+  bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; }

+  CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}

+};

+

+HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs);

+

+#define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,

+#define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo)

+#define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);

+#define IMPL_ISetCompressCodecsInfo2(x) \

+STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \

+  COM_TRY_BEGIN _codecsInfo = compressCodecsInfo;  return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END }

+#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)

+

+#define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs

+

+#define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs;

+#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,

+

+#define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs

+#define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs

+

+#define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2,

+#define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2,

+

+#else

+

+#define PUBLIC_ISetCompressCodecsInfo

+#define QUERY_ENTRY_ISetCompressCodecsInfo

+#define DECL_ISetCompressCodecsInfo

+#define IMPL_ISetCompressCodecsInfo

+#define EXTERNAL_CODECS_VARS2

+#define DECL_EXTERNAL_CODECS_VARS

+#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2

+#define DECL_EXTERNAL_CODECS_LOC_VARS2

+#define EXTERNAL_CODECS_LOC_VARS2

+#define DECL_EXTERNAL_CODECS_LOC_VARS

+#define EXTERNAL_CODECS_LOC_VARS

+

+#endif

+

+bool FindMethod(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams);

+

+bool FindMethod(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CMethodId methodId, UString &name);

+

+

+HRESULT CreateCoder(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CMethodId methodId,

+  CMyComPtr<ICompressFilter> &filter,

+  CMyComPtr<ICompressCoder> &coder,

+  CMyComPtr<ICompressCoder2> &coder2,

+  bool encode, bool onlyCoder);

+

+HRESULT CreateCoder(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CMethodId methodId,

+  CMyComPtr<ICompressCoder> &coder,

+  CMyComPtr<ICompressCoder2> &coder2,

+  bool encode);

+

+HRESULT CreateCoder(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CMethodId methodId,

+  CMyComPtr<ICompressCoder> &coder, bool encode);

+

+HRESULT CreateFilter(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  CMethodId methodId,

+  CMyComPtr<ICompressFilter> &filter,

+  bool encode);

+

+#endif

diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp
new file mode 100755
index 0000000..d357c5b
--- /dev/null
+++ b/CPP/7zip/Common/FilePathAutoRename.cpp
@@ -0,0 +1,55 @@
+// FilePathAutoRename.cpp

+

+#include "StdAfx.h"

+

+#include "Common/Defs.h"

+#include "Common/IntToString.h"

+

+#include "Windows/FileFind.h"

+

+#include "FilePathAutoRename.h"

+

+using namespace NWindows;

+

+static bool MakeAutoName(const UString &name,

+    const UString &extension, unsigned value, UString &path)

+{

+  wchar_t number[16];

+  ConvertUInt32ToString(value, number);

+  path = name;

+  path += number;

+  path += extension;

+  return NFile::NFind::DoesFileOrDirExist(path);

+}

+

+bool AutoRenamePath(UString &fullProcessedPath)

+{

+  UString path;

+  int dotPos = fullProcessedPath.ReverseFind(L'.');

+

+  int slashPos = fullProcessedPath.ReverseFind(L'/');

+  #ifdef _WIN32

+  int slash1Pos = fullProcessedPath.ReverseFind(L'\\');

+  slashPos = MyMax(slashPos, slash1Pos);

+  #endif

+

+  UString name, extension;

+  if (dotPos > slashPos && dotPos > 0)

+  {

+    name = fullProcessedPath.Left(dotPos);

+    extension = fullProcessedPath.Mid(dotPos);

+  }

+  else

+    name = fullProcessedPath;

+  name += L'_';

+  unsigned left = 1, right = (1 << 30);

+  while (left != right)

+  {

+    unsigned mid = (left + right) / 2;

+    if (MakeAutoName(name, extension, mid, path))

+      left = mid + 1;

+    else

+      right = mid;

+  }

+  return !MakeAutoName(name, extension, right, fullProcessedPath);

+}

diff --git a/CPP/7zip/Common/FilePathAutoRename.h b/CPP/7zip/Common/FilePathAutoRename.h
new file mode 100755
index 0000000..4303962
--- /dev/null
+++ b/CPP/7zip/Common/FilePathAutoRename.h
@@ -0,0 +1,10 @@
+// Util/FilePathAutoRename.h

+

+#ifndef __FILEPATHAUTORENAME_H

+#define __FILEPATHAUTORENAME_H

+

+#include "Common/MyString.h"

+

+bool AutoRenamePath(UString &fullProcessedPath);

+

+#endif

diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp
new file mode 100755
index 0000000..de49911
--- /dev/null
+++ b/CPP/7zip/Common/FileStreams.cpp
@@ -0,0 +1,422 @@
+// FileStreams.cpp

+

+#include "StdAfx.h"

+

+#ifndef _WIN32

+#include <fcntl.h>

+#include <unistd.h>

+#include <errno.h>

+#endif

+

+#ifdef SUPPORT_DEVICE_FILE

+#include "../../../C/Alloc.h"

+#include "../../Common/Defs.h"

+#endif

+

+#include "FileStreams.h"

+

+static inline HRESULT ConvertBoolToHRESULT(bool result)

+{

+  #ifdef _WIN32

+  if (result)

+    return S_OK;

+  DWORD lastError = ::GetLastError();

+  if (lastError == 0)

+    return E_FAIL;

+  return HRESULT_FROM_WIN32(lastError);

+  #else

+  return result ? S_OK: E_FAIL;

+  #endif

+}

+

+bool CInFileStream::Open(LPCTSTR fileName)

+{

+  return File.Open(fileName);

+}

+

+#ifdef USE_WIN_FILE

+#ifndef _UNICODE

+bool CInFileStream::Open(LPCWSTR fileName)

+{

+  return File.Open(fileName);

+}

+#endif

+#endif

+

+bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite)

+{

+  return File.OpenShared(fileName, shareForWrite);

+}

+

+#ifdef USE_WIN_FILE

+#ifndef _UNICODE

+bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite)

+{

+  return File.OpenShared(fileName, shareForWrite);

+}

+#endif

+#endif

+

+#ifdef SUPPORT_DEVICE_FILE

+

+static const UInt32 kClusterSize = 1 << 18;

+CInFileStream::CInFileStream():

+  VirtPos(0),

+  PhyPos(0),

+  Buffer(0),

+  BufferSize(0)

+{

+}

+

+#endif

+

+CInFileStream::~CInFileStream()

+{

+  #ifdef SUPPORT_DEVICE_FILE

+  MidFree(Buffer);

+  #endif

+}

+

+STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  #ifdef USE_WIN_FILE

+  

+  #ifdef SUPPORT_DEVICE_FILE

+  if (processedSize != NULL)

+    *processedSize = 0;

+  if (size == 0)

+    return S_OK;

+  if (File.IsDeviceFile)

+  {

+    if (File.LengthDefined)

+    {

+      if (VirtPos >= File.Length)

+        return VirtPos == File.Length ? S_OK : E_FAIL;

+      UInt64 rem = File.Length - VirtPos;

+      if (size > rem)

+        size = (UInt32)rem;

+    }

+    for (;;)

+    {

+      const UInt32 mask = kClusterSize - 1;

+      UInt64 mask2 = ~(UInt64)mask;

+      UInt64 alignedPos = VirtPos & mask2;

+      if (BufferSize > 0 && BufferStartPos == alignedPos)

+      {

+        UInt32 pos = (UInt32)VirtPos & mask;

+        if (pos >= BufferSize)

+          return S_OK;

+        UInt32 rem = MyMin(BufferSize - pos, size);

+        memcpy(data, Buffer + pos, rem);

+        VirtPos += rem;

+        if (processedSize != NULL)

+          *processedSize += rem;

+        return S_OK;

+      }

+      

+      bool useBuffer = false;

+      if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 )

+        useBuffer = true;

+      else

+      {

+        UInt64 end = VirtPos + size;

+        if ((end & mask) != 0)

+        {

+          end &= mask2;

+          if (end <= VirtPos)

+            useBuffer = true;

+          else

+            size = (UInt32)(end - VirtPos);

+        }

+      }

+      if (!useBuffer)

+        break;

+      if (alignedPos != PhyPos)

+      {

+        UInt64 realNewPosition;

+        bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition);

+        if (!result)

+          return ConvertBoolToHRESULT(result);

+        PhyPos = realNewPosition;

+      }

+

+      BufferStartPos = alignedPos;

+      UInt32 readSize = kClusterSize;

+      if (File.LengthDefined)

+        readSize = (UInt32)MyMin(File.Length - PhyPos, (UInt64)kClusterSize);

+

+      if (Buffer == 0)

+      {

+        Buffer = (Byte *)MidAlloc(kClusterSize);

+        if (Buffer == 0)

+          return E_OUTOFMEMORY;

+      }

+      bool result = File.Read1(Buffer, readSize, BufferSize);

+      if (!result)

+        return ConvertBoolToHRESULT(result);

+

+      if (BufferSize == 0)

+        return S_OK;

+      PhyPos += BufferSize;

+    }

+

+    if (VirtPos != PhyPos)

+    {

+      UInt64 realNewPosition;

+      bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition);

+      if (!result)

+        return ConvertBoolToHRESULT(result);

+      PhyPos = VirtPos = realNewPosition;

+    }

+  }

+  #endif

+

+  UInt32 realProcessedSize;

+  bool result = File.ReadPart(data, size, realProcessedSize);

+  if (processedSize != NULL)

+    *processedSize = realProcessedSize;

+  #ifdef SUPPORT_DEVICE_FILE

+  VirtPos += realProcessedSize;

+  PhyPos += realProcessedSize;

+  #endif

+  return ConvertBoolToHRESULT(result);

+  

+  #else

+  

+  if (processedSize != NULL)

+    *processedSize = 0;

+  ssize_t res = File.Read(data, (size_t)size);

+  if (res == -1)

+    return E_FAIL;

+  if (processedSize != NULL)

+    *processedSize = (UInt32)res;

+  return S_OK;

+

+  #endif

+}

+

+#ifdef UNDER_CE

+STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  size_t s2 = fread(data, 1, size, stdout);

+  if (processedSize != 0)

+    *processedSize = s2;

+  return (s2 = size) ? S_OK : E_FAIL;

+}

+#else

+STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  #ifdef _WIN32

+  

+  DWORD realProcessedSize;

+  UInt32 sizeTemp = (1 << 20);

+  if (sizeTemp > size)

+    sizeTemp = size;

+  BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL);

+  if (processedSize != NULL)

+    *processedSize = realProcessedSize;

+  if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)

+    return S_OK;

+  return ConvertBoolToHRESULT(res != FALSE);

+  

+  #else

+

+  if (processedSize != NULL)

+    *processedSize = 0;

+  ssize_t res;

+  do

+  {

+    res = read(0, data, (size_t)size);

+  }

+  while (res < 0 && (errno == EINTR));

+  if (res == -1)

+    return E_FAIL;

+  if (processedSize != NULL)

+    *processedSize = (UInt32)res;

+  return S_OK;

+  

+  #endif

+}

+  

+#endif

+

+STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin,

+    UInt64 *newPosition)

+{

+  if (seekOrigin >= 3)

+    return STG_E_INVALIDFUNCTION;

+

+  #ifdef USE_WIN_FILE

+

+  #ifdef SUPPORT_DEVICE_FILE

+  if (File.IsDeviceFile)

+  {

+    UInt64 newVirtPos = offset;

+    switch(seekOrigin)

+    {

+      case STREAM_SEEK_SET: break;

+      case STREAM_SEEK_CUR: newVirtPos += VirtPos; break;

+      case STREAM_SEEK_END: newVirtPos += File.Length; break;

+      default: return STG_E_INVALIDFUNCTION;

+    }

+    VirtPos = newVirtPos;

+    if (newPosition)

+      *newPosition = newVirtPos;

+    return S_OK;

+  }

+  #endif

+  

+  UInt64 realNewPosition;

+  bool result = File.Seek(offset, seekOrigin, realNewPosition);

+  

+  #ifdef SUPPORT_DEVICE_FILE

+  PhyPos = VirtPos = realNewPosition;

+  #endif

+

+  if (newPosition != NULL)

+    *newPosition = realNewPosition;

+  return ConvertBoolToHRESULT(result);

+  

+  #else

+  

+  off_t res = File.Seek(offset, seekOrigin);

+  if (res == -1)

+    return E_FAIL;

+  if (newPosition != NULL)

+    *newPosition = (UInt64)res;

+  return S_OK;

+  

+  #endif

+}

+

+STDMETHODIMP CInFileStream::GetSize(UInt64 *size)

+{

+  return ConvertBoolToHRESULT(File.GetLength(*size));

+}

+

+

+//////////////////////////

+// COutFileStream

+

+HRESULT COutFileStream::Close()

+{

+  return ConvertBoolToHRESULT(File.Close());

+}

+

+STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  #ifdef USE_WIN_FILE

+

+  UInt32 realProcessedSize;

+  bool result = File.WritePart(data, size, realProcessedSize);

+  ProcessedSize += realProcessedSize;

+  if (processedSize != NULL)

+    *processedSize = realProcessedSize;

+  return ConvertBoolToHRESULT(result);

+  

+  #else

+  

+  if (processedSize != NULL)

+    *processedSize = 0;

+  ssize_t res = File.Write(data, (size_t)size);

+  if (res == -1)

+    return E_FAIL;

+  if (processedSize != NULL)

+    *processedSize = (UInt32)res;

+  ProcessedSize += res;

+  return S_OK;

+  

+  #endif

+}

+  

+STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  if (seekOrigin >= 3)

+    return STG_E_INVALIDFUNCTION;

+  #ifdef USE_WIN_FILE

+

+  UInt64 realNewPosition;

+  bool result = File.Seek(offset, seekOrigin, realNewPosition);

+  if (newPosition != NULL)

+    *newPosition = realNewPosition;

+  return ConvertBoolToHRESULT(result);

+  

+  #else

+  

+  off_t res = File.Seek(offset, seekOrigin);

+  if (res == -1)

+    return E_FAIL;

+  if (newPosition != NULL)

+    *newPosition = (UInt64)res;

+  return S_OK;

+  

+  #endif

+}

+

+STDMETHODIMP COutFileStream::SetSize(UInt64 newSize)

+{

+  #ifdef USE_WIN_FILE

+  UInt64 currentPos;

+  if (!File.Seek(0, FILE_CURRENT, currentPos))

+    return E_FAIL;

+  bool result = File.SetLength(newSize);

+  UInt64 currentPos2;

+  result = result && File.Seek(currentPos, currentPos2);

+  return result ? S_OK : E_FAIL;

+  #else

+  return E_FAIL;

+  #endif

+}

+

+#ifdef UNDER_CE

+STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  size_t s2 = fwrite(data, 1, size, stdout);

+  if (processedSize != 0)

+    *processedSize = s2;

+  return (s2 = size) ? S_OK : E_FAIL;

+}

+#else

+STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize != NULL)

+    *processedSize = 0;

+

+  #ifdef _WIN32

+  UInt32 realProcessedSize;

+  BOOL res = TRUE;

+  if (size > 0)

+  {

+    // Seems that Windows doesn't like big amounts writing to stdout.

+    // So we limit portions by 32KB.

+    UInt32 sizeTemp = (1 << 15);

+    if (sizeTemp > size)

+      sizeTemp = size;

+    res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),

+        data, sizeTemp, (DWORD *)&realProcessedSize, NULL);

+    size -= realProcessedSize;

+    data = (const void *)((const Byte *)data + realProcessedSize);

+    if (processedSize != NULL)

+      *processedSize += realProcessedSize;

+  }

+  return ConvertBoolToHRESULT(res != FALSE);

+

+  #else

+  

+  ssize_t res;

+  do

+  {

+    res = write(1, data, (size_t)size);

+  }

+  while (res < 0 && (errno == EINTR));

+  if (res == -1)

+    return E_FAIL;

+  if (processedSize != NULL)

+    *processedSize = (UInt32)res;

+  return S_OK;

+  

+  return S_OK;

+  #endif

+}

+

+#endif

diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h
new file mode 100755
index 0000000..f979294
--- /dev/null
+++ b/CPP/7zip/Common/FileStreams.h
@@ -0,0 +1,144 @@
+// FileStreams.h

+

+#ifndef __FILESTREAMS_H

+#define __FILESTREAMS_H

+

+#ifdef _WIN32

+#define USE_WIN_FILE

+#endif

+

+#ifdef USE_WIN_FILE

+#include "../../Windows/FileIO.h"

+#else

+#include "../../Common/C_FileIO.h"

+#endif

+

+#include "../../Common/MyCom.h"

+

+#include "../IStream.h"

+

+class CInFileStream:

+  public IInStream,

+  public IStreamGetSize,

+  public CMyUnknownImp

+{

+public:

+  #ifdef USE_WIN_FILE

+  NWindows::NFile::NIO::CInFile File;

+  #ifdef SUPPORT_DEVICE_FILE

+  UInt64 VirtPos;

+  UInt64 PhyPos;

+  UInt64 BufferStartPos;

+  Byte *Buffer;

+  UInt32 BufferSize;

+  #endif

+  #else

+  NC::NFile::NIO::CInFile File;

+  #endif

+  virtual ~CInFileStream();

+

+  #ifdef SUPPORT_DEVICE_FILE

+  CInFileStream();

+  #endif

+  

+  bool Open(LPCTSTR fileName);

+  #ifdef USE_WIN_FILE

+  #ifndef _UNICODE

+  bool Open(LPCWSTR fileName);

+  #endif

+  #endif

+

+  bool OpenShared(LPCTSTR fileName, bool shareForWrite);

+  #ifdef USE_WIN_FILE

+  #ifndef _UNICODE

+  bool OpenShared(LPCWSTR fileName, bool shareForWrite);

+  #endif

+  #endif

+

+  MY_UNKNOWN_IMP2(IInStream, IStreamGetSize)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+

+  STDMETHOD(GetSize)(UInt64 *size);

+};

+

+class CStdInFileStream:

+  public ISequentialInStream,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP

+

+  virtual ~CStdInFileStream() {}

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+};

+

+class COutFileStream:

+  public IOutStream,

+  public CMyUnknownImp

+{

+  #ifdef USE_WIN_FILE

+  NWindows::NFile::NIO::COutFile File;

+  #else

+  NC::NFile::NIO::COutFile File;

+  #endif

+public:

+  virtual ~COutFileStream() {}

+  bool Create(LPCTSTR fileName, bool createAlways)

+  {

+    ProcessedSize = 0;

+    return File.Create(fileName, createAlways);

+  }

+  bool Open(LPCTSTR fileName, DWORD creationDisposition)

+  {

+    ProcessedSize = 0;

+    return File.Open(fileName, creationDisposition);

+  }

+  #ifdef USE_WIN_FILE

+  #ifndef _UNICODE

+  bool Create(LPCWSTR fileName, bool createAlways)

+  {

+    ProcessedSize = 0;

+    return File.Create(fileName, createAlways);

+  }

+  bool Open(LPCWSTR fileName, DWORD creationDisposition)

+  {

+    ProcessedSize = 0;

+    return File.Open(fileName, creationDisposition);

+  }

+  #endif

+  #endif

+

+  HRESULT Close();

+  

+  UInt64 ProcessedSize;

+

+  #ifdef USE_WIN_FILE

+  bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)

+  {

+    return File.SetTime(cTime, aTime, mTime);

+  }

+  bool SetMTime(const FILETIME *mTime) {  return File.SetMTime(mTime); }

+  #endif

+

+

+  MY_UNKNOWN_IMP1(IOutStream)

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+  STDMETHOD(SetSize)(UInt64 newSize);

+};

+

+class CStdOutFileStream:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP

+

+  virtual ~CStdOutFileStream() {}

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+#endif

diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp
new file mode 100755
index 0000000..03a2aa0
--- /dev/null
+++ b/CPP/7zip/Common/FilterCoder.cpp
@@ -0,0 +1,247 @@
+// FilterCoder.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+

+#include "../../Common/Defs.h"

+

+#include "FilterCoder.h"

+#include "StreamUtils.h"

+

+static const UInt32 kBufferSize = 1 << 17;

+

+CFilterCoder::CFilterCoder()

+{

+  _buffer = (Byte *)::MidAlloc(kBufferSize);

+  if (_buffer == 0)

+    throw 1;

+}

+

+CFilterCoder::~CFilterCoder()

+{

+  ::MidFree(_buffer);

+}

+

+HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)

+{

+  if (_outSizeIsDefined)

+  {

+    UInt64 remSize = _outSize - _nowPos64;

+    if (size > remSize)

+      size = (UInt32)remSize;

+  }

+  RINOK(WriteStream(outStream, _buffer, size));

+  _nowPos64 += size;

+  return S_OK;

+}

+

+STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)

+{

+  RINOK(Init());

+  UInt32 bufferPos = 0;

+  _outSizeIsDefined = (outSize != 0);

+  if (_outSizeIsDefined)

+    _outSize = *outSize;

+

+  while (!_outSizeIsDefined || _nowPos64 < _outSize)

+  {

+    size_t processedSize = kBufferSize - bufferPos;

+    

+    // Change it: It can be optimized using ReadPart

+    RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize));

+    

+    UInt32 endPos = bufferPos + (UInt32)processedSize;

+

+    bufferPos = Filter->Filter(_buffer, endPos);

+    if (bufferPos > endPos)

+    {

+      for (; endPos < bufferPos; endPos++)

+        _buffer[endPos] = 0;

+      bufferPos = Filter->Filter(_buffer, endPos);

+    }

+

+    if (bufferPos == 0)

+    {

+      if (endPos == 0)

+        return S_OK;

+      return WriteWithLimit(outStream, endPos);

+    }

+    RINOK(WriteWithLimit(outStream, bufferPos));

+    if (progress != NULL)

+    {

+      RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));

+    }

+    UInt32 i = 0;

+    while (bufferPos < endPos)

+      _buffer[i++] = _buffer[bufferPos++];

+    bufferPos = i;

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)

+{

+  _bufferPos = 0;

+  _outStream = outStream;

+  return Init();

+}

+

+STDMETHODIMP CFilterCoder::ReleaseOutStream()

+{

+  _outStream.Release();

+  return S_OK;

+}

+

+

+STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize != NULL)

+    *processedSize = 0;

+  while (size > 0)

+  {

+    UInt32 sizeTemp = MyMin(size, kBufferSize - _bufferPos);

+    memcpy(_buffer + _bufferPos, data, sizeTemp);

+    size -= sizeTemp;

+    if (processedSize != NULL)

+      *processedSize += sizeTemp;

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

+    UInt32 endPos = _bufferPos + sizeTemp;

+    _bufferPos = Filter->Filter(_buffer, endPos);

+    if (_bufferPos == 0)

+    {

+      _bufferPos = endPos;

+      break;

+    }

+    if (_bufferPos > endPos)

+    {

+      if (size != 0)

+        return E_FAIL;

+      break;

+    }

+    RINOK(WriteWithLimit(_outStream, _bufferPos));

+    UInt32 i = 0;

+    while (_bufferPos < endPos)

+      _buffer[i++] = _buffer[_bufferPos++];

+    _bufferPos = i;

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CFilterCoder::Flush()

+{

+  if (_bufferPos != 0)

+  {

+    // _buffer contains only data refused by previous Filter->Filter call.

+    UInt32 endPos = Filter->Filter(_buffer, _bufferPos);

+    if (endPos > _bufferPos)

+    {

+      for (; _bufferPos < endPos; _bufferPos++)

+        _buffer[_bufferPos] = 0;

+      if (Filter->Filter(_buffer, endPos) != endPos)

+        return E_FAIL;

+    }

+    RINOK(WriteWithLimit(_outStream, _bufferPos));

+    _bufferPos = 0;

+  }

+  CMyComPtr<IOutStreamFlush> flush;

+  _outStream.QueryInterface(IID_IOutStreamFlush, &flush);

+  if (flush)

+    return flush->Flush();

+  return S_OK;

+}

+

+

+STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)

+{

+  _convertedPosBegin = _convertedPosEnd = _bufferPos = 0;

+  _inStream = inStream;

+  return Init();

+}

+

+STDMETHODIMP CFilterCoder::ReleaseInStream()

+{

+  _inStream.Release();

+  return S_OK;

+}

+

+STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize != NULL)

+    *processedSize = 0;

+  while (size > 0)

+  {

+    if (_convertedPosBegin != _convertedPosEnd)

+    {

+      UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);

+      memcpy(data, _buffer + _convertedPosBegin, sizeTemp);

+      _convertedPosBegin += sizeTemp;

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

+      size -= sizeTemp;

+      if (processedSize != NULL)

+        *processedSize += sizeTemp;

+      break;

+    }

+    UInt32 i;

+    for (i = 0; _convertedPosEnd + i < _bufferPos; i++)

+      _buffer[i] = _buffer[_convertedPosEnd + i];

+    _bufferPos = i;

+    _convertedPosBegin = _convertedPosEnd = 0;

+    size_t processedSizeTemp = kBufferSize - _bufferPos;

+    RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp));

+    _bufferPos += (UInt32)processedSizeTemp;

+    _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);

+    if (_convertedPosEnd == 0)

+    {

+      if (_bufferPos == 0)

+        break;

+      _convertedPosEnd = _bufferPos; // check it

+      continue;

+    }

+    if (_convertedPosEnd > _bufferPos)

+    {

+      for (; _bufferPos < _convertedPosEnd; _bufferPos++)

+        _buffer[_bufferPos] = 0;

+      _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);

+    }

+  }

+  return S_OK;

+}

+

+#ifndef _NO_CRYPTO

+STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)

+{

+  return _setPassword->CryptoSetPassword(data, size);

+}

+#endif

+

+#ifndef EXTRACT_ONLY

+STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,

+      const PROPVARIANT *properties, UInt32 numProperties)

+{

+  return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);

+}

+

+STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)

+{

+  return _writeCoderProperties->WriteCoderProperties(outStream);

+}

+

+/*

+STDMETHODIMP CFilterCoder::ResetSalt()

+{

+  return _CryptoResetSalt->ResetSalt();

+}

+*/

+

+STDMETHODIMP CFilterCoder::ResetInitVector()

+{

+  return _CryptoResetInitVector->ResetInitVector();

+}

+#endif

+

+STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)

+{

+  return _setDecoderProperties->SetDecoderProperties2(data, size);

+}

diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h
new file mode 100755
index 0000000..1b0125d
--- /dev/null
+++ b/CPP/7zip/Common/FilterCoder.h
@@ -0,0 +1,128 @@
+// FilterCoder.h

+

+#ifndef __FILTER_CODER_H

+#define __FILTER_CODER_H

+

+#include "../../Common/MyCom.h"

+#include "../ICoder.h"

+#include "../IPassword.h"

+

+#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \

+{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \

+*outObject = (void *)(i *)this; AddRef(); return S_OK; }

+

+class CFilterCoder:

+  public ICompressCoder,

+  public ICompressSetInStream,

+  public ISequentialInStream,

+  public ICompressSetOutStream,

+  public ISequentialOutStream,

+  public IOutStreamFlush,

+

+  #ifndef _NO_CRYPTO

+  public ICryptoSetPassword,

+  #endif

+  #ifndef EXTRACT_ONLY

+  public ICompressSetCoderProperties,

+  public ICompressWriteCoderProperties,

+  // public ICryptoResetSalt,

+  public ICryptoResetInitVector,

+  #endif

+  public ICompressSetDecoderProperties2,

+  public CMyUnknownImp

+{

+protected:

+  Byte *_buffer;

+  CMyComPtr<ISequentialInStream> _inStream;

+  CMyComPtr<ISequentialOutStream> _outStream;

+  UInt32 _bufferPos;

+  UInt32 _convertedPosBegin;

+  UInt32 _convertedPosEnd;

+  bool _outSizeIsDefined;

+  UInt64 _outSize;

+  UInt64 _nowPos64;

+

+  HRESULT Init()

+  {

+    _nowPos64 = 0;

+    _outSizeIsDefined = false;

+    return Filter->Init();

+  }

+

+  CMyComPtr<ICryptoSetPassword> _setPassword;

+  #ifndef EXTRACT_ONLY

+  CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;

+  CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;

+  // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;

+  CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;

+  #endif

+  CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties;

+public:

+  CMyComPtr<ICompressFilter> Filter;

+

+  CFilterCoder();

+  ~CFilterCoder();

+  HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size);

+

+public:

+  MY_QUERYINTERFACE_BEGIN2(ICompressCoder)

+    MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)

+    MY_QUERYINTERFACE_ENTRY(ISequentialInStream)

+    MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)

+    MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)

+    MY_QUERYINTERFACE_ENTRY(IOutStreamFlush)

+

+    #ifndef _NO_CRYPTO

+    MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)

+    #endif

+

+    #ifndef EXTRACT_ONLY

+    MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties)

+    MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)

+    // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)

+    MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)

+    #endif

+

+    MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties)

+  MY_QUERYINTERFACE_END

+  MY_ADDREF_RELEASE

+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

+  STDMETHOD(ReleaseInStream)();

+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \

+  STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);

+  STDMETHOD(ReleaseOutStream)();

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Flush)();

+

+  #ifndef _NO_CRYPTO

+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);

+  #endif

+  #ifndef EXTRACT_ONLY

+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs,

+      const PROPVARIANT *properties, UInt32 numProperties);

+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);

+  // STDMETHOD(ResetSalt)();

+  STDMETHOD(ResetInitVector)();

+  #endif

+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

+};

+

+class CInStreamReleaser

+{

+public:

+  CFilterCoder *FilterCoder;

+  CInStreamReleaser(): FilterCoder(0) {}

+  ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }

+};

+

+class COutStreamReleaser

+{

+public:

+  CFilterCoder *FilterCoder;

+  COutStreamReleaser(): FilterCoder(0) {}

+  ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }

+};

+

+#endif

diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp
new file mode 100755
index 0000000..3f84f48
--- /dev/null
+++ b/CPP/7zip/Common/InBuffer.cpp
@@ -0,0 +1,83 @@
+// InBuffer.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+

+#include "InBuffer.h"

+

+CInBuffer::CInBuffer():

+  _buffer(0),

+  _bufferLimit(0),

+  _bufferBase(0),

+  _stream(0),

+  _bufferSize(0)

+{}

+

+bool CInBuffer::Create(UInt32 bufferSize)

+{

+  const UInt32 kMinBlockSize = 1;

+  if (bufferSize < kMinBlockSize)

+    bufferSize = kMinBlockSize;

+  if (_bufferBase != 0 && _bufferSize == bufferSize)

+    return true;

+  Free();

+  _bufferSize = bufferSize;

+  _bufferBase = (Byte *)::MidAlloc(bufferSize);

+  return (_bufferBase != 0);

+}

+

+void CInBuffer::Free()

+{

+  ::MidFree(_bufferBase);

+  _bufferBase = 0;

+}

+

+void CInBuffer::SetStream(ISequentialInStream *stream)

+{

+  _stream = stream;

+}

+

+void CInBuffer::Init()

+{

+  _processedSize = 0;

+  _buffer = _bufferBase;

+  _bufferLimit = _buffer;

+  _wasFinished = false;

+  #ifdef _NO_EXCEPTIONS

+  ErrorCode = S_OK;

+  #endif

+}

+

+bool CInBuffer::ReadBlock()

+{

+  #ifdef _NO_EXCEPTIONS

+  if (ErrorCode != S_OK)

+    return false;

+  #endif

+  if (_wasFinished)

+    return false;

+  _processedSize += (_buffer - _bufferBase);

+  UInt32 numProcessedBytes;

+  HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes);

+  #ifdef _NO_EXCEPTIONS

+  ErrorCode = result;

+  #else

+  if (result != S_OK)

+    throw CInBufferException(result);

+  #endif

+  _buffer = _bufferBase;

+  _bufferLimit = _buffer + numProcessedBytes;

+  _wasFinished = (numProcessedBytes == 0);

+  return (!_wasFinished);

+}

+

+Byte CInBuffer::ReadBlock2()

+{

+  if (!ReadBlock())

+  {

+    _processedSize++;

+    return 0xFF;

+  }

+  return *_buffer++;

+}

diff --git a/CPP/7zip/Common/InBuffer.h b/CPP/7zip/Common/InBuffer.h
new file mode 100755
index 0000000..cdd50f1
--- /dev/null
+++ b/CPP/7zip/Common/InBuffer.h
@@ -0,0 +1,81 @@
+// InBuffer.h

+

+#ifndef __INBUFFER_H

+#define __INBUFFER_H

+

+#include "../IStream.h"

+#include "../../Common/MyCom.h"

+#include "../../Common/MyException.h"

+

+#ifndef _NO_EXCEPTIONS

+struct CInBufferException: public CSystemException

+{

+  CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}

+};

+#endif

+

+class CInBuffer

+{

+  Byte *_buffer;

+  Byte *_bufferLimit;

+  Byte *_bufferBase;

+  CMyComPtr<ISequentialInStream> _stream;

+  UInt64 _processedSize;

+  UInt32 _bufferSize;

+  bool _wasFinished;

+

+  bool ReadBlock();

+  Byte ReadBlock2();

+

+public:

+  #ifdef _NO_EXCEPTIONS

+  HRESULT ErrorCode;

+  #endif

+

+  CInBuffer();

+  ~CInBuffer() { Free(); }

+

+  bool Create(UInt32 bufferSize);

+  void Free();

+  

+  void SetStream(ISequentialInStream *stream);

+  void Init();

+  void ReleaseStream() { _stream.Release(); }

+

+  bool ReadByte(Byte &b)

+  {

+    if (_buffer >= _bufferLimit)

+      if (!ReadBlock())

+        return false;

+    b = *_buffer++;

+    return true;

+  }

+  Byte ReadByte()

+  {

+    if (_buffer >= _bufferLimit)

+      return ReadBlock2();

+    return *_buffer++;

+  }

+  UInt32 ReadBytes(Byte *buf, UInt32 size)

+  {

+    if ((UInt32)(_bufferLimit - _buffer) >= size)

+    {

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

+        buf[i] = _buffer[i];

+      _buffer += size;

+      return size;

+    }

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

+    {

+      if (_buffer >= _bufferLimit)

+        if (!ReadBlock())

+          return i;

+      buf[i] = *_buffer++;

+    }

+    return size;

+  }

+  UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); }

+  bool WasFinished() const { return _wasFinished; }

+};

+

+#endif

diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp
new file mode 100755
index 0000000..13a7696
--- /dev/null
+++ b/CPP/7zip/Common/InOutTempBuffer.cpp
@@ -0,0 +1,122 @@
+// InOutTempBuffer.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/7zCrc.h"

+

+#include "InOutTempBuffer.h"

+#include "StreamUtils.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NDirectory;

+

+static const UInt32 kTempBufSize = (1 << 20);

+

+static LPCTSTR kTempFilePrefixString = TEXT("7zt");

+

+CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }

+

+void CInOutTempBuffer::Create()

+{

+  if (!_buf)

+    _buf = new Byte[kTempBufSize];

+}

+

+CInOutTempBuffer::~CInOutTempBuffer()

+{

+  delete []_buf;

+}

+

+void CInOutTempBuffer::InitWriting()

+{

+  _bufPos = 0;

+  _tempFileCreated = false;

+  _size = 0;

+  _crc = CRC_INIT_VAL;

+}

+

+bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size)

+{

+  if (size == 0)

+    return true;

+  if (!_tempFileCreated)

+  {

+    CSysString tempDirPath;

+    if (!MyGetTempPath(tempDirPath))

+      return false;

+    if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tempFileName) == 0)

+      return false;

+    if (!_outFile.Create(_tempFileName, true))

+      return false;

+    _tempFileCreated = true;

+  }

+  UInt32 processed;

+  if (!_outFile.Write(data, size, processed))

+    return false;

+  _crc = CrcUpdate(_crc, data, processed);

+  _size += processed;

+  return (processed == size);

+}

+

+bool CInOutTempBuffer::Write(const void *data, UInt32 size)

+{

+  if (_bufPos < kTempBufSize)

+  {

+    UInt32 cur = MyMin(kTempBufSize - _bufPos, size);

+    memcpy(_buf + _bufPos, data, cur);

+    _crc = CrcUpdate(_crc, data, cur);

+    _bufPos += cur;

+    size -= cur;

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

+    _size += cur;

+  }

+  return WriteToFile(data, size);

+}

+

+HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)

+{

+  if (!_outFile.Close())

+    return E_FAIL;

+

+  UInt64 size = 0;

+  UInt32 crc = CRC_INIT_VAL;

+

+  if (_bufPos > 0)

+  {

+    RINOK(WriteStream(stream, _buf, _bufPos));

+    crc = CrcUpdate(crc, _buf, _bufPos);

+    size += _bufPos;

+  }

+  if (_tempFileCreated)

+  {

+    NIO::CInFile inFile;

+    if (!inFile.Open(_tempFileName))

+      return E_FAIL;

+    while (size < _size)

+    {

+      UInt32 processed;

+      if (!inFile.ReadPart(_buf, kTempBufSize, processed))

+        return E_FAIL;

+      if (processed == 0)

+        break;

+      RINOK(WriteStream(stream, _buf, processed));

+      crc = CrcUpdate(crc, _buf, processed);

+      size += processed;

+    }

+  }

+  return (_crc == crc && size == _size) ? S_OK : E_FAIL;

+}

+

+STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed)

+{

+  if (!_buf->Write(data, size))

+  {

+    if (processed != NULL)

+      *processed = 0;

+    return E_FAIL;

+  }

+  if (processed != NULL)

+    *processed = size;

+  return S_OK;

+}

diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h
new file mode 100755
index 0000000..a69bc85
--- /dev/null
+++ b/CPP/7zip/Common/InOutTempBuffer.h
@@ -0,0 +1,48 @@
+// InOutTempBuffer.h

+

+#ifndef __IN_OUT_TEMP_BUFFER_H

+#define __IN_OUT_TEMP_BUFFER_H

+

+#include "../../Common/MyCom.h"

+#include "../../Windows/FileDir.h"

+#include "../../Windows/FileIO.h"

+

+#include "../IStream.h"

+

+class CInOutTempBuffer

+{

+  NWindows::NFile::NDirectory::CTempFile _tempFile;

+  NWindows::NFile::NIO::COutFile _outFile;

+  Byte *_buf;

+  UInt32 _bufPos;

+  CSysString _tempFileName;

+  bool _tempFileCreated;

+  UInt64 _size;

+  UInt32 _crc;

+

+  bool WriteToFile(const void *data, UInt32 size);

+public:

+  CInOutTempBuffer();

+  ~CInOutTempBuffer();

+  void Create();

+

+  void InitWriting();

+  bool Write(const void *data, UInt32 size);

+

+  HRESULT WriteToStream(ISequentialOutStream *stream);

+  UInt64 GetDataSize() const { return _size; }

+};

+

+class CSequentialOutTempBufferImp:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  CInOutTempBuffer *_buf;

+public:

+  void Init(CInOutTempBuffer *buffer)  { _buf = buffer; }

+  MY_UNKNOWN_IMP

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+#endif

diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp
new file mode 100755
index 0000000..dd2d2d5
--- /dev/null
+++ b/CPP/7zip/Common/LimitedStreams.cpp
@@ -0,0 +1,154 @@
+// LimitedStreams.cpp

+

+#include "StdAfx.h"

+

+#include "LimitedStreams.h"

+#include "../../Common/Defs.h"

+

+STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  UInt32 realProcessedSize = 0;

+  UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size);

+  HRESULT result = S_OK;

+  if (sizeToRead > 0)

+  {

+    result = _stream->Read(data, sizeToRead, &realProcessedSize);

+    _pos += realProcessedSize;

+    if (realProcessedSize == 0)

+      _wasFinished = true;

+  }

+  if (processedSize != NULL)

+    *processedSize = realProcessedSize;

+  return result;

+}

+

+STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize != NULL)

+    *processedSize = 0;

+  if (_virtPos >= _size)

+    return (_virtPos == _size) ? S_OK: E_FAIL;

+  UInt64 rem = _size - _virtPos;

+  if (rem < size)

+    size = (UInt32)rem;

+  UInt64 newPos = _startOffset + _virtPos;

+  if (newPos != _physPos)

+  {

+    _physPos = newPos;

+    RINOK(SeekToPhys());

+  }

+  HRESULT res = _stream->Read(data, size, &size);

+  if (processedSize != NULL)

+    *processedSize = size;

+  _physPos += size;

+  _virtPos += size;

+  return res;

+}

+

+STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  switch(seekOrigin)

+  {

+    case STREAM_SEEK_SET: _virtPos = offset; break;

+    case STREAM_SEEK_CUR: _virtPos += offset; break;

+    case STREAM_SEEK_END: _virtPos = _size + offset; break;

+    default: return STG_E_INVALIDFUNCTION;

+  }

+  if (newPosition)

+    *newPosition = _virtPos;

+  return S_OK;

+}

+

+STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize != NULL)

+    *processedSize = 0;

+  if (_virtPos >= Size)

+    return (_virtPos == Size) ? S_OK: E_FAIL;

+

+  if (_curRem == 0)

+  {

+    UInt32 blockSize = (UInt32)1 << BlockSizeLog;

+    UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);

+    UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);

+    UInt32 phyBlock = Vector[virtBlock];

+    UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock;

+    if (newPos != _physPos)

+    {

+      _physPos = newPos;

+      RINOK(SeekToPhys());

+    }

+    _curRem = blockSize - offsetInBlock;

+    for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)

+      _curRem += (UInt32)1 << BlockSizeLog;

+    UInt64 rem = Size - _virtPos;

+    if (_curRem > rem)

+      _curRem = (UInt32)rem;

+  }

+  if (size > _curRem)

+    size = _curRem;

+  HRESULT res = Stream->Read(data, size, &size);

+  if (processedSize != NULL)

+    *processedSize = size;

+  _physPos += size;

+  _virtPos += size;

+  _curRem -= size;

+  return res;

+}

+ 

+STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  UInt64 newVirtPos = offset;

+  switch(seekOrigin)

+  {

+    case STREAM_SEEK_SET: break;

+    case STREAM_SEEK_CUR: newVirtPos += _virtPos; break;

+    case STREAM_SEEK_END: newVirtPos += Size; break;

+    default: return STG_E_INVALIDFUNCTION;

+  }

+  if (_virtPos != newVirtPos)

+    _curRem = 0;

+  _virtPos = newVirtPos;

+  if (newPosition)

+    *newPosition = newVirtPos;

+  return S_OK;

+}

+

+

+HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream)

+{

+  *resStream = 0;

+  CLimitedInStream *streamSpec = new CLimitedInStream;

+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;

+  streamSpec->SetStream(inStream);

+  RINOK(streamSpec->InitAndSeek(pos, size));

+  streamSpec->SeekToStart();

+  *resStream = streamTemp.Detach();

+  return S_OK;

+}

+

+STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  HRESULT result = S_OK;

+  if (processedSize != NULL)

+    *processedSize = 0;

+  if (size > _size)

+  {

+    if (_size == 0)

+    {

+      _overflow = true;

+      if (!_overflowIsAllowed)

+        return E_FAIL;

+      if (processedSize != NULL)

+        *processedSize = size;

+      return S_OK;

+    }

+    size = (UInt32)_size;

+  }

+  if (_stream)

+    result = _stream->Write(data, size, &size);

+  _size -= size;

+  if (processedSize != NULL)

+    *processedSize = size;

+  return result;

+}

diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h
new file mode 100755
index 0000000..caec98f
--- /dev/null
+++ b/CPP/7zip/Common/LimitedStreams.h
@@ -0,0 +1,125 @@
+// LimitedStreams.h

+

+#ifndef __LIMITED_STREAMS_H

+#define __LIMITED_STREAMS_H

+

+#include "../../Common/MyCom.h"

+#include "../../Common/MyVector.h"

+#include "../IStream.h"

+

+class CLimitedSequentialInStream:

+  public ISequentialInStream,

+  public CMyUnknownImp

+{

+  CMyComPtr<ISequentialInStream> _stream;

+  UInt64 _size;

+  UInt64 _pos;

+  bool _wasFinished;

+public:

+  void SetStream(ISequentialInStream *stream) { _stream = stream; }

+  void ReleaseStream() { _stream.Release(); }

+  void Init(UInt64 streamSize)

+  {

+    _size = streamSize;

+    _pos = 0;

+    _wasFinished = false;

+  }

+ 

+  MY_UNKNOWN_IMP

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  UInt64 GetSize() const { return _pos; }

+  bool WasFinished() const { return _wasFinished; }

+};

+

+class CLimitedInStream:

+  public IInStream,

+  public CMyUnknownImp

+{

+  CMyComPtr<IInStream> _stream;

+  UInt64 _virtPos;

+  UInt64 _physPos;

+  UInt64 _size;

+  UInt64 _startOffset;

+

+  HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }

+public:

+  void SetStream(IInStream *stream) { _stream = stream; }

+  HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)

+  {

+    _startOffset = startOffset;

+    _physPos = startOffset;

+    _virtPos = 0;

+    _size = size;

+    return SeekToPhys();

+  }

+ 

+  MY_UNKNOWN_IMP1(IInStream)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+

+  HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }

+};

+

+class CClusterInStream:

+  public IInStream,

+  public CMyUnknownImp

+{

+  UInt64 _virtPos;

+  UInt64 _physPos;

+  UInt32 _curRem;

+public:

+  CMyComPtr<IInStream> Stream;

+  UInt64 StartOffset;

+  UInt64 Size;

+  int BlockSizeLog;

+  CRecordVector<UInt32> Vector;

+

+  HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }

+

+  HRESULT InitAndSeek()

+  {

+    _curRem = 0;

+    _virtPos = 0;

+    _physPos = StartOffset;

+    if (Vector.Size() > 0)

+    {

+      _physPos = StartOffset + (Vector[0] << BlockSizeLog);

+      return SeekToPhys();

+    }

+    return S_OK;

+  }

+

+  MY_UNKNOWN_IMP1(IInStream)

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+};

+

+HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream);

+

+class CLimitedSequentialOutStream:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  CMyComPtr<ISequentialOutStream> _stream;

+  UInt64 _size;

+  bool _overflow;

+  bool _overflowIsAllowed;

+public:

+  MY_UNKNOWN_IMP

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }

+  void ReleaseStream() { _stream.Release(); }

+  void Init(UInt64 size, bool overflowIsAllowed = false)

+  {

+    _size = size;

+    _overflow = false;

+    _overflowIsAllowed = overflowIsAllowed;

+  }

+  bool IsFinishedOK() const { return (_size == 0 && !_overflow); }

+  UInt64 GetRem() const { return _size; }

+};

+

+#endif

diff --git a/CPP/7zip/Common/LockedStream.cpp b/CPP/7zip/Common/LockedStream.cpp
new file mode 100755
index 0000000..d1bbf6d
--- /dev/null
+++ b/CPP/7zip/Common/LockedStream.cpp
@@ -0,0 +1,23 @@
+// LockedStream.cpp

+

+#include "StdAfx.h"

+

+#include "LockedStream.h"

+

+HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size,

+  UInt32 *processedSize)

+{

+  NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);

+  RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL));

+  return _stream->Read(data, size, processedSize);

+}

+

+STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  UInt32 realProcessedSize = 0;

+  HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize);

+  _pos += realProcessedSize;

+  if (processedSize != NULL)

+    *processedSize = realProcessedSize;

+  return result;

+}

diff --git a/CPP/7zip/Common/LockedStream.h b/CPP/7zip/Common/LockedStream.h
new file mode 100755
index 0000000..e12e22a
--- /dev/null
+++ b/CPP/7zip/Common/LockedStream.h
@@ -0,0 +1,38 @@
+// LockedStream.h

+

+#ifndef __LOCKEDSTREAM_H

+#define __LOCKEDSTREAM_H

+

+#include "../../Windows/Synchronization.h"

+#include "../../Common/MyCom.h"

+#include "../IStream.h"

+

+class CLockedInStream

+{

+  CMyComPtr<IInStream> _stream;

+  NWindows::NSynchronization::CCriticalSection _criticalSection;

+public:

+  void Init(IInStream *stream)

+    { _stream = stream; }

+  HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize);

+};

+

+class CLockedSequentialInStreamImp:

+  public ISequentialInStream,

+  public CMyUnknownImp

+{

+  CLockedInStream *_lockedInStream;

+  UInt64 _pos;

+public:

+  void Init(CLockedInStream *lockedInStream, UInt64 startPos)

+  {

+    _lockedInStream = lockedInStream;

+    _pos = startPos;

+  }

+

+  MY_UNKNOWN_IMP

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+};

+

+#endif

diff --git a/CPP/7zip/Common/MethodId.cpp b/CPP/7zip/Common/MethodId.cpp
new file mode 100755
index 0000000..705cc4d
--- /dev/null
+++ b/CPP/7zip/Common/MethodId.cpp
@@ -0,0 +1,27 @@
+// MethodId.cpp

+

+#include "StdAfx.h"

+

+#include "MethodId.h"

+#include "../../Common/MyString.h"

+

+static inline wchar_t GetHex(Byte value)

+{

+  return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

+}

+

+UString ConvertMethodIdToString(UInt64 id)

+{

+  wchar_t s[32];

+  int len = 32;

+  s[--len] = 0;

+  do

+  {

+    s[--len] = GetHex((Byte)id & 0xF);

+    id >>= 4;

+    s[--len] = GetHex((Byte)id & 0xF);

+    id >>= 4;

+  }

+  while (id != 0);

+  return s + len;

+}

diff --git a/CPP/7zip/Common/MethodId.h b/CPP/7zip/Common/MethodId.h
new file mode 100755
index 0000000..9551723
--- /dev/null
+++ b/CPP/7zip/Common/MethodId.h
@@ -0,0 +1,10 @@
+// MethodId.h

+

+#ifndef __7Z_METHOD_ID_H

+#define __7Z_METHOD_ID_H

+

+#include "../../Common/Types.h"

+

+typedef UInt64 CMethodId;

+

+#endif

diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp
new file mode 100755
index 0000000..937708e
--- /dev/null
+++ b/CPP/7zip/Common/MethodProps.cpp
@@ -0,0 +1,99 @@
+// MethodProps.cpp

+

+#include "StdAfx.h"

+

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+

+#include "MethodProps.h"

+

+static const UInt64 k_LZMA = 0x030101;

+static const UInt64 k_LZMA2 = 0x21;

+

+HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder)

+{

+  bool tryReduce = false;

+  UInt32 reducedDictionarySize = 1 << 10;

+  if (inSizeForReduce != 0 && (method.Id == k_LZMA || method.Id == k_LZMA2))

+  {

+    for (;;)

+    {

+      const UInt32 step = (reducedDictionarySize >> 1);

+      if (reducedDictionarySize >= *inSizeForReduce)

+      {

+        tryReduce = true;

+        break;

+      }

+      reducedDictionarySize += step;

+      if (reducedDictionarySize >= *inSizeForReduce)

+      {

+        tryReduce = true;

+        break;

+      }

+      if (reducedDictionarySize >= ((UInt32)3 << 30))

+        break;

+      reducedDictionarySize += step;

+    }

+  }

+

+  {

+    int numProps = method.Props.Size();

+    CMyComPtr<ICompressSetCoderProperties> setCoderProperties;

+    coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);

+    if (setCoderProperties == NULL)

+    {

+      if (numProps != 0)

+        return E_INVALIDARG;

+    }

+    else

+    {

+      CRecordVector<PROPID> propIDs;

+      NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps];

+      HRESULT res = S_OK;

+      try

+      {

+        for (int i = 0; i < numProps; i++)

+        {

+          const CProp &prop = method.Props[i];

+          propIDs.Add(prop.Id);

+          NWindows::NCOM::CPropVariant &value = values[i];

+          value = prop.Value;

+          // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal)

+          if (tryReduce)

+            if (prop.Id == NCoderPropID::kDictionarySize)

+              if (value.vt == VT_UI4)

+                if (reducedDictionarySize < value.ulVal)

+            value.ulVal = reducedDictionarySize;

+        }

+        CMyComPtr<ICompressSetCoderProperties> setCoderProperties;

+        coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);

+        res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps);

+      }

+      catch(...)

+      {

+        delete []values;

+        throw;

+      }

+      delete []values;

+      RINOK(res);

+    }

+  }

+ 

+  /*

+  CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;

+  coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);

+  if (writeCoderProperties != NULL)

+  {

+    CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;

+    CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);

+    outStreamSpec->Init();

+    RINOK(writeCoderProperties->WriteCoderProperties(outStream));

+    size_t size = outStreamSpec->GetSize();

+    filterProps.SetCapacity(size);

+    memmove(filterProps, outStreamSpec->GetBuffer(), size);

+  }

+  */

+  return S_OK;

+}

+

diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h
new file mode 100755
index 0000000..75b87f1
--- /dev/null
+++ b/CPP/7zip/Common/MethodProps.h
@@ -0,0 +1,41 @@
+// MethodProps.h

+

+#ifndef __7Z_METHOD_PROPS_H

+#define __7Z_METHOD_PROPS_H

+

+#include "../../Common/MyVector.h"

+

+#include "../../Windows/PropVariant.h"

+

+#include "MethodId.h"

+

+struct CProp

+{

+  PROPID Id;

+  NWindows::NCOM::CPropVariant Value;

+};

+

+struct CMethod

+{

+  CMethodId Id;

+  CObjectVector<CProp> Props;

+};

+

+struct CMethodsMode

+{

+  CObjectVector<CMethod> Methods;

+  #ifndef _7ZIP_ST

+  UInt32 NumThreads;

+  #endif

+

+  CMethodsMode()

+      #ifndef _7ZIP_ST

+      : NumThreads(1)

+      #endif

+  {}

+  bool IsEmpty() const { return Methods.IsEmpty() ; }

+};

+

+HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder);

+

+#endif

diff --git a/CPP/7zip/Common/OffsetStream.cpp b/CPP/7zip/Common/OffsetStream.cpp
new file mode 100755
index 0000000..f10f54c
--- /dev/null
+++ b/CPP/7zip/Common/OffsetStream.cpp
@@ -0,0 +1,35 @@
+// OffsetStream.cpp

+

+#include "StdAfx.h"

+

+#include "Common/Defs.h"

+#include "OffsetStream.h"

+

+HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset)

+{

+  _offset = offset;

+  _stream = stream;

+  return _stream->Seek(offset, STREAM_SEEK_SET, NULL);

+}

+

+STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  return _stream->Write(data, size, processedSize);

+}

+

+STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin,

+    UInt64 *newPosition)

+{

+  UInt64 absoluteNewPosition;

+  if (seekOrigin == STREAM_SEEK_SET)

+    offset += _offset;

+  HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition);

+  if (newPosition != NULL)

+    *newPosition = absoluteNewPosition - _offset;

+  return result;

+}

+

+STDMETHODIMP COffsetOutStream::SetSize(UInt64 newSize)

+{

+  return _stream->SetSize(_offset + newSize);

+}

diff --git a/CPP/7zip/Common/OffsetStream.h b/CPP/7zip/Common/OffsetStream.h
new file mode 100755
index 0000000..972a8ce
--- /dev/null
+++ b/CPP/7zip/Common/OffsetStream.h
@@ -0,0 +1,25 @@
+// OffsetStream.h

+

+#ifndef __OFFSETSTREAM_H

+#define __OFFSETSTREAM_H

+

+#include "Common/MyCom.h"

+#include "../IStream.h"

+

+class COffsetOutStream:

+  public IOutStream,

+  public CMyUnknownImp

+{

+  UInt64 _offset;

+  CMyComPtr<IOutStream> _stream;

+public:

+  HRESULT Init(IOutStream *stream, UInt64 offset);

+  

+  MY_UNKNOWN_IMP

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+  STDMETHOD(SetSize)(UInt64 newSize);

+};

+

+#endif

diff --git a/CPP/7zip/Common/OutBuffer.cpp b/CPP/7zip/Common/OutBuffer.cpp
new file mode 100755
index 0000000..4e55f55
--- /dev/null
+++ b/CPP/7zip/Common/OutBuffer.cpp
@@ -0,0 +1,116 @@
+// OutBuffer.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+

+#include "OutBuffer.h"

+

+bool COutBuffer::Create(UInt32 bufferSize)

+{

+  const UInt32 kMinBlockSize = 1;

+  if (bufferSize < kMinBlockSize)

+    bufferSize = kMinBlockSize;

+  if (_buffer != 0 && _bufferSize == bufferSize)

+    return true;

+  Free();

+  _bufferSize = bufferSize;

+  _buffer = (Byte *)::MidAlloc(bufferSize);

+  return (_buffer != 0);

+}

+

+void COutBuffer::Free()

+{

+  ::MidFree(_buffer);

+  _buffer = 0;

+}

+

+void COutBuffer::SetStream(ISequentialOutStream *stream)

+{

+  _stream = stream;

+}

+

+void COutBuffer::Init()

+{

+  _streamPos = 0;

+  _limitPos = _bufferSize;

+  _pos = 0;

+  _processedSize = 0;

+  _overDict = false;

+  #ifdef _NO_EXCEPTIONS

+  ErrorCode = S_OK;

+  #endif

+}

+

+UInt64 COutBuffer::GetProcessedSize() const

+{

+  UInt64 res = _processedSize + _pos - _streamPos;

+  if (_streamPos > _pos)

+    res += _bufferSize;

+  return res;

+}

+

+

+HRESULT COutBuffer::FlushPart()

+{

+  // _streamPos < _bufferSize

+  UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos);

+  HRESULT result = S_OK;

+  #ifdef _NO_EXCEPTIONS

+  result = ErrorCode;

+  #endif

+  if (_buffer2 != 0)

+  {

+    memmove(_buffer2, _buffer + _streamPos, size);

+    _buffer2 += size;

+  }

+

+  if (_stream != 0

+      #ifdef _NO_EXCEPTIONS

+      && (ErrorCode == S_OK)

+      #endif

+     )

+  {

+    UInt32 processedSize = 0;

+    result = _stream->Write(_buffer + _streamPos, size, &processedSize);

+    size = processedSize;

+  }

+  _streamPos += size;

+  if (_streamPos == _bufferSize)

+    _streamPos = 0;

+  if (_pos == _bufferSize)

+  {

+    _overDict = true;

+    _pos = 0;

+  }

+  _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize;

+  _processedSize += size;

+  return result;

+}

+

+HRESULT COutBuffer::Flush()

+{

+  #ifdef _NO_EXCEPTIONS

+  if (ErrorCode != S_OK)

+    return ErrorCode;

+  #endif

+

+  while(_streamPos != _pos)

+  {

+    HRESULT result = FlushPart();

+    if (result != S_OK)

+      return result;

+  }

+  return S_OK;

+}

+

+void COutBuffer::FlushWithCheck()

+{

+  HRESULT result = Flush();

+  #ifdef _NO_EXCEPTIONS

+  ErrorCode = result;

+  #else

+  if (result != S_OK)

+    throw COutBufferException(result);

+  #endif

+}

diff --git a/CPP/7zip/Common/OutBuffer.h b/CPP/7zip/Common/OutBuffer.h
new file mode 100755
index 0000000..e2e76ad
--- /dev/null
+++ b/CPP/7zip/Common/OutBuffer.h
@@ -0,0 +1,64 @@
+// OutBuffer.h

+

+#ifndef __OUTBUFFER_H

+#define __OUTBUFFER_H

+

+#include "../IStream.h"

+#include "../../Common/MyCom.h"

+#include "../../Common/MyException.h"

+

+#ifndef _NO_EXCEPTIONS

+struct COutBufferException: public CSystemException

+{

+  COutBufferException(HRESULT errorCode): CSystemException(errorCode) {}

+};

+#endif

+

+class COutBuffer

+{

+protected:

+  Byte *_buffer;

+  UInt32 _pos;

+  UInt32 _limitPos;

+  UInt32 _streamPos;

+  UInt32 _bufferSize;

+  CMyComPtr<ISequentialOutStream> _stream;

+  UInt64 _processedSize;

+  Byte  *_buffer2;

+  bool _overDict;

+

+  HRESULT FlushPart();

+public:

+  #ifdef _NO_EXCEPTIONS

+  HRESULT ErrorCode;

+  #endif

+

+  COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {}

+  ~COutBuffer() { Free(); }

+  

+  bool Create(UInt32 bufferSize);

+  void Free();

+

+  void SetMemStream(Byte *buffer) { _buffer2 = buffer; }

+  void SetStream(ISequentialOutStream *stream);

+  void Init();

+  HRESULT Flush();

+  void FlushWithCheck();

+  void ReleaseStream() {  _stream.Release(); }

+

+  void WriteByte(Byte b)

+  {

+    _buffer[_pos++] = b;

+    if(_pos == _limitPos)

+      FlushWithCheck();

+  }

+  void WriteBytes(const void *data, size_t size)

+  {

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

+      WriteByte(((const Byte *)data)[i]);

+  }

+

+  UInt64 GetProcessedSize() const;

+};

+

+#endif

diff --git a/CPP/7zip/Common/ProgressUtils.cpp b/CPP/7zip/Common/ProgressUtils.cpp
new file mode 100755
index 0000000..84a3eaf
--- /dev/null
+++ b/CPP/7zip/Common/ProgressUtils.cpp
@@ -0,0 +1,42 @@
+// ProgressUtils.h

+

+#include "StdAfx.h"

+

+#include "ProgressUtils.h"

+

+CLocalProgress::CLocalProgress()

+{

+  ProgressOffset = InSize = OutSize = 0;

+  SendRatio = SendProgress = true;

+}

+

+void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)

+{

+  _ratioProgress.Release();

+  _progress = progress;

+  _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress);

+  _inSizeIsMain = inSizeIsMain;

+}

+

+STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)

+{

+  UInt64 inSizeNew = InSize, outSizeNew = OutSize;

+  if (inSize)

+    inSizeNew += (*inSize);

+  if (outSize)

+    outSizeNew += (*outSize);

+  if (SendRatio && _ratioProgress)

+  {

+    RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew));

+  }

+  inSizeNew += ProgressOffset;

+  outSizeNew += ProgressOffset;

+  if (SendProgress)

+    return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew);

+  return S_OK;

+}

+

+HRESULT CLocalProgress::SetCur()

+{

+  return SetRatioInfo(NULL, NULL);

+}

diff --git a/CPP/7zip/Common/ProgressUtils.h b/CPP/7zip/Common/ProgressUtils.h
new file mode 100755
index 0000000..c620484
--- /dev/null
+++ b/CPP/7zip/Common/ProgressUtils.h
@@ -0,0 +1,34 @@
+// ProgressUtils.h

+

+#ifndef __PROGRESSUTILS_H

+#define __PROGRESSUTILS_H

+

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+#include "../IProgress.h"

+

+class CLocalProgress:

+  public ICompressProgressInfo,

+  public CMyUnknownImp

+{

+  CMyComPtr<IProgress> _progress;

+  CMyComPtr<ICompressProgressInfo> _ratioProgress;

+  bool _inSizeIsMain;

+public:

+  UInt64 ProgressOffset;

+  UInt64 InSize;

+  UInt64 OutSize;

+  bool SendRatio;

+  bool SendProgress;

+

+  CLocalProgress();

+  void Init(IProgress *progress, bool inSizeIsMain);

+  HRESULT SetCur();

+

+  MY_UNKNOWN_IMP

+

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

+};

+

+#endif

diff --git a/CPP/7zip/Common/RegisterArc.h b/CPP/7zip/Common/RegisterArc.h
new file mode 100755
index 0000000..7066325
--- /dev/null
+++ b/CPP/7zip/Common/RegisterArc.h
@@ -0,0 +1,32 @@
+// RegisterArc.h

+

+#ifndef __REGISTER_ARC_H

+#define __REGISTER_ARC_H

+

+#include "../Archive/IArchive.h"

+

+typedef IInArchive * (*CreateInArchiveP)();

+typedef IOutArchive * (*CreateOutArchiveP)();

+

+struct CArcInfo

+{

+  const wchar_t *Name;

+  const wchar_t *Ext;

+  const wchar_t *AddExt;

+  Byte ClassId;

+  Byte Signature[16];

+  int SignatureSize;

+  bool KeepName;

+  CreateInArchiveP CreateInArchive;

+  CreateOutArchiveP CreateOutArchive;

+};

+

+void RegisterArc(const CArcInfo *arcInfo);

+

+#define REGISTER_ARC_NAME(x) CRegister ## x

+

+#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \

+    REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \

+    static REGISTER_ARC_NAME(x) g_RegisterArc;

+

+#endif

diff --git a/CPP/7zip/Common/RegisterCodec.h b/CPP/7zip/Common/RegisterCodec.h
new file mode 100755
index 0000000..c59ab66
--- /dev/null
+++ b/CPP/7zip/Common/RegisterCodec.h
@@ -0,0 +1,33 @@
+// RegisterCodec.h

+

+#ifndef __REGISTERCODEC_H

+#define __REGISTERCODEC_H

+

+#include "../Common/MethodId.h"

+

+typedef void * (*CreateCodecP)();

+struct CCodecInfo

+{

+  CreateCodecP CreateDecoder;

+  CreateCodecP CreateEncoder;

+  CMethodId Id;

+  const wchar_t *Name;

+  UInt32 NumInStreams;

+  bool IsFilter;

+};

+

+void RegisterCodec(const CCodecInfo *codecInfo);

+

+#define REGISTER_CODEC_NAME(x) CRegisterCodec ## x

+

+#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \

+    REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \

+    static REGISTER_CODEC_NAME(x) g_RegisterCodec;

+

+#define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x

+#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \

+    REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \

+    RegisterCodec(&g_CodecsInfo[i]); }}; \

+    static REGISTER_CODECS_NAME(x) g_RegisterCodecs;

+

+#endif

diff --git a/CPP/7zip/Common/StdAfx.h b/CPP/7zip/Common/StdAfx.h
new file mode 100755
index 0000000..f56e92f
--- /dev/null
+++ b/CPP/7zip/Common/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../Common/MyWindows.h"

+#include "../../Common/NewHandler.h"

+

+#endif

diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp
new file mode 100755
index 0000000..cb3bf99
--- /dev/null
+++ b/CPP/7zip/Common/StreamBinder.cpp
@@ -0,0 +1,150 @@
+// StreamBinder.cpp

+

+#include "StdAfx.h"

+

+#include "StreamBinder.h"

+#include "../../Common/Defs.h"

+#include "../../Common/MyCom.h"

+

+using namespace NWindows;

+using namespace NSynchronization;

+

+class CSequentialInStreamForBinder:

+  public ISequentialInStream,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP

+

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+private:

+  CStreamBinder *m_StreamBinder;

+public:

+  ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); }

+  void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }

+};

+

+STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize)

+  { return m_StreamBinder->Read(data, size, processedSize); }

+

+class CSequentialOutStreamForBinder:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+

+private:

+  CStreamBinder *m_StreamBinder;

+public:

+  ~CSequentialOutStreamForBinder() {  m_StreamBinder->CloseWrite(); }

+  void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }

+};

+

+STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)

+  { return m_StreamBinder->Write(data, size, processedSize); }

+

+

+//////////////////////////

+// CStreamBinder

+// (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished.

+

+HRes CStreamBinder::CreateEvents()

+{

+  RINOK(_allBytesAreWritenEvent.Create(true));

+  RINOK(_thereAreBytesToReadEvent.Create());

+  return _readStreamIsClosedEvent.Create();

+}

+

+void CStreamBinder::ReInit()

+{

+  _thereAreBytesToReadEvent.Reset();

+  _readStreamIsClosedEvent.Reset();

+  ProcessedSize = 0;

+}

+

+

+  

+void CStreamBinder::CreateStreams(ISequentialInStream **inStream,

+      ISequentialOutStream **outStream)

+{

+  CSequentialInStreamForBinder *inStreamSpec = new

+      CSequentialInStreamForBinder;

+  CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);

+  inStreamSpec->SetBinder(this);

+  *inStream = inStreamLoc.Detach();

+

+  CSequentialOutStreamForBinder *outStreamSpec = new

+      CSequentialOutStreamForBinder;

+  CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);

+  outStreamSpec->SetBinder(this);

+  *outStream = outStreamLoc.Detach();

+

+  _buffer = NULL;

+  _bufferSize= 0;

+  ProcessedSize = 0;

+}

+

+HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  UInt32 sizeToRead = size;

+  if (size > 0)

+  {

+    RINOK(_thereAreBytesToReadEvent.Lock());

+    sizeToRead = MyMin(_bufferSize, size);

+    if (_bufferSize > 0)

+    {

+      memcpy(data, _buffer, sizeToRead);

+      _buffer = ((const Byte *)_buffer) + sizeToRead;

+      _bufferSize -= sizeToRead;

+      if (_bufferSize == 0)

+      {

+        _thereAreBytesToReadEvent.Reset();

+        _allBytesAreWritenEvent.Set();

+      }

+    }

+  }

+  if (processedSize != NULL)

+    *processedSize = sizeToRead;

+  ProcessedSize += sizeToRead;

+  return S_OK;

+}

+

+void CStreamBinder::CloseRead()

+{

+  _readStreamIsClosedEvent.Set();

+}

+

+HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (size > 0)

+  {

+    _buffer = data;

+    _bufferSize = size;

+    _allBytesAreWritenEvent.Reset();

+    _thereAreBytesToReadEvent.Set();

+

+    HANDLE events[2];

+    events[0] = _allBytesAreWritenEvent;

+    events[1] = _readStreamIsClosedEvent;

+    DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);

+    if (waitResult != WAIT_OBJECT_0 + 0)

+    {

+      // ReadingWasClosed = true;

+      return S_FALSE;

+    }

+    // if(!_allBytesAreWritenEvent.Lock())

+    //   return E_FAIL;

+  }

+  if (processedSize != NULL)

+    *processedSize = size;

+  return S_OK;

+}

+

+void CStreamBinder::CloseWrite()

+{

+  // _bufferSize must be = 0

+  _thereAreBytesToReadEvent.Set();

+}

diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h
new file mode 100755
index 0000000..b5d6c0d
--- /dev/null
+++ b/CPP/7zip/Common/StreamBinder.h
@@ -0,0 +1,32 @@
+// StreamBinder.h

+

+#ifndef __STREAMBINDER_H

+#define __STREAMBINDER_H

+

+#include "../IStream.h"

+#include "../../Windows/Synchronization.h"

+

+class CStreamBinder

+{

+  NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent;

+  NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent;

+  NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent;

+  UInt32 _bufferSize;

+  const void *_buffer;

+public:

+  // bool ReadingWasClosed;

+  UInt64 ProcessedSize;

+  CStreamBinder() {}

+  HRes CreateEvents();

+

+  void CreateStreams(ISequentialInStream **inStream,

+      ISequentialOutStream **outStream);

+  HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);

+  void CloseRead();

+

+  HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize);

+  void CloseWrite();

+  void ReInit();

+};

+

+#endif

diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp
new file mode 100755
index 0000000..a18f1bc
--- /dev/null
+++ b/CPP/7zip/Common/StreamObjects.cpp
@@ -0,0 +1,221 @@
+// StreamObjects.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+

+#include "StreamObjects.h"

+

+STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+  if (size == 0)

+    return S_OK;

+  if (_pos > _size)

+    return E_FAIL;

+  size_t rem = _size - (size_t)_pos;

+  if (rem > size)

+    rem = (size_t)size;

+  memcpy(data, _data + (size_t)_pos, rem);

+  _pos += rem;

+  if (processedSize)

+    *processedSize = (UInt32)rem;

+  return S_OK;

+}

+

+STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  switch(seekOrigin)

+  {

+    case STREAM_SEEK_SET: _pos = offset; break;

+    case STREAM_SEEK_CUR: _pos += offset; break;

+    case STREAM_SEEK_END: _pos = _size + offset; break;

+    default: return STG_E_INVALIDFUNCTION;

+  }

+  if (newPosition)

+    *newPosition = _pos;

+  return S_OK;

+}

+

+void CByteDynBuffer::Free()

+{

+  free(_buf);

+  _buf = 0;

+  _capacity = 0;

+}

+

+bool CByteDynBuffer::EnsureCapacity(size_t cap)

+{

+  if (cap <= _capacity)

+    return true;

+  size_t delta;

+  if (_capacity > 64)

+    delta = _capacity / 4;

+  else if (_capacity > 8)

+    delta = 16;

+  else

+    delta = 4;

+  cap = MyMax(_capacity + delta, cap);

+  Byte *buf = (Byte *)realloc(_buf, cap);

+  if (!buf)

+    return false;

+  _buf = buf;

+  _capacity = cap;

+  return true;

+}

+

+Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize)

+{

+  addSize += _size;

+  if (addSize < _size)

+    return NULL;

+  if (!_buffer.EnsureCapacity(addSize))

+    return NULL;

+  return (Byte *)_buffer + _size;

+}

+

+void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const

+{

+  dest.SetCapacity(_size);

+  memcpy(dest, _buffer, _size);

+}

+

+STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+  if (size == 0)

+    return S_OK;

+  Byte *buf = GetBufPtrForWriting(size);

+  if (!buf)

+    return E_OUTOFMEMORY;

+  memcpy(buf, data, size);

+  UpdateSize(size);

+  if (processedSize)

+    *processedSize = size;

+  return S_OK;

+}

+

+STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  size_t rem = _size - _pos;

+  if (rem > size)

+    rem = (size_t)size;

+  memcpy(_buffer + _pos, data, rem);

+  _pos += rem;

+  if (processedSize)

+    *processedSize = (UInt32)rem;

+  return (rem != 0 || size == 0) ? S_OK : E_FAIL;

+}

+

+STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  UInt32 realProcessedSize;

+  HRESULT result = _stream->Write(data, size, &realProcessedSize);

+  _size += realProcessedSize;

+  if (processedSize)

+    *processedSize = realProcessedSize;

+  return result;

+}

+

+static const UInt64 kEmptyTag = (UInt64)(Int64)-1;

+

+void CCachedInStream::Free()

+{

+  MyFree(_tags);

+  _tags = 0;

+  MidFree(_data);

+  _data = 0;

+}

+

+bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog)

+{

+  unsigned sizeLog = blockSizeLog + numBlocksLog;

+  if (sizeLog >= sizeof(size_t) * 8)

+    return false;

+  size_t dataSize = (size_t)1 << sizeLog;

+  if (_data == 0 || dataSize != _dataSize)

+  {

+    MidFree(_data);

+    _data = (Byte *)MidAlloc(dataSize);

+    if (_data == 0)

+      return false;

+    _dataSize = dataSize;

+  }

+  if (_tags == 0 || numBlocksLog != _numBlocksLog)

+  {

+    MyFree(_tags);

+    _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog);

+    if (_tags == 0)

+      return false;

+    _numBlocksLog = numBlocksLog;

+  }

+  _blockSizeLog = blockSizeLog;

+  return true;

+}

+

+void CCachedInStream::Init(UInt64 size)

+{

+  _size = size;

+  _pos = 0;

+  size_t numBlocks = (size_t)1 << _numBlocksLog;

+  for (size_t i = 0; i < numBlocks; i++)

+    _tags[i] = kEmptyTag;

+}

+

+STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+  if (size == 0)

+    return S_OK;

+  if (_pos > _size)

+    return E_FAIL;

+

+  {

+    UInt64 rem = _size - _pos;

+    if (size > rem)

+      size = (UInt32)rem;

+  }

+

+  while (size != 0)

+  {

+    UInt64 cacheTag = _pos >> _blockSizeLog;

+    size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1);

+    Byte *p = _data + (cacheIndex << _blockSizeLog);

+    if (_tags[cacheIndex] != cacheTag)

+    {

+      UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);

+      size_t blockSize = (size_t)1 << _blockSizeLog;

+      if (blockSize > remInBlock)

+        blockSize = (size_t)remInBlock;

+      RINOK(ReadBlock(cacheTag, p, blockSize));

+      _tags[cacheIndex] = cacheTag;

+    }

+    size_t offset = (size_t)_pos & (((size_t)1 << _blockSizeLog) - 1);

+    UInt32 cur = (UInt32)MyMin(((size_t)1 << _blockSizeLog) - offset, (size_t)size);

+    memcpy(data, p + offset, cur);

+    if (processedSize)

+      *processedSize += cur;

+    data = (void *)((const Byte *)data + cur);

+    _pos += cur;

+    size -= cur;

+  }

+

+  return S_OK;

+}

+ 

+STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  switch(seekOrigin)

+  {

+    case STREAM_SEEK_SET: _pos = offset; break;

+    case STREAM_SEEK_CUR: _pos = _pos + offset; break;

+    case STREAM_SEEK_END: _pos = _size + offset; break;

+    default: return STG_E_INVALIDFUNCTION;

+  }

+  if (newPosition != 0)

+    *newPosition = _pos;

+  return S_OK;

+}

diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h
new file mode 100755
index 0000000..ed1532c
--- /dev/null
+++ b/CPP/7zip/Common/StreamObjects.h
@@ -0,0 +1,135 @@
+// StreamObjects.h

+

+#ifndef __STREAM_OBJECTS_H

+#define __STREAM_OBJECTS_H

+

+#include "../../Common/Buffer.h"

+#include "../../Common/MyCom.h"

+#include "../IStream.h"

+

+struct CReferenceBuf:

+  public IUnknown,

+  public CMyUnknownImp

+{

+  CByteBuffer Buf;

+  MY_UNKNOWN_IMP

+};

+

+class CBufInStream:

+  public IInStream,

+  public CMyUnknownImp

+{

+  const Byte *_data;

+  UInt64 _pos;

+  size_t _size;

+  CMyComPtr<IUnknown> _ref;

+public:

+  void Init(const Byte *data, size_t size, IUnknown *ref = 0)

+  {

+    _data = data;

+    _size = size;

+    _pos = 0;

+    _ref = ref;

+  }

+  void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.GetCapacity(), ref); }

+

+  MY_UNKNOWN_IMP1(IInStream)

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+};

+

+class CByteDynBuffer

+{

+  size_t _capacity;

+  Byte *_buf;

+public:

+  CByteDynBuffer(): _capacity(0), _buf(0) {};

+  // there is no copy constructor. So don't copy this object.

+  ~CByteDynBuffer() { Free(); }

+  void Free();

+  size_t GetCapacity() const { return  _capacity; }

+  operator Byte*() const { return _buf; };

+  operator const Byte*() const { return _buf; };

+  bool EnsureCapacity(size_t capacity);

+};

+

+class CDynBufSeqOutStream:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  CByteDynBuffer _buffer;

+  size_t _size;

+public:

+  CDynBufSeqOutStream(): _size(0) {}

+  void Init() { _size = 0;  }

+  size_t GetSize() const { return _size; }

+  const Byte *GetBuffer() const { return _buffer; }

+  void CopyToBuffer(CByteBuffer &dest) const;

+  Byte *GetBufPtrForWriting(size_t addSize);

+  void UpdateSize(size_t addSize) { _size += addSize; }

+

+  MY_UNKNOWN_IMP

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+class CBufPtrSeqOutStream:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  Byte *_buffer;

+  size_t _size;

+  size_t _pos;

+public:

+  void Init(Byte *buffer, size_t size)

+  {

+    _buffer = buffer;

+    _pos = 0;

+    _size = size;

+  }

+  size_t GetPos() const { return _pos; }

+

+  MY_UNKNOWN_IMP

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+class CSequentialOutStreamSizeCount:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+  CMyComPtr<ISequentialOutStream> _stream;

+  UInt64 _size;

+public:

+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }

+  void Init() { _size = 0; }

+  UInt64 GetSize() const { return _size; }

+

+  MY_UNKNOWN_IMP

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+class CCachedInStream:

+  public IInStream,

+  public CMyUnknownImp

+{

+  UInt64 *_tags;

+  Byte *_data;

+  size_t _dataSize;

+  unsigned _blockSizeLog;

+  unsigned _numBlocksLog;

+  UInt64 _size;

+  UInt64 _pos;

+protected:

+  virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0;

+public:

+  CCachedInStream(): _tags(0), _data(0) {}

+  virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!!

+  void Free();

+  bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog);

+  void Init(UInt64 size);

+

+  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+};

+

+#endif

diff --git a/CPP/7zip/Common/StreamUtils.cpp b/CPP/7zip/Common/StreamUtils.cpp
new file mode 100755
index 0000000..57ff4ee
--- /dev/null
+++ b/CPP/7zip/Common/StreamUtils.cpp
@@ -0,0 +1,56 @@
+// StreamUtils.cpp

+

+#include "StdAfx.h"

+

+#include "StreamUtils.h"

+

+static const UInt32 kBlockSize = ((UInt32)1 << 31);

+

+HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize)

+{

+  size_t size = *processedSize;

+  *processedSize = 0;

+  while (size != 0)

+  {

+    UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;

+    UInt32 processedSizeLoc;

+    HRESULT res = stream->Read(data, curSize, &processedSizeLoc);

+    *processedSize += processedSizeLoc;

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

+    size -= processedSizeLoc;

+    RINOK(res);

+    if (processedSizeLoc == 0)

+      return S_OK;

+  }

+  return S_OK;

+}

+

+HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size)

+{

+  size_t processedSize = size;

+  RINOK(ReadStream(stream, data, &processedSize));

+  return (size == processedSize) ? S_OK : S_FALSE;

+}

+

+HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size)

+{

+  size_t processedSize = size;

+  RINOK(ReadStream(stream, data, &processedSize));

+  return (size == processedSize) ? S_OK : E_FAIL;

+}

+

+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size)

+{

+  while (size != 0)

+  {

+    UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;

+    UInt32 processedSizeLoc;

+    HRESULT res = stream->Write(data, curSize, &processedSizeLoc);

+    data = (const void *)((const Byte *)data + processedSizeLoc);

+    size -= processedSizeLoc;

+    RINOK(res);

+    if (processedSizeLoc == 0)

+      return E_FAIL;

+  }

+  return S_OK;

+}

diff --git a/CPP/7zip/Common/StreamUtils.h b/CPP/7zip/Common/StreamUtils.h
new file mode 100755
index 0000000..30535ab
--- /dev/null
+++ b/CPP/7zip/Common/StreamUtils.h
@@ -0,0 +1,13 @@
+// StreamUtils.h

+

+#ifndef __STREAMUTILS_H

+#define __STREAMUTILS_H

+

+#include "../IStream.h"

+

+HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size);

+HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size);

+HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size);

+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size);

+

+#endif

diff --git a/CPP/7zip/Common/VirtThread.cpp b/CPP/7zip/Common/VirtThread.cpp
new file mode 100755
index 0000000..c07caba
--- /dev/null
+++ b/CPP/7zip/Common/VirtThread.cpp
@@ -0,0 +1,46 @@
+// VirtThread.cpp

+

+#include "StdAfx.h"

+

+#include "VirtThread.h"

+

+static THREAD_FUNC_DECL CoderThread(void *p)

+{

+  for (;;)

+  {

+    CVirtThread *t = (CVirtThread *)p;

+    t->StartEvent.Lock();

+    if (t->ExitEvent)

+      return 0;

+    t->Execute();

+    t->FinishedEvent.Set();

+  }

+}

+

+WRes CVirtThread::Create()

+{

+  RINOK(StartEvent.CreateIfNotCreated());

+  RINOK(FinishedEvent.CreateIfNotCreated());

+  StartEvent.Reset();

+  FinishedEvent.Reset();

+  ExitEvent = false;

+  if (Thread.IsCreated())

+    return S_OK;

+  return Thread.Create(CoderThread, this);

+}

+

+void CVirtThread::Start()

+{

+  ExitEvent = false;

+  StartEvent.Set();

+}

+

+CVirtThread::~CVirtThread()

+{

+  ExitEvent = true;

+  if (StartEvent.IsCreated())

+    StartEvent.Set();

+  if (Thread.IsCreated())

+    Thread.Wait();

+}

+

diff --git a/CPP/7zip/Common/VirtThread.h b/CPP/7zip/Common/VirtThread.h
new file mode 100755
index 0000000..bfc10dc
--- /dev/null
+++ b/CPP/7zip/Common/VirtThread.h
@@ -0,0 +1,23 @@
+// VirtThread.h

+

+#ifndef __VIRTTHREAD_H

+#define __VIRTTHREAD_H

+

+#include "../../Windows/Synchronization.h"

+#include "../../Windows/Thread.h"

+

+struct CVirtThread

+{

+  NWindows::NSynchronization::CAutoResetEvent StartEvent;

+  NWindows::NSynchronization::CAutoResetEvent FinishedEvent;

+  NWindows::CThread Thread;

+  bool ExitEvent;

+

+  ~CVirtThread();

+  WRes Create();

+  void Start();

+  void WaitFinish() { FinishedEvent.Lock(); }

+  virtual void Execute() = 0;

+};

+

+#endif

diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp
new file mode 100755
index 0000000..05590e7
--- /dev/null
+++ b/CPP/7zip/Compress/Bcj2Coder.cpp
@@ -0,0 +1,386 @@
+// Bcj2Coder.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+

+#include "Bcj2Coder.h"

+

+namespace NCompress {

+namespace NBcj2 {

+

+inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); }

+inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); }

+inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); }

+

+#ifndef EXTRACT_ONLY

+

+static const int kBufferSize = 1 << 17;

+

+static bool inline Test86MSByte(Byte b)

+{

+  return (b == 0 || b == 0xFF);

+}

+

+bool CEncoder::Create()

+{

+  if (!_mainStream.Create(1 << 18))

+    return false;

+  if (!_callStream.Create(1 << 18))

+    return false;

+  if (!_jumpStream.Create(1 << 18))

+    return false;

+  if (!_rangeEncoder.Create(1 << 20))

+    return false;

+  if (_buffer == 0)

+  {

+    _buffer = (Byte *)MidAlloc(kBufferSize);

+    if (_buffer == 0)

+      return false;

+  }

+  return true;

+}

+

+CEncoder::~CEncoder()

+{

+  ::MidFree(_buffer);

+}

+

+HRESULT CEncoder::Flush()

+{

+  RINOK(_mainStream.Flush());

+  RINOK(_callStream.Flush());

+  RINOK(_jumpStream.Flush());

+  _rangeEncoder.FlushData();

+  return _rangeEncoder.FlushStream();

+}

+

+const UInt32 kDefaultLimit = (1 << 24);

+

+HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

+    ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams,

+    ICompressProgressInfo *progress)

+{

+  if (numInStreams != 1 || numOutStreams != 4)

+    return E_INVALIDARG;

+

+  if (!Create())

+    return E_OUTOFMEMORY;

+

+  bool sizeIsDefined = false;

+  UInt64 inSize = 0;

+  if (inSizes != NULL)

+    if (inSizes[0] != NULL)

+    {

+      inSize = *inSizes[0];

+      if (inSize <= kDefaultLimit)

+        sizeIsDefined = true;

+    }

+

+  CCoderReleaser releaser(this);

+

+  ISequentialInStream *inStream = inStreams[0];

+

+  _mainStream.SetStream(outStreams[0]);

+  _mainStream.Init();

+  _callStream.SetStream(outStreams[1]);

+  _callStream.Init();

+  _jumpStream.SetStream(outStreams[2]);

+  _jumpStream.Init();

+  _rangeEncoder.SetStream(outStreams[3]);

+  _rangeEncoder.Init();

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

+    _statusEncoder[i].Init();

+

+  CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;

+  {

+    inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);

+  }

+

+  UInt32 nowPos = 0;

+  UInt64 nowPos64 = 0;

+  UInt32 bufferPos = 0;

+

+  Byte prevByte = 0;

+

+  UInt64 subStreamIndex = 0;

+  UInt64 subStreamStartPos  = 0;

+  UInt64 subStreamEndPos = 0;

+

+  for (;;)

+  {

+    UInt32 processedSize = 0;

+    for (;;)

+    {

+      UInt32 size = kBufferSize - (bufferPos + processedSize);

+      UInt32 processedSizeLoc;

+      if (size == 0)

+        break;

+      RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc));

+      if (processedSizeLoc == 0)

+        break;

+      processedSize += processedSizeLoc;

+    }

+    UInt32 endPos = bufferPos + processedSize;

+    

+    if (endPos < 5)

+    {

+      // change it

+      for (bufferPos = 0; bufferPos < endPos; bufferPos++)

+      {

+        Byte b = _buffer[bufferPos];

+        _mainStream.WriteByte(b);

+        UInt32 index;

+        if (b == 0xE8)

+          index = prevByte;

+        else if (b == 0xE9)

+          index = 256;

+        else if (IsJcc(prevByte, b))

+          index = 257;

+        else

+        {

+          prevByte = b;

+          continue;

+        }

+        _statusEncoder[index].Encode(&_rangeEncoder, 0);

+        prevByte = b;

+      }

+      return Flush();

+    }

+

+    bufferPos = 0;

+

+    UInt32 limit = endPos - 5;

+    while(bufferPos <= limit)

+    {

+      Byte b = _buffer[bufferPos];

+      _mainStream.WriteByte(b);

+      if (!IsJ(prevByte, b))

+      {

+        bufferPos++;

+        prevByte = b;

+        continue;

+      }

+      Byte nextByte = _buffer[bufferPos + 4];

+      UInt32 src =

+        (UInt32(nextByte) << 24) |

+        (UInt32(_buffer[bufferPos + 3]) << 16) |

+        (UInt32(_buffer[bufferPos + 2]) << 8) |

+        (_buffer[bufferPos + 1]);

+      UInt32 dest = (nowPos + bufferPos + 5) + src;

+      // if (Test86MSByte(nextByte))

+      bool convert;

+      if (getSubStreamSize != NULL)

+      {

+        UInt64 currentPos = (nowPos64 + bufferPos);

+        while (subStreamEndPos < currentPos)

+        {

+          UInt64 subStreamSize;

+          HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);

+          if (result == S_OK)

+          {

+            subStreamStartPos = subStreamEndPos;

+            subStreamEndPos += subStreamSize;

+            subStreamIndex++;

+          }

+          else if (result == S_FALSE || result == E_NOTIMPL)

+          {

+            getSubStreamSize.Release();

+            subStreamStartPos = 0;

+            subStreamEndPos = subStreamStartPos - 1;

+          }

+          else

+            return result;

+        }

+        if (getSubStreamSize == NULL)

+        {

+          if (sizeIsDefined)

+            convert = (dest < inSize);

+          else

+            convert = Test86MSByte(nextByte);

+        }

+        else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)

+          convert = Test86MSByte(nextByte);

+        else

+        {

+          UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));

+          convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);

+        }

+      }

+      else if (sizeIsDefined)

+        convert = (dest < inSize);

+      else

+        convert = Test86MSByte(nextByte);

+      unsigned index = GetIndex(prevByte, b);

+      if (convert)

+      {

+        _statusEncoder[index].Encode(&_rangeEncoder, 1);

+        bufferPos += 5;

+        COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;

+        for (int i = 24; i >= 0; i -= 8)

+          s.WriteByte((Byte)(dest >> i));

+        prevByte = nextByte;

+      }

+      else

+      {

+        _statusEncoder[index].Encode(&_rangeEncoder, 0);

+        bufferPos++;

+        prevByte = b;

+      }

+    }

+    nowPos += bufferPos;

+    nowPos64 += bufferPos;

+

+    if (progress != NULL)

+    {

+      /*

+      const UInt64 compressedSize =

+        _mainStream.GetProcessedSize() +

+        _callStream.GetProcessedSize() +

+        _jumpStream.GetProcessedSize() +

+        _rangeEncoder.GetProcessedSize();

+      */

+      RINOK(progress->SetRatioInfo(&nowPos64, NULL));

+    }

+ 

+    UInt32 i = 0;

+    while(bufferPos < endPos)

+      _buffer[i++] = _buffer[bufferPos++];

+    bufferPos = i;

+  }

+}

+

+STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

+    ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

+    ICompressProgressInfo *progress)

+{

+  try

+  {

+    return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress);

+  }

+  catch(const COutBufferException &e) { return e.ErrorCode; }

+  catch(...) { return S_FALSE; }

+}

+

+#endif

+

+

+STDMETHODIMP CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size) { _inBufSizes[streamIndex] = size; return S_OK; }

+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }

+

+CDecoder::CDecoder():

+  _outBufSize(1 << 16)

+{

+  _inBufSizes[0] = 1 << 20;

+  _inBufSizes[1] = 1 << 20;

+  _inBufSizes[2] = 1 << 20;

+  _inBufSizes[3] = 1 << 20;

+}

+

+HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams,

+    ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams,

+    ICompressProgressInfo *progress)

+{

+  if (numInStreams != 4 || numOutStreams != 1)

+    return E_INVALIDARG;

+

+  if (!_mainInStream.Create(_inBufSizes[0]))

+    return E_OUTOFMEMORY;

+  if (!_callStream.Create(_inBufSizes[1]))

+    return E_OUTOFMEMORY;

+  if (!_jumpStream.Create(_inBufSizes[2]))

+    return E_OUTOFMEMORY;

+  if (!_rangeDecoder.Create(_inBufSizes[3]))

+    return E_OUTOFMEMORY;

+  if (!_outStream.Create(_outBufSize))

+    return E_OUTOFMEMORY;

+

+  CCoderReleaser releaser(this);

+

+  _mainInStream.SetStream(inStreams[0]);

+  _callStream.SetStream(inStreams[1]);

+  _jumpStream.SetStream(inStreams[2]);

+  _rangeDecoder.SetStream(inStreams[3]);

+  _outStream.SetStream(outStreams[0]);

+

+  _mainInStream.Init();

+  _callStream.Init();

+  _jumpStream.Init();

+  _rangeDecoder.Init();

+  _outStream.Init();

+

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

+    _statusDecoder[i].Init();

+

+  Byte prevByte = 0;

+  UInt32 processedBytes = 0;

+  for (;;)

+  {

+    if (processedBytes >= (1 << 20) && progress != NULL)

+    {

+      /*

+      const UInt64 compressedSize =

+        _mainInStream.GetProcessedSize() +

+        _callStream.GetProcessedSize() +

+        _jumpStream.GetProcessedSize() +

+        _rangeDecoder.GetProcessedSize();

+      */

+      const UInt64 nowPos64 = _outStream.GetProcessedSize();

+      RINOK(progress->SetRatioInfo(NULL, &nowPos64));

+      processedBytes = 0;

+    }

+    UInt32 i;

+    Byte b = 0;

+    const UInt32 kBurstSize = (1 << 18);

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

+    {

+      if (!_mainInStream.ReadByte(b))

+        return Flush();

+      _outStream.WriteByte(b);

+      if (IsJ(prevByte, b))

+        break;

+      prevByte = b;

+    }

+    processedBytes += i;

+    if (i == kBurstSize)

+      continue;

+    unsigned index = GetIndex(prevByte, b);

+    if (_statusDecoder[index].Decode(&_rangeDecoder) == 1)

+    {

+      UInt32 src = 0;

+      CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;

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

+      {

+        Byte b0;

+        if(!s.ReadByte(b0))

+          return S_FALSE;

+        src <<= 8;

+        src |= ((UInt32)b0);

+      }

+      UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ;

+      _outStream.WriteByte((Byte)(dest));

+      _outStream.WriteByte((Byte)(dest >> 8));

+      _outStream.WriteByte((Byte)(dest >> 16));

+      _outStream.WriteByte((Byte)(dest >> 24));

+      prevByte = (Byte)(dest >> 24);

+      processedBytes += 4;

+    }

+    else

+      prevByte = b;

+  }

+}

+

+STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

+    ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

+    ICompressProgressInfo *progress)

+{

+  try

+  {

+    return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress);

+  }

+  catch(const CInBufferException &e) { return e.ErrorCode; }

+  catch(const COutBufferException &e) { return e.ErrorCode; }

+  catch(...) { return S_FALSE; }

+}

+

+}}

diff --git a/CPP/7zip/Compress/Bcj2Coder.h b/CPP/7zip/Compress/Bcj2Coder.h
new file mode 100755
index 0000000..c8f0893
--- /dev/null
+++ b/CPP/7zip/Compress/Bcj2Coder.h
@@ -0,0 +1,115 @@
+// Bcj2Coder.h

+

+#ifndef __COMPRESS_BCJ2_CODER_H

+#define __COMPRESS_BCJ2_CODER_H

+

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+

+#include "RangeCoderBit.h"

+

+namespace NCompress {

+namespace NBcj2 {

+

+const int kNumMoveBits = 5;

+

+#ifndef EXTRACT_ONLY

+

+class CEncoder:

+  public ICompressCoder2,

+  public CMyUnknownImp

+{

+  Byte *_buffer;

+  bool Create();

+

+  COutBuffer _mainStream;

+  COutBuffer _callStream;

+  COutBuffer _jumpStream;

+  NCompress::NRangeCoder::CEncoder _rangeEncoder;

+  NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2];

+

+  HRESULT Flush();

+public:

+  void ReleaseStreams()

+  {

+    _mainStream.ReleaseStream();

+    _callStream.ReleaseStream();

+    _jumpStream.ReleaseStream();

+    _rangeEncoder.ReleaseStream();

+  }

+

+  class CCoderReleaser

+  {

+    CEncoder *_coder;

+  public:

+    CCoderReleaser(CEncoder *coder): _coder(coder) {}

+    ~CCoderReleaser() {  _coder->ReleaseStreams(); }

+  };

+

+public:

+  MY_UNKNOWN_IMP

+

+  HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

+      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

+      ICompressProgressInfo *progress);

+  STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

+      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

+      ICompressProgressInfo *progress);

+  CEncoder(): _buffer(0) {};

+  ~CEncoder();

+};

+

+#endif

+

+class CDecoder:

+  public ICompressCoder2,

+  public ICompressSetBufSize,

+  public CMyUnknownImp

+{

+  CInBuffer _mainInStream;

+  CInBuffer _callStream;

+  CInBuffer _jumpStream;

+  NCompress::NRangeCoder::CDecoder _rangeDecoder;

+  NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2];

+

+  COutBuffer _outStream;

+  UInt32 _inBufSizes[4];

+  UInt32 _outBufSize;

+

+public:

+  void ReleaseStreams()

+  {

+    _mainInStream.ReleaseStream();

+    _callStream.ReleaseStream();

+    _jumpStream.ReleaseStream();

+    _rangeDecoder.ReleaseStream();

+    _outStream.ReleaseStream();

+  }

+

+  HRESULT Flush() { return _outStream.Flush(); }

+  class CCoderReleaser

+  {

+    CDecoder *_coder;

+  public:

+    CCoderReleaser(CDecoder *coder): _coder(coder) {}

+    ~CCoderReleaser()  { _coder->ReleaseStreams(); }

+  };

+

+public:

+  MY_UNKNOWN_IMP1(ICompressSetBufSize);

+  HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

+      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

+      ICompressProgressInfo *progress);

+  STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

+      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

+      ICompressProgressInfo *progress);

+

+  STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);

+  STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);

+  CDecoder();

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Compress/Bcj2Register.cpp b/CPP/7zip/Compress/Bcj2Register.cpp
new file mode 100755
index 0000000..b063f3f
--- /dev/null
+++ b/CPP/7zip/Compress/Bcj2Register.cpp
@@ -0,0 +1,19 @@
+// Bcj2Register.cpp

+

+#include "StdAfx.h"

+

+#include "../Common/RegisterCodec.h"

+

+#include "Bcj2Coder.h"

+

+static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); }

+#ifndef EXTRACT_ONLY

+static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder());  }

+#else

+#define CreateCodecOut 0

+#endif

+

+static CCodecInfo g_CodecInfo =

+  { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false };

+

+REGISTER_CODEC(BCJ2)

diff --git a/CPP/7zip/Compress/BcjCoder.cpp b/CPP/7zip/Compress/BcjCoder.cpp
new file mode 100755
index 0000000..108c573
--- /dev/null
+++ b/CPP/7zip/Compress/BcjCoder.cpp
@@ -0,0 +1,15 @@
+// BcjCoder.cpp

+

+#include "StdAfx.h"

+

+#include "BcjCoder.h"

+

+UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size)

+{

+  return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1);

+}

+

+UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size)

+{

+  return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0);

+}

diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h
new file mode 100755
index 0000000..c86d5fc
--- /dev/null
+++ b/CPP/7zip/Compress/BcjCoder.h
@@ -0,0 +1,19 @@
+// BcjCoder.h

+

+#ifndef __COMPRESS_BCJ_CODER_H

+#define __COMPRESS_BCJ_CODER_H

+

+#include "../../../C/Bra.h"

+

+#include "BranchCoder.h"

+

+struct CBranch86

+{

+  UInt32 _prevMask;

+  void x86Init() { x86_Convert_Init(_prevMask); }

+};

+

+MyClassB(BCJ_x86, 0x01, 3, CBranch86 ,

+    virtual void SubInit() { x86Init(); })

+

+#endif

diff --git a/CPP/7zip/Compress/BcjRegister.cpp b/CPP/7zip/Compress/BcjRegister.cpp
new file mode 100755
index 0000000..09e53c6
--- /dev/null
+++ b/CPP/7zip/Compress/BcjRegister.cpp
@@ -0,0 +1,19 @@
+// BcjRegister.cpp

+

+#include "StdAfx.h"

+

+#include "../Common/RegisterCodec.h"

+

+#include "BcjCoder.h"

+

+static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); }

+#ifndef EXTRACT_ONLY

+static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder());  }

+#else

+#define CreateCodecOut 0

+#endif

+

+static CCodecInfo g_CodecInfo =

+  { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true };

+

+REGISTER_CODEC(BCJ)

diff --git a/CPP/7zip/Compress/BranchCoder.cpp b/CPP/7zip/Compress/BranchCoder.cpp
new file mode 100755
index 0000000..6cacc66
--- /dev/null
+++ b/CPP/7zip/Compress/BranchCoder.cpp
@@ -0,0 +1,19 @@
+// BranchCoder.cpp

+

+#include "StdAfx.h"

+

+#include "BranchCoder.h"

+

+STDMETHODIMP CBranchConverter::Init()

+{

+  _bufferPos = 0;

+  SubInit();

+  return S_OK;

+}

+

+STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size)

+{

+  UInt32 processedSize = SubFilter(data, size);

+  _bufferPos += processedSize;

+  return processedSize;

+}

diff --git a/CPP/7zip/Compress/BranchCoder.h b/CPP/7zip/Compress/BranchCoder.h
new file mode 100755
index 0000000..473286a
--- /dev/null
+++ b/CPP/7zip/Compress/BranchCoder.h
@@ -0,0 +1,44 @@
+// BranchCoder.h

+

+#ifndef __COMPRESS_BRANCH_CODER_H

+#define __COMPRESS_BRANCH_CODER_H

+

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+

+class CBranchConverter:

+  public ICompressFilter,

+  public CMyUnknownImp

+{

+protected:

+  UInt32 _bufferPos;

+  virtual void SubInit() {}

+  virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0;

+public:

+  MY_UNKNOWN_IMP;

+  STDMETHOD(Init)();

+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

+};

+

+#define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \

+  { public: UInt32 SubFilter(Byte *data, UInt32 size); };

+

+#define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \

+  { public: UInt32 SubFilter(Byte *data, UInt32 size); };

+

+#define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \

+  { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};

+

+#define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \

+  { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};

+

+#define MyClassA(Name, id, subId)  \

+MyClassEncoderA(Name ## _Encoder) \

+MyClassDecoderA(Name ## _Decoder)

+

+#define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT)  \

+MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \

+MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT)

+

+#endif

diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp
new file mode 100755
index 0000000..1a46bb1
--- /dev/null
+++ b/CPP/7zip/Compress/BranchMisc.cpp
@@ -0,0 +1,37 @@
+// BranchMisc.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Bra.h"

+

+#include "BranchMisc.h"

+

+UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size)

+  { return (UInt32)::ARM_Convert(data, size, _bufferPos, 1); }

+

+UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size)

+  { return (UInt32)::ARM_Convert(data, size, _bufferPos, 0); }

+

+UInt32 CBC_ARMT_Encoder::SubFilter(Byte *data, UInt32 size)

+  { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 1); }

+

+UInt32 CBC_ARMT_Decoder::SubFilter(Byte *data, UInt32 size)

+  { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 0); }

+

+UInt32 CBC_PPC_Encoder::SubFilter(Byte *data, UInt32 size)

+  { return (UInt32)::PPC_Convert(data, size, _bufferPos, 1); }

+

+UInt32 CBC_PPC_Decoder::SubFilter(Byte *data, UInt32 size)

+  { return (UInt32)::PPC_Convert(data, size, _bufferPos, 0); }

+

+UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size)

+  { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 1); }

+

+UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size)

+  { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 0); }

+

+UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size)

+  { return (UInt32)::IA64_Convert(data, size, _bufferPos, 1); }

+

+UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size)

+  {  return (UInt32)::IA64_Convert(data, size, _bufferPos, 0); }

diff --git a/CPP/7zip/Compress/BranchMisc.h b/CPP/7zip/Compress/BranchMisc.h
new file mode 100755
index 0000000..053e923
--- /dev/null
+++ b/CPP/7zip/Compress/BranchMisc.h
@@ -0,0 +1,14 @@
+// BranchMisc.h

+

+#ifndef __COMPRESS_BRANCH_MISC_H

+#define __COMPRESS_BRANCH_MISC_H

+

+#include "BranchCoder.h"

+

+MyClassA(BC_ARM,   0x05, 1)

+MyClassA(BC_ARMT,  0x07, 1)

+MyClassA(BC_PPC,   0x02, 5)

+MyClassA(BC_SPARC, 0x08, 5)

+MyClassA(BC_IA64,  0x04, 1)

+

+#endif

diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp
new file mode 100755
index 0000000..bc55dd6
--- /dev/null
+++ b/CPP/7zip/Compress/BranchRegister.cpp
@@ -0,0 +1,30 @@
+// BranchRegister.cpp

+

+#include "StdAfx.h"

+

+#include "../Common/RegisterCodec.h"

+

+#include "BranchMisc.h"

+

+#define CREATE_CODEC(x) \

+  static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \

+  static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); }

+

+CREATE_CODEC(BC_PPC)

+CREATE_CODEC(BC_IA64)

+CREATE_CODEC(BC_ARM)

+CREATE_CODEC(BC_ARMT)

+CREATE_CODEC(BC_SPARC)

+

+#define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true  }

+

+static CCodecInfo g_CodecsInfo[] =

+{

+  METHOD_ITEM(BC_PPC,   0x02, 0x05, L"PPC"),

+  METHOD_ITEM(BC_IA64,  0x04, 1, L"IA64"),

+  METHOD_ITEM(BC_ARM,   0x05, 1, L"ARM"),

+  METHOD_ITEM(BC_ARMT,  0x07, 1, L"ARMT"),

+  METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"SPARC")

+};

+

+REGISTER_CODECS(Branch)

diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp
new file mode 100755
index 0000000..7f028fb
--- /dev/null
+++ b/CPP/7zip/Compress/ByteSwap.cpp
@@ -0,0 +1,73 @@
+// ByteSwap.cpp

+

+#include "StdAfx.h"

+

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+

+#include "../Common/RegisterCodec.h"

+

+class CByteSwap2:

+  public ICompressFilter,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP

+  STDMETHOD(Init)();

+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

+};

+

+class CByteSwap4:

+  public ICompressFilter,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP

+  STDMETHOD(Init)();

+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

+};

+

+STDMETHODIMP CByteSwap2::Init() { return S_OK; }

+

+STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size)

+{

+  const UInt32 kStep = 2;

+  UInt32 i;

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

+  {

+    Byte b = data[i];

+    data[i] = data[i + 1];

+    data[i + 1] = b;

+  }

+  return i;

+}

+

+STDMETHODIMP CByteSwap4::Init() { return S_OK; }

+

+STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size)

+{

+  const UInt32 kStep = 4;

+  UInt32 i;

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

+  {

+    Byte b0 = data[i];

+    Byte b1 = data[i + 1];

+    data[i] = data[i + 3];

+    data[i + 1] = data[i + 2];

+    data[i + 2] = b1;

+    data[i + 3] = b0;

+  }

+  return i;

+}

+

+static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); }

+static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); }

+

+static CCodecInfo g_CodecsInfo[] =

+{

+  { CreateCodec2, CreateCodec2, 0x020302, L"Swap2", 1, true },

+  { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true }

+};

+

+REGISTER_CODECS(ByteSwap)

diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp
new file mode 100755
index 0000000..84a27cf
--- /dev/null
+++ b/CPP/7zip/Compress/CodecExports.cpp
@@ -0,0 +1,160 @@
+// CodecExports.cpp

+

+#include "StdAfx.h"

+

+#include "../../Common/ComTry.h"

+

+#include "../../Windows/PropVariant.h"

+

+#include "../ICoder.h"

+

+#include "../Common/RegisterCodec.h"

+

+extern unsigned int g_NumCodecs;

+extern const CCodecInfo *g_Codecs[];

+

+static const UInt16 kDecodeId = 0x2790;

+

+DEFINE_GUID(CLSID_CCodec,

+0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);

+

+static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)

+{

+  if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)

+    value->vt = VT_BSTR;

+  return S_OK;

+}

+

+static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)

+{

+  return SetPropString((const char *)&guid, sizeof(GUID), value);

+}

+

+static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value)

+{

+  GUID clsId = CLSID_CCodec;

+  for (int i = 0; i < sizeof(id); i++, id >>= 8)

+    clsId.Data4[i] = (Byte)(id & 0xFF);

+  if (encode)

+    clsId.Data3++;

+  return SetPropGUID(clsId, value);

+}

+

+static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index)

+{

+  index = -1;

+  if (clsID->Data1 != CLSID_CCodec.Data1 ||

+      clsID->Data2 != CLSID_CCodec.Data2 ||

+      (clsID->Data3 & ~1) != kDecodeId)

+    return S_OK;

+  encode = (clsID->Data3 != kDecodeId);

+  UInt64 id = 0;

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

+    id |= ((UInt64)clsID->Data4[j]) << (8 * j);

+  for (unsigned i = 0; i < g_NumCodecs; i++)

+  {

+    const CCodecInfo &codec = *g_Codecs[i];

+    if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder)

+      continue;

+    if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||

+        codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)

+      return E_NOINTERFACE;

+    index = i;

+    return S_OK;

+  }

+  return S_OK;

+}

+

+STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)

+{

+  COM_TRY_BEGIN

+  *outObject = 0;

+  bool isCoder = (*iid == IID_ICompressCoder) != 0;

+  bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;

+  bool isFilter = (*iid == IID_ICompressFilter) != 0;

+  const CCodecInfo &codec = *g_Codecs[index];

+  if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||

+      codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)

+    return E_NOINTERFACE;

+  if (encode)

+  {

+    if (!codec.CreateEncoder)

+      return CLASS_E_CLASSNOTAVAILABLE;

+    *outObject = codec.CreateEncoder();

+  }

+  else

+  {

+    if (!codec.CreateDecoder)

+      return CLASS_E_CLASSNOTAVAILABLE;

+    *outObject = codec.CreateDecoder();

+  }

+  if (isCoder)

+    ((ICompressCoder *)*outObject)->AddRef();

+  else if (isCoder2)

+    ((ICompressCoder2 *)*outObject)->AddRef();

+  else

+    ((ICompressFilter *)*outObject)->AddRef();

+  return S_OK;

+  COM_TRY_END

+}

+

+STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)

+{

+  *outObject = 0;

+  bool isCoder = (*iid == IID_ICompressCoder) != 0;

+  bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;

+  bool isFilter = (*iid == IID_ICompressFilter) != 0;

+  if (!isCoder && !isCoder2 && !isFilter)

+    return E_NOINTERFACE;

+  bool encode;

+  int codecIndex;

+  HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex);

+  if (res != S_OK)

+    return res;

+  if (codecIndex < 0)

+    return CLASS_E_CLASSNOTAVAILABLE;

+  return CreateCoder2(encode, codecIndex, iid, outObject);

+}

+

+STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)

+{

+  ::VariantClear((VARIANTARG *)value);

+  const CCodecInfo &codec = *g_Codecs[codecIndex];

+  switch(propID)

+  {

+    case NMethodPropID::kID:

+    {

+      value->uhVal.QuadPart = (UInt64)codec.Id;

+      value->vt = VT_UI8;

+      break;

+    }

+    case NMethodPropID::kName:

+      if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)

+        value->vt = VT_BSTR;

+      break;

+    case NMethodPropID::kDecoder:

+      if (codec.CreateDecoder)

+        return SetClassID(codec.Id, false, value);

+      break;

+    case NMethodPropID::kEncoder:

+      if (codec.CreateEncoder)

+        return SetClassID(codec.Id, true, value);

+      break;

+    case NMethodPropID::kInStreams:

+    {

+      if (codec.NumInStreams != 1)

+      {

+        value->vt = VT_UI4;

+        value->ulVal = (ULONG)codec.NumInStreams;

+      }

+      break;

+    }

+  }

+  return S_OK;

+}

+

+STDAPI GetNumberOfMethods(UINT32 *numCodecs)

+{

+  *numCodecs = g_NumCodecs;

+  return S_OK;

+}

diff --git a/CPP/7zip/Compress/CopyCoder.cpp b/CPP/7zip/Compress/CopyCoder.cpp
new file mode 100755
index 0000000..da15d04
--- /dev/null
+++ b/CPP/7zip/Compress/CopyCoder.cpp
@@ -0,0 +1,67 @@
+// Compress/CopyCoder.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+

+#include "../Common/StreamUtils.h"

+

+#include "CopyCoder.h"

+

+namespace NCompress {

+

+static const UInt32 kBufferSize = 1 << 17;

+

+CCopyCoder::~CCopyCoder()

+{

+  ::MidFree(_buffer);

+}

+

+STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,

+    ISequentialOutStream *outStream,

+    const UInt64 * /* inSize */, const UInt64 *outSize,

+    ICompressProgressInfo *progress)

+{

+  if (_buffer == 0)

+  {

+    _buffer = (Byte *)::MidAlloc(kBufferSize);

+    if (_buffer == 0)

+      return E_OUTOFMEMORY;

+  }

+

+  TotalSize = 0;

+  for (;;)

+  {

+    UInt32 size = kBufferSize;

+    if (outSize != 0)

+      if (size > *outSize - TotalSize)

+        size = (UInt32)(*outSize - TotalSize);

+    RINOK(inStream->Read(_buffer, size, &size));

+    if (size == 0)

+      break;

+    if (outStream)

+    {

+      RINOK(WriteStream(outStream, _buffer, size));

+    }

+    TotalSize += size;

+    if (progress != NULL)

+    {

+      RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize));

+    }

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value)

+{

+  *value = TotalSize;

+  return S_OK;

+}

+

+HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)

+{

+  CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;

+  return copyCoder->Code(inStream, outStream, NULL, NULL, progress);

+}

+

+}

diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h
new file mode 100755
index 0000000..16c42ee
--- /dev/null
+++ b/CPP/7zip/Compress/CopyCoder.h
@@ -0,0 +1,34 @@
+// Compress/CopyCoder.h

+

+#ifndef __COMPRESS_COPY_CODER_H

+#define __COMPRESS_COPY_CODER_H

+

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+

+namespace NCompress {

+

+class CCopyCoder:

+  public ICompressCoder,

+  public ICompressGetInStreamProcessedSize,

+  public CMyUnknownImp

+{

+  Byte *_buffer;

+public:

+  UInt64 TotalSize;

+  CCopyCoder(): TotalSize(0), _buffer(0) {};

+  ~CCopyCoder();

+

+  MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize)

+

+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

+  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);

+};

+

+HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);

+

+}

+

+#endif

diff --git a/CPP/7zip/Compress/CopyRegister.cpp b/CPP/7zip/Compress/CopyRegister.cpp
new file mode 100755
index 0000000..3ef2459
--- /dev/null
+++ b/CPP/7zip/Compress/CopyRegister.cpp
@@ -0,0 +1,14 @@
+// CopyRegister.cpp

+

+#include "StdAfx.h"

+

+#include "../Common/RegisterCodec.h"

+

+#include "CopyCoder.h"

+

+static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); }

+

+static CCodecInfo g_CodecInfo =

+{ CreateCodec, CreateCodec, 0x00, L"Copy", 1, false };

+

+REGISTER_CODEC(Copy)

diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp
new file mode 100755
index 0000000..e7e3822
--- /dev/null
+++ b/CPP/7zip/Compress/DeltaFilter.cpp
@@ -0,0 +1,112 @@
+// DeltaFilter.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Delta.h"

+

+#include "../Common/RegisterCodec.h"

+

+#include "BranchCoder.h"

+

+struct CDelta

+{

+  unsigned _delta;

+  Byte _state[DELTA_STATE_SIZE];

+  CDelta(): _delta(1) {}

+  void DeltaInit() { Delta_Init(_state); }

+};

+

+class CDeltaEncoder:

+  public ICompressFilter,

+  public ICompressSetCoderProperties,

+  public ICompressWriteCoderProperties,

+  CDelta,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)

+  STDMETHOD(Init)();

+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);

+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);

+};

+

+class CDeltaDecoder:

+  public ICompressFilter,

+  public ICompressSetDecoderProperties2,

+  CDelta,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)

+  STDMETHOD(Init)();

+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);

+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

+};

+

+STDMETHODIMP CDeltaEncoder::Init()

+{

+  DeltaInit();

+  return S_OK;

+}

+

+STDMETHODIMP_(UInt32) CDeltaEncoder::Filter(Byte *data, UInt32 size)

+{

+  Delta_Encode(_state, _delta, data, size);

+  return size;

+}

+

+STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)

+{

+  UInt32 delta = _delta;

+  for (UInt32 i = 0; i < numProps; i++)

+  {

+    const PROPVARIANT &prop = props[i];

+    if (propIDs[i] != NCoderPropID::kDefaultProp || prop.vt != VT_UI4 || prop.ulVal < 1 || prop.ulVal > 256)

+      return E_INVALIDARG;

+    delta = prop.ulVal;

+  }

+  _delta = delta;

+  return S_OK;

+}

+

+STDMETHODIMP CDeltaEncoder::WriteCoderProperties(ISequentialOutStream *outStream)

+{

+  Byte prop = (Byte)(_delta - 1);

+  return outStream->Write(&prop, 1, NULL);

+}

+

+STDMETHODIMP CDeltaDecoder::Init()

+{

+  DeltaInit();

+  return S_OK;

+}

+

+STDMETHODIMP_(UInt32) CDeltaDecoder::Filter(Byte *data, UInt32 size)

+{

+  Delta_Decode(_state, _delta, data, size);

+  return size;

+}

+

+STDMETHODIMP CDeltaDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)

+{

+  if (size != 1)

+    return E_INVALIDARG;

+  _delta = (unsigned)props[0] + 1;

+  return S_OK;

+}

+

+#define CREATE_CODEC(x) \

+  static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## Decoder); } \

+  static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## Encoder); }

+

+CREATE_CODEC(Delta)

+

+#define METHOD_ITEM(x, id, name) { CreateCodec ## x, CreateCodec ## x ## Out, id, name, 1, true  }

+

+static CCodecInfo g_CodecsInfo[] =

+{

+  METHOD_ITEM(Delta, 3, L"Delta")

+};

+

+REGISTER_CODECS(Delta)

diff --git a/CPP/7zip/Compress/Lzma2Decoder.cpp b/CPP/7zip/Compress/Lzma2Decoder.cpp
new file mode 100755
index 0000000..8d3d830
--- /dev/null
+++ b/CPP/7zip/Compress/Lzma2Decoder.cpp
@@ -0,0 +1,189 @@
+// Lzma2Decoder.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+

+#include "../Common/StreamUtils.h"

+

+#include "Lzma2Decoder.h"

+

+static HRESULT SResToHRESULT(SRes res)

+{

+  switch(res)

+  {

+    case SZ_OK: return S_OK;

+    case SZ_ERROR_MEM: return E_OUTOFMEMORY;

+    case SZ_ERROR_PARAM: return E_INVALIDARG;

+    // case SZ_ERROR_PROGRESS: return E_ABORT;

+    case SZ_ERROR_DATA: return S_FALSE;

+  }

+  return E_FAIL;

+}

+

+namespace NCompress {

+namespace NLzma2 {

+

+static const UInt32 kInBufSize = 1 << 20;

+

+CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false)

+{

+  Lzma2Dec_Construct(&_state);

+}

+

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

+

+CDecoder::~CDecoder()

+{

+  Lzma2Dec_Free(&_state, &g_Alloc);

+  MyFree(_inBuf);

+}

+

+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)

+{

+  if (size != 1) return SZ_ERROR_UNSUPPORTED;

+  RINOK(SResToHRESULT(Lzma2Dec_Allocate(&_state, prop[0], &g_Alloc)));

+  if (_inBuf == 0)

+  {

+    _inBuf = (Byte *)MyAlloc(kInBufSize);

+    if (_inBuf == 0)

+      return E_OUTOFMEMORY;

+  }

+

+  return S_OK;

+}

+

+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; }

+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }

+STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }

+

+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)

+{

+  _outSizeDefined = (outSize != NULL);

+  if (_outSizeDefined)

+    _outSize = *outSize;

+

+  Lzma2Dec_Init(&_state);

+  

+  _inPos = _inSize = 0;

+  _inSizeProcessed = _outSizeProcessed = 0;

+  return S_OK;

+}

+

+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,

+    ISequentialOutStream *outStream, const UInt64 * /* inSize */,

+    const UInt64 *outSize, ICompressProgressInfo *progress)

+{

+  if (_inBuf == 0)

+    return S_FALSE;

+  SetOutStreamSize(outSize);

+

+  for (;;)

+  {

+    if (_inPos == _inSize)

+    {

+      _inPos = _inSize = 0;

+      RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize));

+    }

+

+    SizeT dicPos = _state.decoder.dicPos;

+    SizeT curSize = _state.decoder.dicBufSize - dicPos;

+    const UInt32 kStepSize = ((UInt32)1 << 22);

+    if (curSize > kStepSize)

+      curSize = (SizeT)kStepSize;

+    

+    ELzmaFinishMode finishMode = LZMA_FINISH_ANY;

+    if (_outSizeDefined)

+    {

+      const UInt64 rem = _outSize - _outSizeProcessed;

+      if (rem < curSize)

+      {

+        curSize = (SizeT)rem;

+        /*

+        // finishMode = LZMA_FINISH_END;

+        we can't use LZMA_FINISH_END here to allow partial decoding

+        */

+      }

+    }

+

+    SizeT inSizeProcessed = _inSize - _inPos;

+    ELzmaStatus status;

+    SRes res = Lzma2Dec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status);

+

+    _inPos += (UInt32)inSizeProcessed;

+    _inSizeProcessed += inSizeProcessed;

+    SizeT outSizeProcessed = _state.decoder.dicPos - dicPos;

+    _outSizeProcessed += outSizeProcessed;

+

+    bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0);

+    bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize);

+

+    if (res != 0 || _state.decoder.dicPos == _state.decoder.dicBufSize || finished || stopDecoding)

+    {

+      HRESULT res2 = WriteStream(outStream, _state.decoder.dic, _state.decoder.dicPos);

+      if (res != 0)

+        return S_FALSE;

+      RINOK(res2);

+      if (stopDecoding)

+        return S_OK;

+      if (finished)

+        return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);

+    }

+    if (_state.decoder.dicPos == _state.decoder.dicBufSize)

+      _state.decoder.dicPos = 0;

+

+    if (progress != NULL)

+    {

+      RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed));

+    }

+  }

+}

+

+#ifndef NO_READ_FROM_CODER

+

+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+  do

+  {

+    if (_inPos == _inSize)

+    {

+      _inPos = _inSize = 0;

+      RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize));

+    }

+    {

+      SizeT inProcessed = _inSize - _inPos;

+

+      if (_outSizeDefined)

+      {

+        const UInt64 rem = _outSize - _outSizeProcessed;

+        if (rem < size)

+          size = (UInt32)rem;

+      }

+

+      SizeT outProcessed = size;

+      ELzmaStatus status;

+      SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,

+          _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status);

+      _inPos += (UInt32)inProcessed;

+      _inSizeProcessed += inProcessed;

+      _outSizeProcessed += outProcessed;

+      size -= (UInt32)outProcessed;

+      data = (Byte *)data + outProcessed;

+      if (processedSize)

+        *processedSize += (UInt32)outProcessed;

+      RINOK(SResToHRESULT(res));

+      if (inProcessed == 0 && outProcessed == 0)

+        return S_OK;

+    }

+  }

+  while (size != 0);

+  return S_OK;

+}

+

+#endif

+

+}}

diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h
new file mode 100755
index 0000000..3540097
--- /dev/null
+++ b/CPP/7zip/Compress/Lzma2Decoder.h
@@ -0,0 +1,73 @@
+// Lzma2Decoder.h

+

+#ifndef __LZMA2_DECODER_H

+#define __LZMA2_DECODER_H

+

+#include "../../../C/Lzma2Dec.h"

+

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+

+namespace NCompress {

+namespace NLzma2 {

+

+class CDecoder:

+  public ICompressCoder,

+  public ICompressSetDecoderProperties2,

+  public ICompressGetInStreamProcessedSize,

+  #ifndef NO_READ_FROM_CODER

+  public ICompressSetInStream,

+  public ICompressSetOutStreamSize,

+  public ISequentialInStream,

+  #endif

+  public CMyUnknownImp

+{

+  CMyComPtr<ISequentialInStream> _inStream;

+  Byte *_inBuf;

+  UInt32 _inPos;

+  UInt32 _inSize;

+  CLzma2Dec _state;

+  bool _outSizeDefined;

+  UInt64 _outSize;

+  UInt64 _inSizeProcessed;

+  UInt64 _outSizeProcessed;

+public:

+

+  #ifndef NO_READ_FROM_CODER

+  MY_UNKNOWN_IMP5(

+      ICompressSetDecoderProperties2,

+      ICompressGetInStreamProcessedSize,

+      ICompressSetInStream,

+      ICompressSetOutStreamSize,

+      ISequentialInStream)

+  #else

+  MY_UNKNOWN_IMP2(

+      ICompressSetDecoderProperties2,

+      ICompressGetInStreamProcessedSize)

+  #endif

+

+  STDMETHOD(Code)(ISequentialInStream *inStream,

+      ISequentialOutStream *outStream, const UInt64 *_inSize, const UInt64 *outSize,

+      ICompressProgressInfo *progress);

+

+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

+

+  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);

+

+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);

+  STDMETHOD(ReleaseInStream)();

+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);

+

+  #ifndef NO_READ_FROM_CODER

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  #endif

+

+  CDecoder();

+  virtual ~CDecoder();

+

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp
new file mode 100755
index 0000000..871f146
--- /dev/null
+++ b/CPP/7zip/Compress/Lzma2Encoder.cpp
@@ -0,0 +1,94 @@
+// Lzma2Encoder.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+

+#include "../Common/CWrappers.h"

+#include "../Common/StreamUtils.h"

+

+#include "Lzma2Encoder.h"

+

+namespace NCompress {

+

+namespace NLzma {

+

+HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep);

+

+}

+

+namespace NLzma2 {

+

+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }

+static void SzBigFree(void *, void *address) { BigFree(address); }

+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

+

+static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }

+static void SzFree(void *, void *address) { MyFree(address); }

+static ISzAlloc g_Alloc = { SzAlloc, SzFree };

+

+CEncoder::CEncoder()

+{

+  _encoder = 0;

+  _encoder = Lzma2Enc_Create(&g_Alloc, &g_BigAlloc);

+  if (_encoder == 0)

+    throw 1;

+}

+

+CEncoder::~CEncoder()

+{

+  if (_encoder != 0)

+    Lzma2Enc_Destroy(_encoder);

+}

+

+HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props)

+{

+  switch (propID)

+  {

+    case NCoderPropID::kBlockSize:

+      if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.blockSize = prop.ulVal; break;

+    case NCoderPropID::kNumThreads:

+      if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.numTotalThreads = (int)(prop.ulVal); break;

+    default:

+      RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps));

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,

+    const PROPVARIANT *coderProps, UInt32 numProps)

+{

+  CLzma2EncProps lzma2Props;

+  Lzma2EncProps_Init(&lzma2Props);

+

+  for (UInt32 i = 0; i < numProps; i++)

+  {

+    RINOK(SetLzma2Prop(propIDs[i], coderProps[i], lzma2Props));

+  }

+  return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props));

+}

+

+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)

+{

+  Byte prop = Lzma2Enc_WriteProperties(_encoder);

+  return WriteStream(outStream, &prop, 1);

+}

+

+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)

+{

+  CSeqInStreamWrap inWrap(inStream);

+  CSeqOutStreamWrap outWrap(outStream);

+  CCompressProgressWrap progressWrap(progress);

+

+  SRes res = Lzma2Enc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL);

+  if (res == SZ_ERROR_READ && inWrap.Res != S_OK)

+    return inWrap.Res;

+  if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)

+    return outWrap.Res;

+  if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK)

+    return progressWrap.Res;

+  return SResToHRESULT(res);

+}

+  

+}}

diff --git a/CPP/7zip/Compress/Lzma2Encoder.h b/CPP/7zip/Compress/Lzma2Encoder.h
new file mode 100755
index 0000000..fc43702
--- /dev/null
+++ b/CPP/7zip/Compress/Lzma2Encoder.h
@@ -0,0 +1,36 @@
+// Lzma2Encoder.h

+

+#ifndef __LZMA2_ENCODER_H

+#define __LZMA2_ENCODER_H

+

+#include "../../../C/Lzma2Enc.h"

+

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+

+namespace NCompress {

+namespace NLzma2 {

+

+class CEncoder:

+  public ICompressCoder,

+  public ICompressSetCoderProperties,

+  public ICompressWriteCoderProperties,

+  public CMyUnknownImp

+{

+  CLzma2EncHandle _encoder;

+public:

+  MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)

+ 

+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);

+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);

+

+  CEncoder();

+  virtual ~CEncoder();

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp
new file mode 100755
index 0000000..28430b4
--- /dev/null
+++ b/CPP/7zip/Compress/Lzma2Register.cpp
@@ -0,0 +1,20 @@
+// Lzma2Register.cpp

+

+#include "StdAfx.h"

+

+#include "../Common/RegisterCodec.h"

+

+#include "Lzma2Decoder.h"

+

+static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CDecoder); }

+#ifndef EXTRACT_ONLY

+#include "Lzma2Encoder.h"

+static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CEncoder);  }

+#else

+#define CreateCodecOut 0

+#endif

+

+static CCodecInfo g_CodecInfo =

+  { CreateCodec, CreateCodecOut, 0x21, L"LZMA2", 1, false };

+

+REGISTER_CODEC(LZMA2)

diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp
new file mode 100755
index 0000000..9f15fdb
--- /dev/null
+++ b/CPP/7zip/Compress/LzmaDecoder.cpp
@@ -0,0 +1,252 @@
+// LzmaDecoder.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+

+#include "../Common/StreamUtils.h"

+

+#include "LzmaDecoder.h"

+

+static HRESULT SResToHRESULT(SRes res)

+{

+  switch(res)

+  {

+    case SZ_OK: return S_OK;

+    case SZ_ERROR_MEM: return E_OUTOFMEMORY;

+    case SZ_ERROR_PARAM: return E_INVALIDARG;

+    case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;

+    case SZ_ERROR_DATA: return S_FALSE;

+  }

+  return E_FAIL;

+}

+

+namespace NCompress {

+namespace NLzma {

+

+CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false),

+  _inBufSize(1 << 20),

+  _outBufSize(1 << 22),

+  FinishStream(false)

+{

+  _inSizeProcessed = 0;

+  _inPos = _inSize = 0;

+  LzmaDec_Construct(&_state);

+}

+

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

+

+CDecoder::~CDecoder()

+{

+  LzmaDec_Free(&_state, &g_Alloc);

+  MyFree(_inBuf);

+}

+

+STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }

+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }

+

+HRESULT CDecoder::CreateInputBuffer()

+{

+  if (_inBuf == 0 || _inBufSize != _inBufSizeAllocated)

+  {

+    MyFree(_inBuf);

+    _inBuf = (Byte *)MyAlloc(_inBufSize);

+    if (_inBuf == 0)

+      return E_OUTOFMEMORY;

+    _inBufSizeAllocated = _inBufSize;

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)

+{

+  RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc)));

+  _propsWereSet = true;

+  return CreateInputBuffer();

+}

+

+void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize)

+{

+  _outSizeDefined = (outSize != NULL);

+  if (_outSizeDefined)

+    _outSize = *outSize;

+  _outSizeProcessed = 0;

+  _wrPos = 0;

+  LzmaDec_Init(&_state);

+}

+

+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)

+{

+  _inSizeProcessed = 0;

+  _inPos = _inSize = 0;

+  SetOutStreamSizeResume(outSize);

+  return S_OK;

+}

+

+HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)

+{

+  if (_inBuf == 0 || !_propsWereSet)

+    return S_FALSE;

+

+  UInt64 startInProgress = _inSizeProcessed;

+

+  SizeT next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize);

+  for (;;)

+  {

+    if (_inPos == _inSize)

+    {

+      _inPos = _inSize = 0;

+      RINOK(inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));

+    }

+

+    SizeT dicPos = _state.dicPos;

+    SizeT curSize = next - dicPos;

+    

+    ELzmaFinishMode finishMode = LZMA_FINISH_ANY;

+    if (_outSizeDefined)

+    {

+      const UInt64 rem = _outSize - _outSizeProcessed;

+      if (rem <= curSize)

+      {

+        curSize = (SizeT)rem;

+        if (FinishStream)

+          finishMode = LZMA_FINISH_END;

+      }

+    }

+

+    SizeT inSizeProcessed = _inSize - _inPos;

+    ELzmaStatus status;

+    SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status);

+

+    _inPos += (UInt32)inSizeProcessed;

+    _inSizeProcessed += inSizeProcessed;

+    SizeT outSizeProcessed = _state.dicPos - dicPos;

+    _outSizeProcessed += outSizeProcessed;

+

+    bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0);

+    bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize);

+

+    if (res != 0 || _state.dicPos == next || finished || stopDecoding)

+    {

+      HRESULT res2 = WriteStream(outStream, _state.dic + _wrPos, _state.dicPos - _wrPos);

+

+      _wrPos = _state.dicPos;

+      if (_state.dicPos == _state.dicBufSize)

+      {

+        _state.dicPos = 0;

+        _wrPos = 0;

+      }

+      next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize);

+

+      if (res != 0)

+        return S_FALSE;

+      RINOK(res2);

+      if (stopDecoding)

+        return S_OK;

+      if (finished)

+        return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);

+    }

+    if (progress)

+    {

+      UInt64 inSize = _inSizeProcessed - startInProgress;

+      RINOK(progress->SetRatioInfo(&inSize, &_outSizeProcessed));

+    }

+  }

+}

+

+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)

+{

+  if (_inBuf == 0)

+    return E_INVALIDARG;

+  SetOutStreamSize(outSize);

+  return CodeSpec(inStream, outStream, progress);

+}

+

+#ifndef NO_READ_FROM_CODER

+

+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }

+STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }

+

+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize)

+    *processedSize = 0;

+  do

+  {

+    if (_inPos == _inSize)

+    {

+      _inPos = _inSize = 0;

+      RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));

+    }

+    {

+      SizeT inProcessed = _inSize - _inPos;

+

+      if (_outSizeDefined)

+      {

+        const UInt64 rem = _outSize - _outSizeProcessed;

+        if (rem < size)

+          size = (UInt32)rem;

+      }

+

+      SizeT outProcessed = size;

+      ELzmaStatus status;

+      SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,

+          _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status);

+      _inPos += (UInt32)inProcessed;

+      _inSizeProcessed += inProcessed;

+      _outSizeProcessed += outProcessed;

+      size -= (UInt32)outProcessed;

+      data = (Byte *)data + outProcessed;

+      if (processedSize)

+        *processedSize += (UInt32)outProcessed;

+      RINOK(SResToHRESULT(res));

+      if (inProcessed == 0 && outProcessed == 0)

+        return S_OK;

+    }

+  }

+  while (size != 0);

+  return S_OK;

+}

+

+HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)

+{

+  SetOutStreamSizeResume(outSize);

+  return CodeSpec(_inStream, outStream, progress);

+}

+

+HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize)

+{

+  RINOK(CreateInputBuffer());

+  if (processedSize)

+    *processedSize = 0;

+  while (size > 0)

+  {

+    if (_inPos == _inSize)

+    {

+      _inPos = _inSize = 0;

+      RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));

+      if (_inSize == 0)

+        break;

+    }

+    {

+      UInt32 curSize = _inSize - _inPos;

+      if (curSize > size)

+        curSize = size;

+      memcpy(data, _inBuf + _inPos, curSize);

+      _inPos += curSize;

+      _inSizeProcessed += curSize;

+      size -= curSize;

+      data = (Byte *)data + curSize;

+      if (processedSize)

+        *processedSize += curSize;

+    }

+  }

+  return S_OK;

+}

+

+#endif

+

+}}

diff --git a/CPP/7zip/Compress/LzmaDecoder.h b/CPP/7zip/Compress/LzmaDecoder.h
new file mode 100755
index 0000000..801a77b
--- /dev/null
+++ b/CPP/7zip/Compress/LzmaDecoder.h
@@ -0,0 +1,84 @@
+// LzmaDecoder.h

+

+#ifndef __LZMA_DECODER_H

+#define __LZMA_DECODER_H

+

+#include "../../../C/LzmaDec.h"

+

+#include "../../Common/MyCom.h"

+#include "../ICoder.h"

+

+namespace NCompress {

+namespace NLzma {

+

+class CDecoder:

+  public ICompressCoder,

+  public ICompressSetDecoderProperties2,

+  public ICompressSetBufSize,

+  #ifndef NO_READ_FROM_CODER

+  public ICompressSetInStream,

+  public ICompressSetOutStreamSize,

+  public ISequentialInStream,

+  #endif

+  public CMyUnknownImp

+{

+  CMyComPtr<ISequentialInStream> _inStream;

+  Byte *_inBuf;

+  UInt32 _inPos;

+  UInt32 _inSize;

+  CLzmaDec _state;

+  bool _propsWereSet;

+  bool _outSizeDefined;

+  UInt64 _outSize;

+  UInt64 _inSizeProcessed;

+  UInt64 _outSizeProcessed;

+

+  UInt32 _inBufSizeAllocated;

+  UInt32 _inBufSize;

+  UInt32 _outBufSize;

+  SizeT _wrPos;

+

+  HRESULT CreateInputBuffer();

+  HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);

+  void SetOutStreamSizeResume(const UInt64 *outSize);

+

+public:

+  MY_QUERYINTERFACE_BEGIN2(ICompressCoder)

+  MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)

+  MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)

+  #ifndef NO_READ_FROM_CODER

+  MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)

+  MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)

+  MY_QUERYINTERFACE_ENTRY(ISequentialInStream)

+  #endif

+  MY_QUERYINTERFACE_END

+  MY_ADDREF_RELEASE

+

+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);

+  STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);

+  STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);

+

+  #ifndef NO_READ_FROM_CODER

+  

+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);

+  STDMETHOD(ReleaseInStream)();

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+

+  HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress);

+  HRESULT ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize);

+  UInt64 GetInputProcessedSize() const { return _inSizeProcessed; }

+

+  #endif

+

+  bool FinishStream;

+

+  CDecoder();

+  virtual ~CDecoder();

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp
new file mode 100755
index 0000000..aa96c0e
--- /dev/null
+++ b/CPP/7zip/Compress/LzmaEncoder.cpp
@@ -0,0 +1,149 @@
+// LzmaEncoder.cpp

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+

+#include "../Common/CWrappers.h"

+#include "../Common/StreamUtils.h"

+

+#include "LzmaEncoder.h"

+

+namespace NCompress {

+namespace NLzma {

+

+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }

+static void SzBigFree(void *, void *address) { BigFree(address); }

+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

+

+static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }

+static void SzFree(void *, void *address) { MyFree(address); }

+static ISzAlloc g_Alloc = { SzAlloc, SzFree };

+

+CEncoder::CEncoder()

+{

+  _encoder = 0;

+  _encoder = LzmaEnc_Create(&g_Alloc);

+  if (_encoder == 0)

+    throw 1;

+}

+

+CEncoder::~CEncoder()

+{

+  if (_encoder != 0)

+    LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc);

+}

+

+inline wchar_t GetUpperChar(wchar_t c)

+{

+  if (c >= 'a' && c <= 'z')

+    c -= 0x20;

+  return c;

+}

+

+static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes)

+{

+  wchar_t c = GetUpperChar(*s++);

+  if (c == L'H')

+  {

+    if (GetUpperChar(*s++) != L'C')

+      return 0;

+    int numHashBytesLoc = (int)(*s++ - L'0');

+    if (numHashBytesLoc < 4 || numHashBytesLoc > 4)

+      return 0;

+    if (*s++ != 0)

+      return 0;

+    *btMode = 0;

+    *numHashBytes = numHashBytesLoc;

+    return 1;

+  }

+  if (c != L'B')

+    return 0;

+

+  if (GetUpperChar(*s++) != L'T')

+    return 0;

+  int numHashBytesLoc = (int)(*s++ - L'0');

+  if (numHashBytesLoc < 2 || numHashBytesLoc > 4)

+    return 0;

+  c = GetUpperChar(*s++);

+  if (c != L'\0')

+    return 0;

+  *btMode = 1;

+  *numHashBytes = numHashBytesLoc;

+  return 1;

+}

+

+HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)

+{

+  if (propID == NCoderPropID::kMatchFinder)

+  {

+    if (prop.vt != VT_BSTR)

+      return E_INVALIDARG;

+    return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;

+  }

+  if (prop.vt != VT_UI4)

+    return E_INVALIDARG;

+  UInt32 v = prop.ulVal;

+  switch (propID)

+  {

+    case NCoderPropID::kNumFastBytes: ep.fb = v; break;

+    case NCoderPropID::kMatchFinderCycles: ep.mc = v; break;

+    case NCoderPropID::kAlgorithm: ep.algo = v; break;

+    case NCoderPropID::kDictionarySize: ep.dictSize = v; break;

+    case NCoderPropID::kPosStateBits: ep.pb = v; break;

+    case NCoderPropID::kLitPosBits: ep.lp = v; break;

+    case NCoderPropID::kLitContextBits: ep.lc = v; break;

+    default: return E_INVALIDARG;

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,

+    const PROPVARIANT *coderProps, UInt32 numProps)

+{

+  CLzmaEncProps props;

+  LzmaEncProps_Init(&props);

+

+  for (UInt32 i = 0; i < numProps; i++)

+  {

+    const PROPVARIANT &prop = coderProps[i];

+    PROPID propID = propIDs[i];

+    switch (propID)

+    {

+      case NCoderPropID::kEndMarker:

+        if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break;

+      case NCoderPropID::kNumThreads:

+        if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break;

+      default:

+        RINOK(SetLzmaProp(propID, prop, props));

+    }

+  }

+  return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props));

+}

+

+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)

+{

+  Byte props[LZMA_PROPS_SIZE];

+  size_t size = LZMA_PROPS_SIZE;

+  RINOK(LzmaEnc_WriteProperties(_encoder, props, &size));

+  return WriteStream(outStream, props, size);

+}

+

+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)

+{

+  CSeqInStreamWrap inWrap(inStream);

+  CSeqOutStreamWrap outWrap(outStream);

+  CCompressProgressWrap progressWrap(progress);

+

+  SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc);

+  if (res == SZ_ERROR_READ && inWrap.Res != S_OK)

+    return inWrap.Res;

+  if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)

+    return outWrap.Res;

+  if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK)

+    return progressWrap.Res;

+  return SResToHRESULT(res);

+}

+  

+}}

diff --git a/CPP/7zip/Compress/LzmaEncoder.h b/CPP/7zip/Compress/LzmaEncoder.h
new file mode 100755
index 0000000..c3e8961
--- /dev/null
+++ b/CPP/7zip/Compress/LzmaEncoder.h
@@ -0,0 +1,36 @@
+// LzmaEncoder.h

+

+#ifndef __LZMA_ENCODER_H

+#define __LZMA_ENCODER_H

+

+#include "../../../C/LzmaEnc.h"

+

+#include "../../Common/MyCom.h"

+

+#include "../ICoder.h"

+

+namespace NCompress {

+namespace NLzma {

+

+class CEncoder:

+  public ICompressCoder,

+  public ICompressSetCoderProperties,

+  public ICompressWriteCoderProperties,

+  public CMyUnknownImp

+{

+  CLzmaEncHandle _encoder;

+public:

+  MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)

+    

+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);

+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);

+

+  CEncoder();

+  virtual ~CEncoder();

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Compress/LzmaRegister.cpp b/CPP/7zip/Compress/LzmaRegister.cpp
new file mode 100755
index 0000000..9c67eaf
--- /dev/null
+++ b/CPP/7zip/Compress/LzmaRegister.cpp
@@ -0,0 +1,20 @@
+// LzmaRegister.cpp

+

+#include "StdAfx.h"

+

+#include "../Common/RegisterCodec.h"

+

+#include "LzmaDecoder.h"

+

+static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CDecoder); }

+#ifndef EXTRACT_ONLY

+#include "LzmaEncoder.h"

+static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CEncoder);  }

+#else

+#define CreateCodecOut 0

+#endif

+

+static CCodecInfo g_CodecInfo =

+  { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false };

+

+REGISTER_CODEC(LZMA)

diff --git a/CPP/7zip/Compress/PpmdDecoder.h b/CPP/7zip/Compress/PpmdDecoder.h
new file mode 100755
index 0000000..c61d1d0
--- /dev/null
+++ b/CPP/7zip/Compress/PpmdDecoder.h
@@ -0,0 +1,78 @@
+// PpmdDecoder.h

+// 2009-03-11 : Igor Pavlov : Public domain

+

+#ifndef __COMPRESS_PPMD_DECODER_H

+#define __COMPRESS_PPMD_DECODER_H

+

+#include "../../../C/Ppmd7.h"

+

+#include "../../Common/MyCom.h"

+

+#include "../Common/CWrappers.h"

+

+#include "../ICoder.h"

+

+namespace NCompress {

+namespace NPpmd {

+

+class CDecoder :

+  public ICompressCoder,

+  public ICompressSetDecoderProperties2,

+  #ifndef NO_READ_FROM_CODER

+  public ICompressSetInStream,

+  public ICompressSetOutStreamSize,

+  public ISequentialInStream,

+  #endif

+  public CMyUnknownImp

+{

+  Byte *_outBuf;

+  CPpmd7z_RangeDec _rangeDec;

+  CByteInBufWrap _inStream;

+  CPpmd7 _ppmd;

+

+  Byte _order;

+  bool _outSizeDefined;

+  int _status;

+  UInt64 _outSize;

+  UInt64 _processedSize;

+

+  HRESULT CodeSpec(Byte *memStream, UInt32 size);

+

+public:

+

+  #ifndef NO_READ_FROM_CODER

+  CMyComPtr<ISequentialInStream> InSeqStream;

+  MY_UNKNOWN_IMP4(

+      ICompressSetDecoderProperties2,

+      ICompressSetInStream,

+      ICompressSetOutStreamSize,

+      ISequentialInStream)

+  #else

+  MY_UNKNOWN_IMP1(

+      ICompressSetDecoderProperties2)

+  #endif

+

+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);

+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);

+

+  #ifndef NO_READ_FROM_CODER

+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);

+  STDMETHOD(ReleaseInStream)();

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+  #endif

+

+  CDecoder(): _outBuf(NULL), _outSizeDefined(false)

+  {

+    Ppmd7z_RangeDec_CreateVTable(&_rangeDec);

+    _rangeDec.Stream = &_inStream.p;

+    Ppmd7_Construct(&_ppmd);

+  }

+

+  ~CDecoder();

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp
new file mode 100755
index 0000000..3a8df78
--- /dev/null
+++ b/CPP/7zip/Compress/PpmdEncoder.cpp
@@ -0,0 +1,119 @@
+// PpmdEncoder.cpp

+// 2009-03-11 : Igor Pavlov : Public domain

+

+#include "StdAfx.h"

+

+#include "../../../C/Alloc.h"

+#include "../../../C/CpuArch.h"

+

+#include "../Common/StreamUtils.h"

+

+#include "PpmdEncoder.h"

+

+namespace NCompress {

+namespace NPpmd {

+

+static const UInt32 kBufSize = (1 << 20);

+

+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }

+static void SzBigFree(void *, void *address) { BigFree(address); }

+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

+

+CEncoder::CEncoder():

+  _inBuf(NULL),

+  _usedMemSize(1 << 24),

+  _order(6)

+{

+  _rangeEnc.Stream = &_outStream.p;

+  Ppmd7_Construct(&_ppmd);

+}

+

+CEncoder::~CEncoder()

+{

+  ::MidFree(_inBuf);

+  Ppmd7_Free(&_ppmd, &g_BigAlloc);

+}

+

+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)

+{

+  for (UInt32 i = 0; i < numProps; i++)

+  {

+    const PROPVARIANT &prop = props[i];

+    if (prop.vt != VT_UI4)

+      return E_INVALIDARG;

+    UInt32 v = (UInt32)prop.ulVal;

+    switch(propIDs[i])

+    {

+      case NCoderPropID::kUsedMemorySize:

+        if (v < (1 << 16) || v > PPMD7_MAX_MEM_SIZE || (v & 3) != 0)

+          return E_INVALIDARG;

+        _usedMemSize = v;

+        break;

+      case NCoderPropID::kOrder:

+        if (v < 2 || v > 32)

+          return E_INVALIDARG;

+        _order = (Byte)v;

+        break;

+      default:

+        return E_INVALIDARG;

+    }

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)

+{

+  const UInt32 kPropSize = 5;

+  Byte props[kPropSize];

+  props[0] = _order;

+  SetUi32(props + 1, _usedMemSize);

+  return WriteStream(outStream, props, kPropSize);

+}

+

+HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)

+{

+  if (!_inBuf)

+  {

+    _inBuf = (Byte *)::MidAlloc(kBufSize);

+    if (!_inBuf)

+      return E_OUTOFMEMORY;

+  }

+  if (!_outStream.Alloc(1 << 20))

+    return E_OUTOFMEMORY;

+  if (!Ppmd7_Alloc(&_ppmd, _usedMemSize, &g_BigAlloc))

+    return E_OUTOFMEMORY;

+

+  _outStream.Stream = outStream;

+  _outStream.Init();

+

+  Ppmd7z_RangeEnc_Init(&_rangeEnc);

+  Ppmd7_Init(&_ppmd, _order);

+

+  UInt64 processed = 0;

+  for (;;)

+  {

+    UInt32 size;

+    RINOK(inStream->Read(_inBuf, kBufSize, &size));

+    if (size == 0)

+    {

+      // We don't write EndMark in PPMD-7z.

+      // Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, -1);

+      Ppmd7z_RangeEnc_FlushData(&_rangeEnc);

+      return _outStream.Flush();

+    }

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

+    {

+      Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, _inBuf[i]);

+      RINOK(_outStream.Res);

+    }

+    processed += size;

+    if (progress)

+    {

+      UInt64 outSize = _outStream.GetProcessed();

+      RINOK(progress->SetRatioInfo(&processed, &outSize));

+    }

+  }

+}

+

+}}

diff --git a/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp
new file mode 100755
index 0000000..e2fd007
--- /dev/null
+++ b/CPP/7zip/Compress/PpmdRegister.cpp
@@ -0,0 +1,21 @@
+// PpmdRegister.cpp

+// 2009-05-30 : Igor Pavlov : Public domain

+

+#include "StdAfx.h"

+

+#include "../Common/RegisterCodec.h"

+

+#include "PpmdDecoder.h"

+

+static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CDecoder); }

+#ifndef EXTRACT_ONLY

+#include "PpmdEncoder.h"

+static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CEncoder);  }

+#else

+#define CreateCodecOut 0

+#endif

+

+static CCodecInfo g_CodecInfo =

+  { CreateCodec, CreateCodecOut, 0x030401, L"PPMD", 1, false };

+

+REGISTER_CODEC(PPMD)

diff --git a/CPP/7zip/Compress/RangeCoder.h b/CPP/7zip/Compress/RangeCoder.h
new file mode 100755
index 0000000..e9e8e32
--- /dev/null
+++ b/CPP/7zip/Compress/RangeCoder.h
@@ -0,0 +1,205 @@
+// Compress/RangeCoder.h

+// 2009-05-30 : Igor Pavlov : Public domain

+

+#ifndef __COMPRESS_RANGE_CODER_H

+#define __COMPRESS_RANGE_CODER_H

+

+#include "../Common/InBuffer.h"

+#include "../Common/OutBuffer.h"

+

+namespace NCompress {

+namespace NRangeCoder {

+

+const int kNumTopBits = 24;

+const UInt32 kTopValue = (1 << kNumTopBits);

+

+class CEncoder

+{

+  UInt32 _cacheSize;

+  Byte _cache;

+public:

+  UInt64 Low;

+  UInt32 Range;

+  COutBuffer Stream;

+  bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }

+

+  void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }

+  void Init()

+  {

+    Stream.Init();

+    Low = 0;

+    Range = 0xFFFFFFFF;

+    _cacheSize = 1;

+    _cache = 0;

+  }

+

+  void FlushData()

+  {

+    // Low += 1;

+    for(int i = 0; i < 5; i++)

+      ShiftLow();

+  }

+

+  HRESULT FlushStream() { return Stream.Flush();  }

+

+  void ReleaseStream() { Stream.ReleaseStream(); }

+

+  void Encode(UInt32 start, UInt32 size, UInt32 total)

+  {

+    Low += start * (Range /= total);

+    Range *= size;

+    while (Range < kTopValue)

+    {

+      Range <<= 8;

+      ShiftLow();

+    }

+  }

+

+  void ShiftLow()

+  {

+    if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0)

+    {

+      Byte temp = _cache;

+      do

+      {

+        Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));

+        temp = 0xFF;

+      }

+      while(--_cacheSize != 0);

+      _cache = (Byte)((UInt32)Low >> 24);

+    }

+    _cacheSize++;

+    Low = (UInt32)Low << 8;

+  }

+  

+  void EncodeDirectBits(UInt32 value, int numBits)

+  {

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

+    {

+      Range >>= 1;

+      Low += Range & (0 - ((value >> numBits) & 1));

+      if (Range < kTopValue)

+      {

+        Range <<= 8;

+        ShiftLow();

+      }

+    }

+  }

+

+  void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)

+  {

+    UInt32 newBound = (Range >> numTotalBits) * size0;

+    if (symbol == 0)

+      Range = newBound;

+    else

+    {

+      Low += newBound;

+      Range -= newBound;

+    }

+    while (Range < kTopValue)

+    {

+      Range <<= 8;

+      ShiftLow();

+    }

+  }

+

+  UInt64 GetProcessedSize() {  return Stream.GetProcessedSize() + _cacheSize + 4; }

+};

+

+class CDecoder

+{

+public:

+  CInBuffer Stream;

+  UInt32 Range;

+  UInt32 Code;

+  bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }

+

+  void Normalize()

+  {

+    while (Range < kTopValue)

+    {

+      Code = (Code << 8) | Stream.ReadByte();

+      Range <<= 8;

+    }

+  }

+  

+  void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }

+  void Init()

+  {

+    Stream.Init();

+    Code = 0;

+    Range = 0xFFFFFFFF;

+    for(int i = 0; i < 5; i++)

+      Code = (Code << 8) | Stream.ReadByte();

+  }

+

+  void ReleaseStream() { Stream.ReleaseStream(); }

+

+  UInt32 GetThreshold(UInt32 total)

+  {

+    return (Code) / ( Range /= total);

+  }

+

+  void Decode(UInt32 start, UInt32 size)

+  {

+    Code -= start * Range;

+    Range *= size;

+    Normalize();

+  }

+

+  UInt32 DecodeDirectBits(int numTotalBits)

+  {

+    UInt32 range = Range;

+    UInt32 code = Code;

+    UInt32 result = 0;

+    for (int i = numTotalBits; i != 0; i--)

+    {

+      range >>= 1;

+      /*

+      result <<= 1;

+      if (code >= range)

+      {

+        code -= range;

+        result |= 1;

+      }

+      */

+      UInt32 t = (code - range) >> 31;

+      code -= range & (t - 1);

+      result = (result << 1) | (1 - t);

+

+      if (range < kTopValue)

+      {

+        code = (code << 8) | Stream.ReadByte();

+        range <<= 8;

+      }

+    }

+    Range = range;

+    Code = code;

+    return result;

+  }

+

+  UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)

+  {

+    UInt32 newBound = (Range >> numTotalBits) * size0;

+    UInt32 symbol;

+    if (Code < newBound)

+    {

+      symbol = 0;

+      Range = newBound;

+    }

+    else

+    {

+      symbol = 1;

+      Code -= newBound;

+      Range -= newBound;

+    }

+    Normalize();

+    return symbol;

+  }

+

+  UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Compress/RangeCoderBit.h b/CPP/7zip/Compress/RangeCoderBit.h
new file mode 100755
index 0000000..f06408c
--- /dev/null
+++ b/CPP/7zip/Compress/RangeCoderBit.h
@@ -0,0 +1,114 @@
+// Compress/RangeCoderBit.h

+// 2009-05-30 : Igor Pavlov : Public domain

+

+#ifndef __COMPRESS_RANGE_CODER_BIT_H

+#define __COMPRESS_RANGE_CODER_BIT_H

+

+#include "RangeCoder.h"

+

+namespace NCompress {

+namespace NRangeCoder {

+

+const int kNumBitModelTotalBits  = 11;

+const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);

+

+const int kNumMoveReducingBits = 4;

+

+const int kNumBitPriceShiftBits = 4;

+const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;

+

+extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];

+

+template <int numMoveBits>

+class CBitModel

+{

+public:

+  UInt32 Prob;

+  void UpdateModel(UInt32 symbol)

+  {

+    /*

+    Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;

+    Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);

+    */

+    if (symbol == 0)

+      Prob += (kBitModelTotal - Prob) >> numMoveBits;

+    else

+      Prob -= (Prob) >> numMoveBits;

+  }

+public:

+  void Init() { Prob = kBitModelTotal / 2; }

+};

+

+template <int numMoveBits>

+class CBitEncoder: public CBitModel<numMoveBits>

+{

+public:

+  void Encode(CEncoder *encoder, UInt32 symbol)

+  {

+    /*

+    encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);

+    this->UpdateModel(symbol);

+    */

+    UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;

+    if (symbol == 0)

+    {

+      encoder->Range = newBound;

+      this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;

+    }

+    else

+    {

+      encoder->Low += newBound;

+      encoder->Range -= newBound;

+      this->Prob -= (this->Prob) >> numMoveBits;

+    }

+    if (encoder->Range < kTopValue)

+    {

+      encoder->Range <<= 8;

+      encoder->ShiftLow();

+    }

+  }

+  UInt32 GetPrice(UInt32 symbol) const

+  {

+    return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];

+  }

+  UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; }

+  UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; }

+};

+

+

+template <int numMoveBits>

+class CBitDecoder: public CBitModel<numMoveBits>

+{

+public:

+  UInt32 Decode(CDecoder *decoder)

+  {

+    UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob;

+    if (decoder->Code < newBound)

+    {

+      decoder->Range = newBound;

+      this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;

+      if (decoder->Range < kTopValue)

+      {

+        decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();

+        decoder->Range <<= 8;

+      }

+      return 0;

+    }

+    else

+    {

+      decoder->Range -= newBound;

+      decoder->Code -= newBound;

+      this->Prob -= (this->Prob) >> numMoveBits;

+      if (decoder->Range < kTopValue)

+      {

+        decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();

+        decoder->Range <<= 8;

+      }

+      return 1;

+    }

+  }

+};

+

+}}

+

+#endif

diff --git a/CPP/7zip/Compress/StdAfx.h b/CPP/7zip/Compress/StdAfx.h
new file mode 100755
index 0000000..c28ffce
--- /dev/null
+++ b/CPP/7zip/Compress/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../Common/MyWindows.h"

+

+#endif

diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak
new file mode 100755
index 0000000..444f8fe
--- /dev/null
+++ b/CPP/7zip/Crc.mak
@@ -0,0 +1,8 @@
+C_OBJS = $(C_OBJS) \

+  $O\7zCrc.obj

+!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS"

+C_OBJS = $(C_OBJS) \

+!ELSE

+ASM_OBJS = $(ASM_OBJS) \

+!ENDIF

+  $O\7zCrcOpt.obj

diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt
new file mode 100755
index 0000000..cbd45a4
--- /dev/null
+++ b/CPP/7zip/Guid.txt
@@ -0,0 +1,170 @@
+{23170F69-40C1-278A-0000-00yy00xx0000}

+

+00 IProgress.h

+

+  05  IProgress

+

+01 IFolderArchive.h

+

+  05  IArchiveFolder

+  // 06  IInFolderArchive // old

+  07  IFileExtractCallback.h::IFolderArchiveExtractCallback

+  0A  IOutFolderArchive

+  0B  IFolderArchiveUpdateCallback

+  0C  Agent.h::IArchiveFolderInternal

+  0D

+  0E  IInFolderArchive

+

+03 IStream.h

+

+  01  ISequentialInStream

+  02  ISequentialOutStream

+  03  IInStream

+  04  IOutStream

+  06  IStreamGetSize

+  07  IOutStreamFlush

+

+

+04 ICoder.h

+

+  04  ICompressProgressInfo

+  05  ICompressCoder

+  18  ICompressCoder2

+  20  ICompressSetCoderProperties

+  21  ICompressSetDecoderProperties //

+  22  ICompressSetDecoderProperties2

+  23  ICompressWriteCoderProperties

+  24  ICompressGetInStreamProcessedSize

+  25  ICompressSetCoderMt

+  30  ICompressGetSubStreamSize

+  31  ICompressSetInStream

+  32  ICompressSetOutStream

+  33  ICompressSetInStreamSize

+  34  ICompressSetOutStreamSize

+  35  ICompressSetBufSize

+  40  ICompressFilter

+  60  ICompressCodecsInfo

+  61  ISetCompressCodecsInfo

+  80  ICryptoProperties

+  88  ICryptoResetSalt

+  8C  ICryptoResetInitVector

+  90  ICryptoSetPassword

+  A0  ICryptoSetCRC

+

+

+05 IPassword.h

+

+  10 ICryptoGetTextPassword

+  11 ICryptoGetTextPassword2

+

+

+06 IArchive.h

+

+  03  ISetProperties

+

+  10  IArchiveOpenCallback

+  20  IArchiveExtractCallback

+  30  IArchiveOpenVolumeCallback

+  40  IInArchiveGetStream

+  50  IArchiveOpenSetSubArchiveName

+  60  IInArchive

+  61  IArchiveOpenSeq

+

+  80  IArchiveUpdateCallback

+  82  IArchiveUpdateCallback2

+  A0  IOutArchive

+

+

+

+08 IFolder.h

+

+  00 IFolderFolder

+  01 IEnumProperties

+  02 IFolderGetTypeID

+  03 IFolderGetPath

+  04 IFolderWasChanged

+  05 // IFolderReload

+  06 IFolderOperations

+  07 IFolderGetSystemIconIndex

+  08 IFolderGetItemFullSize

+  09 IFolderClone

+  0A IFolderSetFlatMode

+  0B IFolderOperationsExtractCallback

+  0C // 

+  0D // 

+  0E IFolderProperties

+  0F 

+  10 IFolderArcProps

+  11 IGetFolderArcProps

+

+

+09 IFolder.h :: FOLDER_MANAGER_INTERFACE

+

+  00 - 04 // old IFolderManager

+  05 IFolderManager

+

+

+// 0A PluginInterface.h

+  00 IInitContextMenu

+  01 IPluginOptionsCallback

+  02 IPluginOptions

+

+

+Handler GUIDs:

+

+{23170F69-40C1-278A-1000-000110xx0000}

+

+  01 Zip

+  02 BZip2

+  03 Rar

+  04 Arj

+  05 Z

+  06 Lzh

+  07 7z

+  08 Cab

+  09 Nsis

+  0A lzma

+  0B lzma86

+  0C xz

+  0D ppmd

+

+  D2 SquashFS

+  D3 CramFS

+  D4 APM

+  D5 Mslz

+  D6 Flv

+  D7 Swf

+  D8 Swfc

+  D9 Ntfs

+  DA Fat

+  DB Mbr

+  DC Vhd

+  DD Pe

+  DE Elf

+  DF Mach-O

+  E0 Udf

+  E1 Xar

+  E2 Mub

+  E3 Hfs

+  E4 Dmg

+  E5 Compound

+  E6 Wim

+  E7 Iso

+  E8 Bkf

+  E9 Chm

+  EA Split

+  EB Rpm

+  EC Deb

+  ED Cpio

+  EE Tar

+  EF GZip

+

+{23170F69-40C1-278A-1000-000100030000} CAgentArchiveHandle

+{23170F69-40C1-278A-1000-000100020000} ContextMenu.h::CZipContextMenu

+

+{23170F69-40C1-278B- old codecs clsids

+

+{23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions

+

+{23170F69-40C1-2790-id} Codec Decoders

+{23170F69-40C1-2791-id} Codec Encoders

diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h
new file mode 100755
index 0000000..cb74f98
--- /dev/null
+++ b/CPP/7zip/ICoder.h
@@ -0,0 +1,186 @@
+// ICoder.h

+

+#ifndef __ICODER_H

+#define __ICODER_H

+

+#include "IStream.h"

+

+#define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x)

+

+CODER_INTERFACE(ICompressProgressInfo, 0x04)

+{

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE;

+};

+

+CODER_INTERFACE(ICompressCoder, 0x05)

+{

+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,

+      const UInt64 *inSize, const UInt64 *outSize,

+      ICompressProgressInfo *progress) PURE;

+};

+

+CODER_INTERFACE(ICompressCoder2, 0x18)

+{

+  STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,

+      ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,

+      ICompressProgressInfo *progress) PURE;

+};

+

+namespace NCoderPropID

+{

+  enum EEnum

+  {

+    kDefaultProp = 0,

+    kDictionarySize,

+    kUsedMemorySize,

+    kOrder,

+    kBlockSize,

+    kPosStateBits,

+    kLitContextBits,

+    kLitPosBits,

+    kNumFastBytes,

+    kMatchFinder,

+    kMatchFinderCycles,

+    kNumPasses,

+    kAlgorithm,

+    kNumThreads,

+    kEndMarker

+  };

+}

+

+CODER_INTERFACE(ICompressSetCoderProperties, 0x20)

+{

+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE;

+};

+

+/*

+CODER_INTERFACE(ICompressSetCoderProperties, 0x21)

+{

+  STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE;

+};

+*/

+

+CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22)

+{

+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE;

+};

+

+CODER_INTERFACE(ICompressWriteCoderProperties, 0x23)

+{

+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream) PURE;

+};

+

+CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24)

+{

+  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE;

+};

+

+CODER_INTERFACE(ICompressSetCoderMt, 0x25)

+{

+  STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE;

+};

+

+CODER_INTERFACE(ICompressGetSubStreamSize, 0x30)

+{

+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE;

+};

+

+CODER_INTERFACE(ICompressSetInStream, 0x31)

+{

+  STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE;

+  STDMETHOD(ReleaseInStream)() PURE;

+};

+

+CODER_INTERFACE(ICompressSetOutStream, 0x32)

+{

+  STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE;

+  STDMETHOD(ReleaseOutStream)() PURE;

+};

+

+CODER_INTERFACE(ICompressSetInStreamSize, 0x33)

+{

+  STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE;

+};

+

+CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)

+{

+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE;

+};

+

+CODER_INTERFACE(ICompressSetBufSize, 0x35)

+{

+  STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size) PURE;

+  STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE;

+};

+

+CODER_INTERFACE(ICompressFilter, 0x40)

+{

+  STDMETHOD(Init)() PURE;

+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE;

+  // Filter converts as most as possible bytes

+  // Filter return outSize (UInt32)

+  // if (outSize <= size): Filter have converted outSize bytes

+  // if (outSize > size): Filter have not converted anything.

+  //      and it needs at least outSize bytes to convert one block

+  //      (it's for crypto block algorithms).

+};

+

+CODER_INTERFACE(ICompressCodecsInfo, 0x60)

+{

+  STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE;

+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;

+  STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE;

+  STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE;

+};

+CODER_INTERFACE(ISetCompressCodecsInfo, 0x61)

+{

+  STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE;

+};

+

+CODER_INTERFACE(ICryptoProperties, 0x80)

+{

+  STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE;

+  STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE;

+};

+

+/*

+CODER_INTERFACE(ICryptoResetSalt, 0x88)

+{

+  STDMETHOD(ResetSalt)() PURE;

+};

+*/

+

+CODER_INTERFACE(ICryptoResetInitVector, 0x8C)

+{

+  STDMETHOD(ResetInitVector)() PURE;

+};

+

+CODER_INTERFACE(ICryptoSetPassword, 0x90)

+{

+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE;

+};

+

+CODER_INTERFACE(ICryptoSetCRC, 0xA0)

+{

+  STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE;

+};

+

+//////////////////////

+// It's for DLL file

+namespace NMethodPropID

+{

+  enum EEnum

+  {

+    kID,

+    kName,

+    kDecoder,

+    kEncoder,

+    kInStreams,

+    kOutStreams,

+    kDescription,

+    kDecoderIsAssigned,

+    kEncoderIsAssigned

+  };

+}

+

+#endif

diff --git a/CPP/7zip/IDecl.h b/CPP/7zip/IDecl.h
new file mode 100755
index 0000000..768bbe7
--- /dev/null
+++ b/CPP/7zip/IDecl.h
@@ -0,0 +1,15 @@
+// IDecl.h

+

+#ifndef __IDECL_H

+#define __IDECL_H

+

+#include "../Common/MyUnknown.h"

+

+#define DECL_INTERFACE_SUB(i, base, groupId, subId) \

+DEFINE_GUID(IID_ ## i, \

+0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \

+struct i: public base

+

+#define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId)

+

+#endif

diff --git a/CPP/7zip/IPassword.h b/CPP/7zip/IPassword.h
new file mode 100755
index 0000000..5679d84
--- /dev/null
+++ b/CPP/7zip/IPassword.h
@@ -0,0 +1,24 @@
+// IPassword.h

+

+#ifndef __IPASSWORD_H

+#define __IPASSWORD_H

+

+#include "../Common/MyUnknown.h"

+#include "../Common/Types.h"

+

+#include "IDecl.h"

+

+#define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x)

+

+PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10)

+{

+  STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE;

+};

+

+PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11)

+{

+  STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE;

+};

+

+#endif

+

diff --git a/CPP/7zip/IProgress.h b/CPP/7zip/IProgress.h
new file mode 100755
index 0000000..09486ba
--- /dev/null
+++ b/CPP/7zip/IProgress.h
@@ -0,0 +1,33 @@
+// Interface/IProgress.h

+

+#ifndef __IPROGRESS_H

+#define __IPROGRESS_H

+

+#include "../Common/MyUnknown.h"

+#include "../Common/Types.h"

+

+#include "IDecl.h"

+

+#define INTERFACE_IProgress(x) \

+  STDMETHOD(SetTotal)(UInt64 total) x; \

+  STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \

+

+DECL_INTERFACE(IProgress, 0, 5)

+{

+  INTERFACE_IProgress(PURE)

+};

+

+/*

+// {23170F69-40C1-278A-0000-000000050002}

+DEFINE_GUID(IID_IProgress2,

+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02);

+MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002")

+IProgress2: public IUnknown

+{

+public:

+  STDMETHOD(SetTotal)(const UInt64 *total) PURE;

+  STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE;

+};

+*/

+

+#endif

diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h
new file mode 100755
index 0000000..89f02f5
--- /dev/null
+++ b/CPP/7zip/IStream.h
@@ -0,0 +1,58 @@
+// IStream.h

+

+#ifndef __ISTREAM_H

+#define __ISTREAM_H

+

+#include "../Common/MyUnknown.h"

+#include "../Common/Types.h"

+

+#include "IDecl.h"

+

+#define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x)

+#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x)

+

+STREAM_INTERFACE(ISequentialInStream, 0x01)

+{

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;

+  /*

+  Out: if size != 0, return_value = S_OK and (*processedSize == 0),

+    then there are no more bytes in stream.

+  if (size > 0) && there are bytes in stream,

+  this function must read at least 1 byte.

+  This function is allowed to read less than number of remaining bytes in stream.

+  You must call Read function in loop, if you need exact amount of data

+  */

+};

+

+STREAM_INTERFACE(ISequentialOutStream, 0x02)

+{

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;

+  /*

+  if (size > 0) this function must write at least 1 byte.

+  This function is allowed to write less than "size".

+  You must call Write function in loop, if you need to write exact amount of data

+  */

+};

+

+STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03)

+{

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;

+};

+

+STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04)

+{

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;

+  STDMETHOD(SetSize)(UInt64 newSize) PURE;

+};

+

+STREAM_INTERFACE(IStreamGetSize, 0x06)

+{

+  STDMETHOD(GetSize)(UInt64 *size) PURE;

+};

+

+STREAM_INTERFACE(IOutStreamFlush, 0x07)

+{

+  STDMETHOD(Flush)() PURE;

+};

+

+#endif

diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h
new file mode 100755
index 0000000..f549249
--- /dev/null
+++ b/CPP/7zip/MyVersion.h
@@ -0,0 +1,8 @@
+#define MY_VER_MAJOR 9

+#define MY_VER_MINOR 20

+#define MY_VER_BUILD 0

+#define MY_VERSION "9.20"

+#define MY_7ZIP_VERSION "7-Zip 9.20"

+#define MY_DATE "2010-11-18"

+#define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov"

+#define MY_VERSION_COPYRIGHT_DATE MY_VERSION "  " MY_COPYRIGHT "  " MY_DATE

diff --git a/CPP/7zip/MyVersionInfo.rc b/CPP/7zip/MyVersionInfo.rc
new file mode 100755
index 0000000..84e4ac3
--- /dev/null
+++ b/CPP/7zip/MyVersionInfo.rc
@@ -0,0 +1,52 @@
+#define MY_VS_FFI_FILEFLAGSMASK  0x0000003FL

+#define MY_VOS_NT_WINDOWS32  0x00040004L

+#define MY_VOS_CE_WINDOWS32  0x00050004L

+

+#define MY_VFT_APP  0x00000001L

+#define MY_VFT_DLL  0x00000002L

+

+// #include <WinVer.h>

+#include "MyVersion.h"

+

+#define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0

+

+#ifdef DEBUG

+#define DBG_FL VS_FF_DEBUG

+#else

+#define DBG_FL 0

+#endif

+

+#define MY_VERSION_INFO(fileType, descr, intName, origName)  \

+LANGUAGE 9, 1 \

+1 VERSIONINFO \

+  FILEVERSION MY_VER \

+  PRODUCTVERSION MY_VER \

+  FILEFLAGSMASK MY_VS_FFI_FILEFLAGSMASK \

+  FILEFLAGS DBG_FL \

+  FILEOS MY_VOS_NT_WINDOWS32 \

+  FILETYPE fileType \

+  FILESUBTYPE 0x0L \

+BEGIN \

+    BLOCK "StringFileInfo" \

+    BEGIN  \

+        BLOCK "040904b0" \

+        BEGIN \

+            VALUE "CompanyName", "Igor Pavlov" \

+            VALUE "FileDescription", descr \

+            VALUE "FileVersion", MY_VERSION  \

+            VALUE "InternalName", intName \

+            VALUE "LegalCopyright", MY_COPYRIGHT \

+            VALUE "OriginalFilename", origName \

+            VALUE "ProductName", "7-Zip" \

+            VALUE "ProductVersion", MY_VERSION \

+        END \

+    END \

+    BLOCK "VarFileInfo" \

+    BEGIN \

+        VALUE "Translation", 0x409, 1200 \

+    END \

+END

+

+#define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(MY_VFT_APP, descr, intName, intName ".exe")

+

+#define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(MY_VFT_DLL, descr, intName, intName ".dll")

diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h
new file mode 100755
index 0000000..1aabc65
--- /dev/null
+++ b/CPP/7zip/PropID.h
@@ -0,0 +1,76 @@
+// PropID.h

+

+#ifndef __7ZIP_PROPID_H

+#define __7ZIP_PROPID_H

+

+enum

+{

+  kpidNoProperty = 0,

+  kpidMainSubfile = 1,

+  kpidHandlerItemIndex = 2,

+  kpidPath,

+  kpidName,

+  kpidExtension,

+  kpidIsDir,

+  kpidSize,

+  kpidPackSize,

+  kpidAttrib,

+  kpidCTime,

+  kpidATime,

+  kpidMTime,

+  kpidSolid,

+  kpidCommented,

+  kpidEncrypted,

+  kpidSplitBefore,

+  kpidSplitAfter,

+  kpidDictionarySize,

+  kpidCRC,

+  kpidType,

+  kpidIsAnti,

+  kpidMethod,

+  kpidHostOS,

+  kpidFileSystem,

+  kpidUser,

+  kpidGroup,

+  kpidBlock,

+  kpidComment,

+  kpidPosition,

+  kpidPrefix,

+  kpidNumSubDirs,

+  kpidNumSubFiles,

+  kpidUnpackVer,

+  kpidVolume,

+  kpidIsVolume,

+  kpidOffset,

+  kpidLinks,

+  kpidNumBlocks,

+  kpidNumVolumes,

+  kpidTimeType,

+  kpidBit64,

+  kpidBigEndian,

+  kpidCpu,

+  kpidPhySize,

+  kpidHeadersSize,

+  kpidChecksum,

+  kpidCharacts,

+  kpidVa,

+  kpidId,

+  kpidShortName,

+  kpidCreatorApp,

+  kpidSectorSize,

+  kpidPosixAttrib,

+  kpidLink,

+  kpidError,

+

+  kpidTotalSize = 0x1100,

+  kpidFreeSpace,

+  kpidClusterSize,

+  kpidVolumeName,

+

+  kpidLocalName = 0x1200,

+  kpidProvider,

+

+  kpidUserDefined = 0x10000

+};

+

+#endif

diff --git a/CPP/7zip/SubBuild.mak b/CPP/7zip/SubBuild.mak
new file mode 100755
index 0000000..0c49d3b
--- /dev/null
+++ b/CPP/7zip/SubBuild.mak
@@ -0,0 +1,3 @@
+	cd $(@D)

+	$(MAKE) -nologo $(TARGETS)

+	cd ..

diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
new file mode 100755
index 0000000..7001fe8
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/Client7z.cpp
@@ -0,0 +1,871 @@
+// Client7z.cpp

+

+#include "StdAfx.h"

+

+#include "Common/IntToString.h"

+#include "Common/MyInitGuid.h"

+#include "Common/StringConvert.h"

+

+#include "Windows/DLL.h"

+#include "Windows/FileDir.h"

+#include "Windows/FileFind.h"

+#include "Windows/FileName.h"

+#include "Windows/NtCheck.h"

+#include "Windows/PropVariant.h"

+#include "Windows/PropVariantConversions.h"

+

+#include "../../Common/FileStreams.h"

+

+#include "../../Archive/IArchive.h"

+

+#include "../../IPassword.h"

+#include "../../MyVersion.h"

+

+// use another CLSIDs, if you want to support other formats (zip, rar, ...).

+// {23170F69-40C1-278A-1000-000110070000}

+DEFINE_GUID(CLSID_CFormat7z,

+  0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00);

+

+using namespace NWindows;

+

+#define kDllName "7z.dll"

+

+static const char *kCopyrightString = MY_7ZIP_VERSION

+" ("  kDllName " client) "

+MY_COPYRIGHT " " MY_DATE;

+

+static const char *kHelpString =

+"Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n"

+"Examples:\n"

+"  Client7z.exe a archive.7z f1.txt f2.txt  : compress two files to archive.7z\n"

+"  Client7z.exe l archive.7z   : List contents of archive.7z\n"

+"  Client7z.exe x archive.7z   : eXtract files from archive.7z\n";

+

+

+typedef UINT32 (WINAPI * CreateObjectFunc)(

+    const GUID *clsID,

+    const GUID *interfaceID,

+    void **outObject);

+

+

+void PrintString(const UString &s)

+{

+  printf("%s", (LPCSTR)GetOemString(s));

+}

+

+void PrintString(const AString &s)

+{

+  printf("%s", (LPCSTR)s);

+}

+

+void PrintNewLine()

+{

+  PrintString("\n");

+}

+

+void PrintStringLn(const AString &s)

+{

+  PrintString(s);

+  PrintNewLine();

+}

+

+void PrintError(const AString &s)

+{

+  PrintNewLine();

+  PrintString(s);

+  PrintNewLine();

+}

+

+static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)

+{

+  NCOM::CPropVariant prop;

+  RINOK(archive->GetProperty(index, propID, &prop));

+  if (prop.vt == VT_BOOL)

+    result = VARIANT_BOOLToBool(prop.boolVal);

+  else if (prop.vt == VT_EMPTY)

+    result = false;

+  else

+    return E_FAIL;

+  return S_OK;

+}

+

+static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)

+{

+  return IsArchiveItemProp(archive, index, kpidIsDir, result);

+}

+

+

+static const wchar_t *kEmptyFileAlias = L"[Content]";

+

+

+//////////////////////////////////////////////////////////////

+// Archive Open callback class

+

+

+class CArchiveOpenCallback:

+  public IArchiveOpenCallback,

+  public ICryptoGetTextPassword,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP1(ICryptoGetTextPassword)

+

+  STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);

+  STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);

+

+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);

+

+  bool PasswordIsDefined;

+  UString Password;

+

+  CArchiveOpenCallback() : PasswordIsDefined(false) {}

+};

+

+STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)

+{

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */)

+{

+  return S_OK;

+}

+  

+STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password)

+{

+  if (!PasswordIsDefined)

+  {

+    // You can ask real password here from user

+    // Password = GetPassword(OutStream);

+    // PasswordIsDefined = true;

+    PrintError("Password is not defined");

+    return E_ABORT;

+  }

+  return StringToBstr(Password, password);

+}

+

+

+//////////////////////////////////////////////////////////////

+// Archive Extracting callback class

+

+static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";

+

+static const char *kTestingString    =  "Testing     ";

+static const char *kExtractingString =  "Extracting  ";

+static const char *kSkippingString   =  "Skipping    ";

+

+static const char *kUnsupportedMethod = "Unsupported Method";

+static const char *kCRCFailed = "CRC Failed";

+static const char *kDataError = "Data Error";

+static const char *kUnknownError = "Unknown Error";

+

+class CArchiveExtractCallback:

+  public IArchiveExtractCallback,

+  public ICryptoGetTextPassword,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP1(ICryptoGetTextPassword)

+

+  // IProgress

+  STDMETHOD(SetTotal)(UInt64 size);

+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);

+

+  // IArchiveExtractCallback

+  STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode);

+  STDMETHOD(PrepareOperation)(Int32 askExtractMode);

+  STDMETHOD(SetOperationResult)(Int32 resultEOperationResult);

+

+  // ICryptoGetTextPassword

+  STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword);

+

+private:

+  CMyComPtr<IInArchive> _archiveHandler;

+  UString _directoryPath;  // Output directory

+  UString _filePath;       // name inside arcvhive

+  UString _diskFilePath;   // full path to file on disk

+  bool _extractMode;

+  struct CProcessedFileInfo

+  {

+    FILETIME MTime;

+    UInt32 Attrib;

+    bool isDir;

+    bool AttribDefined;

+    bool MTimeDefined;

+  } _processedFileInfo;

+

+  COutFileStream *_outFileStreamSpec;

+  CMyComPtr<ISequentialOutStream> _outFileStream;

+

+public:

+  void Init(IInArchive *archiveHandler, const UString &directoryPath);

+

+  UInt64 NumErrors;

+  bool PasswordIsDefined;

+  UString Password;

+

+  CArchiveExtractCallback() : PasswordIsDefined(false) {}

+};

+

+void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath)

+{

+  NumErrors = 0;

+  _archiveHandler = archiveHandler;

+  _directoryPath = directoryPath;

+  NFile::NName::NormalizeDirPathPrefix(_directoryPath);

+}

+

+STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */)

+{

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */)

+{

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index,

+    ISequentialOutStream **outStream, Int32 askExtractMode)

+{

+  *outStream = 0;

+  _outFileStream.Release();

+

+  {

+    // Get Name

+    NCOM::CPropVariant prop;

+    RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop));

+    

+    UString fullPath;

+    if (prop.vt == VT_EMPTY)

+      fullPath = kEmptyFileAlias;

+    else

+    {

+      if (prop.vt != VT_BSTR)

+        return E_FAIL;

+      fullPath = prop.bstrVal;

+    }

+    _filePath = fullPath;

+  }

+

+  if (askExtractMode != NArchive::NExtract::NAskMode::kExtract)

+    return S_OK;

+

+  {

+    // Get Attrib

+    NCOM::CPropVariant prop;

+    RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));

+    if (prop.vt == VT_EMPTY)

+    {

+      _processedFileInfo.Attrib = 0;

+      _processedFileInfo.AttribDefined = false;

+    }

+    else

+    {

+      if (prop.vt != VT_UI4)

+        return E_FAIL;

+      _processedFileInfo.Attrib = prop.ulVal;

+      _processedFileInfo.AttribDefined = true;

+    }

+  }

+

+  RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir));

+

+  {

+    // Get Modified Time

+    NCOM::CPropVariant prop;

+    RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));

+    _processedFileInfo.MTimeDefined = false;

+    switch(prop.vt)

+    {

+      case VT_EMPTY:

+        // _processedFileInfo.MTime = _utcMTimeDefault;

+        break;

+      case VT_FILETIME:

+        _processedFileInfo.MTime = prop.filetime;

+        _processedFileInfo.MTimeDefined = true;

+        break;

+      default:

+        return E_FAIL;

+    }

+

+  }

+  {

+    // Get Size

+    NCOM::CPropVariant prop;

+    RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop));

+    bool newFileSizeDefined = (prop.vt != VT_EMPTY);

+    UInt64 newFileSize;

+    if (newFileSizeDefined)

+      newFileSize = ConvertPropVariantToUInt64(prop);

+  }

+

+  

+  {

+    // Create folders for file

+    int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);

+    if (slashPos >= 0)

+      NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos));

+  }

+

+  UString fullProcessedPath = _directoryPath + _filePath;

+  _diskFilePath = fullProcessedPath;

+

+  if (_processedFileInfo.isDir)

+  {

+    NFile::NDirectory::CreateComplexDirectory(fullProcessedPath);

+  }

+  else

+  {

+    NFile::NFind::CFileInfoW fi;

+    if (fi.Find(fullProcessedPath))

+    {

+      if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))

+      {

+        PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath);

+        return E_ABORT;

+      }

+    }

+    

+    _outFileStreamSpec = new COutFileStream;

+    CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);

+    if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS))

+    {

+      PrintString((UString)L"can not open output file " + fullProcessedPath);

+      return E_ABORT;

+    }

+    _outFileStream = outStreamLoc;

+    *outStream = outStreamLoc.Detach();

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)

+{

+  _extractMode = false;

+  switch (askExtractMode)

+  {

+    case NArchive::NExtract::NAskMode::kExtract:  _extractMode = true; break;

+  };

+  switch (askExtractMode)

+  {

+    case NArchive::NExtract::NAskMode::kExtract:  PrintString(kExtractingString); break;

+    case NArchive::NExtract::NAskMode::kTest:  PrintString(kTestingString); break;

+    case NArchive::NExtract::NAskMode::kSkip:  PrintString(kSkippingString); break;

+  };

+  PrintString(_filePath);

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)

+{

+  switch(operationResult)

+  {

+    case NArchive::NExtract::NOperationResult::kOK:

+      break;

+    default:

+    {

+      NumErrors++;

+      PrintString("     ");

+      switch(operationResult)

+      {

+        case NArchive::NExtract::NOperationResult::kUnSupportedMethod:

+          PrintString(kUnsupportedMethod);

+          break;

+        case NArchive::NExtract::NOperationResult::kCRCError:

+          PrintString(kCRCFailed);

+          break;

+        case NArchive::NExtract::NOperationResult::kDataError:

+          PrintString(kDataError);

+          break;

+        default:

+          PrintString(kUnknownError);

+      }

+    }

+  }

+

+  if (_outFileStream != NULL)

+  {

+    if (_processedFileInfo.MTimeDefined)

+      _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);

+    RINOK(_outFileStreamSpec->Close());

+  }

+  _outFileStream.Release();

+  if (_extractMode && _processedFileInfo.AttribDefined)

+    NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib);

+  PrintNewLine();

+  return S_OK;

+}

+

+

+STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)

+{

+  if (!PasswordIsDefined)

+  {

+    // You can ask real password here from user

+    // Password = GetPassword(OutStream);

+    // PasswordIsDefined = true;

+    PrintError("Password is not defined");

+    return E_ABORT;

+  }

+  return StringToBstr(Password, password);

+}

+

+

+

+//////////////////////////////////////////////////////////////

+// Archive Creating callback class

+

+struct CDirItem

+{

+  UInt64 Size;

+  FILETIME CTime;

+  FILETIME ATime;

+  FILETIME MTime;

+  UString Name;

+  UString FullPath;

+  UInt32 Attrib;

+

+  bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }

+};

+

+class CArchiveUpdateCallback:

+  public IArchiveUpdateCallback2,

+  public ICryptoGetTextPassword2,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)

+

+  // IProgress

+  STDMETHOD(SetTotal)(UInt64 size);

+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);

+

+  // IUpdateCallback2

+  STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);

+  STDMETHOD(GetUpdateItemInfo)(UInt32 index,

+      Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);

+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);

+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);

+  STDMETHOD(SetOperationResult)(Int32 operationResult);

+  STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size);

+  STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream);

+

+  STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);

+

+public:

+  CRecordVector<UInt64> VolumesSizes;

+  UString VolName;

+  UString VolExt;

+

+  UString DirPrefix;

+  const CObjectVector<CDirItem> *DirItems;

+

+  bool PasswordIsDefined;

+  UString Password;

+  bool AskPassword;

+

+  bool m_NeedBeClosed;

+

+  UStringVector FailedFiles;

+  CRecordVector<HRESULT> FailedCodes;

+

+  CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {};

+

+  ~CArchiveUpdateCallback() { Finilize(); }

+  HRESULT Finilize();

+

+  void Init(const CObjectVector<CDirItem> *dirItems)

+  {

+    DirItems = dirItems;

+    m_NeedBeClosed = false;

+    FailedFiles.Clear();

+    FailedCodes.Clear();

+  }

+};

+

+STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */)

+{

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */)

+{

+  return S_OK;

+}

+

+

+STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */)

+{

+  return E_NOTIMPL;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */,

+      Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)

+{

+  if (newData != NULL)

+    *newData = BoolToInt(true);

+  if (newProperties != NULL)

+    *newProperties = BoolToInt(true);

+  if (indexInArchive != NULL)

+    *indexInArchive = (UInt32)-1;

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)

+{

+  NWindows::NCOM::CPropVariant prop;

+  

+  if (propID == kpidIsAnti)

+  {

+    prop = false;

+    prop.Detach(value);

+    return S_OK;

+  }

+

+  {

+    const CDirItem &dirItem = (*DirItems)[index];

+    switch(propID)

+    {

+      case kpidPath:  prop = dirItem.Name; break;

+      case kpidIsDir:  prop = dirItem.isDir(); break;

+      case kpidSize:  prop = dirItem.Size; break;

+      case kpidAttrib:  prop = dirItem.Attrib; break;

+      case kpidCTime:  prop = dirItem.CTime; break;

+      case kpidATime:  prop = dirItem.ATime; break;

+      case kpidMTime:  prop = dirItem.MTime; break;

+    }

+  }

+  prop.Detach(value);

+  return S_OK;

+}

+

+HRESULT CArchiveUpdateCallback::Finilize()

+{

+  if (m_NeedBeClosed)

+  {

+    PrintNewLine();

+    m_NeedBeClosed = false;

+  }

+  return S_OK;

+}

+

+static void GetStream2(const wchar_t *name)

+{

+  PrintString("Compressing  ");

+  if (name[0] == 0)

+    name = kEmptyFileAlias;

+  PrintString(name);

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)

+{

+  RINOK(Finilize());

+

+  const CDirItem &dirItem = (*DirItems)[index];

+  GetStream2(dirItem.Name);

+ 

+  if (dirItem.isDir())

+    return S_OK;

+

+  {

+    CInFileStream *inStreamSpec = new CInFileStream;

+    CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);

+    UString path = DirPrefix + dirItem.FullPath;

+    if (!inStreamSpec->Open(path))

+    {

+      DWORD sysError = ::GetLastError();

+      FailedCodes.Add(sysError);

+      FailedFiles.Add(path);

+      // if (systemError == ERROR_SHARING_VIOLATION)

+      {

+        PrintNewLine();

+        PrintError("WARNING: can't open file");

+        // PrintString(NError::MyFormatMessageW(systemError));

+        return S_FALSE;

+      }

+      // return sysError;

+    }

+    *inStream = inStreamLoc.Detach();

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */)

+{

+  m_NeedBeClosed = true;

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)

+{

+  if (VolumesSizes.Size() == 0)

+    return S_FALSE;

+  if (index >= (UInt32)VolumesSizes.Size())

+    index = VolumesSizes.Size() - 1;

+  *size = VolumesSizes[index];

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)

+{

+  wchar_t temp[16];

+  ConvertUInt32ToString(index + 1, temp);

+  UString res = temp;

+  while (res.Length() < 2)

+    res = UString(L'0') + res;

+  UString fileName = VolName;

+  fileName += L'.';

+  fileName += res;

+  fileName += VolExt;

+  COutFileStream *streamSpec = new COutFileStream;

+  CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);

+  if (!streamSpec->Create(fileName, false))

+    return ::GetLastError();

+  *volumeStream = streamLoc.Detach();

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)

+{

+  if (!PasswordIsDefined)

+  {

+    if (AskPassword)

+    {

+      // You can ask real password here from user

+      // Password = GetPassword(OutStream);

+      // PasswordIsDefined = true;

+      PrintError("Password is not defined");

+      return E_ABORT;

+    }

+  }

+  *passwordIsDefined = BoolToInt(PasswordIsDefined);

+  return StringToBstr(Password, password);

+}

+

+

+

+//////////////////////////////////////////////////////////////////////////

+// Main function

+

+#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1;

+

+int MY_CDECL main(int numArgs, const char *args[])

+{

+  NT_CHECK

+

+  PrintStringLn(kCopyrightString);

+

+  if (numArgs < 3)

+  {

+    PrintStringLn(kHelpString);

+    return 1;

+  }

+  NWindows::NDLL::CLibrary lib;

+  if (!lib.Load(TEXT(kDllName)))

+  {

+    PrintError("Can not load 7-zip library");

+    return 1;

+  }

+  CreateObjectFunc createObjectFunc = (CreateObjectFunc)lib.GetProc("CreateObject");

+  if (createObjectFunc == 0)

+  {

+    PrintError("Can not get CreateObject");

+    return 1;

+  }

+

+  char c;

+  {

+    AString command = args[1];

+    if (command.Length() != 1)

+    {

+      PrintError("incorrect command");

+      return 1;

+    }

+    c = MyCharLower(command[0]);

+  }

+  UString archiveName = GetUnicodeString(args[2]);

+  if (c == 'a')

+  {

+    // create archive command

+    if (numArgs < 4)

+    {

+      PrintStringLn(kHelpString);

+      return 1;

+    }

+    CObjectVector<CDirItem> dirItems;

+    int i;

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

+    {

+      CDirItem di;

+      UString name = GetUnicodeString(args[i]);

+      

+      NFile::NFind::CFileInfoW fi;

+      if (!fi.Find(name))

+      {

+        PrintString(UString(L"Can't find file") + name);

+        return 1;

+      }

+

+      di.Attrib = fi.Attrib;

+      di.Size = fi.Size;

+      di.CTime = fi.CTime;

+      di.ATime = fi.ATime;

+      di.MTime = fi.MTime;

+      di.Name = name;

+      di.FullPath = name;

+      dirItems.Add(di);

+    }

+    COutFileStream *outFileStreamSpec = new COutFileStream;

+    CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;

+    if (!outFileStreamSpec->Create(archiveName, false))

+    {

+      PrintError("can't create archive file");

+      return 1;

+    }

+

+    CMyComPtr<IOutArchive> outArchive;

+    if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK)

+    {

+      PrintError("Can not get class object");

+      return 1;

+    }

+

+    CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;

+    CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);

+    updateCallbackSpec->Init(&dirItems);

+    // updateCallbackSpec->PasswordIsDefined = true;

+    // updateCallbackSpec->Password = L"1";

+

+    /*

+    {

+      const wchar_t *names[] =

+      {

+        L"s",

+        L"x"

+      };

+      const int kNumProps = sizeof(names) / sizeof(names[0]);

+      NWindows::NCOM::CPropVariant values[kNumProps] =

+      {

+        false,    // solid mode OFF

+        (UInt32)9 // compression level = 9 - ultra

+      };

+      CMyComPtr<ISetProperties> setProperties;

+      outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties);

+      if (!setProperties)

+      {

+        PrintError("ISetProperties unsupported");

+        return 1;

+      }

+      RINOK(setProperties->SetProperties(names, values, kNumProps));

+    }

+    */

+    

+    HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback);

+    updateCallbackSpec->Finilize();

+    if (result != S_OK)

+    {

+      PrintError("Update Error");

+      return 1;

+    }

+    for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++)

+    {

+      PrintNewLine();

+      PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]);

+    }

+    if (updateCallbackSpec->FailedFiles.Size() != 0)

+      return 1;

+  }

+  else

+  {

+    if (numArgs != 3)

+    {

+      PrintStringLn(kHelpString);

+      return 1;

+    }

+

+    bool listCommand;

+    if (c == 'l')

+      listCommand = true;

+    else if (c == 'x')

+      listCommand = false;

+    else

+    {

+      PrintError("incorrect command");

+      return 1;

+    }

+  

+    CMyComPtr<IInArchive> archive;

+    if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK)

+    {

+      PrintError("Can not get class object");

+      return 1;

+    }

+    

+    CInFileStream *fileSpec = new CInFileStream;

+    CMyComPtr<IInStream> file = fileSpec;

+    

+    if (!fileSpec->Open(archiveName))

+    {

+      PrintError("Can not open archive file");

+      return 1;

+    }

+

+    {

+      CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback;

+      CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);

+      openCallbackSpec->PasswordIsDefined = false;

+      // openCallbackSpec->PasswordIsDefined = true;

+      // openCallbackSpec->Password = L"1";

+      

+      if (archive->Open(file, 0, openCallback) != S_OK)

+      {

+        PrintError("Can not open archive");

+        return 1;

+      }

+    }

+    

+    if (listCommand)

+    {

+      // List command

+      UInt32 numItems = 0;

+      archive->GetNumberOfItems(&numItems);

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

+      {

+        {

+          // Get uncompressed size of file

+          NWindows::NCOM::CPropVariant prop;

+          archive->GetProperty(i, kpidSize, &prop);

+          UString s = ConvertPropVariantToString(prop);

+          PrintString(s);

+          PrintString("  ");

+        }

+        {

+          // Get name of file

+          NWindows::NCOM::CPropVariant prop;

+          archive->GetProperty(i, kpidPath, &prop);

+          UString s = ConvertPropVariantToString(prop);

+          PrintString(s);

+        }

+        PrintString("\n");

+      }

+    }

+    else

+    {

+      // Extract command

+      CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;

+      CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);

+      extractCallbackSpec->Init(archive, L""); // second parameter is output folder path

+      extractCallbackSpec->PasswordIsDefined = false;

+      // extractCallbackSpec->PasswordIsDefined = true;

+      // extractCallbackSpec->Password = L"1";

+      HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback);

+      if (result != S_OK)

+      {

+        PrintError("Extract Error");

+        return 1;

+      }

+    }

+  }

+  return 0;

+}

diff --git a/CPP/7zip/UI/Client7z/Client7z.dsp b/CPP/7zip/UI/Client7z/Client7z.dsp
new file mode 100755
index 0000000..34eb42b
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/Client7z.dsp
@@ -0,0 +1,226 @@
+# Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Console Application" 0x0103

+

+CFG=Client7z - 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 "Client7z.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 "Client7z.mak" CFG="Client7z - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application")

+!MESSAGE "Client7z - 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)" == "Client7z - 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 Target_Dir ""

+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c

+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /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

+

+!ELSEIF  "$(CFG)" == "Client7z - 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" /Yu"stdafx.h" /FD /GZ /c

+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /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 /pdbtype:sept

+

+!ENDIF 

+

+# Begin Target

+

+# Name "Client7z - Win32 Release"

+# Name "Client7z - Win32 Debug"

+# Begin Group "Spec"

+

+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"

+# Begin Source File

+

+SOURCE=.\StdAfx.cpp

+# ADD CPP /Yc"stdafx.h"

+# End Source File

+# Begin Source File

+

+SOURCE=.\StdAfx.h

+# End Source File

+# End Group

+# Begin Group "Windows"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Windows\DLL.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\DLL.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileDir.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileDir.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileFind.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileFind.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileIO.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileName.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\FileName.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariant.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariant.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariantConversions.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Windows\PropVariantConversions.h

+# End Source File

+# End Group

+# Begin Group "Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\IntToString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyString.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\MyVector.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\NewHandler.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\StringConvert.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Wildcard.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\..\Common\Wildcard.h

+# End Source File

+# End Group

+# Begin Group "7zip Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.cpp

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Common\FileStreams.h

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=.\Client7z.cpp

+# End Source File

+# End Target

+# End Project

diff --git a/CPP/7zip/UI/Client7z/Client7z.dsw b/CPP/7zip/UI/Client7z/Client7z.dsw
new file mode 100755
index 0000000..4c26851
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/Client7z.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00

+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

+

+###############################################################################

+

+Project: "Client7z"=.\Client7z.dsp - Package Owner=<4>

+

+Package=<5>

+{{{

+}}}

+

+Package=<4>

+{{{

+}}}

+

+###############################################################################

+

+Global:

+

+Package=<5>

+{{{

+}}}

+

+Package=<3>

+{{{

+}}}

+

+###############################################################################

+

diff --git a/CPP/7zip/UI/Client7z/StdAfx.cpp b/CPP/7zip/UI/Client7z/StdAfx.cpp
new file mode 100755
index 0000000..c6d3b1f
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp

+

+#include "StdAfx.h"

diff --git a/CPP/7zip/UI/Client7z/StdAfx.h b/CPP/7zip/UI/Client7z/StdAfx.h
new file mode 100755
index 0000000..2edddf4
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include <windows.h>

+#include <stdio.h>

+

+#endif

diff --git a/CPP/7zip/UI/Client7z/makefile b/CPP/7zip/UI/Client7z/makefile
new file mode 100755
index 0000000..e3a8239
--- /dev/null
+++ b/CPP/7zip/UI/Client7z/makefile
@@ -0,0 +1,45 @@
+PROG = 7z.exe

+MY_CONSOLE = 1

+CFLAGS = $(CFLAGS) -I ../../../

+

+CONSOLE_OBJS = \

+  $O\Client7z.obj \

+

+COMMON_OBJS = \

+  $O\IntToString.obj \

+  $O\NewHandler.obj \

+  $O\MyString.obj \

+  $O\StringConvert.obj \

+  $O\StringToInt.obj \

+  $O\MyVector.obj \

+  $O\Wildcard.obj \

+

+WIN_OBJS = \

+  $O\DLL.obj \

+  $O\FileDir.obj \

+  $O\FileFind.obj \

+  $O\FileIO.obj \

+  $O\FileName.obj \

+  $O\PropVariant.obj \

+  $O\PropVariantConversions.obj \

+

+7ZIP_COMMON_OBJS = \

+  $O\FileStreams.obj \

+

+OBJS = \

+  $O\StdAfx.obj \

+  $(CONSOLE_OBJS) \

+  $(COMMON_OBJS) \

+  $(WIN_OBJS) \

+  $(7ZIP_COMMON_OBJS) \

+

+!include "../../../Build.mak"

+

+$(CONSOLE_OBJS): $(*B).cpp

+	$(COMPL)

+$(COMMON_OBJS): ../../../Common/$(*B).cpp

+	$(COMPL)

+$(WIN_OBJS): ../../../Windows/$(*B).cpp

+	$(COMPL)

+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

+	$(COMPL)

diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
new file mode 100755
index 0000000..7fd012b
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -0,0 +1,1042 @@
+// ArchiveCommandLine.cpp

+

+#include "StdAfx.h"

+

+#ifdef _WIN32

+#ifndef UNDER_CE

+#include <io.h>

+#endif

+#endif

+#include <stdio.h>

+

+#include "Common/ListFileUtils.h"

+#include "Common/StringConvert.h"

+#include "Common/StringToInt.h"

+

+#include "Windows/FileDir.h"

+#include "Windows/FileName.h"

+#ifdef _WIN32

+#include "Windows/FileMapping.h"

+#include "Windows/Synchronization.h"

+#endif

+

+#include "ArchiveCommandLine.h"

+#include "EnumDirItems.h"

+#include "SortUtils.h"

+#include "Update.h"

+#include "UpdateAction.h"

+

+extern bool g_CaseSensitive;

+

+#ifdef UNDER_CE

+

+#define MY_IS_TERMINAL(x) false;

+

+#else

+

+#if _MSC_VER >= 1400

+#define MY_isatty_fileno(x) _isatty(_fileno(x))

+#else

+#define MY_isatty_fileno(x) isatty(fileno(x))

+#endif

+

+#define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0);

+

+#endif

+

+using namespace NCommandLineParser;

+using namespace NWindows;

+using namespace NFile;

+

+int g_CodePage = -1;

+

+namespace NKey {

+enum Enum

+{

+  kHelp1 = 0,

+  kHelp2,

+  kHelp3,

+  kDisableHeaders,

+  kDisablePercents,

+  kArchiveType,

+  kYes,

+  #ifndef _NO_CRYPTO

+  kPassword,

+  #endif

+  kProperty,

+  kOutputDir,

+  kWorkingDir,

+  kInclude,

+  kExclude,

+  kArInclude,

+  kArExclude,

+  kNoArName,

+  kUpdate,

+  kVolume,

+  kRecursed,

+  kSfx,

+  kStdIn,

+  kStdOut,

+  kOverwrite,

+  kEmail,

+  kShowDialog,

+  kLargePages,

+  kListfileCharSet,

+  kConsoleCharSet,

+  kTechMode,

+  kShareForWrite,

+  kCaseSensitive,

+  kCalcCrc

+};

+

+}

+

+

+static const wchar_t kRecursedIDChar = 'R';

+static const wchar_t *kRecursedPostCharSet = L"0-";

+

+namespace NRecursedPostCharIndex {

+  enum EEnum

+  {

+    kWildCardRecursionOnly = 0,

+    kNoRecursion = 1

+  };

+}

+

+static const char kImmediateNameID = '!';

+static const char kMapNameID = '#';

+static const char kFileListID = '@';

+

+static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be

+static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be

+

+static const wchar_t *kOverwritePostCharSet = L"asut";

+

+NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =

+{

+  NExtract::NOverwriteMode::kWithoutPrompt,

+  NExtract::NOverwriteMode::kSkipExisting,

+  NExtract::NOverwriteMode::kAutoRename,

+  NExtract::NOverwriteMode::kAutoRenameExisting

+};

+

+static const CSwitchForm kSwitchForms[] =

+  {

+    { L"?",  NSwitchType::kSimple, false },

+    { L"H",  NSwitchType::kSimple, false },

+    { L"-HELP",  NSwitchType::kSimple, false },

+    { L"BA", NSwitchType::kSimple, false },

+    { L"BD", NSwitchType::kSimple, false },

+    { L"T",  NSwitchType::kUnLimitedPostString, false, 1 },

+    { L"Y",  NSwitchType::kSimple, false },

+    #ifndef _NO_CRYPTO

+    { L"P",  NSwitchType::kUnLimitedPostString, false, 0 },

+    #endif

+    { L"M",  NSwitchType::kUnLimitedPostString, true, 1 },

+    { L"O",  NSwitchType::kUnLimitedPostString, false, 1 },

+    { L"W",  NSwitchType::kUnLimitedPostString, false, 0 },

+    { L"I",  NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},

+    { L"X",  NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},

+    { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},

+    { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},

+    { L"AN", NSwitchType::kSimple, false },

+    { L"U",  NSwitchType::kUnLimitedPostString, true, 1},

+    { L"V",  NSwitchType::kUnLimitedPostString, true, 1},

+    { L"R",  NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet },

+    { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 },

+    { L"SI", NSwitchType::kUnLimitedPostString, false, 0 },

+    { L"SO", NSwitchType::kSimple, false, 0 },

+    { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet},

+    { L"SEML", NSwitchType::kUnLimitedPostString, false, 0},

+    { L"AD",  NSwitchType::kSimple, false },

+    { L"SLP", NSwitchType::kUnLimitedPostString, false, 0},

+    { L"SCS", NSwitchType::kUnLimitedPostString, false, 0},

+    { L"SCC", NSwitchType::kUnLimitedPostString, false, 0},

+    { L"SLT", NSwitchType::kSimple, false },

+    { L"SSW", NSwitchType::kSimple, false },

+    { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" },

+    { L"SCRC", NSwitchType::kSimple, false }

+  };

+

+static const CCommandForm g_CommandForms[] =

+{

+  { L"A", false },

+  { L"U", false },

+  { L"D", false },

+  { L"T", false },

+  { L"E", false },

+  { L"X", false },

+  { L"L", false },

+  { L"B", false },

+  { L"I", false }

+};

+

+static const int kNumCommandForms = sizeof(g_CommandForms) /  sizeof(g_CommandForms[0]);

+

+static const wchar_t *kUniversalWildcard = L"*";

+static const int kMinNonSwitchWords = 1;

+static const int kCommandIndex = 0;

+

+// ---------------------------

+// exception messages

+

+static const char *kUserErrorMessage  = "Incorrect command line";

+static const char *kCannotFindListFile = "Cannot find listfile";

+static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch.";

+static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile";

+static const char *kIncorrectWildCardInCommandLine  = "Incorrect wildcard in command line";

+static const char *kTerminalOutError = "I won't write compressed data to a terminal";

+static const char *kSameTerminalError = "I won't write data and program's messages to same terminal";

+static const char *kEmptyFilePath = "Empty file path";

+

+static void ThrowException(const char *errorMessage)

+{

+  throw CArchiveCommandLineException(errorMessage);

+}

+

+static void ThrowUserErrorException()

+{

+  ThrowException(kUserErrorMessage);

+}

+

+// ---------------------------

+

+bool CArchiveCommand::IsFromExtractGroup() const

+{

+  switch(CommandType)

+  {

+    case NCommandType::kTest:

+    case NCommandType::kExtract:

+    case NCommandType::kFullExtract:

+      return true;

+    default:

+      return false;

+  }

+}

+

+NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const

+{

+  switch(CommandType)

+  {

+    case NCommandType::kTest:

+    case NCommandType::kFullExtract:

+      return NExtract::NPathMode::kFullPathnames;

+    default:

+      return NExtract::NPathMode::kNoPathnames;

+  }

+}

+

+bool CArchiveCommand::IsFromUpdateGroup() const

+{

+  return (CommandType == NCommandType::kAdd ||

+    CommandType == NCommandType::kUpdate ||

+    CommandType == NCommandType::kDelete);

+}

+

+static NRecursedType::EEnum GetRecursedTypeFromIndex(int index)

+{

+  switch (index)

+  {

+    case NRecursedPostCharIndex::kWildCardRecursionOnly:

+      return NRecursedType::kWildCardOnlyRecursed;

+    case NRecursedPostCharIndex::kNoRecursion:

+      return NRecursedType::kNonRecursed;

+    default:

+      return NRecursedType::kRecursed;

+  }

+}

+

+static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)

+{

+  UString commandStringUpper = commandString;

+  commandStringUpper.MakeUpper();

+  UString postString;

+  int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper,

+      postString) ;

+  if (commandIndex < 0)

+    return false;

+  command.CommandType = (NCommandType::EEnum)commandIndex;

+  return true;

+}

+

+// ------------------------------------------------------------------

+// filenames functions

+

+static void AddNameToCensor(NWildcard::CCensor &wildcardCensor,

+    const UString &name, bool include, NRecursedType::EEnum type)

+{

+  bool recursed = false;

+

+  switch (type)

+  {

+    case NRecursedType::kWildCardOnlyRecursed:

+      recursed = DoesNameContainWildCard(name);

+      break;

+    case NRecursedType::kRecursed:

+      recursed = true;

+      break;

+  }

+  wildcardCensor.AddItem(include, name, recursed);

+}

+

+static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor,

+    LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage)

+{

+  UStringVector names;

+  if (!NFind::DoesFileExist(fileName))

+    throw kCannotFindListFile;

+  if (!ReadNamesFromListFile(fileName, names, codePage))

+    throw kIncorrectListFile;

+  for (int i = 0; i < names.Size(); i++)

+    AddNameToCensor(wildcardCensor, names[i], include, type);

+}

+

+static void AddToCensorFromNonSwitchesStrings(

+    int startIndex,

+    NWildcard::CCensor &wildcardCensor,

+    const UStringVector &nonSwitchStrings, NRecursedType::EEnum type,

+    bool thereAreSwitchIncludes, UINT codePage)

+{

+  if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes))

+    AddNameToCensor(wildcardCensor, kUniversalWildcard, true, type);

+  for (int i = startIndex; i < nonSwitchStrings.Size(); i++)

+  {

+    const UString &s = nonSwitchStrings[i];

+    if (s.IsEmpty())

+      throw kEmptyFilePath;

+    if (s[0] == kFileListID)

+      AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage);

+    else

+      AddNameToCensor(wildcardCensor, s, true, type);

+  }

+}

+

+#ifdef _WIN32

+static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor,

+    const UString &switchParam, bool include,

+    NRecursedType::EEnum commonRecursedType)

+{

+  int splitPos = switchParam.Find(L':');

+  if (splitPos < 0)

+    ThrowUserErrorException();

+  UString mappingName = switchParam.Left(splitPos);

+  

+  UString switchParam2 = switchParam.Mid(splitPos + 1);

+  splitPos = switchParam2.Find(L':');

+  if (splitPos < 0)

+    ThrowUserErrorException();

+  

+  UString mappingSize = switchParam2.Left(splitPos);

+  UString eventName = switchParam2.Mid(splitPos + 1);

+  

+  UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL);

+  UInt32 dataSize = (UInt32)dataSize64;

+  {

+    CFileMapping fileMapping;

+    if (fileMapping.Open(FILE_MAP_READ, GetSystemString(mappingName)) != 0)

+      ThrowException("Can not open mapping");

+    LPVOID data = fileMapping.Map(FILE_MAP_READ, 0, dataSize);

+    if (data == NULL)

+      ThrowException("MapViewOfFile error");

+    try

+    {

+      const wchar_t *curData = (const wchar_t *)data;

+      if (*curData != 0)

+        ThrowException("Incorrect mapping data");

+      UInt32 numChars = dataSize / sizeof(wchar_t);

+      UString name;

+      for (UInt32 i = 1; i < numChars; i++)

+      {

+        wchar_t c = curData[i];

+        if (c == L'\0')

+        {

+          AddNameToCensor(wildcardCensor, name, include, commonRecursedType);

+          name.Empty();

+        }

+        else

+          name += c;

+      }

+      if (!name.IsEmpty())

+        ThrowException("data error");

+    }

+    catch(...)

+    {

+      UnmapViewOfFile(data);

+      throw;

+    }

+    UnmapViewOfFile(data);

+  }

+  

+  {

+    NSynchronization::CManualResetEvent event;

+    if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK)

+      event.Set();

+  }

+}

+#endif

+

+static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor,

+    const UStringVector &strings, bool include,

+    NRecursedType::EEnum commonRecursedType, UINT codePage)

+{

+  for (int i = 0; i < strings.Size(); i++)

+  {

+    const UString &name = strings[i];

+    NRecursedType::EEnum recursedType;

+    int pos = 0;

+    if (name.Length() < kSomeCludePostStringMinSize)

+      ThrowUserErrorException();

+    if (::MyCharUpper(name[pos]) == kRecursedIDChar)

+    {

+      pos++;

+      int index = UString(kRecursedPostCharSet).Find(name[pos]);

+      recursedType = GetRecursedTypeFromIndex(index);

+      if (index >= 0)

+        pos++;

+    }

+    else

+      recursedType = commonRecursedType;

+    if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize)

+      ThrowUserErrorException();

+    UString tail = name.Mid(pos + 1);

+    if (name[pos] == kImmediateNameID)

+      AddNameToCensor(wildcardCensor, tail, include, recursedType);

+    else if (name[pos] == kFileListID)

+      AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage);

+    #ifdef _WIN32

+    else if (name[pos] == kMapNameID)

+      ParseMapWithPaths(wildcardCensor, tail, include, recursedType);

+    #endif

+    else

+      ThrowUserErrorException();

+  }

+}

+

+#ifdef _WIN32

+

+// This code converts all short file names to long file names.

+

+static void ConvertToLongName(const UString &prefix, UString &name)

+{

+  if (name.IsEmpty() || DoesNameContainWildCard(name))

+    return;

+  NFind::CFileInfoW fi;

+  if (fi.Find(prefix + name))

+    name = fi.Name;

+}

+

+static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items)

+{

+  for (int i = 0; i < items.Size(); i++)

+  {

+    NWildcard::CItem &item = items[i];

+    if (item.Recursive || item.PathParts.Size() != 1)

+      continue;

+    ConvertToLongName(prefix, item.PathParts.Front());

+  }

+}

+

+static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node)

+{

+  ConvertToLongNames(prefix, node.IncludeItems);

+  ConvertToLongNames(prefix, node.ExcludeItems);

+  int i;

+  for (i = 0; i < node.SubNodes.Size(); i++)

+    ConvertToLongName(prefix, node.SubNodes[i].Name);

+  // mix folders with same name

+  for (i = 0; i < node.SubNodes.Size(); i++)

+  {

+    NWildcard::CCensorNode &nextNode1 = node.SubNodes[i];

+    for (int j = i + 1; j < node.SubNodes.Size();)

+    {

+      const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];

+      if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0)

+      {

+        nextNode1.IncludeItems += nextNode2.IncludeItems;

+        nextNode1.ExcludeItems += nextNode2.ExcludeItems;

+        node.SubNodes.Delete(j);

+      }

+      else

+        j++;

+    }

+  }

+  for (i = 0; i < node.SubNodes.Size(); i++)

+  {

+    NWildcard::CCensorNode &nextNode = node.SubNodes[i];

+    ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode);

+  }

+}

+

+static void ConvertToLongNames(NWildcard::CCensor &censor)

+{

+  for (int i = 0; i < censor.Pairs.Size(); i++)

+  {

+    NWildcard::CPair &pair = censor.Pairs[i];

+    ConvertToLongNames(pair.Prefix, pair.Head);

+  }

+}

+

+#endif

+

+static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)

+{

+  switch(i)

+  {

+    case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore;

+    case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy;

+    case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress;

+    case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti;

+  }

+  throw 98111603;

+}

+

+const UString kUpdatePairStateIDSet = L"PQRXYZW";

+const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};

+

+const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti

+

+const wchar_t *kUpdateIgnoreItselfPostStringID = L"-";

+const wchar_t kUpdateNewArchivePostCharID = '!';

+

+

+static bool ParseUpdateCommandString2(const UString &command,

+    NUpdateArchive::CActionSet &actionSet, UString &postString)

+{

+  for (int i = 0; i < command.Length();)

+  {

+    wchar_t c = MyCharUpper(command[i]);

+    int statePos = kUpdatePairStateIDSet.Find(c);

+    if (statePos < 0)

+    {

+      postString = command.Mid(i);

+      return true;

+    }

+    i++;

+    if (i >= command.Length())

+      return false;

+    int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i]));

+    if (actionPos < 0)

+      return false;

+    actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos);

+    if (kUpdatePairStateNotSupportedActions[statePos] == actionPos)

+      return false;

+    i++;

+  }

+  postString.Empty();

+  return true;

+}

+

+static void ParseUpdateCommandString(CUpdateOptions &options,

+    const UStringVector &updatePostStrings,

+    const NUpdateArchive::CActionSet &defaultActionSet)

+{

+  for (int i = 0; i < updatePostStrings.Size(); i++)

+  {

+    const UString &updateString = updatePostStrings[i];

+    if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0)

+    {

+      if (options.UpdateArchiveItself)

+      {

+        options.UpdateArchiveItself = false;

+        options.Commands.Delete(0);

+      }

+    }

+    else

+    {

+      NUpdateArchive::CActionSet actionSet = defaultActionSet;

+

+      UString postString;

+      if (!ParseUpdateCommandString2(updateString, actionSet, postString))

+        ThrowUserErrorException();

+      if (postString.IsEmpty())

+      {

+        if (options.UpdateArchiveItself)

+          options.Commands[0].ActionSet = actionSet;

+      }

+      else

+      {

+        if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID)

+          ThrowUserErrorException();

+        CUpdateArchiveCommand uc;

+        UString archivePath = postString.Mid(1);

+        if (archivePath.IsEmpty())

+          ThrowUserErrorException();

+        uc.UserArchivePath = archivePath;

+        uc.ActionSet = actionSet;

+        options.Commands.Add(uc);

+      }

+    }

+  }

+}

+

+static const char kByteSymbol = 'B';

+static const char kKiloSymbol = 'K';

+static const char kMegaSymbol = 'M';

+static const char kGigaSymbol = 'G';

+

+static bool ParseComplexSize(const UString &src, UInt64 &result)

+{

+  UString s = src;

+  s.MakeUpper();

+

+  const wchar_t *start = s;

+  const wchar_t *end;

+  UInt64 number = ConvertStringToUInt64(start, &end);

+  int numDigits = (int)(end - start);

+  if (numDigits == 0 || s.Length() > numDigits + 1)

+    return false;

+  if (s.Length() == numDigits)

+  {

+    result = number;

+    return true;

+  }

+  int numBits;

+  switch (s[numDigits])

+  {

+    case kByteSymbol:

+      result = number;

+      return true;

+    case kKiloSymbol:

+      numBits = 10;

+      break;

+    case kMegaSymbol:

+      numBits = 20;

+      break;

+    case kGigaSymbol:

+      numBits = 30;

+      break;

+    default:

+      return false;

+  }

+  if (number >= ((UInt64)1 << (64 - numBits)))

+    return false;

+  result = number << numBits;

+  return true;

+}

+

+static void SetAddCommandOptions(

+    NCommandType::EEnum commandType,

+    const CParser &parser,

+    CUpdateOptions &options)

+{

+  NUpdateArchive::CActionSet defaultActionSet;

+  switch(commandType)

+  {

+    case NCommandType::kAdd:

+      defaultActionSet = NUpdateArchive::kAddActionSet;

+      break;

+    case NCommandType::kDelete:

+      defaultActionSet = NUpdateArchive::kDeleteActionSet;

+      break;

+    default:

+      defaultActionSet = NUpdateArchive::kUpdateActionSet;

+  }

+  

+  options.UpdateArchiveItself = true;

+  

+  options.Commands.Clear();

+  CUpdateArchiveCommand updateMainCommand;

+  updateMainCommand.ActionSet = defaultActionSet;

+  options.Commands.Add(updateMainCommand);

+  if (parser[NKey::kUpdate].ThereIs)

+    ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings,

+        defaultActionSet);

+  if (parser[NKey::kWorkingDir].ThereIs)

+  {

+    const UString &postString = parser[NKey::kWorkingDir].PostStrings[0];

+    if (postString.IsEmpty())

+      NDirectory::MyGetTempPath(options.WorkingDir);

+    else

+      options.WorkingDir = postString;

+  }

+  options.SfxMode = parser[NKey::kSfx].ThereIs;

+  if (options.SfxMode)

+    options.SfxModule = parser[NKey::kSfx].PostStrings[0];

+

+  if (parser[NKey::kVolume].ThereIs)

+  {

+    const UStringVector &sv = parser[NKey::kVolume].PostStrings;

+    for (int i = 0; i < sv.Size(); i++)

+    {

+      UInt64 size;

+      if (!ParseComplexSize(sv[i], size))

+        ThrowException("Incorrect volume size");

+      options.VolumesSizes.Add(size);

+    }

+  }

+}

+

+static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties)

+{

+  if (parser[NKey::kProperty].ThereIs)

+  {

+    // options.MethodMode.Properties.Clear();

+    for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)

+    {

+      CProperty property;

+      const UString &postString = parser[NKey::kProperty].PostStrings[i];

+      int index = postString.Find(L'=');

+      if (index < 0)

+        property.Name = postString;

+      else

+      {

+        property.Name = postString.Left(index);

+        property.Value = postString.Mid(index + 1);

+      }

+      properties.Add(property);

+    }

+  }

+}

+

+CArchiveCommandLineParser::CArchiveCommandLineParser():

+  parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {}

+

+void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings,

+    CArchiveCommandLineOptions &options)

+{

+  try

+  {

+    parser.ParseStrings(kSwitchForms, commandStrings);

+  }

+  catch(...)

+  {

+    ThrowUserErrorException();

+  }

+

+  options.IsInTerminal = MY_IS_TERMINAL(stdin);

+  options.IsStdOutTerminal = MY_IS_TERMINAL(stdout);

+  options.IsStdErrTerminal = MY_IS_TERMINAL(stderr);

+  options.StdInMode = parser[NKey::kStdIn].ThereIs;

+  options.StdOutMode = parser[NKey::kStdOut].ThereIs;

+  options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;

+  options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs  || parser[NKey::kHelp3].ThereIs;

+

+  #ifdef _WIN32

+  options.LargePages = false;

+  if (parser[NKey::kLargePages].ThereIs)

+  {

+    const UString &postString = parser[NKey::kLargePages].PostStrings.Front();

+    if (postString.IsEmpty())

+      options.LargePages = true;

+  }

+  #endif

+}

+

+struct CCodePagePair

+{

+  const wchar_t *Name;

+  UINT CodePage;

+};

+

+static CCodePagePair g_CodePagePairs[] =

+{

+  { L"UTF-8", CP_UTF8 },

+  { L"WIN", CP_ACP },

+  { L"DOS", CP_OEMCP }

+};

+

+static int FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, int defaultVal)

+{

+  if (!parser[keyIndex].ThereIs)

+    return defaultVal;

+

+  UString name = parser[keyIndex].PostStrings.Back();

+  name.MakeUpper();

+  int i;

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

+  {

+    const CCodePagePair &pair = g_CodePagePairs[i];

+    if (name.Compare(pair.Name) == 0)

+      return pair.CodePage;

+  }

+  if (i == sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]))

+    ThrowUserErrorException();

+  return -1;

+}

+

+static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v)

+{

+  const wchar_t *end;

+  UInt64 number = ConvertStringToUInt64(s, &end);

+  if (*end != 0)

+    return false;

+  if (number > (UInt32)0xFFFFFFFF)

+    return false;

+  v = (UInt32)number;

+  return true;

+}

+

+void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor,

+    UStringVector &sortedPaths,

+    UStringVector &sortedFullPaths)

+{

+  UStringVector paths;

+  {

+    CDirItems dirItems;

+    {

+      UStringVector errorPaths;

+      CRecordVector<DWORD> errorCodes;

+      HRESULT res = EnumerateItems(wildcardCensor, dirItems, NULL, errorPaths, errorCodes);

+      if (res != S_OK || errorPaths.Size() > 0)

+        throw "cannot find archive";

+    }

+    for (int i = 0; i < dirItems.Items.Size(); i++)

+    {

+      const CDirItem &dirItem = dirItems.Items[i];

+      if (!dirItem.IsDir())

+        paths.Add(dirItems.GetPhyPath(i));

+    }

+  }

+  

+  if (paths.Size() == 0)

+    throw "there is no such archive";

+  

+  UStringVector fullPaths;

+  

+  int i;

+  for (i = 0; i < paths.Size(); i++)

+  {

+    UString fullPath;

+    NFile::NDirectory::MyGetFullPathName(paths[i], fullPath);

+    fullPaths.Add(fullPath);

+  }

+  CIntVector indices;

+  SortFileNames(fullPaths, indices);

+  sortedPaths.Reserve(indices.Size());

+  sortedFullPaths.Reserve(indices.Size());

+  for (i = 0; i < indices.Size(); i++)

+  {

+    int index = indices[i];

+    sortedPaths.Add(paths[index]);

+    sortedFullPaths.Add(fullPaths[index]);

+  }

+}

+

+void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)

+{

+  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;

+  int numNonSwitchStrings = nonSwitchStrings.Size();

+  if (numNonSwitchStrings < kMinNonSwitchWords)

+    ThrowUserErrorException();

+

+  if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))

+    ThrowUserErrorException();

+

+  options.TechMode = parser[NKey::kTechMode].ThereIs;

+  options.CalcCrc = parser[NKey::kCalcCrc].ThereIs;

+

+  if (parser[NKey::kCaseSensitive].ThereIs)

+    g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0);

+

+  NRecursedType::EEnum recursedType;

+  if (parser[NKey::kRecursed].ThereIs)

+    recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex);

+  else

+    recursedType = NRecursedType::kNonRecursed;

+

+  g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, -1);

+  UINT codePage = FindCharset(parser, NKey::kListfileCharSet, CP_UTF8);

+

+  bool thereAreSwitchIncludes = false;

+  if (parser[NKey::kInclude].ThereIs)

+  {

+    thereAreSwitchIncludes = true;

+    AddSwitchWildCardsToCensor(options.WildcardCensor,

+        parser[NKey::kInclude].PostStrings, true, recursedType, codePage);

+  }

+  if (parser[NKey::kExclude].ThereIs)

+    AddSwitchWildCardsToCensor(options.WildcardCensor,

+        parser[NKey::kExclude].PostStrings, false, recursedType, codePage);

+ 

+  int curCommandIndex = kCommandIndex + 1;

+  bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs &&

+      options.Command.CommandType != NCommandType::kBenchmark &&

+      options.Command.CommandType != NCommandType::kInfo;

+

+  bool isExtractGroupCommand = options.Command.IsFromExtractGroup();

+  bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList;

+

+  if (isExtractOrList && options.StdInMode)

+    thereIsArchiveName = false;

+

+  if (thereIsArchiveName)

+  {

+    if (curCommandIndex >= numNonSwitchStrings)

+      ThrowUserErrorException();

+    options.ArchiveName = nonSwitchStrings[curCommandIndex++];

+    if (options.ArchiveName.IsEmpty())

+      ThrowUserErrorException();

+  }

+

+  AddToCensorFromNonSwitchesStrings(

+      curCommandIndex, options.WildcardCensor,

+      nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage);

+

+  options.YesToAll = parser[NKey::kYes].ThereIs;

+

+

+  #ifndef _NO_CRYPTO

+  options.PasswordEnabled = parser[NKey::kPassword].ThereIs;

+  if (options.PasswordEnabled)

+    options.Password = parser[NKey::kPassword].PostStrings[0];

+  #endif

+

+  options.ShowDialog = parser[NKey::kShowDialog].ThereIs;

+

+  if (parser[NKey::kArchiveType].ThereIs)

+    options.ArcType = parser[NKey::kArchiveType].PostStrings[0];

+

+  if (isExtractOrList)

+  {

+    if (!options.WildcardCensor.AllAreRelative())

+      ThrowException("Cannot use absolute pathnames for this command");

+

+    NWildcard::CCensor archiveWildcardCensor;

+

+    if (parser[NKey::kArInclude].ThereIs)

+      AddSwitchWildCardsToCensor(archiveWildcardCensor,

+          parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage);

+    if (parser[NKey::kArExclude].ThereIs)

+      AddSwitchWildCardsToCensor(archiveWildcardCensor,

+          parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage);

+

+    if (thereIsArchiveName)

+      AddNameToCensor(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);

+

+    #ifdef _WIN32

+    ConvertToLongNames(archiveWildcardCensor);

+    #endif

+

+    archiveWildcardCensor.ExtendExclude();

+

+    if (options.StdInMode)

+    {

+      UString arcName = parser[NKey::kStdIn].PostStrings.Front();

+      options.ArchivePathsSorted.Add(arcName);

+      options.ArchivePathsFullSorted.Add(arcName);

+    }

+    else

+    {

+      EnumerateDirItemsAndSort(archiveWildcardCensor,

+        options.ArchivePathsSorted,

+        options.ArchivePathsFullSorted);

+    }

+    

+    if (isExtractGroupCommand)

+    {

+      SetMethodOptions(parser, options.ExtractProperties);

+      if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal)

+        throw kSameTerminalError;

+      if (parser[NKey::kOutputDir].ThereIs)

+      {

+        options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];

+        NFile::NName::NormalizeDirPathPrefix(options.OutputDir);

+      }

+

+      options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;

+      if (parser[NKey::kOverwrite].ThereIs)

+        options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];

+      else if (options.YesToAll)

+        options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;

+    }

+  }

+  else if (options.Command.IsFromUpdateGroup())

+  {

+    CUpdateOptions &updateOptions = options.UpdateOptions;

+

+    SetAddCommandOptions(options.Command.CommandType, parser, updateOptions);

+    

+    SetMethodOptions(parser, updateOptions.MethodMode.Properties);

+

+    if (parser[NKey::kShareForWrite].ThereIs)

+      updateOptions.OpenShareForWrite = true;

+

+    options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;

+

+    if (options.EnablePercents)

+    {

+      if ((options.StdOutMode && !options.IsStdErrTerminal) ||

+         (!options.StdOutMode && !options.IsStdOutTerminal))

+        options.EnablePercents = false;

+    }

+

+    updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;

+    if (updateOptions.EMailMode)

+    {

+      updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();

+      if (updateOptions.EMailAddress.Length() > 0)

+        if (updateOptions.EMailAddress[0] == L'.')

+        {

+          updateOptions.EMailRemoveAfter = true;

+          updateOptions.EMailAddress.Delete(0);

+        }

+    }

+

+    updateOptions.StdOutMode = options.StdOutMode;

+    updateOptions.StdInMode = options.StdInMode;

+

+    if (updateOptions.StdOutMode && updateOptions.EMailMode)

+      throw "stdout mode and email mode cannot be combined";

+    if (updateOptions.StdOutMode && options.IsStdOutTerminal)

+      throw kTerminalOutError;

+    if (updateOptions.StdInMode)

+      updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();

+

+    #ifdef _WIN32

+    ConvertToLongNames(options.WildcardCensor);

+    #endif

+  }

+  else if (options.Command.CommandType == NCommandType::kBenchmark)

+  {

+    options.NumThreads = (UInt32)-1;

+    options.DictionarySize = (UInt32)-1;

+    options.NumIterations = 1;

+    if (curCommandIndex < numNonSwitchStrings)

+    {

+      if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations))

+        ThrowUserErrorException();

+    }

+    for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)

+    {

+      UString postString = parser[NKey::kProperty].PostStrings[i];

+      postString.MakeUpper();

+      if (postString.Length() < 2)

+        ThrowUserErrorException();

+      if (postString[0] == 'D')

+      {

+        int pos = 1;

+        if (postString[pos] == '=')

+          pos++;

+        UInt32 logSize;

+        if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize))

+          ThrowUserErrorException();

+        if (logSize > 31)

+          ThrowUserErrorException();

+        options.DictionarySize = 1 << logSize;

+      }

+      else if (postString[0] == 'M' && postString[1] == 'T' )

+      {

+        int pos = 2;

+        if (postString[pos] == '=')

+          pos++;

+        if (postString[pos] != 0)

+          if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads))

+            ThrowUserErrorException();

+      }

+      else if (postString[0] == 'M' && postString[1] == '=' )

+      {

+        int pos = 2;

+        if (postString[pos] != 0)

+          options.Method = postString.Mid(2);

+      }

+      else

+        ThrowUserErrorException();

+    }

+  }

+  else if (options.Command.CommandType == NCommandType::kInfo)

+  {

+  }

+  else

+    ThrowUserErrorException();

+  options.WildcardCensor.ExtendExclude();

+}

diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h
new file mode 100755
index 0000000..491689e
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h
@@ -0,0 +1,111 @@
+// ArchiveCommandLine.h

+

+#ifndef __ARCHIVE_COMMAND_LINE_H

+#define __ARCHIVE_COMMAND_LINE_H

+

+#include "Common/CommandLineParser.h"

+#include "Common/Wildcard.h"

+

+#include "Extract.h"

+#include "Update.h"

+

+struct CArchiveCommandLineException: public AString

+{

+  CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {}

+};

+

+namespace NCommandType { enum EEnum

+{

+  kAdd = 0,

+  kUpdate,

+  kDelete,

+  kTest,

+  kExtract,

+  kFullExtract,

+  kList,

+  kBenchmark,

+  kInfo

+};}

+

+namespace NRecursedType { enum EEnum

+{

+  kRecursed,

+  kWildCardOnlyRecursed,

+  kNonRecursed

+};}

+

+struct CArchiveCommand

+{

+  NCommandType::EEnum CommandType;

+  bool IsFromExtractGroup() const;

+  bool IsFromUpdateGroup() const;

+  bool IsTestMode() const { return CommandType == NCommandType::kTest; }

+  NExtract::NPathMode::EEnum GetPathMode() const;

+};

+

+struct CArchiveCommandLineOptions

+{

+  bool HelpMode;

+

+  #ifdef _WIN32

+  bool LargePages;

+  #endif

+

+  bool IsInTerminal;

+  bool IsStdOutTerminal;

+  bool IsStdErrTerminal;

+  bool StdInMode;

+  bool StdOutMode;

+  bool EnableHeaders;

+

+  bool YesToAll;

+  bool ShowDialog;

+  // NWildcard::CCensor ArchiveWildcardCensor;

+  NWildcard::CCensor WildcardCensor;

+

+  CArchiveCommand Command;

+  UString ArchiveName;

+

+  #ifndef _NO_CRYPTO

+  bool PasswordEnabled;

+  UString Password;

+  #endif

+

+  bool TechMode;

+  // Extract

+  bool CalcCrc;

+  bool AppendName;

+  UString OutputDir;

+  NExtract::NOverwriteMode::EEnum OverwriteMode;

+  UStringVector ArchivePathsSorted;

+  UStringVector ArchivePathsFullSorted;

+  CObjectVector<CProperty> ExtractProperties;

+

+  CUpdateOptions UpdateOptions;

+  UString ArcType;

+  bool EnablePercents;

+

+  // Benchmark

+  UInt32 NumIterations;

+  UInt32 NumThreads;

+  UInt32 DictionarySize;

+  UString Method;

+

+

+  CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {};

+};

+

+class CArchiveCommandLineParser

+{

+  NCommandLineParser::CParser parser;

+public:

+  CArchiveCommandLineParser();

+  void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options);

+  void Parse2(CArchiveCommandLineOptions &options);

+};

+

+void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor,

+    UStringVector &sortedPaths,

+    UStringVector &sortedFullPaths);

+

+#endif

diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
new file mode 100755
index 0000000..2a322c5
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -0,0 +1,488 @@
+// ArchiveExtractCallback.cpp

+

+#include "StdAfx.h"

+

+#include "Common/ComTry.h"

+#include "Common/Wildcard.h"

+

+#include "Windows/FileDir.h"

+#include "Windows/FileFind.h"

+#include "Windows/PropVariant.h"

+#include "Windows/PropVariantConversions.h"

+

+#include "../../Common/FilePathAutoRename.h"

+

+#include "../Common/ExtractingFilePath.h"

+

+#include "ArchiveExtractCallback.h"

+

+using namespace NWindows;

+

+static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name";

+static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file ";

+static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";

+

+void CArchiveExtractCallback::Init(

+    const NWildcard::CCensorNode *wildcardCensor,

+    const CArc *arc,

+    IFolderArchiveExtractCallback *extractCallback2,

+    bool stdOutMode, bool testMode, bool crcMode,

+    const UString &directoryPath,

+    const UStringVector &removePathParts,

+    UInt64 packSize)

+{

+  _wildcardCensor = wildcardCensor;

+

+  _stdOutMode = stdOutMode;

+  _testMode = testMode;

+  _crcMode = crcMode;

+  _unpTotal = 1;

+  _packTotal = packSize;

+

+  _extractCallback2 = extractCallback2;

+  _compressProgress.Release();

+  _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);

+

+  LocalProgressSpec->Init(extractCallback2, true);

+  LocalProgressSpec->SendProgress = false;

+

+ 

+  _removePathParts = removePathParts;

+  _arc = arc;

+  _directoryPath = directoryPath;

+  NFile::NName::NormalizeDirPathPrefix(_directoryPath);

+}

+

+STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)

+{

+  COM_TRY_BEGIN

+  _unpTotal = size;

+  if (!_multiArchives && _extractCallback2)

+    return _extractCallback2->SetTotal(size);

+  return S_OK;

+  COM_TRY_END

+}

+

+static void NormalizeVals(UInt64 &v1, UInt64 &v2)

+{

+  const UInt64 kMax = (UInt64)1 << 31;

+  while (v1 > kMax)

+  {

+    v1 >>= 1;

+    v2 >>= 1;

+  }

+}

+

+static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal)

+{

+  NormalizeVals(packTotal, unpTotal);

+  NormalizeVals(unpCur, unpTotal);

+  if (unpTotal == 0)

+    unpTotal = 1;

+  return unpCur * packTotal / unpTotal;

+}

+

+STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)

+{

+  COM_TRY_BEGIN

+  if (!_extractCallback2)

+    return S_OK;

+

+  if (_multiArchives)

+  {

+    if (completeValue != NULL)

+    {

+      UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal);

+      return _extractCallback2->SetCompleted(&packCur);

+    }

+  }

+  return _extractCallback2->SetCompleted(completeValue);

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)

+{

+  COM_TRY_BEGIN

+  return _localProgress->SetRatioInfo(inSize, outSize);

+  COM_TRY_END

+}

+

+void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath)

+{

+  fullPath = _directoryPath;

+  for (int i = 0; i < dirPathParts.Size(); i++)

+  {

+    if (i > 0)

+      fullPath += wchar_t(NFile::NName::kDirDelimiter);

+    fullPath += dirPathParts[i];

+    NFile::NDirectory::MyCreateDirectory(fullPath);

+  }

+}

+

+HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)

+{

+  filetimeIsDefined = false;

+  NCOM::CPropVariant prop;

+  RINOK(_arc->Archive->GetProperty(index, propID, &prop));

+  if (prop.vt == VT_FILETIME)

+  {

+    filetime = prop.filetime;

+    filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0);

+  }

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+HRESULT CArchiveExtractCallback::GetUnpackSize()

+{

+  NCOM::CPropVariant prop;

+  RINOK(_arc->Archive->GetProperty(_index, kpidSize, &prop));

+  _curSizeDefined = (prop.vt != VT_EMPTY);

+  if (_curSizeDefined)

+    _curSize = ConvertPropVariantToUInt64(prop);

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)

+{

+  COM_TRY_BEGIN

+  _crcStream.Release();

+  *outStream = 0;

+  _outFileStream.Release();

+

+  _encrypted = false;

+  _isSplit = false;

+  _curSize = 0;

+  _curSizeDefined = false;

+  _index = index;

+

+  UString fullPath;

+

+  IInArchive *archive = _arc->Archive;

+  RINOK(_arc->GetItemPath(index, fullPath));

+  RINOK(IsArchiveItemFolder(archive, index, _fi.IsDir));

+

+  _filePath = fullPath;

+

+  {

+    NCOM::CPropVariant prop;

+    RINOK(archive->GetProperty(index, kpidPosition, &prop));

+    if (prop.vt != VT_EMPTY)

+    {

+      if (prop.vt != VT_UI8)

+        return E_FAIL;

+      _position = prop.uhVal.QuadPart;

+      _isSplit = true;

+    }

+  }

+    

+  RINOK(GetArchiveItemBoolProp(archive, index, kpidEncrypted, _encrypted));

+

+  RINOK(GetUnpackSize());

+

+  if (_wildcardCensor)

+  {

+    if (!_wildcardCensor->CheckPath(fullPath, !_fi.IsDir))

+      return S_OK;

+  }

+

+  if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)

+  {

+    if (_stdOutMode)

+    {

+      CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream;

+      *outStream = outStreamLoc.Detach();

+      return S_OK;

+    }

+

+    {

+      NCOM::CPropVariant prop;

+      RINOK(archive->GetProperty(index, kpidAttrib, &prop));

+      if (prop.vt == VT_UI4)

+      {

+        _fi.Attrib = prop.ulVal;

+        _fi.AttribDefined = true;

+      }

+      else if (prop.vt == VT_EMPTY)

+        _fi.AttribDefined = false;

+      else

+        return E_FAIL;

+    }

+

+    RINOK(GetTime(index, kpidCTime, _fi.CTime, _fi.CTimeDefined));

+    RINOK(GetTime(index, kpidATime, _fi.ATime, _fi.ATimeDefined));

+    RINOK(GetTime(index, kpidMTime, _fi.MTime, _fi.MTimeDefined));

+

+    bool isAnti = false;

+    RINOK(_arc->IsItemAnti(index, isAnti));

+

+    UStringVector pathParts;

+    SplitPathToParts(fullPath, pathParts);

+    

+    if (pathParts.IsEmpty())

+      return E_FAIL;

+    int numRemovePathParts = 0;

+    switch(_pathMode)

+    {

+      case NExtract::NPathMode::kFullPathnames:

+        break;

+      case NExtract::NPathMode::kCurrentPathnames:

+      {

+        numRemovePathParts = _removePathParts.Size();

+        if (pathParts.Size() <= numRemovePathParts)

+          return E_FAIL;

+        for (int i = 0; i < numRemovePathParts; i++)

+          if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0)

+            return E_FAIL;

+        break;

+      }

+      case NExtract::NPathMode::kNoPathnames:

+      {

+        numRemovePathParts = pathParts.Size() - 1;

+        break;

+      }

+    }

+    pathParts.Delete(0, numRemovePathParts);

+    MakeCorrectPath(pathParts);

+    UString processedPath = MakePathNameFromParts(pathParts);

+    if (!isAnti)

+    {

+      if (!_fi.IsDir)

+      {

+        if (!pathParts.IsEmpty())

+          pathParts.DeleteBack();

+      }

+    

+      if (!pathParts.IsEmpty())

+      {

+        UString fullPathNew;

+        CreateComplexDirectory(pathParts, fullPathNew);

+        if (_fi.IsDir)

+          NFile::NDirectory::SetDirTime(fullPathNew,

+            (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,

+            (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,

+            (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));

+      }

+    }

+

+

+    UString fullProcessedPath = _directoryPath + processedPath;

+

+    if (_fi.IsDir)

+    {

+      _diskFilePath = fullProcessedPath;

+      if (isAnti)

+        NFile::NDirectory::MyRemoveDirectory(_diskFilePath);

+      return S_OK;

+    }

+

+    if (!_isSplit)

+    {

+    NFile::NFind::CFileInfoW fileInfo;

+    if (fileInfo.Find(fullProcessedPath))

+    {

+      switch(_overwriteMode)

+      {

+        case NExtract::NOverwriteMode::kSkipExisting:

+          return S_OK;

+        case NExtract::NOverwriteMode::kAskBefore:

+        {

+          Int32 overwiteResult;

+          RINOK(_extractCallback2->AskOverwrite(

+              fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath,

+              _fi.MTimeDefined ? &_fi.MTime : NULL,

+              _curSizeDefined ? &_curSize : NULL,

+              &overwiteResult))

+

+          switch(overwiteResult)

+          {

+            case NOverwriteAnswer::kCancel:

+              return E_ABORT;

+            case NOverwriteAnswer::kNo:

+              return S_OK;

+            case NOverwriteAnswer::kNoToAll:

+              _overwriteMode = NExtract::NOverwriteMode::kSkipExisting;

+              return S_OK;

+            case NOverwriteAnswer::kYesToAll:

+              _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;

+              break;

+            case NOverwriteAnswer::kYes:

+              break;

+            case NOverwriteAnswer::kAutoRename:

+              _overwriteMode = NExtract::NOverwriteMode::kAutoRename;

+              break;

+            default:

+              return E_FAIL;

+          }

+        }

+      }

+      if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename)

+      {

+        if (!AutoRenamePath(fullProcessedPath))

+        {

+          UString message = UString(kCantAutoRename) + fullProcessedPath;

+          RINOK(_extractCallback2->MessageError(message));

+          return E_FAIL;

+        }

+      }

+      else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting)

+      {

+        UString existPath = fullProcessedPath;

+        if (!AutoRenamePath(existPath))

+        {

+          UString message = kCantAutoRename + fullProcessedPath;

+          RINOK(_extractCallback2->MessageError(message));

+          return E_FAIL;

+        }

+        if (!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath))

+        {

+          UString message = UString(kCantRenameFile) + fullProcessedPath;

+          RINOK(_extractCallback2->MessageError(message));

+          return E_FAIL;

+        }

+      }

+      else

+        if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))

+        {

+          UString message = UString(kCantDeleteOutputFile) +  fullProcessedPath;

+          RINOK(_extractCallback2->MessageError(message));

+          return S_OK;

+          // return E_FAIL;

+        }

+    }

+    }

+    if (!isAnti)

+    {

+      _outFileStreamSpec = new COutFileStream;

+      CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);

+      if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))

+      {

+        // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)

+        {

+          UString message = L"can not open output file " + fullProcessedPath;

+          RINOK(_extractCallback2->MessageError(message));

+          return S_OK;

+        }

+      }

+      if (_isSplit)

+      {

+        RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));

+      }

+      _outFileStream = outStreamLoc;

+      *outStream = outStreamLoc.Detach();

+    }

+    _diskFilePath = fullProcessedPath;

+  }

+  else

+  {

+    *outStream = NULL;

+  }

+  if (_crcMode)

+  {

+    _crcStreamSpec = new COutStreamWithCRC;

+    _crcStream = _crcStreamSpec;

+    CMyComPtr<ISequentialOutStream> crcStream = _crcStreamSpec;

+    _crcStreamSpec->SetStream(*outStream);

+    if (*outStream)

+      (*outStream)->Release();

+    *outStream = crcStream.Detach();

+    _crcStreamSpec->Init(true);

+  }

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)

+{

+  COM_TRY_BEGIN

+  _extractMode = false;

+  switch (askExtractMode)

+  {

+    case NArchive::NExtract::NAskMode::kExtract:

+      if (_testMode)

+        askExtractMode = NArchive::NExtract::NAskMode::kTest;

+      else

+        _extractMode = true;

+      break;

+  };

+  return _extractCallback2->PrepareOperation(_filePath, _fi.IsDir,

+      askExtractMode, _isSplit ? &_position: 0);

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)

+{

+  COM_TRY_BEGIN

+  switch(operationResult)

+  {

+    case NArchive::NExtract::NOperationResult::kOK:

+    case NArchive::NExtract::NOperationResult::kUnSupportedMethod:

+    case NArchive::NExtract::NOperationResult::kCRCError:

+    case NArchive::NExtract::NOperationResult::kDataError:

+      break;

+    default:

+      _outFileStream.Release();

+      return E_FAIL;

+  }

+  if (_crcStream)

+  {

+    CrcSum += _crcStreamSpec->GetCRC();

+    _curSize = _crcStreamSpec->GetSize();

+    _curSizeDefined = true;

+    _crcStream.Release();

+  }

+  if (_outFileStream)

+  {

+    _outFileStreamSpec->SetTime(

+        (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,

+        (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,

+        (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));

+    _curSize = _outFileStreamSpec->ProcessedSize;

+    _curSizeDefined = true;

+    RINOK(_outFileStreamSpec->Close());

+    _outFileStream.Release();

+  }

+  if (!_curSizeDefined)

+    GetUnpackSize();

+  if (_curSizeDefined)

+    UnpackSize += _curSize;

+  if (_fi.IsDir)

+    NumFolders++;

+  else

+    NumFiles++;

+

+  if (_extractMode && _fi.AttribDefined)

+    NFile::NDirectory::MySetFileAttributes(_diskFilePath, _fi.Attrib);

+  RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted));

+  return S_OK;

+  COM_TRY_END

+}

+

+/*

+STDMETHODIMP CArchiveExtractCallback::GetInStream(

+    const wchar_t *name, ISequentialInStream **inStream)

+{

+  COM_TRY_BEGIN

+  CInFileStream *inFile = new CInFileStream;

+  CMyComPtr<ISequentialInStream> inStreamTemp = inFile;

+  if (!inFile->Open(_srcDirectoryPrefix + name))

+    return ::GetLastError();

+  *inStream = inStreamTemp.Detach();

+  return S_OK;

+  COM_TRY_END

+}

+*/

+

+STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)

+{

+  COM_TRY_BEGIN

+  if (!_cryptoGetTextPassword)

+  {

+    RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword,

+        &_cryptoGetTextPassword));

+  }

+  return _cryptoGetTextPassword->CryptoGetTextPassword(password);

+  COM_TRY_END

+}

+

diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
new file mode 100755
index 0000000..b7a6a47
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -0,0 +1,143 @@
+// ArchiveExtractCallback.h

+

+#ifndef __ARCHIVE_EXTRACT_CALLBACK_H

+#define __ARCHIVE_EXTRACT_CALLBACK_H

+

+#include "Common/MyCom.h"

+#include "Common/Wildcard.h"

+

+#include "../../IPassword.h"

+

+#include "../../Common/FileStreams.h"

+#include "../../Common/ProgressUtils.h"

+

+#include "../../Archive/IArchive.h"

+

+#include "../../Archive/Common/OutStreamWithCRC.h"

+

+#include "ExtractMode.h"

+#include "IFileExtractCallback.h"

+#include "OpenArchive.h"

+

+class CArchiveExtractCallback:

+  public IArchiveExtractCallback,

+  // public IArchiveVolumeExtractCallback,

+  public ICryptoGetTextPassword,

+  public ICompressProgressInfo,

+  public CMyUnknownImp

+{

+  const CArc *_arc;

+  const NWildcard::CCensorNode *_wildcardCensor;

+  CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;

+  CMyComPtr<ICompressProgressInfo> _compressProgress;

+  CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;

+  UString _directoryPath;

+  NExtract::NPathMode::EEnum _pathMode;

+  NExtract::NOverwriteMode::EEnum _overwriteMode;

+

+  UString _diskFilePath;

+  UString _filePath;

+  UInt64 _position;

+  bool _isSplit;

+

+  bool _extractMode;

+

+  bool WriteCTime;

+  bool WriteATime;

+  bool WriteMTime;

+

+  bool _encrypted;

+

+  struct CProcessedFileInfo

+  {

+    FILETIME CTime;

+    FILETIME ATime;

+    FILETIME MTime;

+    UInt32 Attrib;

+  

+    bool CTimeDefined;

+    bool ATimeDefined;

+    bool MTimeDefined;

+    bool AttribDefined;

+

+    bool IsDir;

+  } _fi;

+

+  UInt32 _index;

+  UInt64 _curSize;

+  bool _curSizeDefined;

+  COutFileStream *_outFileStreamSpec;

+  CMyComPtr<ISequentialOutStream> _outFileStream;

+

+  COutStreamWithCRC *_crcStreamSpec;

+  CMyComPtr<ISequentialOutStream> _crcStream;

+

+  UStringVector _removePathParts;

+

+  bool _stdOutMode;

+  bool _testMode;

+  bool _crcMode;

+  bool _multiArchives;

+

+  CMyComPtr<ICompressProgressInfo> _localProgress;

+  UInt64 _packTotal;

+  UInt64 _unpTotal;

+

+  void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath);

+  HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);

+  HRESULT GetUnpackSize();

+

+public:

+

+  CLocalProgress *LocalProgressSpec;

+

+  UInt64 NumFolders;

+  UInt64 NumFiles;

+  UInt64 UnpackSize;

+  UInt32 CrcSum;

+  

+  MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo)

+  // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback)

+

+  INTERFACE_IArchiveExtractCallback(;)

+

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

+

+  // IArchiveVolumeExtractCallback

+  // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream);

+

+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);

+

+  CArchiveExtractCallback():

+      WriteCTime(true),

+      WriteATime(true),

+      WriteMTime(true),

+      _multiArchives(false)

+  {

+    LocalProgressSpec = new CLocalProgress();

+    _localProgress = LocalProgressSpec;

+  }

+

+  void InitForMulti(bool multiArchives,

+      NExtract::NPathMode::EEnum pathMode,

+      NExtract::NOverwriteMode::EEnum overwriteMode)

+  {

+    _multiArchives = multiArchives;

+    _pathMode = pathMode;

+    _overwriteMode = overwriteMode;

+    NumFolders = NumFiles = UnpackSize = 0;

+    CrcSum = 0;

+  }

+

+  void Init(

+      const NWildcard::CCensorNode *wildcardCensor,

+      const CArc *arc,

+      IFolderArchiveExtractCallback *extractCallback2,

+      bool stdOutMode, bool testMode, bool crcMode,

+      const UString &directoryPath,

+      const UStringVector &removePathParts,

+      UInt64 packSize);

+

+};

+

+#endif

diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp
new file mode 100755
index 0000000..c62c7f1
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveName.cpp
@@ -0,0 +1,54 @@
+// ArchiveName.cpp

+

+#include "StdAfx.h"

+

+#include "Windows/FileDir.h"

+#include "Windows/FileFind.h"

+

+#include "ExtractingFilePath.h"

+

+using namespace NWindows;

+

+static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool keepName)

+{

+  UString resultName = L"Archive";

+  if (fromPrev)

+  {

+    UString dirPrefix;

+    if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix))

+    {

+      if (dirPrefix.Length() > 0)

+        if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR)

+        {

+          dirPrefix.Delete(dirPrefix.Length() - 1);

+          NFile::NFind::CFileInfoW fileInfo;

+          if (fileInfo.Find(dirPrefix))

+            resultName = fileInfo.Name;

+        }

+    }

+  }

+  else

+  {

+    NFile::NFind::CFileInfoW fileInfo;

+    if (!fileInfo.Find(srcName))

+      // return resultName;

+      return srcName;

+    resultName = fileInfo.Name;

+    if (!fileInfo.IsDir() && !keepName)

+    {

+      int dotPos = resultName.ReverseFind('.');

+      if (dotPos > 0)

+      {

+        UString archiveName2 = resultName.Left(dotPos);

+        if (archiveName2.ReverseFind('.') < 0)

+          resultName = archiveName2;

+      }

+    }

+  }

+  return resultName;

+}

+

+UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName)

+{

+  return GetCorrectFsPath(CreateArchiveName2(srcName, fromPrev, keepName));

+}

diff --git a/CPP/7zip/UI/Common/ArchiveName.h b/CPP/7zip/UI/Common/ArchiveName.h
new file mode 100755
index 0000000..ba18eea
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveName.h
@@ -0,0 +1,10 @@
+// ArchiveName.h

+

+#ifndef __ARCHIVENAME_H

+#define __ARCHIVENAME_H

+

+#include "Common/MyString.h"

+

+UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName);

+

+#endif

diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
new file mode 100755
index 0000000..bb8b6cc
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
@@ -0,0 +1,133 @@
+// ArchiveOpenCallback.cpp

+

+#include "StdAfx.h"

+

+#include "Common/StringConvert.h"

+#include "Common/ComTry.h"

+

+#include "Windows/PropVariant.h"

+

+#include "../../Common/FileStreams.h"

+

+#include "ArchiveOpenCallback.h"

+

+using namespace NWindows;

+

+STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)

+{

+  COM_TRY_BEGIN

+  if (ReOpenCallback)

+    return ReOpenCallback->SetTotal(files, bytes);

+  if (!Callback)

+    return S_OK;

+  return Callback->Open_SetTotal(files, bytes);

+  COM_TRY_END

+}

+

+STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)

+{

+  COM_TRY_BEGIN

+  if (ReOpenCallback)

+    return ReOpenCallback->SetCompleted(files, bytes);

+  if (!Callback)

+    return S_OK;

+  return Callback->Open_SetCompleted(files, bytes);

+  COM_TRY_END

+}

+  

+STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)

+{

+  COM_TRY_BEGIN

+  NCOM::CPropVariant prop;

+  if (_subArchiveMode)

+    switch(propID)

+    {

+      case kpidName: prop = _subArchiveName; break;

+    }

+  else

+    switch(propID)

+    {

+      case kpidName:  prop = _fileInfo.Name; break;

+      case kpidIsDir:  prop = _fileInfo.IsDir(); break;

+      case kpidSize:  prop = _fileInfo.Size; break;

+      case kpidAttrib:  prop = (UInt32)_fileInfo.Attrib; break;

+      case kpidCTime:  prop = _fileInfo.CTime; break;

+      case kpidATime:  prop = _fileInfo.ATime; break;

+      case kpidMTime:  prop = _fileInfo.MTime; break;

+    }

+  prop.Detach(value);

+  return S_OK;

+  COM_TRY_END

+}

+

+int COpenCallbackImp::FindName(const UString &name)

+{

+  for (int i = 0; i < FileNames.Size(); i++)

+    if (name.CompareNoCase(FileNames[i]) == 0)

+      return i;

+  return -1;

+}

+

+struct CInFileStreamVol: public CInFileStream

+{

+  UString Name;

+  COpenCallbackImp *OpenCallbackImp;

+  CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;

+  ~CInFileStreamVol()

+  {

+    if (OpenCallbackRef)

+    {

+      int index = OpenCallbackImp->FindName(Name);

+      if (index >= 0)

+        OpenCallbackImp->FileNames.Delete(index);

+    }

+  }

+};

+

+STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)

+{

+  COM_TRY_BEGIN

+  if (_subArchiveMode)

+    return S_FALSE;

+  if (Callback)

+  {

+    RINOK(Callback->Open_CheckBreak());

+  }

+  *inStream = NULL;

+  UString fullPath = _folderPrefix + name;

+  if (!_fileInfo.Find(fullPath))

+    return S_FALSE;

+  if (_fileInfo.IsDir())

+    return S_FALSE;

+  CInFileStreamVol *inFile = new CInFileStreamVol;

+  CMyComPtr<IInStream> inStreamTemp = inFile;

+  if (!inFile->Open(fullPath))

+    return ::GetLastError();

+  *inStream = inStreamTemp.Detach();

+  inFile->Name = name;

+  inFile->OpenCallbackImp = this;

+  inFile->OpenCallbackRef = this;

+  FileNames.Add(name);

+  TotalSize += _fileInfo.Size;

+  return S_OK;

+  COM_TRY_END

+}

+

+#ifndef _NO_CRYPTO

+STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)

+{

+  COM_TRY_BEGIN

+  if (ReOpenCallback)

+  {

+    CMyComPtr<ICryptoGetTextPassword> getTextPassword;

+    ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);

+    if (getTextPassword)

+      return getTextPassword->CryptoGetTextPassword(password);

+  }

+  if (!Callback)

+    return E_NOTIMPL;

+  return Callback->Open_CryptoGetTextPassword(password);

+  COM_TRY_END

+}

+#endif

+  

diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
new file mode 100755
index 0000000..a60fca3
--- /dev/null
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
@@ -0,0 +1,103 @@
+// ArchiveOpenCallback.h

+

+#ifndef __ARCHIVE_OPEN_CALLBACK_H

+#define __ARCHIVE_OPEN_CALLBACK_H

+

+#include "Common/MyCom.h"

+#include "Common/MyString.h"

+

+#include "Windows/FileFind.h"

+

+#ifndef _NO_CRYPTO

+#include "../../IPassword.h"

+#endif

+#include "../../Archive/IArchive.h"

+

+#ifdef _NO_CRYPTO

+

+#define INTERFACE_IOpenCallbackUI_Crypto(x)

+

+#else

+

+#define INTERFACE_IOpenCallbackUI_Crypto(x) \

+  virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \

+  virtual HRESULT Open_GetPasswordIfAny(UString &password) x; \

+  virtual bool Open_WasPasswordAsked() x; \

+  virtual void Open_ClearPasswordWasAskedFlag() x; \

+  

+#endif

+

+#define INTERFACE_IOpenCallbackUI(x) \

+  virtual HRESULT Open_CheckBreak() x; \

+  virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \

+  virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \

+  INTERFACE_IOpenCallbackUI_Crypto(x)

+

+struct IOpenCallbackUI

+{

+  INTERFACE_IOpenCallbackUI(=0)

+};

+

+class COpenCallbackImp:

+  public IArchiveOpenCallback,

+  public IArchiveOpenVolumeCallback,

+  public IArchiveOpenSetSubArchiveName,

+  #ifndef _NO_CRYPTO

+  public ICryptoGetTextPassword,

+  #endif

+  public CMyUnknownImp

+{

+public:

+  #ifndef _NO_CRYPTO

+  MY_UNKNOWN_IMP3(

+      IArchiveOpenVolumeCallback,

+      ICryptoGetTextPassword,

+      IArchiveOpenSetSubArchiveName

+      )

+  #else

+  MY_UNKNOWN_IMP2(

+      IArchiveOpenVolumeCallback,

+      IArchiveOpenSetSubArchiveName

+      )

+  #endif

+

+  INTERFACE_IArchiveOpenCallback(;)

+  INTERFACE_IArchiveOpenVolumeCallback(;)

+

+  #ifndef _NO_CRYPTO

+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);

+  #endif

+

+  STDMETHOD(SetSubArchiveName(const wchar_t *name))

+  {

+    _subArchiveMode = true;

+    _subArchiveName = name;

+    TotalSize = 0;

+    return  S_OK;

+  }

+

+private:

+  UString _folderPrefix;

+  NWindows::NFile::NFind::CFileInfoW _fileInfo;

+  bool _subArchiveMode;

+  UString _subArchiveName;

+public:

+  UStringVector FileNames;

+  IOpenCallbackUI *Callback;

+  CMyComPtr<IArchiveOpenCallback> ReOpenCallback;

+  UInt64 TotalSize;

+

+  COpenCallbackImp(): Callback(NULL) {}

+  void Init(const UString &folderPrefix, const UString &fileName)

+  {

+    _folderPrefix = folderPrefix;

+    if (!_fileInfo.Find(_folderPrefix + fileName))

+      throw 1;

+    FileNames.Clear();

+    _subArchiveMode = false;

+    TotalSize = 0;

+  }

+  int FindName(const UString &name);

+};

+

+#endif

diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp
new file mode 100755
index 0000000..0c85695
--- /dev/null
+++ b/CPP/7zip/UI/Common/Bench.cpp
@@ -0,0 +1,1028 @@
+// Bench.cpp

+

+#include "StdAfx.h"

+

+#include "Bench.h"

+

+#ifndef _WIN32

+#define USE_POSIX_TIME

+#define USE_POSIX_TIME2

+#endif

+

+#ifdef USE_POSIX_TIME

+#include <time.h>

+#ifdef USE_POSIX_TIME2

+#include <sys/time.h>

+#endif

+#endif

+

+#ifdef _WIN32

+#define USE_ALLOCA

+#endif

+

+#ifdef USE_ALLOCA

+#ifdef _WIN32

+#include <malloc.h>

+#else

+#include <stdlib.h>

+#endif

+#endif

+

+#include "../../../../C/7zCrc.h"

+#include "../../../../C/Alloc.h"

+

+#ifndef _7ZIP_ST

+#include "../../../Windows/Synchronization.h"

+#include "../../../Windows/Thread.h"

+#endif

+

+#include "../../../Windows/PropVariant.h"

+

+static const UInt32 kUncompressMinBlockSize =

+#ifdef UNDER_CE

+1 << 24;

+#else

+1 << 26;

+#endif

+

+static const UInt32 kCrcBlockSize =

+#ifdef UNDER_CE

+1 << 25;

+#else

+1 << 30;

+#endif

+

+static const UInt32 kAdditionalSize = (1 << 16);

+static const UInt32 kCompressedAdditionalSize = (1 << 10);

+static const UInt32 kMaxLzmaPropSize = 5;

+

+class CBaseRandomGenerator

+{

+  UInt32 A1;

+  UInt32 A2;

+public:

+  CBaseRandomGenerator() { Init(); }

+  void Init() { A1 = 362436069; A2 = 521288629;}

+  UInt32 GetRnd()

+  {

+    return

+      ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) +

+      ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) );

+  }

+};

+

+class CBenchBuffer

+{

+public:

+  size_t BufferSize;

+  Byte *Buffer;

+  CBenchBuffer(): Buffer(0) {}

+  virtual ~CBenchBuffer() { Free(); }

+  void Free()

+  {

+    ::MidFree(Buffer);

+    Buffer = 0;

+  }

+  bool Alloc(size_t bufferSize)

+  {

+    if (Buffer != 0 && BufferSize == bufferSize)

+      return true;

+    Free();

+    Buffer = (Byte *)::MidAlloc(bufferSize);

+    BufferSize = bufferSize;

+    return (Buffer != 0);

+  }

+};

+

+class CBenchRandomGenerator: public CBenchBuffer

+{

+  CBaseRandomGenerator *RG;

+public:

+  void Set(CBaseRandomGenerator *rg) { RG = rg; }

+  UInt32 GetVal(UInt32 &res, int numBits)

+  {

+    UInt32 val = res & (((UInt32)1 << numBits) - 1);

+    res >>= numBits;

+    return val;

+  }

+  UInt32 GetLen(UInt32 &res)

+  {

+    UInt32 len = GetVal(res, 2);

+    return GetVal(res, 1 + len);

+  }

+  void Generate()

+  {

+    UInt32 pos = 0;

+    UInt32 rep0 = 1;

+    while (pos < BufferSize)

+    {

+      UInt32 res = RG->GetRnd();

+      res >>= 1;

+      if (GetVal(res, 1) == 0 || pos < 1024)

+        Buffer[pos++] = (Byte)(res & 0xFF);

+      else

+      {

+        UInt32 len;

+        len = 1 + GetLen(res);

+        if (GetVal(res, 3) != 0)

+        {

+          len += GetLen(res);

+          do

+          {

+            UInt32 ppp = GetVal(res, 5) + 6;

+            res = RG->GetRnd();

+            if (ppp > 30)

+              continue;

+            rep0 = /* (1 << ppp) +*/  GetVal(res, ppp);

+            res = RG->GetRnd();

+          }

+          while (rep0 >= pos);

+          rep0++;

+        }

+

+        for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++)

+          Buffer[pos] = Buffer[pos - rep0];

+      }

+    }

+  }

+};

+

+

+class CBenchmarkInStream:

+  public ISequentialInStream,

+  public CMyUnknownImp

+{

+  const Byte *Data;

+  size_t Pos;

+  size_t Size;

+public:

+  MY_UNKNOWN_IMP

+  void Init(const Byte *data, size_t size)

+  {

+    Data = data;

+    Size = size;

+    Pos = 0;

+  }

+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);

+};

+

+STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)

+{

+  size_t remain = Size - Pos;

+  UInt32 kMaxBlockSize = (1 << 20);

+  if (size > kMaxBlockSize)

+    size = kMaxBlockSize;

+  if (size > remain)

+    size = (UInt32)remain;

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

+    ((Byte *)data)[i] = Data[Pos + i];

+  Pos += size;

+  if(processedSize != NULL)

+    *processedSize = size;

+  return S_OK;

+}

+  

+class CBenchmarkOutStream:

+  public ISequentialOutStream,

+  public CBenchBuffer,

+  public CMyUnknownImp

+{

+  // bool _overflow;

+public:

+  UInt32 Pos;

+  // CBenchmarkOutStream(): _overflow(false) {}

+  void Init()

+  {

+    // _overflow = false;

+    Pos = 0;

+  }

+  MY_UNKNOWN_IMP

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  size_t curSize = BufferSize - Pos;

+  if (curSize > size)

+    curSize = size;

+  memcpy(Buffer + Pos, data, curSize);

+  Pos += (UInt32)curSize;

+  if(processedSize != NULL)

+    *processedSize = (UInt32)curSize;

+  if (curSize != size)

+  {

+    // _overflow = true;

+    return E_FAIL;

+  }

+  return S_OK;

+}

+  

+class CCrcOutStream:

+  public ISequentialOutStream,

+  public CMyUnknownImp

+{

+public:

+  UInt32 Crc;

+  MY_UNKNOWN_IMP

+  void Init() { Crc = CRC_INIT_VAL; }

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+};

+

+STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  Crc = CrcUpdate(Crc, data, size);

+  if (processedSize != NULL)

+    *processedSize = size;

+  return S_OK;

+}

+  

+static UInt64 GetTimeCount()

+{

+  #ifdef USE_POSIX_TIME

+  #ifdef USE_POSIX_TIME2

+  timeval v;

+  if (gettimeofday(&v, 0) == 0)

+    return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec;

+  return (UInt64)time(NULL) * 1000000;

+  #else

+  return time(NULL);

+  #endif

+  #else

+  /*

+  LARGE_INTEGER value;

+  if (::QueryPerformanceCounter(&value))

+    return value.QuadPart;

+  */

+  return GetTickCount();

+  #endif

+}

+

+static UInt64 GetFreq()

+{

+  #ifdef USE_POSIX_TIME

+  #ifdef USE_POSIX_TIME2

+  return 1000000;

+  #else

+  return 1;

+  #endif

+  #else

+  /*

+  LARGE_INTEGER value;

+  if (::QueryPerformanceFrequency(&value))

+    return value.QuadPart;

+  */

+  return 1000;

+  #endif

+}

+

+#ifndef USE_POSIX_TIME

+static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }

+#endif

+

+static UInt64 GetUserTime()

+{

+  #ifdef USE_POSIX_TIME

+  return clock();

+  #else

+  FILETIME creationTime, exitTime, kernelTime, userTime;

+  if (

+  #ifdef UNDER_CE

+    ::GetThreadTimes(::GetCurrentThread()

+  #else

+    ::GetProcessTimes(::GetCurrentProcess()

+  #endif

+    , &creationTime, &exitTime, &kernelTime, &userTime) != 0)

+    return GetTime64(userTime) + GetTime64(kernelTime);

+  return (UInt64)GetTickCount() * 10000;

+  #endif

+}

+

+static UInt64 GetUserFreq()

+{

+  #ifdef USE_POSIX_TIME

+  return CLOCKS_PER_SEC;

+  #else

+  return 10000000;

+  #endif

+}

+

+class CBenchProgressStatus

+{

+  #ifndef _7ZIP_ST

+  NWindows::NSynchronization::CCriticalSection CS;

+  #endif

+public:

+  HRESULT Res;

+  bool EncodeMode;

+  void SetResult(HRESULT res)

+  {

+    #ifndef _7ZIP_ST

+    NWindows::NSynchronization::CCriticalSectionLock lock(CS);

+    #endif

+    Res = res;

+  }

+  HRESULT GetResult()

+  {

+    #ifndef _7ZIP_ST

+    NWindows::NSynchronization::CCriticalSectionLock lock(CS);

+    #endif

+    return Res;

+  }

+};

+

+class CBenchProgressInfo:

+  public ICompressProgressInfo,

+  public CMyUnknownImp

+{

+public:

+  CBenchProgressStatus *Status;

+  CBenchInfo BenchInfo;

+  HRESULT Res;

+  IBenchCallback *callback;

+  CBenchProgressInfo(): callback(0) {}

+  MY_UNKNOWN_IMP

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

+};

+

+static void SetStartTime(CBenchInfo &bi)

+{

+  bi.GlobalFreq = GetFreq();

+  bi.UserFreq = GetUserFreq();

+  bi.GlobalTime = ::GetTimeCount();

+  bi.UserTime = ::GetUserTime();

+}

+

+static void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest)

+{

+  dest.GlobalFreq = GetFreq();

+  dest.UserFreq = GetUserFreq();

+  dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime;

+  dest.UserTime = ::GetUserTime() - biStart.UserTime;

+}

+

+STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)

+{

+  HRESULT res = Status->GetResult();

+  if (res != S_OK)

+    return res;

+  if (!callback)

+    return res;

+  CBenchInfo info = BenchInfo;

+  SetFinishTime(BenchInfo, info);

+  if (Status->EncodeMode)

+  {

+    info.UnpackSize = *inSize;

+    info.PackSize = *outSize;

+    res = callback->SetEncodeResult(info, false);

+  }

+  else

+  {

+    info.PackSize = BenchInfo.PackSize + *inSize;

+    info.UnpackSize = BenchInfo.UnpackSize + *outSize;

+    res = callback->SetDecodeResult(info, false);

+  }

+  if (res != S_OK)

+    Status->SetResult(res);

+  return res;

+}

+

+static const int kSubBits = 8;

+

+static UInt32 GetLogSize(UInt32 size)

+{

+  for (int i = kSubBits; i < 32; i++)

+    for (UInt32 j = 0; j < (1 << kSubBits); j++)

+      if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))

+        return (i << kSubBits) + j;

+  return (32 << kSubBits);

+}

+

+static void NormalizeVals(UInt64 &v1, UInt64 &v2)

+{

+  while (v1 > 1000000)

+  {

+    v1 >>= 1;

+    v2 >>= 1;

+  }

+}

+

+UInt64 GetUsage(const CBenchInfo &info)

+{

+  UInt64 userTime = info.UserTime;

+  UInt64 userFreq = info.UserFreq;

+  UInt64 globalTime = info.GlobalTime;

+  UInt64 globalFreq = info.GlobalFreq;

+  NormalizeVals(userTime, userFreq);

+  NormalizeVals(globalFreq, globalTime);

+  if (userFreq == 0)

+    userFreq = 1;

+  if (globalTime == 0)

+    globalTime = 1;

+  return userTime * globalFreq * 1000000 / userFreq / globalTime;

+}

+

+UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating)

+{

+  UInt64 userTime = info.UserTime;

+  UInt64 userFreq = info.UserFreq;

+  UInt64 globalTime = info.GlobalTime;

+  UInt64 globalFreq = info.GlobalFreq;

+  NormalizeVals(userFreq, userTime);

+  NormalizeVals(globalTime, globalFreq);

+  if (globalFreq == 0)

+    globalFreq = 1;

+  if (userTime == 0)

+    userTime = 1;

+  return userFreq * globalTime / globalFreq *  rating / userTime;

+}

+

+static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)

+{

+  UInt64 elTime = elapsedTime;

+  NormalizeVals(freq, elTime);

+  if (elTime == 0)

+    elTime = 1;

+  return value * freq / elTime;

+}

+

+UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size)

+{

+  UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits);

+  UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits));

+  UInt64 numCommands = (UInt64)(size) * numCommandsForOne;

+  return MyMultDiv64(numCommands, elapsedTime, freq);

+}

+

+UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations)

+{

+  UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations;

+  return MyMultDiv64(numCommands, elapsedTime, freq);

+}

+

+struct CEncoderInfo;

+

+struct CEncoderInfo

+{

+  #ifndef _7ZIP_ST

+  NWindows::CThread thread[2];

+  #endif

+  CMyComPtr<ICompressCoder> encoder;

+  CBenchProgressInfo *progressInfoSpec[2];

+  CMyComPtr<ICompressProgressInfo> progressInfo[2];

+  UInt32 NumIterations;

+  #ifdef USE_ALLOCA

+  size_t AllocaSize;

+  #endif

+

+  struct CDecoderInfo

+  {

+    CEncoderInfo *Encoder;

+    UInt32 DecoderIndex;

+    #ifdef USE_ALLOCA

+    size_t AllocaSize;

+    #endif

+    bool CallbackMode;

+  };

+  CDecoderInfo decodersInfo[2];

+

+  CMyComPtr<ICompressCoder> decoders[2];

+  HRESULT Results[2];

+  CBenchmarkOutStream *outStreamSpec;

+  CMyComPtr<ISequentialOutStream> outStream;

+  IBenchCallback *callback;

+  UInt32 crc;

+  UInt32 kBufferSize;

+  UInt32 compressedSize;

+  CBenchRandomGenerator rg;

+  CBenchmarkOutStream *propStreamSpec;

+  CMyComPtr<ISequentialOutStream> propStream;

+  HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg);

+  HRESULT Encode();

+  HRESULT Decode(UInt32 decoderIndex);

+

+  CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {}

+

+  #ifndef _7ZIP_ST

+  static THREAD_FUNC_DECL EncodeThreadFunction(void *param)

+  {

+    CEncoderInfo *encoder = (CEncoderInfo *)param;

+    #ifdef USE_ALLOCA

+    alloca(encoder->AllocaSize);

+    #endif

+    HRESULT res = encoder->Encode();

+    encoder->Results[0] = res;

+    if (res != S_OK)

+      encoder->progressInfoSpec[0]->Status->SetResult(res);

+

+    return 0;

+  }

+  static THREAD_FUNC_DECL DecodeThreadFunction(void *param)

+  {

+    CDecoderInfo *decoder = (CDecoderInfo *)param;

+    #ifdef USE_ALLOCA

+    alloca(decoder->AllocaSize);

+    #endif

+    CEncoderInfo *encoder = decoder->Encoder;

+    encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex);

+    return 0;

+  }

+

+  HRESULT CreateEncoderThread()

+  {

+    return thread[0].Create(EncodeThreadFunction, this);

+  }

+

+  HRESULT CreateDecoderThread(int index, bool callbackMode

+      #ifdef USE_ALLOCA

+      , size_t allocaSize

+      #endif

+      )

+  {

+    CDecoderInfo &decoder = decodersInfo[index];

+    decoder.DecoderIndex = index;

+    decoder.Encoder = this;

+    #ifdef USE_ALLOCA

+    decoder.AllocaSize = allocaSize;

+    #endif

+    decoder.CallbackMode = callbackMode;

+    return thread[index].Create(DecodeThreadFunction, &decoder);

+  }

+  #endif

+};

+

+HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc)

+{

+  rg.Set(rgLoc);

+  kBufferSize = dictionarySize + kAdditionalSize;

+  UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;

+  if (!rg.Alloc(kBufferSize))

+    return E_OUTOFMEMORY;

+  rg.Generate();

+  crc = CrcCalc(rg.Buffer, rg.BufferSize);

+

+  outStreamSpec = new CBenchmarkOutStream;

+  if (!outStreamSpec->Alloc(kCompressedBufferSize))

+    return E_OUTOFMEMORY;

+

+  outStream = outStreamSpec;

+

+  propStreamSpec = 0;

+  if (!propStream)

+  {

+    propStreamSpec = new CBenchmarkOutStream;

+    propStream = propStreamSpec;

+  }

+  if (!propStreamSpec->Alloc(kMaxLzmaPropSize))

+    return E_OUTOFMEMORY;

+  propStreamSpec->Init();

+  

+  PROPID propIDs[] =

+  {

+    NCoderPropID::kDictionarySize,

+    NCoderPropID::kNumThreads

+  };

+  const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);

+  PROPVARIANT props[kNumProps];

+  props[0].vt = VT_UI4;

+  props[0].ulVal = dictionarySize;

+

+  props[1].vt = VT_UI4;

+  props[1].ulVal = numThreads;

+

+  {

+    CMyComPtr<ICompressSetCoderProperties> setCoderProperties;

+    RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties));

+    if (!setCoderProperties)

+      return E_FAIL;

+    RINOK(setCoderProperties->SetCoderProperties(propIDs, props, kNumProps));

+

+    CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;

+    encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties);

+    if (writeCoderProperties)

+    {

+      RINOK(writeCoderProperties->WriteCoderProperties(propStream));

+    }

+  }

+  return S_OK;

+}

+

+HRESULT CEncoderInfo::Encode()

+{

+  CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;

+  CMyComPtr<ISequentialInStream> inStream = inStreamSpec;

+  inStreamSpec->Init(rg.Buffer, rg.BufferSize);

+  outStreamSpec->Init();

+

+  RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0]));

+  compressedSize = outStreamSpec->Pos;

+  encoder.Release();

+  return S_OK;

+}

+

+HRESULT CEncoderInfo::Decode(UInt32 decoderIndex)

+{

+  CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;

+  CMyComPtr<ISequentialInStream> inStream = inStreamSpec;

+  CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex];

+

+  CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;

+  decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties);

+  if (!compressSetDecoderProperties)

+    return E_FAIL;

+

+  CCrcOutStream *crcOutStreamSpec = new CCrcOutStream;

+  CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec;

+    

+  CBenchProgressInfo *pi = progressInfoSpec[decoderIndex];

+  pi->BenchInfo.UnpackSize = 0;

+  pi->BenchInfo.PackSize = 0;

+

+  for (UInt32 j = 0; j < NumIterations; j++)

+  {

+    inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);

+    crcOutStreamSpec->Init();

+    

+    RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));

+    UInt64 outSize = kBufferSize;

+    RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex]));

+    if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc)

+      return S_FALSE;

+    pi->BenchInfo.UnpackSize += kBufferSize;

+    pi->BenchInfo.PackSize += compressedSize;

+  }

+  decoder.Release();

+  return S_OK;

+}

+

+static const UInt32 kNumThreadsMax = (1 << 16);

+

+struct CBenchEncoders

+{

+  CEncoderInfo *encoders;

+  CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; }

+  ~CBenchEncoders() { delete []encoders; }

+};

+

+HRESULT LzmaBench(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback)

+{

+  UInt32 numEncoderThreads =

+    #ifndef _7ZIP_ST

+    (numThreads > 1 ? numThreads / 2 : 1);

+    #else

+    1;

+    #endif

+  UInt32 numSubDecoderThreads =

+    #ifndef _7ZIP_ST

+    (numThreads > 1 ? 2 : 1);

+    #else

+    1;

+    #endif

+  if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax)

+  {

+    return E_INVALIDARG;

+  }

+

+  CBenchEncoders encodersSpec(numEncoderThreads);

+  CEncoderInfo *encoders = encodersSpec.encoders;

+

+

+  UInt32 i;

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

+  {

+    CEncoderInfo &encoder = encoders[i];

+    encoder.callback = (i == 0) ? callback : 0;

+

+    const UInt32 kLzmaId = 0x030101;

+    RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.encoder, true));

+    if (!encoder.encoder)

+      return E_NOTIMPL;

+    for (UInt32 j = 0; j < numSubDecoderThreads; j++)

+    {

+      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.decoders[j], false));

+      if (!encoder.decoders[j])

+        return E_NOTIMPL;

+    }

+  }

+

+  CBaseRandomGenerator rg;

+  rg.Init();

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

+  {

+    RINOK(encoders[i].Init(dictionarySize, numThreads, &rg));

+  }

+

+  CBenchProgressStatus status;

+  status.Res = S_OK;

+  status.EncodeMode = true;

+

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

+  {

+    CEncoderInfo &encoder = encoders[i];

+    for (int j = 0; j < 2; j++)

+    {

+      encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo;

+      encoder.progressInfoSpec[j]->Status = &status;

+    }

+    if (i == 0)

+    {

+      encoder.progressInfoSpec[0]->callback = callback;

+      encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads;

+      SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);

+    }

+

+    #ifndef _7ZIP_ST

+    if (numEncoderThreads > 1)

+    {

+      #ifdef USE_ALLOCA

+      encoder.AllocaSize = (i * 16 * 21) & 0x7FF;

+      #endif

+      RINOK(encoder.CreateEncoderThread())

+    }

+    else

+    #endif

+    {

+      RINOK(encoder.Encode());

+    }

+  }

+  #ifndef _7ZIP_ST

+  if (numEncoderThreads > 1)

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

+      encoders[i].thread[0].Wait();

+  #endif

+

+  RINOK(status.Res);

+

+  CBenchInfo info;

+

+  SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);

+  info.UnpackSize = 0;

+  info.PackSize = 0;

+  info.NumIterations = 1; // progressInfoSpec->NumIterations;

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

+  {

+    CEncoderInfo &encoder = encoders[i];

+    info.UnpackSize += encoder.kBufferSize;

+    info.PackSize += encoder.compressedSize;

+  }

+  RINOK(callback->SetEncodeResult(info, true));

+

+

+  status.Res = S_OK;

+  status.EncodeMode = false;

+

+  UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads;

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

+  {

+    CEncoderInfo &encoder = encoders[i];

+    encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize;

+

+    if (i == 0)

+    {

+      encoder.progressInfoSpec[0]->callback = callback;

+      encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads;

+      SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);

+    }

+

+    #ifndef _7ZIP_ST

+    if (numDecoderThreads > 1)

+    {

+      for (UInt32 j = 0; j < numSubDecoderThreads; j++)

+      {

+        HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0)

+            #ifdef USE_ALLOCA

+            , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF

+            #endif

+            );

+        RINOK(res);

+      }

+    }

+    else

+    #endif

+    {

+      RINOK(encoder.Decode(0));

+    }

+  }

+  #ifndef _7ZIP_ST

+  HRESULT res = S_OK;

+  if (numDecoderThreads > 1)

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

+      for (UInt32 j = 0; j < numSubDecoderThreads; j++)

+      {

+        CEncoderInfo &encoder = encoders[i];

+        encoder.thread[j].Wait();

+        if (encoder.Results[j] != S_OK)

+          res = encoder.Results[j];

+      }

+  RINOK(res);

+  #endif

+  RINOK(status.Res);

+  SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);

+  #ifndef _7ZIP_ST

+  #ifdef UNDER_CE

+  if (numDecoderThreads > 1)

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

+      for (UInt32 j = 0; j < numSubDecoderThreads; j++)

+      {

+        FILETIME creationTime, exitTime, kernelTime, userTime;

+        if (::GetThreadTimes(encoders[i].thread[j], &creationTime, &exitTime, &kernelTime, &userTime) != 0)

+          info.UserTime += GetTime64(userTime) + GetTime64(kernelTime);

+      }

+  #endif

+  #endif

+  info.UnpackSize = 0;

+  info.PackSize = 0;

+  info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations;

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

+  {

+    CEncoderInfo &encoder = encoders[i];

+    info.UnpackSize += encoder.kBufferSize;

+    info.PackSize += encoder.compressedSize;

+  }

+  RINOK(callback->SetDecodeResult(info, false));

+  RINOK(callback->SetDecodeResult(info, true));

+  return S_OK;

+}

+

+

+inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary)

+{

+  UInt32 hs = dictionary - 1;

+  hs |= (hs >> 1);

+  hs |= (hs >> 2);

+  hs |= (hs >> 4);

+  hs |= (hs >> 8);

+  hs >>= 1;

+  hs |= 0xFFFF;

+  if (hs > (1 << 24))

+    hs >>= 1;

+  hs++;

+  return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 +

+      (1 << 20) + (multiThread ? (6 << 20) : 0);

+}

+

+UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary)

+{

+  const UInt32 kBufferSize = dictionary;

+  const UInt32 kCompressedBufferSize = (kBufferSize / 2);

+  UInt32 numSubThreads = (numThreads > 1) ? 2 : 1;

+  UInt32 numBigThreads = numThreads / numSubThreads;

+  return (kBufferSize + kCompressedBufferSize +

+    GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads;

+}

+

+static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase)

+{

+  for (UInt32 i = 0; i < numCycles; i++)

+    if (CrcCalc(data, size) != crcBase)

+      return false;

+  return true;

+}

+

+#ifndef _7ZIP_ST

+struct CCrcInfo

+{

+  NWindows::CThread Thread;

+  const Byte *Data;

+  UInt32 Size;

+  UInt32 NumCycles;

+  UInt32 Crc;

+  bool Res;

+  void Wait()

+  {

+    Thread.Wait();

+    Thread.Close();

+  }

+};

+

+static THREAD_FUNC_DECL CrcThreadFunction(void *param)

+{

+  CCrcInfo *p = (CCrcInfo *)param;

+  p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc);

+  return 0;

+}

+

+struct CCrcThreads

+{

+  UInt32 NumThreads;

+  CCrcInfo *Items;

+  CCrcThreads(): Items(0), NumThreads(0) {}

+  void WaitAll()

+  {

+    for (UInt32 i = 0; i < NumThreads; i++)

+      Items[i].Wait();

+    NumThreads = 0;

+  }

+  ~CCrcThreads()

+  {

+    WaitAll();

+    delete []Items;

+  }

+};

+#endif

+

+static UInt32 CrcCalc1(const Byte *buf, UInt32 size)

+{

+  UInt32 crc = CRC_INIT_VAL;;

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

+    crc = CRC_UPDATE_BYTE(crc, buf[i]);

+  return CRC_GET_DIGEST(crc);

+}

+

+static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)

+{

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

+    buf[i] = (Byte)RG.GetRnd();

+}

+

+static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)

+{

+  RandGen(buf, size, RG);

+  return CrcCalc1(buf, size);

+}

+

+bool CrcInternalTest()

+{

+  CBenchBuffer buffer;

+  const UInt32 kBufferSize0 = (1 << 8);

+  const UInt32 kBufferSize1 = (1 << 10);

+  const UInt32 kCheckSize = (1 << 5);

+  if (!buffer.Alloc(kBufferSize0 + kBufferSize1))

+    return false;

+  Byte *buf = buffer.Buffer;

+  UInt32 i;

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

+    buf[i] = (Byte)i;

+  UInt32 crc1 = CrcCalc1(buf, kBufferSize0);

+  if (crc1 != 0x29058C73)

+    return false;

+  CBaseRandomGenerator RG;

+  RandGen(buf + kBufferSize0, kBufferSize1, RG);

+  for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++)

+    for (UInt32 j = 0; j < kCheckSize; j++)

+      if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j))

+        return false;

+  return true;

+}

+

+HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed)

+{

+  if (numThreads == 0)

+    numThreads = 1;

+

+  CBenchBuffer buffer;

+  size_t totalSize = (size_t)bufferSize * numThreads;

+  if (totalSize / numThreads != bufferSize)

+    return E_OUTOFMEMORY;

+  if (!buffer.Alloc(totalSize))

+    return E_OUTOFMEMORY;

+

+  Byte *buf = buffer.Buffer;

+  CBaseRandomGenerator RG;

+  UInt32 numCycles = (kCrcBlockSize) / ((bufferSize >> 2) + 1) + 1;

+

+  UInt64 timeVal;

+  #ifndef _7ZIP_ST

+  CCrcThreads threads;

+  if (numThreads > 1)

+  {

+    threads.Items = new CCrcInfo[numThreads];

+    UInt32 i;

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

+    {

+      CCrcInfo &info = threads.Items[i];

+      Byte *data = buf + (size_t)bufferSize * i;

+      info.Data = data;

+      info.NumCycles = numCycles;

+      info.Size = bufferSize;

+      info.Crc = RandGenCrc(data, bufferSize, RG);

+    }

+    timeVal = GetTimeCount();

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

+    {

+      CCrcInfo &info = threads.Items[i];

+      RINOK(info.Thread.Create(CrcThreadFunction, &info));

+      threads.NumThreads++;

+    }

+    threads.WaitAll();

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

+      if (!threads.Items[i].Res)

+        return S_FALSE;

+  }

+  else

+  #endif

+  {

+    UInt32 crc = RandGenCrc(buf, bufferSize, RG);

+    timeVal = GetTimeCount();

+    if (!CrcBig(buf, bufferSize, numCycles, crc))

+      return S_FALSE;

+  }

+  timeVal = GetTimeCount() - timeVal;

+  if (timeVal == 0)

+    timeVal = 1;

+

+  UInt64 size = (UInt64)numCycles * totalSize;

+  speed = MyMultDiv64(size, timeVal, GetFreq());

+  return S_OK;

+}

diff --git a/CPP/7zip/UI/Common/Bench.h b/CPP/7zip/UI/Common/Bench.h
new file mode 100755
index 0000000..f6e8064
--- /dev/null
+++ b/CPP/7zip/UI/Common/Bench.h
@@ -0,0 +1,42 @@
+// Bench.h

+

+#ifndef __7ZIP_BENCH_H

+#define __7ZIP_BENCH_H

+

+#include "../../Common/CreateCoder.h"

+

+struct CBenchInfo

+{

+  UInt64 GlobalTime;

+  UInt64 GlobalFreq;

+  UInt64 UserTime;

+  UInt64 UserFreq;

+  UInt64 UnpackSize;

+  UInt64 PackSize;

+  UInt32 NumIterations;

+  CBenchInfo(): NumIterations(0) {}

+};

+

+struct IBenchCallback

+{

+  virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0;

+  virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0;

+};

+

+UInt64 GetUsage(const CBenchInfo &benchOnfo);

+UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating);

+UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size);

+UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations);

+

+HRESULT LzmaBench(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback);

+

+const int kBenchMinDicLogSize = 18;

+

+UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary);

+

+bool CrcInternalTest();

+HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed);

+

+#endif

diff --git a/CPP/7zip/UI/Common/DefaultName.cpp b/CPP/7zip/UI/Common/DefaultName.cpp
new file mode 100755
index 0000000..5c46500
--- /dev/null
+++ b/CPP/7zip/UI/Common/DefaultName.cpp
@@ -0,0 +1,35 @@
+// DefaultName.cpp

+

+#include "StdAfx.h"

+

+#include "DefaultName.h"

+

+static UString GetDefaultName3(const UString &fileName,

+    const UString &extension, const UString &addSubExtension)

+{

+  int extLength = extension.Length();

+  int fileNameLength = fileName.Length();

+  if (fileNameLength > extLength + 1)

+  {

+    int dotPos = fileNameLength - (extLength + 1);

+    if (fileName[dotPos] == '.')

+      if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0)

+        return fileName.Left(dotPos) + addSubExtension;

+  }

+  int dotPos = fileName.ReverseFind(L'.');

+  if (dotPos > 0)

+    return fileName.Left(dotPos) + addSubExtension;

+

+  if (addSubExtension.IsEmpty())

+    return fileName + L"~";

+  else

+    return fileName + addSubExtension;

+}

+

+UString GetDefaultName2(const UString &fileName,

+    const UString &extension, const UString &addSubExtension)

+{

+  UString name = GetDefaultName3(fileName, extension, addSubExtension);

+  name.TrimRight();

+  return name;

+}

diff --git a/CPP/7zip/UI/Common/DefaultName.h b/CPP/7zip/UI/Common/DefaultName.h
new file mode 100755
index 0000000..3989a1f
--- /dev/null
+++ b/CPP/7zip/UI/Common/DefaultName.h
@@ -0,0 +1,11 @@
+// DefaultName.h

+

+#ifndef __DEFAULTNAME_H

+#define __DEFAULTNAME_H

+

+#include "Common/MyString.h"

+

+UString GetDefaultName2(const UString &fileName,

+    const UString &extension, const UString &addSubExtension);

+

+#endif

diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h
new file mode 100755
index 0000000..e10d6b9
--- /dev/null
+++ b/CPP/7zip/UI/Common/DirItem.h
@@ -0,0 +1,69 @@
+// DirItem.h

+

+#ifndef __DIR_ITEM_H

+#define __DIR_ITEM_H

+

+#include "Common/MyString.h"

+#include "Common/Types.h"

+#include "../../Archive/IArchive.h"

+

+struct CDirItem

+{

+  UInt64 Size;

+  FILETIME CTime;

+  FILETIME ATime;

+  FILETIME MTime;

+  UString Name;

+  UInt32 Attrib;

+  int PhyParent;

+  int LogParent;

+  

+  CDirItem(): PhyParent(-1), LogParent(-1) {}

+  bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }

+};

+

+class CDirItems

+{

+  UStringVector Prefixes;

+  CIntVector PhyParents;

+  CIntVector LogParents;

+

+  UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const;

+public:

+  CObjectVector<CDirItem> Items;

+

+  int GetNumFolders() const { return Prefixes.Size(); }

+  UString GetPhyPath(int index) const;

+  UString GetLogPath(int index) const;

+

+  int AddPrefix(int phyParent, int logParent, const UString &prefix);

+  void DeleteLastPrefix();

+

+  void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix,

+    UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes);

+

+  void EnumerateDirItems2(

+    const UString &phyPrefix,

+    const UString &logPrefix,

+    const UStringVector &filePaths,

+    UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes);

+

+  void ReserveDown();

+};

+

+struct CArcItem

+{

+  UInt64 Size;

+  FILETIME MTime;

+  UString Name;

+  bool IsDir;

+  bool SizeDefined;

+  bool MTimeDefined;

+  bool Censored;

+  UInt32 IndexInServer;

+  int TimeType;

+  

+  CArcItem(): IsDir(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {}

+};

+

+#endif

diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp
new file mode 100755
index 0000000..61ecaba
--- /dev/null
+++ b/CPP/7zip/UI/Common/EnumDirItems.cpp
@@ -0,0 +1,361 @@
+// EnumDirItems.cpp

+

+#include "StdAfx.h"

+

+#include "EnumDirItems.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NName;

+

+void AddDirFileInfo(int phyParent, int logParent,

+    const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems)

+{

+  CDirItem di;

+  di.Size = fi.Size;

+  di.CTime = fi.CTime;

+  di.ATime = fi.ATime;

+  di.MTime = fi.MTime;

+  di.Attrib = fi.Attrib;

+  di.PhyParent = phyParent;

+  di.LogParent = logParent;

+  di.Name = fi.Name;

+  dirItems.Add(di);

+}

+

+UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const

+{

+  UString path;

+  int len = name.Length();

+  int i;

+  for (i = index; i >= 0; i = parents[i])

+    len += Prefixes[i].Length();

+  int totalLen = len;

+  wchar_t *p = path.GetBuffer(len);

+  p[len] = 0;

+  len -= name.Length();

+  memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t));

+  for (i = index; i >= 0; i = parents[i])

+  {

+    const UString &s = Prefixes[i];

+    len -= s.Length();

+    memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t));

+  }

+  path.ReleaseBuffer(totalLen);

+  return path;

+}

+

+UString CDirItems::GetPhyPath(int index) const

+{

+  const CDirItem &di = Items[index];

+  return GetPrefixesPath(PhyParents, di.PhyParent, di.Name);

+}

+

+UString CDirItems::GetLogPath(int index) const

+{

+  const CDirItem &di = Items[index];

+  return GetPrefixesPath(LogParents, di.LogParent, di.Name);

+}

+

+void CDirItems::ReserveDown()

+{

+  Prefixes.ReserveDown();

+  PhyParents.ReserveDown();

+  LogParents.ReserveDown();

+  Items.ReserveDown();

+}

+

+int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix)

+{

+  PhyParents.Add(phyParent);

+  LogParents.Add(logParent);

+  return Prefixes.Add(prefix);

+}

+

+void CDirItems::DeleteLastPrefix()

+{

+  PhyParents.DeleteBack();

+  LogParents.DeleteBack();

+  Prefixes.DeleteBack();

+}

+

+void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix,

+    UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes)

+{

+  NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard);

+  for (;;)

+  {

+    NFind::CFileInfoW fi;

+    bool found;

+    if (!enumerator.Next(fi, found))

+    {

+      errorCodes.Add(::GetLastError());

+      errorPaths.Add(phyPrefix);

+      return;

+    }

+    if (!found)

+      break;

+    AddDirFileInfo(phyParent, logParent, fi, Items);

+    if (fi.IsDir())

+    {

+      const UString name2 = fi.Name + (wchar_t)kDirDelimiter;

+      int parent = AddPrefix(phyParent, logParent, name2);

+      EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes);

+    }

+  }

+}

+

+void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix,

+    const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes)

+{

+  int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix);

+  int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix);

+

+  for (int i = 0; i < filePaths.Size(); i++)

+  {

+    const UString &filePath = filePaths[i];

+    NFind::CFileInfoW fi;

+    const UString phyPath = phyPrefix + filePath;

+    if (!fi.Find(phyPath))

+    {

+      errorCodes.Add(::GetLastError());

+      errorPaths.Add(phyPath);

+      continue;

+    }

+    int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter);

+    UString phyPrefixCur;

+    int phyParentCur = phyParent;

+    if (delimiter >= 0)

+    {

+      phyPrefixCur = filePath.Left(delimiter + 1);

+      phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur);

+    }

+    AddDirFileInfo(phyParentCur, logParent, fi, Items);

+    if (fi.IsDir())

+    {

+      const UString name2 = fi.Name + (wchar_t)kDirDelimiter;

+      int parent = AddPrefix(phyParentCur, logParent, name2);

+      EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes);

+    }

+  }

+  ReserveDown();

+}

+

+static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode,

+    int phyParent, int logParent, const UString &phyPrefix,

+    const UStringVector &addArchivePrefix,

+    CDirItems &dirItems,

+    bool enterToSubFolders,

+    IEnumDirItemCallback *callback,

+    UStringVector &errorPaths,

+    CRecordVector<DWORD> &errorCodes);

+

+static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode,

+    int phyParent, int logParent, const UString &curFolderName,

+    const UString &phyPrefix,

+    const UStringVector &addArchivePrefix,

+    CDirItems &dirItems,

+    bool enterToSubFolders,

+    IEnumDirItemCallback *callback,

+    UStringVector &errorPaths,

+    CRecordVector<DWORD> &errorCodes)

+  

+{

+  const UString name2 = curFolderName + (wchar_t)kDirDelimiter;

+  int parent = dirItems.AddPrefix(phyParent, logParent, name2);

+  int numItems = dirItems.Items.Size();

+  HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2,

+    addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes);

+  if (numItems == dirItems.Items.Size())

+    dirItems.DeleteLastPrefix();

+  return res;

+}

+

+

+static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode,

+    int phyParent, int logParent, const UString &phyPrefix,

+    const UStringVector &addArchivePrefix,  // prefix from curNode

+    CDirItems &dirItems,

+    bool enterToSubFolders,

+    IEnumDirItemCallback *callback,

+    UStringVector &errorPaths,

+    CRecordVector<DWORD> &errorCodes)

+{

+  if (!enterToSubFolders)

+    if (curNode.NeedCheckSubDirs())

+      enterToSubFolders = true;

+  if (callback)

+    RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix));

+

+  // try direct_names case at first

+  if (addArchivePrefix.IsEmpty() && !enterToSubFolders)

+  {

+    // check that all names are direct

+    int i;

+    for (i = 0; i < curNode.IncludeItems.Size(); i++)

+    {

+      const NWildcard::CItem &item = curNode.IncludeItems[i];

+      if (item.Recursive || item.PathParts.Size() != 1)

+        break;

+      const UString &name = item.PathParts.Front();

+      if (name.IsEmpty() || DoesNameContainWildCard(name))

+        break;

+    }

+    if (i == curNode.IncludeItems.Size())

+    {

+      // all names are direct (no wildcards)

+      // so we don't need file_system's dir enumerator

+      CRecordVector<bool> needEnterVector;

+      for (i = 0; i < curNode.IncludeItems.Size(); i++)

+      {

+        const NWildcard::CItem &item = curNode.IncludeItems[i];

+        const UString &name = item.PathParts.Front();

+        const UString fullPath = phyPrefix + name;

+        NFind::CFileInfoW fi;

+        if (!fi.Find(fullPath))

+        {

+          errorCodes.Add(::GetLastError());

+          errorPaths.Add(fullPath);

+          continue;

+        }

+        bool isDir = fi.IsDir();

+        if (isDir && !item.ForDir || !isDir && !item.ForFile)

+        {

+          errorCodes.Add((DWORD)E_FAIL);

+          errorPaths.Add(fullPath);

+          continue;

+        }

+        {

+          UStringVector pathParts;

+          pathParts.Add(fi.Name);

+          if (curNode.CheckPathToRoot(false, pathParts, !isDir))

+            continue;

+        }

+        AddDirFileInfo(phyParent, logParent, fi, dirItems.Items);

+        if (!isDir)

+          continue;

+        

+        UStringVector addArchivePrefixNew;

+        const NWildcard::CCensorNode *nextNode = 0;

+        int index = curNode.FindSubNode(name);

+        if (index >= 0)

+        {

+          for (int t = needEnterVector.Size(); t <= index; t++)

+            needEnterVector.Add(true);

+          needEnterVector[index] = false;

+          nextNode = &curNode.SubNodes[index];

+        }

+        else

+        {

+          nextNode = &curNode;

+          addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support

+        }

+

+        RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix,

+            addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes));

+      }

+      for (i = 0; i < curNode.SubNodes.Size(); i++)

+      {

+        if (i < needEnterVector.Size())

+          if (!needEnterVector[i])

+            continue;

+        const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];

+        const UString fullPath = phyPrefix + nextNode.Name;

+        NFind::CFileInfoW fi;

+        if (!fi.Find(fullPath))

+        {

+          if (!nextNode.AreThereIncludeItems())

+            continue;

+          errorCodes.Add(::GetLastError());

+          errorPaths.Add(fullPath);

+          continue;

+        }

+        if (!fi.IsDir())

+        {

+          errorCodes.Add((DWORD)E_FAIL);

+          errorPaths.Add(fullPath);

+          continue;

+        }

+

+        RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix,

+            UStringVector(), dirItems, false, callback, errorPaths, errorCodes));

+      }

+      return S_OK;

+    }

+  }

+

+

+  NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard));

+  for (int ttt = 0; ; ttt++)

+  {

+    NFind::CFileInfoW fi;

+    bool found;

+    if (!enumerator.Next(fi, found))

+    {

+      errorCodes.Add(::GetLastError());

+      errorPaths.Add(phyPrefix);

+      break;

+    }

+    if (!found)

+      break;

+

+    if (callback && (ttt & 0xFF) == 0xFF)

+      RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix));

+    const UString &name = fi.Name;

+    bool enterToSubFolders2 = enterToSubFolders;

+    UStringVector addArchivePrefixNew = addArchivePrefix;

+    addArchivePrefixNew.Add(name);

+    {

+      UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);

+      if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir()))

+        continue;

+    }

+    if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir()))

+    {

+      AddDirFileInfo(phyParent, logParent, fi, dirItems.Items);

+      if (fi.IsDir())

+        enterToSubFolders2 = true;

+    }

+    if (!fi.IsDir())

+      continue;

+

+    const NWildcard::CCensorNode *nextNode = 0;

+    if (addArchivePrefix.IsEmpty())

+    {

+      int index = curNode.FindSubNode(name);

+      if (index >= 0)

+        nextNode = &curNode.SubNodes[index];

+    }

+    if (!enterToSubFolders2 && nextNode == 0)

+      continue;

+

+    addArchivePrefixNew = addArchivePrefix;

+    if (nextNode == 0)

+    {

+      nextNode = &curNode;

+      addArchivePrefixNew.Add(name);

+    }

+

+    RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix,

+        addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes));

+  }

+  return S_OK;

+}

+

+HRESULT EnumerateItems(

+    const NWildcard::CCensor &censor,

+    CDirItems &dirItems,

+    IEnumDirItemCallback *callback,

+    UStringVector &errorPaths,

+    CRecordVector<DWORD> &errorCodes)

+{

+  for (int i = 0; i < censor.Pairs.Size(); i++)

+  {

+    const NWildcard::CPair &pair = censor.Pairs[i];

+    int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix);

+    RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false,

+        callback, errorPaths, errorCodes));

+  }

+  dirItems.ReserveDown();

+  return S_OK;

+}

diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h
new file mode 100755
index 0000000..835ae02
--- /dev/null
+++ b/CPP/7zip/UI/Common/EnumDirItems.h
@@ -0,0 +1,25 @@
+// EnumDirItems.h

+

+#ifndef __ENUM_DIR_ITEMS_H

+#define __ENUM_DIR_ITEMS_H

+

+#include "Common/Wildcard.h"

+#include "Windows/FileFind.h"

+#include "DirItem.h"

+

+void AddDirFileInfo(int phyParent, int logParent,

+    const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems);

+

+struct IEnumDirItemCallback

+{

+  virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) = 0;

+};

+

+HRESULT EnumerateItems(

+    const NWildcard::CCensor &censor,

+    CDirItems &dirItems,

+    IEnumDirItemCallback *callback,

+    UStringVector &errorPaths,

+    CRecordVector<DWORD> &errorCodes);

+

+#endif

diff --git a/CPP/7zip/UI/Common/ExitCode.h b/CPP/7zip/UI/Common/ExitCode.h
new file mode 100755
index 0000000..d03ec6d
--- /dev/null
+++ b/CPP/7zip/UI/Common/ExitCode.h
@@ -0,0 +1,27 @@
+// ExitCode.h

+

+#ifndef __EXIT_CODE_H

+#define __EXIT_CODE_H

+

+namespace NExitCode {

+

+enum EEnum {

+

+  kSuccess       = 0,     // Successful operation

+  kWarning       = 1,     // Non fatal error(s) occurred

+  kFatalError    = 2,     // A fatal error occurred

+  // kCRCError      = 3,     // A CRC error occurred when unpacking

+  // kLockedArchive = 4,     // Attempt to modify an archive previously locked

+  // kWriteError    = 5,     // Write to disk error

+  // kOpenError     = 6,     // Open file error

+  kUserError     = 7,     // Command line option error

+  kMemoryError   = 8,     // Not enough memory for operation

+  // kCreateFileError = 9,     // Create file error

+  

+  kUserBreak     = 255   // User stopped the process

+

+};

+

+}

+

+#endif

diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp
new file mode 100755
index 0000000..2f5a293
--- /dev/null
+++ b/CPP/7zip/UI/Common/Extract.cpp
@@ -0,0 +1,263 @@
+// Extract.cpp

+

+#include "StdAfx.h"

+

+#include <stdio.h>

+

+#include "Windows/FileDir.h"

+#include "Windows/PropVariant.h"

+#include "Windows/PropVariantConversions.h"

+

+#include "../Common/ExtractingFilePath.h"

+

+#include "Extract.h"

+#include "SetProperties.h"

+

+using namespace NWindows;

+

+static HRESULT DecompressArchive(

+    const CArc &arc,

+    UInt64 packSize,

+    const NWildcard::CCensorNode &wildcardCensor,

+    const CExtractOptions &options,

+    IExtractCallbackUI *callback,

+    CArchiveExtractCallback *extractCallbackSpec,

+    UString &errorMessage,

+    UInt64 &stdInProcessed)

+{

+  stdInProcessed = 0;

+  IInArchive *archive = arc.Archive;

+  CRecordVector<UInt32> realIndices;

+  if (!options.StdInMode)

+  {

+    UInt32 numItems;

+    RINOK(archive->GetNumberOfItems(&numItems));

+    

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

+    {

+      UString filePath;

+      RINOK(arc.GetItemPath(i, filePath));

+      bool isFolder;

+      RINOK(IsArchiveItemFolder(archive, i, isFolder));

+      if (!wildcardCensor.CheckPath(filePath, !isFolder))

+        continue;

+      realIndices.Add(i);

+    }

+    if (realIndices.Size() == 0)

+    {

+      callback->ThereAreNoFiles();

+      return S_OK;

+    }

+  }

+

+  UStringVector removePathParts;

+

+  UString outDir = options.OutputDir;

+  outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName));

+  #ifdef _WIN32

+  // GetCorrectFullFsPath doesn't like "..".

+  // outDir.TrimRight();

+  // outDir = GetCorrectFullFsPath(outDir);

+  #endif

+

+  if (!outDir.IsEmpty())

+    if (!NFile::NDirectory::CreateComplexDirectory(outDir))

+    {

+      HRESULT res = ::GetLastError();

+      if (res == S_OK)

+        res = E_FAIL;

+      errorMessage = ((UString)L"Can not create output directory ") + outDir;

+      return res;

+    }

+

+  extractCallbackSpec->Init(

+      options.StdInMode ? &wildcardCensor : NULL,

+      &arc,

+      callback,

+      options.StdOutMode, options.TestMode, options.CalcCrc,

+      outDir,

+      removePathParts,

+      packSize);

+

+  #if !defined(_7ZIP_ST) && !defined(_SFX)

+  RINOK(SetProperties(archive, options.Properties));

+  #endif

+

+  HRESULT result;

+  Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0;

+  if (options.StdInMode)

+  {

+    result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec);

+    NCOM::CPropVariant prop;

+    if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)

+      if (prop.vt == VT_UI8 || prop.vt == VT_UI4)

+        stdInProcessed = ConvertPropVariantToUInt64(prop);

+  }

+  else

+    result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec);

+

+  return callback->ExtractResult(result);

+}

+

+HRESULT DecompressArchives(

+    CCodecs *codecs, const CIntVector &formatIndices,

+    UStringVector &arcPaths, UStringVector &arcPathsFull,

+    const NWildcard::CCensorNode &wildcardCensor,

+    const CExtractOptions &options,

+    IOpenCallbackUI *openCallback,

+    IExtractCallbackUI *extractCallback,

+    UString &errorMessage,

+    CDecompressStat &stat)

+{

+  stat.Clear();

+  int i;

+  UInt64 totalPackSize = 0;

+  CRecordVector<UInt64> archiveSizes;

+

+  int numArcs = options.StdInMode ? 1 : arcPaths.Size();

+

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

+  {

+    NFile::NFind::CFileInfoW fi;

+    fi.Size = 0;

+    if (!options.StdInMode)

+    {

+      const UString &arcPath = arcPaths[i];

+      if (!fi.Find(arcPath))

+        throw "there is no such archive";

+      if (fi.IsDir())

+        throw "can't decompress folder";

+    }

+    archiveSizes.Add(fi.Size);

+    totalPackSize += fi.Size;

+  }

+  CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;

+  CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec);

+  bool multi = (numArcs > 1);

+  extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode);

+  if (multi)

+  {

+    RINOK(extractCallback->SetTotal(totalPackSize));

+  }

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

+  {

+    const UString &arcPath = arcPaths[i];

+    NFile::NFind::CFileInfoW fi;

+    if (options.StdInMode)

+    {

+      fi.Size = 0;

+      fi.Attrib = 0;

+    }

+    else

+    {

+      if (!fi.Find(arcPath) || fi.IsDir())

+        throw "there is no such archive";

+    }

+

+    #ifndef _NO_CRYPTO

+    openCallback->Open_ClearPasswordWasAskedFlag();

+    #endif

+

+    RINOK(extractCallback->BeforeOpen(arcPath));

+    CArchiveLink archiveLink;

+

+    CIntVector formatIndices2 = formatIndices;

+    #ifndef _SFX

+    if (formatIndices.IsEmpty())

+    {

+      int pos = arcPath.ReverseFind(L'.');

+      if (pos >= 0)

+      {

+        UString s = arcPath.Mid(pos + 1);

+        int index = codecs->FindFormatForExtension(s);

+        if (index >= 0 && s == L"001")

+        {

+          s = arcPath.Left(pos);

+          pos = s.ReverseFind(L'.');

+          if (pos >= 0)

+          {

+            int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1));

+            if (index2 >= 0 && s.CompareNoCase(L"rar") != 0)

+            {

+              formatIndices2.Add(index2);

+              formatIndices2.Add(index);

+            }

+          }

+        }

+      }

+    }

+    #endif

+    HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback);

+    if (result == E_ABORT)

+      return result;

+

+    bool crypted = false;

+    #ifndef _NO_CRYPTO

+    crypted = openCallback->Open_WasPasswordAsked();

+    #endif

+

+    RINOK(extractCallback->OpenResult(arcPath, result, crypted));

+    if (result != S_OK)

+      continue;

+

+    if (!options.StdInMode)

+    for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)

+    {

+      int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);

+      if (index >= 0 && index > i)

+      {

+        arcPaths.Delete(index);

+        arcPathsFull.Delete(index);

+        totalPackSize -= archiveSizes[index];

+        archiveSizes.Delete(index);

+        numArcs = arcPaths.Size();

+      }

+    }

+    if (archiveLink.VolumePaths.Size() != 0)

+    {

+      totalPackSize += archiveLink.VolumesSize;

+      RINOK(extractCallback->SetTotal(totalPackSize));

+    }

+

+    #ifndef _NO_CRYPTO

+    UString password;

+    RINOK(openCallback->Open_GetPasswordIfAny(password));

+    if (!password.IsEmpty())

+    {

+      RINOK(extractCallback->SetPassword(password));

+    }

+    #endif

+

+    for (int v = 0; v < archiveLink.Arcs.Size(); v++)

+    {

+      const UString &s = archiveLink.Arcs[v].ErrorMessage;

+      if (!s.IsEmpty())

+      {

+        RINOK(extractCallback->MessageError(s));

+      }

+    }

+

+    CArc &arc = archiveLink.Arcs.Back();

+    arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);

+    arc.MTime = fi.MTime;

+

+    UInt64 packProcessed;

+    RINOK(DecompressArchive(arc,

+        fi.Size + archiveLink.VolumesSize,

+        wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed));

+    if (!options.StdInMode)

+      packProcessed = fi.Size + archiveLink.VolumesSize;

+    extractCallbackSpec->LocalProgressSpec->InSize += packProcessed;

+    extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize;

+    if (!errorMessage.IsEmpty())

+      return E_FAIL;

+  }

+  stat.NumFolders = extractCallbackSpec->NumFolders;

+  stat.NumFiles = extractCallbackSpec->NumFiles;

+  stat.UnpackSize = extractCallbackSpec->UnpackSize;

+  stat.CrcSum = extractCallbackSpec->CrcSum;

+

+  stat.NumArchives = arcPaths.Size();

+  stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize;

+  return S_OK;

+}

diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h
new file mode 100755
index 0000000..70926d7
--- /dev/null
+++ b/CPP/7zip/UI/Common/Extract.h
@@ -0,0 +1,76 @@
+// Extract.h

+

+#ifndef __EXTRACT_H

+#define __EXTRACT_H

+

+#include "Windows/FileFind.h"

+

+#include "../../Archive/IArchive.h"

+

+#include "ArchiveExtractCallback.h"

+#include "ArchiveOpenCallback.h"

+#include "ExtractMode.h"

+#include "Property.h"

+

+#include "../Common/LoadCodecs.h"

+

+struct CExtractOptions

+{

+  bool StdInMode;

+  bool StdOutMode;

+  bool YesToAll;

+  bool TestMode;

+  bool CalcCrc;

+  NExtract::NPathMode::EEnum PathMode;

+  NExtract::NOverwriteMode::EEnum OverwriteMode;

+  UString OutputDir;

+  

+  // bool ShowDialog;

+  // bool PasswordEnabled;

+  // UString Password;

+  #if !defined(_7ZIP_ST) && !defined(_SFX)

+  CObjectVector<CProperty> Properties;

+  #endif

+

+  #ifdef EXTERNAL_CODECS

+  CCodecs *Codecs;

+  #endif

+

+  CExtractOptions():

+      StdInMode(false),

+      StdOutMode(false),

+      YesToAll(false),

+      TestMode(false),

+      CalcCrc(false),

+      PathMode(NExtract::NPathMode::kFullPathnames),

+      OverwriteMode(NExtract::NOverwriteMode::kAskBefore)

+      {}

+};

+

+struct CDecompressStat

+{

+  UInt64 NumArchives;

+  UInt64 UnpackSize;

+  UInt64 PackSize;

+  UInt64 NumFolders;

+  UInt64 NumFiles;

+  UInt32 CrcSum;

+

+  void Clear()

+  {

+    NumArchives = UnpackSize = PackSize = NumFolders = NumFiles = 0;

+    CrcSum = 0;

+  }

+};

+

+HRESULT DecompressArchives(

+    CCodecs *codecs, const CIntVector &formatIndices,

+    UStringVector &archivePaths, UStringVector &archivePathsFull,

+    const NWildcard::CCensorNode &wildcardCensor,

+    const CExtractOptions &options,

+    IOpenCallbackUI *openCallback,

+    IExtractCallbackUI *extractCallback,

+    UString &errorMessage,

+    CDecompressStat &stat);

+

+#endif

diff --git a/CPP/7zip/UI/Common/ExtractMode.h b/CPP/7zip/UI/Common/ExtractMode.h
new file mode 100755
index 0000000..44c4053
--- /dev/null
+++ b/CPP/7zip/UI/Common/ExtractMode.h
@@ -0,0 +1,31 @@
+// ExtractMode.h

+

+#ifndef __EXTRACT_MODE_H

+#define __EXTRACT_MODE_H

+

+namespace NExtract {

+  

+  namespace NPathMode

+  {

+    enum EEnum

+    {

+      kFullPathnames,

+      kCurrentPathnames,

+      kNoPathnames

+    };

+  }

+  

+  namespace NOverwriteMode

+  {

+    enum EEnum

+    {

+      kAskBefore,

+      kWithoutPrompt,

+      kSkipExisting,

+      kAutoRename,

+      kAutoRenameExisting

+    };

+  }

+}

+

+#endif

diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
new file mode 100755
index 0000000..604148a
--- /dev/null
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
@@ -0,0 +1,142 @@
+// ExtractingFilePath.cpp

+

+#include "StdAfx.h"

+

+#include "../../../../C/Types.h"

+

+#include "Common/Wildcard.h"

+

+#include "ExtractingFilePath.h"

+

+static UString ReplaceIncorrectChars(const UString &s)

+{

+  #ifdef _WIN32

+  UString res;

+  for (int i = 0; i < s.Length(); i++)

+  {

+    wchar_t c = s[i];

+    if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>'  || c == '|' || c == ':' || c == '"')

+      c = '_';

+    res += c;

+  }

+  res.TrimRight();

+  while (!res.IsEmpty() && res[res.Length() - 1] == '.')

+    res.Delete(res.Length() - 1);

+  return res;

+  #else

+  return s;

+  #endif

+}

+

+#ifdef _WIN32

+static const wchar_t *g_ReservedNames[] =

+{

+  L"CON", L"PRN", L"AUX", L"NUL"

+};

+

+static bool CheckTail(const UString &name, int len)

+{

+  int dotPos = name.Find(L'.');

+  if (dotPos < 0)

+    dotPos = name.Length();

+  UString s = name.Left(dotPos);

+  s.TrimRight();

+  return (s.Length() != len);

+}

+

+static bool CheckNameNum(const UString &name, const wchar_t *reservedName)

+{

+  int len = MyStringLen(reservedName);

+  if (name.Length() <= len)

+    return true;

+  if (name.Left(len).CompareNoCase(reservedName) != 0)

+    return true;

+  wchar_t c = name[len];

+  if (c < L'0' || c > L'9')

+    return true;

+  return CheckTail(name, len + 1);

+}

+

+static bool IsSupportedName(const UString &name)

+{

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

+  {

+    const wchar_t *reservedName = g_ReservedNames[i];

+    int len = MyStringLen(reservedName);

+    if (name.Length() < len)

+      continue;

+    if (name.Left(len).CompareNoCase(reservedName) != 0)

+      continue;

+    if (!CheckTail(name, len))

+      return false;

+  }

+  if (!CheckNameNum(name, L"COM"))

+    return false;

+  return CheckNameNum(name, L"LPT");

+}

+#endif

+

+static UString GetCorrectFileName(const UString &path)

+{

+  if (path == L".." || path == L".")

+    return UString();

+  return ReplaceIncorrectChars(path);

+}

+

+void MakeCorrectPath(UStringVector &pathParts)

+{

+  for (int i = 0; i < pathParts.Size();)

+  {

+    UString &s = pathParts[i];

+    s = GetCorrectFileName(s);

+    if (s.IsEmpty())

+      pathParts.Delete(i);

+    else

+    {

+      #ifdef _WIN32

+      if (!IsSupportedName(s))

+        s = (UString)L"_" + s;

+      #endif

+      i++;

+    }

+  }

+}

+

+UString MakePathNameFromParts(const UStringVector &parts)

+{

+  UString result;

+  for (int i = 0; i < parts.Size(); i++)

+  {

+    if (i != 0)

+      result += WCHAR_PATH_SEPARATOR;

+    result += parts[i];

+  }

+  return result;

+}

+

+UString GetCorrectFsPath(const UString &path)

+{

+  UString res = GetCorrectFileName(path);

+  #ifdef _WIN32

+  if (!IsSupportedName(res))

+    res = (UString)L"_" + res;

+  #endif

+  return res;

+}

+  

+UString GetCorrectFullFsPath(const UString &path)

+{

+  UStringVector parts;

+  SplitPathToParts(path, parts);

+  for (int i = 0; i < parts.Size(); i++)

+  {

+    UString &s = parts[i];

+    #ifdef _WIN32

+    while (!s.IsEmpty() && s[s.Length() - 1] == '.')

+      s.Delete(s.Length() - 1);

+    if (!IsSupportedName(s))

+      s = (UString)L"_" + s;

+    #endif

+  }

+  return MakePathNameFromParts(parts);

+}

diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h
new file mode 100755
index 0000000..54bdc72
--- /dev/null
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.h
@@ -0,0 +1,13 @@
+// ExtractingFilePath.h

+

+#ifndef __EXTRACTING_FILE_PATH_H

+#define __EXTRACTING_FILE_PATH_H

+

+#include "Common/MyString.h"

+

+UString MakePathNameFromParts(const UStringVector &parts);

+void MakeCorrectPath(UStringVector &pathParts);

+UString GetCorrectFsPath(const UString &path);

+UString GetCorrectFullFsPath(const UString &path);

+

+#endif

diff --git a/CPP/7zip/UI/Common/IFileExtractCallback.h b/CPP/7zip/UI/Common/IFileExtractCallback.h
new file mode 100755
index 0000000..5aff92f
--- /dev/null
+++ b/CPP/7zip/UI/Common/IFileExtractCallback.h
@@ -0,0 +1,46 @@
+// IFileExtractCallback.h

+

+#ifndef __IFILEEXTRACTCALLBACK_H

+#define __IFILEEXTRACTCALLBACK_H

+

+#include "Common/MyString.h"

+#include "../../IDecl.h"

+

+namespace NOverwriteAnswer

+{

+  enum EEnum

+  {

+    kYes,

+    kYesToAll,

+    kNo,

+    kNoToAll,

+    kAutoRename,

+    kCancel

+  };

+}

+

+DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07)

+{

+public:

+  STDMETHOD(AskOverwrite)(

+      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,

+      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,

+      Int32 *answer) PURE;

+  STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE;

+  STDMETHOD(MessageError)(const wchar_t *message) PURE;

+  STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE;

+};

+

+struct IExtractCallbackUI: IFolderArchiveExtractCallback

+{

+  virtual HRESULT BeforeOpen(const wchar_t *name) = 0;

+  virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0;

+  virtual HRESULT ThereAreNoFiles() = 0;

+  virtual HRESULT ExtractResult(HRESULT result) = 0;

+

+  #ifndef _NO_CRYPTO

+  virtual HRESULT SetPassword(const UString &password) = 0;

+  #endif

+};

+

+#endif

diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
new file mode 100755
index 0000000..67a0cc7
--- /dev/null
+++ b/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -0,0 +1,681 @@
+// LoadCodecs.cpp

+

+#include "StdAfx.h"

+

+#include "LoadCodecs.h"

+

+#include "../../../Common/MyCom.h"

+#ifdef NEW_FOLDER_INTERFACE

+#include "../../../Common/StringToInt.h"

+#endif

+#include "../../../Windows/PropVariant.h"

+

+#include "../../ICoder.h"

+#include "../../Common/RegisterArc.h"

+

+#ifdef EXTERNAL_CODECS

+#include "../../../Windows/FileFind.h"

+#include "../../../Windows/DLL.h"

+#ifdef NEW_FOLDER_INTERFACE

+#include "../../../Windows/ResourceString.h"

+static const UINT kIconTypesResId = 100;

+#endif

+

+#ifdef _WIN32

+#include "Windows/Registry.h"

+#endif

+

+using namespace NWindows;

+using namespace NFile;

+

+#ifdef _WIN32

+extern HINSTANCE g_hInstance;

+#endif

+

+static CSysString GetLibraryFolderPrefix()

+{

+  #ifdef _WIN32

+  TCHAR fullPath[MAX_PATH + 1];

+  ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);

+  CSysString path = fullPath;

+  int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));

+  return path.Left(pos + 1);

+  #else

+  return CSysString(); // FIX IT

+  #endif

+}

+

+#define kCodecsFolderName TEXT("Codecs")

+#define kFormatsFolderName TEXT("Formats")

+static const TCHAR *kMainDll = TEXT("7z.dll");

+

+#ifdef _WIN32

+static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");

+static LPCTSTR kProgramPathValue = TEXT("Path");

+static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path)

+{

+  NRegistry::CKey key;

+  if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)

+    if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS)

+    {

+      NName::NormalizeDirPathPrefix(path);

+      return true;

+    }

+  return false;

+}

+

+#endif

+

+CSysString GetBaseFolderPrefixFromRegistry()

+{

+  CSysString moduleFolderPrefix = GetLibraryFolderPrefix();

+  #ifdef _WIN32

+  if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) &&

+      !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) &&

+      !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName))

+  {

+    CSysString path;

+    if (ReadPathFromRegistry(HKEY_CURRENT_USER, path))

+      return path;

+    if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path))

+      return path;

+  }

+  #endif

+  return moduleFolderPrefix;

+}

+

+typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods);

+typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats);

+typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value);

+typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value);

+typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject);

+typedef UInt32 (WINAPI *SetLargePageModeFunc)();

+

+

+static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index,

+    PROPID propId, CLSID &clsId, bool &isAssigned)

+{

+  NWindows::NCOM::CPropVariant prop;

+  isAssigned = false;

+  RINOK(getMethodProperty(index, propId, &prop));

+  if (prop.vt == VT_BSTR)

+  {

+    isAssigned = true;

+    clsId = *(const GUID *)prop.bstrVal;

+  }

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+HRESULT CCodecs::LoadCodecs()

+{

+  CCodecLib &lib = Libs.Back();

+  lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProc("GetMethodProperty");

+  if (lib.GetMethodProperty == NULL)

+    return S_OK;

+

+  UInt32 numMethods = 1;

+  GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProc("GetNumberOfMethods");

+  if (getNumberOfMethodsFunc != NULL)

+  {

+    RINOK(getNumberOfMethodsFunc(&numMethods));

+  }

+

+  for(UInt32 i = 0; i < numMethods; i++)

+  {

+    CDllCodecInfo info;

+    info.LibIndex = Libs.Size() - 1;

+    info.CodecIndex = i;

+

+    RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));

+    RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));

+

+    Codecs.Add(info);

+  }

+  return S_OK;

+}

+

+static HRESULT ReadProp(

+    GetHandlerPropertyFunc getProp,

+    GetHandlerPropertyFunc2 getProp2,

+    UInt32 index, PROPID propID, NCOM::CPropVariant &prop)

+{

+  if (getProp2)

+    return getProp2(index, propID, &prop);;

+  return getProp(propID, &prop);

+}

+

+static HRESULT ReadBoolProp(

+    GetHandlerPropertyFunc getProp,

+    GetHandlerPropertyFunc2 getProp2,

+    UInt32 index, PROPID propID, bool &res)

+{

+  NCOM::CPropVariant prop;

+  RINOK(ReadProp(getProp, getProp2, index, propID, prop));

+  if (prop.vt == VT_BOOL)

+    res = VARIANT_BOOLToBool(prop.boolVal);

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+static HRESULT ReadStringProp(

+    GetHandlerPropertyFunc getProp,

+    GetHandlerPropertyFunc2 getProp2,

+    UInt32 index, PROPID propID, UString &res)

+{

+  NCOM::CPropVariant prop;

+  RINOK(ReadProp(getProp, getProp2, index, propID, prop));

+  if (prop.vt == VT_BSTR)

+    res = prop.bstrVal;

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+#endif

+

+static const unsigned int kNumArcsMax = 48;

+static unsigned int g_NumArcs = 0;

+static const CArcInfo *g_Arcs[kNumArcsMax];

+void RegisterArc(const CArcInfo *arcInfo)

+{

+  if (g_NumArcs < kNumArcsMax)

+    g_Arcs[g_NumArcs++] = arcInfo;

+}

+

+static void SplitString(const UString &srcString, UStringVector &destStrings)

+{

+  destStrings.Clear();

+  UString s;

+  int len = srcString.Length();

+  if (len == 0)

+    return;

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

+  {

+    wchar_t c = srcString[i];

+    if (c == L' ')

+    {

+      if (!s.IsEmpty())

+      {

+        destStrings.Add(s);

+        s.Empty();

+      }

+    }

+    else

+      s += c;

+  }

+  if (!s.IsEmpty())

+    destStrings.Add(s);

+}

+

+void CArcInfoEx::AddExts(const wchar_t *ext, const wchar_t *addExt)

+{

+  UStringVector exts, addExts;

+  if (ext != 0)

+    SplitString(ext, exts);

+  if (addExt != 0)

+    SplitString(addExt, addExts);

+  for (int i = 0; i < exts.Size(); i++)

+  {

+    CArcExtInfo extInfo;

+    extInfo.Ext = exts[i];

+    if (i < addExts.Size())

+    {

+      extInfo.AddExt = addExts[i];

+      if (extInfo.AddExt == L"*")

+        extInfo.AddExt.Empty();

+    }

+    Exts.Add(extInfo);

+  }

+}

+

+#ifdef EXTERNAL_CODECS

+

+HRESULT CCodecs::LoadFormats()

+{

+  const NDLL::CLibrary &lib = Libs.Back().Lib;

+  GetHandlerPropertyFunc getProp = 0;

+  GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)lib.GetProc("GetHandlerProperty2");

+  if (getProp2 == NULL)

+  {

+    getProp = (GetHandlerPropertyFunc)lib.GetProc("GetHandlerProperty");

+    if (getProp == NULL)

+      return S_OK;

+  }

+

+  UInt32 numFormats = 1;

+  GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)lib.GetProc("GetNumberOfFormats");

+  if (getNumberOfFormats != NULL)

+  {

+    RINOK(getNumberOfFormats(&numFormats));

+  }

+  if (getProp2 == NULL)

+    numFormats = 1;

+

+  for(UInt32 i = 0; i < numFormats; i++)

+  {

+    CArcInfoEx item;

+    item.LibIndex = Libs.Size() - 1;

+    item.FormatIndex = i;

+

+    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name));

+

+    NCOM::CPropVariant prop;

+    if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK)

+      continue;

+    if (prop.vt != VT_BSTR)

+      continue;

+    item.ClassID = *(const GUID *)prop.bstrVal;

+    prop.Clear();

+

+    UString ext, addExt;

+    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext));

+    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt));

+    item.AddExts(ext, addExt);

+

+    ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled);

+    if (item.UpdateEnabled)

+      ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName);

+    

+    if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK)

+      if (prop.vt == VT_BSTR)

+      {

+        UINT len = ::SysStringByteLen(prop.bstrVal);

+        item.StartSignature.SetCapacity(len);

+        memmove(item.StartSignature, prop.bstrVal, len);

+      }

+    Formats.Add(item);

+  }

+  return S_OK;

+}

+

+#ifdef NEW_FOLDER_INTERFACE

+void CCodecIcons::LoadIcons(HMODULE m)

+{

+  UString iconTypes = MyLoadStringW(m, kIconTypesResId);

+  UStringVector pairs;

+  SplitString(iconTypes, pairs);

+  for (int i = 0; i < pairs.Size(); i++)

+  {

+    const UString &s = pairs[i];

+    int pos = s.Find(L':');

+    CIconPair iconPair;

+    iconPair.IconIndex = -1;

+    if (pos < 0)

+      pos = s.Length();

+    else

+    {

+      UString num = s.Mid(pos + 1);

+      if (!num.IsEmpty())

+      {

+        const wchar_t *end;

+        iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end);

+        if (*end != L'\0')

+          continue;

+      }

+    }

+    iconPair.Ext = s.Left(pos);

+    IconPairs.Add(iconPair);

+  }

+}

+

+bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const

+{

+  iconIndex = -1;

+  for (int i = 0; i < IconPairs.Size(); i++)

+  {

+    const CIconPair &pair = IconPairs[i];

+    if (ext.CompareNoCase(pair.Ext) == 0)

+    {

+      iconIndex = pair.IconIndex;

+      return true;

+    }

+  }

+  return false;

+}

+#endif

+

+#ifdef _7ZIP_LARGE_PAGES

+extern "C"

+{

+  extern SIZE_T g_LargePageSize;

+}

+#endif

+

+HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll)

+{

+  if (needCheckDll)

+  {

+    NDLL::CLibrary library;

+    if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))

+      return S_OK;

+  }

+  Libs.Add(CCodecLib());

+  CCodecLib &lib = Libs.Back();

+  #ifdef NEW_FOLDER_INTERFACE

+  lib.Path = dllPath;

+  #endif

+  bool used = false;

+  HRESULT res = S_OK;

+  if (lib.Lib.Load(dllPath))

+  {

+    #ifdef NEW_FOLDER_INTERFACE

+    lib.LoadIcons();

+    #endif

+

+    #ifdef _7ZIP_LARGE_PAGES

+    if (g_LargePageSize != 0)

+    {

+      SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProc("SetLargePageMode");

+      if (setLargePageMode != 0)

+        setLargePageMode();

+    }

+    #endif

+

+    lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProc("CreateObject");

+    if (lib.CreateObject != 0)

+    {

+      int startSize = Codecs.Size();

+      res = LoadCodecs();

+      used = (Codecs.Size() != startSize);

+      if (res == S_OK)

+      {

+        startSize = Formats.Size();

+        res = LoadFormats();

+        used = used || (Formats.Size() != startSize);

+      }

+    }

+  }

+  if (!used)

+    Libs.DeleteBack();

+  return res;

+}

+

+HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix)

+{

+  NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*")));

+  NFile::NFind::CFileInfo fi;

+  while (enumerator.Next(fi))

+  {

+    if (fi.IsDir())

+      continue;

+    RINOK(LoadDll(folderPrefix + fi.Name, true));

+  }

+  return S_OK;

+}

+

+#endif

+

+#ifndef _SFX

+static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size)

+{

+  bb.SetCapacity(size);

+  memmove((Byte *)bb, data, size);

+}

+#endif

+

+HRESULT CCodecs::Load()

+{

+  #ifdef NEW_FOLDER_INTERFACE

+  InternalIcons.LoadIcons(g_hInstance);

+  #endif

+

+  Formats.Clear();

+  #ifdef EXTERNAL_CODECS

+  Codecs.Clear();

+  #endif

+  for (UInt32 i = 0; i < g_NumArcs; i++)

+  {

+    const CArcInfo &arc = *g_Arcs[i];

+    CArcInfoEx item;

+    item.Name = arc.Name;

+    item.CreateInArchive = arc.CreateInArchive;

+    item.CreateOutArchive = arc.CreateOutArchive;

+    item.AddExts(arc.Ext, arc.AddExt);

+    item.UpdateEnabled = (arc.CreateOutArchive != 0);

+    item.KeepName = arc.KeepName;

+

+    #ifndef _SFX

+    SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize);

+    #endif

+    Formats.Add(item);

+  }

+  #ifdef EXTERNAL_CODECS

+  const CSysString baseFolder = GetBaseFolderPrefixFromRegistry();

+  RINOK(LoadDll(baseFolder + kMainDll, false));

+  RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR)));

+  RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR)));

+  #endif

+  return S_OK;

+}

+

+#ifndef _SFX

+

+int CCodecs::FindFormatForArchiveName(const UString &arcPath) const

+{

+  int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR);

+  int slashPos2 = arcPath.ReverseFind(L'.');

+  int dotPos = arcPath.ReverseFind(L'.');

+  if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2)

+    return -1;

+  UString ext = arcPath.Mid(dotPos + 1);

+  for (int i = 0; i < Formats.Size(); i++)

+  {

+    const CArcInfoEx &arc = Formats[i];

+    if (!arc.UpdateEnabled)

+      continue;

+    if (arc.FindExtension(ext) >= 0)

+      return i;

+  }

+  return -1;

+}

+

+int CCodecs::FindFormatForExtension(const UString &ext) const

+{

+  if (ext.IsEmpty())

+    return -1;

+  for (int i = 0; i < Formats.Size(); i++)

+    if (Formats[i].FindExtension(ext) >= 0)

+      return i;

+  return -1;

+}

+

+int CCodecs::FindFormatForArchiveType(const UString &arcType) const

+{

+  for (int i = 0; i < Formats.Size(); i++)

+    if (Formats[i].Name.CompareNoCase(arcType) == 0)

+      return i;

+  return -1;

+}

+

+bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const

+{

+  formatIndices.Clear();

+  for (int pos = 0; pos < arcType.Length();)

+  {

+    int pos2 = arcType.Find('.', pos);

+    if (pos2 < 0)

+      pos2 = arcType.Length();

+    const UString name = arcType.Mid(pos, pos2 - pos);

+    int index = FindFormatForArchiveType(name);

+    if (index < 0 && name != L"*")

+    {

+      formatIndices.Clear();

+      return false;

+    }

+    formatIndices.Add(index);

+    pos = pos2 + 1;

+  }

+  return true;

+}

+

+#endif

+

+#ifdef EXTERNAL_CODECS

+

+#ifdef EXPORT_CODECS

+extern unsigned int g_NumCodecs;

+STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject);

+STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);

+// STDAPI GetNumberOfMethods(UInt32 *numCodecs);

+#endif

+

+STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods)

+{

+  *numMethods =

+      #ifdef EXPORT_CODECS

+      g_NumCodecs +

+      #endif

+      Codecs.Size();

+  return S_OK;

+}

+

+STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)

+{

+  #ifdef EXPORT_CODECS

+  if (index < g_NumCodecs)

+    return GetMethodProperty(index, propID, value);

+  #endif

+

+  const CDllCodecInfo &ci = Codecs[index

+      #ifdef EXPORT_CODECS

+      - g_NumCodecs

+      #endif

+      ];

+

+  if (propID == NMethodPropID::kDecoderIsAssigned)

+  {

+    NWindows::NCOM::CPropVariant propVariant;

+    propVariant = ci.DecoderIsAssigned;

+    propVariant.Detach(value);

+    return S_OK;

+  }

+  if (propID == NMethodPropID::kEncoderIsAssigned)

+  {

+    NWindows::NCOM::CPropVariant propVariant;

+    propVariant = ci.EncoderIsAssigned;

+    propVariant.Detach(value);

+    return S_OK;

+  }

+  return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value);

+}

+

+STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)

+{

+  #ifdef EXPORT_CODECS

+  if (index < g_NumCodecs)

+    return CreateCoder2(false, index, iid, coder);

+  #endif

+  const CDllCodecInfo &ci = Codecs[index

+      #ifdef EXPORT_CODECS

+      - g_NumCodecs

+      #endif

+      ];

+  if (ci.DecoderIsAssigned)

+    return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder);

+  return S_OK;

+}

+

+STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)

+{

+  #ifdef EXPORT_CODECS

+  if (index < g_NumCodecs)

+    return CreateCoder2(true, index, iid, coder);

+  #endif

+  const CDllCodecInfo &ci = Codecs[index

+      #ifdef EXPORT_CODECS

+      - g_NumCodecs

+      #endif

+      ];

+  if (ci.EncoderIsAssigned)

+    return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder);

+  return S_OK;

+}

+

+HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const

+{

+  for (int i = 0; i < Codecs.Size(); i++)

+  {

+    const CDllCodecInfo &codec = Codecs[i];

+    if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned)

+      continue;

+    const CCodecLib &lib = Libs[codec.LibIndex];

+    UString res;

+    NWindows::NCOM::CPropVariant prop;

+    RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop));

+    if (prop.vt == VT_BSTR)

+      res = prop.bstrVal;

+    else if (prop.vt != VT_EMPTY)

+      continue;

+    if (name.CompareNoCase(res) == 0)

+      return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder);

+  }

+  return CLASS_E_CLASSNOTAVAILABLE;

+}

+

+int CCodecs::GetCodecLibIndex(UInt32 index)

+{

+  #ifdef EXPORT_CODECS

+  if (index < g_NumCodecs)

+    return -1;

+  #endif

+  #ifdef EXTERNAL_CODECS

+  const CDllCodecInfo &ci = Codecs[index

+      #ifdef EXPORT_CODECS

+      - g_NumCodecs

+      #endif

+      ];

+  return ci.LibIndex;

+  #else

+  return -1;

+  #endif

+}

+

+bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index)

+{

+  #ifdef EXPORT_CODECS

+  if (index < g_NumCodecs)

+  {

+    NWindows::NCOM::CPropVariant prop;

+    if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK)

+      if (prop.vt != VT_EMPTY)

+        return true;

+    return false;

+  }

+  #endif

+  #ifdef EXTERNAL_CODECS

+  const CDllCodecInfo &ci = Codecs[index

+      #ifdef EXPORT_CODECS

+      - g_NumCodecs

+      #endif

+      ];

+  return ci.EncoderIsAssigned;

+  #else

+  return false;

+  #endif

+}

+

+HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)

+{

+  UString s;

+  NWindows::NCOM::CPropVariant prop;

+  RINOK(GetProperty(index, NMethodPropID::kID, &prop));

+  if (prop.vt != VT_UI8)

+    return E_INVALIDARG;

+  id = prop.uhVal.QuadPart;

+  return S_OK;

+}

+

+UString CCodecs::GetCodecName(UInt32 index)

+{

+  UString s;

+  NWindows::NCOM::CPropVariant prop;

+  if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)

+    if (prop.vt == VT_BSTR)

+      s = prop.bstrVal;

+  return s;

+}

+

+#endif

diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h
new file mode 100755
index 0000000..5630b59
--- /dev/null
+++ b/CPP/7zip/UI/Common/LoadCodecs.h
@@ -0,0 +1,235 @@
+// LoadCodecs.h

+

+#ifndef __LOADCODECS_H

+#define __LOADCODECS_H

+

+#include "../../../Common/Types.h"

+#include "../../../Common/MyCom.h"

+#include "../../../Common/MyString.h"

+#include "../../../Common/Buffer.h"

+#include "../../ICoder.h"

+

+#ifdef EXTERNAL_CODECS

+#include "../../../Windows/DLL.h"

+#endif

+

+struct CDllCodecInfo

+{

+  CLSID Encoder;

+  CLSID Decoder;

+  bool EncoderIsAssigned;

+  bool DecoderIsAssigned;

+  int LibIndex;

+  UInt32 CodecIndex;

+};

+

+#include "../../Archive/IArchive.h"

+

+typedef IInArchive * (*CreateInArchiveP)();

+typedef IOutArchive * (*CreateOutArchiveP)();

+

+struct CArcExtInfo

+{

+  UString Ext;

+  UString AddExt;

+  CArcExtInfo() {}

+  CArcExtInfo(const UString &ext): Ext(ext) {}

+  CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}

+};

+

+

+struct CArcInfoEx

+{

+  #ifdef EXTERNAL_CODECS

+  int LibIndex;

+  UInt32 FormatIndex;

+  CLSID ClassID;

+  #endif

+  bool UpdateEnabled;

+  CreateInArchiveP CreateInArchive;

+  CreateOutArchiveP CreateOutArchive;

+  UString Name;

+  CObjectVector<CArcExtInfo> Exts;

+  #ifndef _SFX

+  CByteBuffer StartSignature;

+  // CByteBuffer FinishSignature;

+  #ifdef NEW_FOLDER_INTERFACE

+  UStringVector AssociateExts;

+  #endif

+  #endif

+  bool KeepName;

+  UString GetMainExt() const

+  {

+    if (Exts.IsEmpty())

+      return UString();

+    return Exts[0].Ext;

+  }

+  int FindExtension(const UString &ext) const

+  {

+    for (int i = 0; i < Exts.Size(); i++)

+      if (ext.CompareNoCase(Exts[i].Ext) == 0)

+        return i;

+    return -1;

+  }

+  UString GetAllExtensions() const

+  {

+    UString s;

+    for (int i = 0; i < Exts.Size(); i++)

+    {

+      if (i > 0)

+        s += ' ';

+      s += Exts[i].Ext;

+    }

+    return s;

+  }

+

+  void AddExts(const wchar_t* ext, const wchar_t* addExt);

+

+  CArcInfoEx():

+    #ifdef EXTERNAL_CODECS

+    LibIndex(-1),

+    #endif

+    UpdateEnabled(false),

+    CreateInArchive(0), CreateOutArchive(0),

+    KeepName(false)

+    #ifndef _SFX

+    #endif

+  {}

+};

+

+#ifdef EXTERNAL_CODECS

+typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value);

+typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject);

+

+

+#ifdef NEW_FOLDER_INTERFACE

+struct CCodecIcons

+{

+  struct CIconPair

+  {

+    UString Ext;

+    int IconIndex;

+  };

+  CObjectVector<CIconPair> IconPairs;

+  void LoadIcons(HMODULE m);

+  bool FindIconIndex(const UString &ext, int &iconIndex) const;

+};

+#endif

+

+struct CCodecLib

+#ifdef NEW_FOLDER_INTERFACE

+: public CCodecIcons

+#endif

+{

+  NWindows::NDLL::CLibrary Lib;

+  GetMethodPropertyFunc GetMethodProperty;

+  CreateObjectFunc CreateObject;

+  #ifdef NEW_FOLDER_INTERFACE

+  CSysString Path;

+  void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); }

+  #endif

+  CCodecLib(): GetMethodProperty(0) {}

+};

+#endif

+

+class CCodecs:

+  #ifdef EXTERNAL_CODECS

+  public ICompressCodecsInfo,

+  #else

+  public IUnknown,

+  #endif

+  public CMyUnknownImp

+{

+public:

+  #ifdef EXTERNAL_CODECS

+  CObjectVector<CCodecLib> Libs;

+  CObjectVector<CDllCodecInfo> Codecs;

+

+  #ifdef NEW_FOLDER_INTERFACE

+  CCodecIcons InternalIcons;

+  #endif

+

+  HRESULT LoadCodecs();

+  HRESULT LoadFormats();

+  HRESULT LoadDll(const CSysString &path, bool needCheckDll);

+  HRESULT LoadDllsFromFolder(const CSysString &folderPrefix);

+

+  HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const

+  {

+    return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);

+  }

+  #endif

+

+public:

+  CObjectVector<CArcInfoEx> Formats;

+  HRESULT Load();

+  

+  #ifndef _SFX

+  int FindFormatForArchiveName(const UString &arcPath) const;

+  int FindFormatForExtension(const UString &ext) const;

+  int FindFormatForArchiveType(const UString &arcType) const;

+  bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const;

+  #endif

+

+  MY_UNKNOWN_IMP

+

+  #ifdef EXTERNAL_CODECS

+  STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods);

+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);

+  STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder);

+  STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder);

+  #endif

+

+  int GetCodecLibIndex(UInt32 index);

+  bool GetCodecEncoderIsAssigned(UInt32 index);

+  HRESULT GetCodecId(UInt32 index, UInt64 &id);

+  UString GetCodecName(UInt32 index);

+

+  HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const

+  {

+    const CArcInfoEx &ai = Formats[formatIndex];

+    #ifdef EXTERNAL_CODECS

+    if (ai.LibIndex < 0)

+    #endif

+    {

+      archive = ai.CreateInArchive();

+      return S_OK;

+    }

+    #ifdef EXTERNAL_CODECS

+    return CreateArchiveHandler(ai, (void **)&archive, false);

+    #endif

+  }

+  HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const

+  {

+    const CArcInfoEx &ai = Formats[formatIndex];

+    #ifdef EXTERNAL_CODECS

+    if (ai.LibIndex < 0)

+    #endif

+    {

+      archive = ai.CreateOutArchive();

+      return S_OK;

+    }

+    #ifdef EXTERNAL_CODECS

+    return CreateArchiveHandler(ai, (void **)&archive, true);

+    #endif

+  }

+  int FindOutFormatFromName(const UString &name) const

+  {

+    for (int i = 0; i < Formats.Size(); i++)

+    {

+      const CArcInfoEx &arc = Formats[i];

+      if (!arc.UpdateEnabled)

+        continue;

+      if (arc.Name.CompareNoCase(name) == 0)

+        return i;

+    }

+    return -1;

+  }

+

+  #ifdef EXTERNAL_CODECS

+  HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const;

+  #endif

+

+};

+

+#endif

diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
new file mode 100755
index 0000000..c489e0a
--- /dev/null
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -0,0 +1,536 @@
+// OpenArchive.cpp

+

+#include "StdAfx.h"

+

+#include "Common/Wildcard.h"

+

+#include "Windows/FileDir.h"

+#include "Windows/PropVariant.h"

+

+#include "../../Common/FileStreams.h"

+#include "../../Common/StreamUtils.h"

+

+#include "DefaultName.h"

+#include "OpenArchive.h"

+

+using namespace NWindows;

+

+// Static-SFX (for Linux) can be big.

+const UInt64 kMaxCheckStartPosition = 1 << 22;

+

+HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)

+{

+  NCOM::CPropVariant prop;

+  result = false;

+  RINOK(archive->GetProperty(index, propID, &prop));

+  if (prop.vt == VT_BOOL)

+    result = VARIANT_BOOLToBool(prop.boolVal);

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  return S_OK;

+}

+

+HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)

+{

+  return GetArchiveItemBoolProp(archive, index, kpidIsDir, result);

+}

+

+HRESULT CArc::GetItemPath(UInt32 index, UString &result) const

+{

+  {

+    NCOM::CPropVariant prop;

+    RINOK(Archive->GetProperty(index, kpidPath, &prop));

+    if (prop.vt == VT_BSTR)

+      result = prop.bstrVal;

+    else if (prop.vt == VT_EMPTY)

+      result.Empty();

+    else

+      return E_FAIL;

+  }

+  if (result.IsEmpty())

+  {

+    result = DefaultName;

+    NCOM::CPropVariant prop;

+    RINOK(Archive->GetProperty(index, kpidExtension, &prop));

+    if (prop.vt == VT_BSTR)

+    {

+      result += L'.';

+      result += prop.bstrVal;

+    }

+    else if (prop.vt != VT_EMPTY)

+      return E_FAIL;

+  }

+  return S_OK;

+}

+

+HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const

+{

+  NCOM::CPropVariant prop;

+  defined = false;

+  ft.dwHighDateTime = ft.dwLowDateTime = 0;

+  RINOK(Archive->GetProperty(index, kpidMTime, &prop));

+  if (prop.vt == VT_FILETIME)

+  {

+    ft = prop.filetime;

+    defined = true;

+  }

+  else if (prop.vt != VT_EMPTY)

+    return E_FAIL;

+  else if (MTimeDefined)

+  {

+    ft = MTime;

+    defined = true;

+  }

+  return S_OK;

+}

+

+#ifndef _SFX

+static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)

+{

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

+    if (p1[i] != p2[i])

+      return false;

+  return true;

+}

+#endif

+

+#ifdef UNDER_CE

+static const int kNumHashBytes = 1;

+#define HASH_VAL(buf, pos) ((buf)[pos])

+#else

+static const int kNumHashBytes = 2;

+#define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8))

+#endif

+

+

+HRESULT CArc::OpenStream(

+    CCodecs *codecs,

+    int formatIndex,

+    IInStream *stream,

+    ISequentialInStream *seqStream,

+    IArchiveOpenCallback *callback)

+{

+  Archive.Release();

+  ErrorMessage.Empty();

+  const UString fileName = ExtractFileNameFromPath(Path);

+  UString extension;

+  {

+    int dotPos = fileName.ReverseFind(L'.');

+    if (dotPos >= 0)

+      extension = fileName.Mid(dotPos + 1);

+  }

+  CIntVector orderIndices;

+  if (formatIndex >= 0)

+    orderIndices.Add(formatIndex);

+  else

+  {

+

+  int i;

+  int numFinded = 0;

+  for (i = 0; i < codecs->Formats.Size(); i++)

+    if (codecs->Formats[i].FindExtension(extension) >= 0)

+      orderIndices.Insert(numFinded++, i);

+    else

+      orderIndices.Add(i);

+  

+  if (!stream)

+  {

+    if (numFinded != 1)

+      return E_NOTIMPL;

+    orderIndices.DeleteFrom(1);

+  }

+

+  #ifndef _SFX

+  if (orderIndices.Size() >= 2 && (numFinded == 0 || extension.CompareNoCase(L"exe") == 0))

+  {

+    CIntVector orderIndices2;

+    CByteBuffer byteBuffer;

+    const size_t kBufferSize = (1 << 21);

+    byteBuffer.SetCapacity(kBufferSize);

+    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));

+    size_t processedSize = kBufferSize;

+    RINOK(ReadStream(stream, byteBuffer, &processedSize));

+    if (processedSize == 0)

+      return S_FALSE;

+

+    const Byte *buf = byteBuffer;

+    CByteBuffer hashBuffer;

+    const UInt32 kNumVals = 1 << (kNumHashBytes * 8);

+    hashBuffer.SetCapacity(kNumVals);

+    Byte *hash = hashBuffer;

+    memset(hash, 0xFF, kNumVals);

+    Byte prevs[256];

+    if (orderIndices.Size() >= 256)

+      return S_FALSE;

+    int i;

+    for (i = 0; i < orderIndices.Size(); i++)

+    {

+      const CArcInfoEx &ai = codecs->Formats[orderIndices[i]];

+      const CByteBuffer &sig = ai.StartSignature;

+      if (sig.GetCapacity() < kNumHashBytes)

+        continue;

+      UInt32 v = HASH_VAL(sig, 0);

+      prevs[i] = hash[v];

+      hash[v] = (Byte)i;

+    }

+

+    processedSize -= (kNumHashBytes - 1);

+    for (UInt32 pos = 0; pos < processedSize; pos++)

+    {

+      for (; pos < processedSize && hash[HASH_VAL(buf, pos)] == 0xFF; pos++);

+      if (pos == processedSize)

+        break;

+      UInt32 v = HASH_VAL(buf, pos);

+      Byte *ptr = &hash[v];

+      int i = *ptr;

+      do

+      {

+        int index = orderIndices[i];

+        const CArcInfoEx &ai = codecs->Formats[index];

+        const CByteBuffer &sig = ai.StartSignature;

+        if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + (kNumHashBytes - 1) &&

+            TestSignature(buf + pos, sig, sig.GetCapacity()))

+        {

+          orderIndices2.Add(index);

+          orderIndices[i] = 0xFF;

+          *ptr = prevs[i];

+        }

+        else

+          ptr = &prevs[i];

+        i = *ptr;

+      }

+      while (i != 0xFF);

+    }

+    

+    for (i = 0; i < orderIndices.Size(); i++)

+    {

+      int val = orderIndices[i];

+      if (val != 0xFF)

+        orderIndices2.Add(val);

+    }

+    orderIndices = orderIndices2;

+  }

+  else if (extension == L"000" || extension == L"001")

+  {

+    CByteBuffer byteBuffer;

+    const size_t kBufferSize = (1 << 10);

+    byteBuffer.SetCapacity(kBufferSize);

+    Byte *buffer = byteBuffer;

+    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));

+    size_t processedSize = kBufferSize;

+    RINOK(ReadStream(stream, buffer, &processedSize));

+    if (processedSize >= 16)

+    {

+      Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00};

+      if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0)

+      {

+        for (int i = 0; i < orderIndices.Size(); i++)

+        {

+          int index = orderIndices[i];

+          const CArcInfoEx &ai = codecs->Formats[index];

+          if (ai.Name.CompareNoCase(L"rar") != 0)

+            continue;

+          orderIndices.Delete(i--);

+          orderIndices.Insert(0, index);

+          break;

+        }

+      }

+    }

+  }

+  if (orderIndices.Size() >= 2)

+  {

+    int isoIndex = codecs->FindFormatForArchiveType(L"iso");

+    int udfIndex = codecs->FindFormatForArchiveType(L"udf");

+    int iIso = -1;

+    int iUdf = -1;

+    for (int i = 0; i < orderIndices.Size(); i++)

+    {

+      if (orderIndices[i] == isoIndex) iIso = i;

+      if (orderIndices[i] == udfIndex) iUdf = i;

+    }

+    if (iUdf > iIso && iIso >= 0)

+    {

+      orderIndices[iUdf] = isoIndex;

+      orderIndices[iIso] = udfIndex;

+    }

+  }

+

+  #endif

+  }

+

+  for (int i = 0; i < orderIndices.Size(); i++)

+  {

+    if (stream)

+    {

+      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));

+    }

+    CMyComPtr<IInArchive> archive;

+

+    FormatIndex = orderIndices[i];

+    RINOK(codecs->CreateInArchive(FormatIndex, archive));

+    if (!archive)

+      continue;

+

+    #ifdef EXTERNAL_CODECS

+    {

+      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;

+      archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);

+      if (setCompressCodecsInfo)

+      {

+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));

+      }

+    }

+    #endif

+

+    // OutputDebugStringW(codecs->Formats[FormatIndex].Name);

+

+    HRESULT result;

+    if (stream)

+      result = archive->Open(stream, &kMaxCheckStartPosition, callback);

+    else

+    {

+      CMyComPtr<IArchiveOpenSeq> openSeq;

+      archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);

+      if (!openSeq)

+        return E_NOTIMPL;

+      result = openSeq->OpenSeq(seqStream);

+    }

+

+    if (result == S_FALSE)

+      continue;

+    RINOK(result);

+

+    {

+      NCOM::CPropVariant prop;

+      archive->GetArchiveProperty(kpidError, &prop);

+      if (prop.vt != VT_EMPTY)

+        ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error";

+    }

+    

+    Archive = archive;

+    const CArcInfoEx &format = codecs->Formats[FormatIndex];

+    if (format.Exts.Size() == 0)

+      DefaultName = GetDefaultName2(fileName, L"", L"");

+    else

+    {

+      int subExtIndex = format.FindExtension(extension);

+      if (subExtIndex < 0)

+        subExtIndex = 0;

+      const CArcExtInfo &extInfo = format.Exts[subExtIndex];

+      DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt);

+    }

+    return S_OK;

+  }

+  return S_FALSE;

+}

+

+HRESULT CArc::OpenStreamOrFile(

+    CCodecs *codecs,

+    int formatIndex,

+    bool stdInMode,

+    IInStream *stream,

+    IArchiveOpenCallback *callback)

+{

+  CMyComPtr<IInStream> fileStream;

+  CMyComPtr<ISequentialInStream> seqStream;

+  if (stdInMode)

+    seqStream = new CStdInFileStream;

+  else if (!stream)

+  {

+    CInFileStream *fileStreamSpec = new CInFileStream;

+    fileStream = fileStreamSpec;

+    if (!fileStreamSpec->Open(Path))

+      return GetLastError();

+    stream = fileStream;

+  }

+

+  /*

+  if (callback)

+  {

+    UInt64 fileSize;

+    RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));

+    RINOK(callback->SetTotal(NULL, &fileSize))

+  }

+  */

+

+  return OpenStream(codecs, formatIndex, stream, seqStream, callback);

+}

+

+HRESULT CArchiveLink::Close()

+{

+  for (int i = Arcs.Size() - 1;  i >= 0; i--)

+  {

+    RINOK(Arcs[i].Archive->Close());

+  }

+  IsOpen = false;

+  return S_OK;

+}

+

+void CArchiveLink::Release()

+{

+  while (!Arcs.IsEmpty())

+    Arcs.DeleteBack();

+}

+

+HRESULT CArchiveLink::Open(

+    CCodecs *codecs,

+    const CIntVector &formatIndices,

+    bool stdInMode,

+    IInStream *stream,

+    const UString &filePath,

+    IArchiveOpenCallback *callback)

+{

+  Release();

+  if (formatIndices.Size() >= 32)

+    return E_NOTIMPL;

+  

+  HRESULT resSpec;

+

+  for (;;)

+  {

+    resSpec = S_OK;

+    int formatIndex = -1;

+    if (formatIndices.Size() >= 1)

+    {

+      if (Arcs.Size() >= formatIndices.Size())

+        break;

+      formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1];

+    }

+    else if (Arcs.Size() >= 32)

+      break;

+

+    if (Arcs.IsEmpty())

+    {

+      CArc arc;

+      arc.Path = filePath;

+      arc.SubfileIndex = (UInt32)(Int32)-1;

+      RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback));

+      Arcs.Add(arc);

+      continue;

+    }

+    

+    const CArc &arc = Arcs.Back();

+    

+    resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL);

+    

+    UInt32 mainSubfile;

+    {

+      NCOM::CPropVariant prop;

+      RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop));

+      if (prop.vt == VT_UI4)

+        mainSubfile = prop.ulVal;

+      else

+        break;

+      UInt32 numItems;

+      RINOK(arc.Archive->GetNumberOfItems(&numItems));

+      if (mainSubfile >= numItems)

+        break;

+    }

+

+  

+    CMyComPtr<IInArchiveGetStream> getStream;

+    if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream)

+      break;

+    

+    CMyComPtr<ISequentialInStream> subSeqStream;

+    if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream)

+      break;

+    

+    CMyComPtr<IInStream> subStream;

+    if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream)

+      break;

+    

+    CArc arc2;

+    RINOK(arc.GetItemPath(mainSubfile, arc2.Path));

+    

+    CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;

+    callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);

+    if (setSubArchiveName)

+      setSubArchiveName->SetSubArchiveName(arc2.Path);

+    

+    arc2.SubfileIndex = mainSubfile;

+    HRESULT result = arc2.OpenStream(codecs, formatIndex, subStream, NULL, callback);

+    resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE);

+    if (result == S_FALSE)

+      break;

+    RINOK(result);

+    RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined));

+    Arcs.Add(arc2);

+  }

+  IsOpen = !Arcs.IsEmpty();

+  return S_OK;

+}

+

+static void SetCallback(const UString &filePath,

+    IOpenCallbackUI *callbackUI,

+    IArchiveOpenCallback *reOpenCallback,

+    CMyComPtr<IArchiveOpenCallback> &callback)

+{

+  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;

+  callback = openCallbackSpec;

+  openCallbackSpec->Callback = callbackUI;

+  openCallbackSpec->ReOpenCallback = reOpenCallback;

+

+  UString fullName;

+  int fileNamePartStartIndex;

+  NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex);

+  openCallbackSpec->Init(

+      fullName.Left(fileNamePartStartIndex),

+      fullName.Mid(fileNamePartStartIndex));

+}

+

+HRESULT CArchiveLink::Open2(CCodecs *codecs,

+    const CIntVector &formatIndices,

+    bool stdInMode,

+    IInStream *stream,

+    const UString &filePath,

+    IOpenCallbackUI *callbackUI)

+{

+  VolumesSize = 0;

+  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;

+  CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec;

+  openCallbackSpec->Callback = callbackUI;

+

+  UString fullName, prefix, name;

+  if (!stream && !stdInMode)

+  {

+    int fileNamePartStartIndex;

+    if (!NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex))

+      return GetLastError();

+    prefix = fullName.Left(fileNamePartStartIndex);

+    name = fullName.Mid(fileNamePartStartIndex);

+    openCallbackSpec->Init(prefix, name);

+  }

+  else

+  {

+    openCallbackSpec->SetSubArchiveName(filePath);

+  }

+

+  RINOK(Open(codecs, formatIndices, stdInMode, stream, filePath, callback));

+  VolumePaths.Add(prefix + name);

+  for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++)

+    VolumePaths.Add(prefix + openCallbackSpec->FileNames[i]);

+  VolumesSize = openCallbackSpec->TotalSize;

+  return S_OK;

+}

+

+HRESULT CArchiveLink::ReOpen(CCodecs *codecs, const UString &filePath,

+    IArchiveOpenCallback *callback)

+{

+  if (Arcs.Size() > 1)

+    return E_NOTIMPL;

+

+  if (Arcs.Size() == 0)

+    return Open2(codecs, CIntVector(), false, NULL, filePath, 0);

+

+  CMyComPtr<IArchiveOpenCallback> openCallbackNew;

+  SetCallback(filePath, NULL, callback, openCallbackNew);

+

+  CInFileStream *fileStreamSpec = new CInFileStream;

+  CMyComPtr<IInStream> stream(fileStreamSpec);

+  if (!fileStreamSpec->Open(filePath))

+    return GetLastError();

+  HRESULT res = GetArchive()->Open(stream, &kMaxCheckStartPosition, callback);

+  IsOpen = (res == S_OK);

+  return res;

+}

diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h
new file mode 100755
index 0000000..18ca0ea
--- /dev/null
+++ b/CPP/7zip/UI/Common/OpenArchive.h
@@ -0,0 +1,87 @@
+// OpenArchive.h

+

+#ifndef __OPEN_ARCHIVE_H

+#define __OPEN_ARCHIVE_H

+

+#include "Common/MyString.h"

+

+#include "Windows/FileFind.h"

+

+#include "../../Archive/IArchive.h"

+

+#include "ArchiveOpenCallback.h"

+#include "LoadCodecs.h"

+

+HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result);

+HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result);

+

+struct CArc

+{

+  CMyComPtr<IInArchive> Archive;

+  UString Path;

+  UString DefaultName;

+  int FormatIndex;

+  int SubfileIndex;

+  FILETIME MTime;

+  bool MTimeDefined;

+  UString ErrorMessage;

+

+  CArc(): MTimeDefined(false) {}

+

+  HRESULT GetItemPath(UInt32 index, UString &result) const;

+  HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const;

+  HRESULT IsItemAnti(UInt32 index, bool &result) const

+    { return GetArchiveItemBoolProp(Archive, index, kpidIsAnti, result); }

+

+  HRESULT OpenStream(

+    CCodecs *codecs,

+    int formatIndex,

+    IInStream *stream,

+    ISequentialInStream *seqStream,

+    IArchiveOpenCallback *callback);

+

+  HRESULT OpenStreamOrFile(

+    CCodecs *codecs,

+    int formatIndex,

+    bool stdInMode,

+    IInStream *stream,

+    IArchiveOpenCallback *callback);

+};

+

+struct CArchiveLink

+{

+  CObjectVector<CArc> Arcs;

+  UStringVector VolumePaths;

+  UInt64 VolumesSize;

+  bool IsOpen;

+

+  CArchiveLink(): VolumesSize(0), IsOpen(false) {}

+  HRESULT Close();

+  void Release();

+  ~CArchiveLink() { Release(); }

+

+  IInArchive *GetArchive() const { return Arcs.Back().Archive; }

+

+  HRESULT Open(

+    CCodecs *codecs,

+    const CIntVector &formatIndices,

+    bool stdInMode,

+    IInStream *stream,

+    const UString &filePath,

+    IArchiveOpenCallback *callback);

+

+  HRESULT Open2(

+    CCodecs *codecs,

+    const CIntVector &formatIndices,

+    bool stdInMode,

+    IInStream *stream,

+    const UString &filePath,

+    IOpenCallbackUI *callbackUI);

+

+  HRESULT ReOpen(

+    CCodecs *codecs,

+    const UString &filePath,

+    IArchiveOpenCallback *callback);

+};

+

+#endif

diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
new file mode 100755
index 0000000..4a9e294
--- /dev/null
+++ b/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -0,0 +1,120 @@
+// PropIDUtils.cpp

+

+#include "StdAfx.h"

+

+#include "Common/IntToString.h"

+

+#include "Windows/FileFind.h"

+#include "Windows/PropVariantConversions.h"

+

+#include "../../PropID.h"

+

+#include "PropIDUtils.h"

+

+using namespace NWindows;

+

+void ConvertUInt32ToHex(UInt32 value, wchar_t *s)

+{

+  for (int i = 0; i < 8; i++)

+  {

+    int t = value & 0xF;

+    value >>= 4;

+    s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10)));

+  }

+  s[8] = L'\0';

+}

+

+static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_";

+/*

+0 READONLY

+1 HIDDEN

+3 SYSTEM

+

+4 DIRECTORY

+5 ARCHIVE

+6 DEVICE

+7 NORMAL

+8 TEMPORARY

+9 SPARSE_FILE

+10 REPARSE_POINT

+11 COMPRESSED

+12 OFFLINE

+13 NOT_CONTENT_INDEXED

+14 ENCRYPTED

+

+16 VIRTUAL

+*/

+

+static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };

+#define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-';

+

+UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full)

+{

+  switch(propID)

+  {

+    case kpidCTime:

+    case kpidATime:

+    case kpidMTime:

+    {

+      if (prop.vt != VT_FILETIME)

+        break;

+      FILETIME localFileTime;

+      if ((prop.filetime.dwHighDateTime == 0 &&

+          prop.filetime.dwLowDateTime == 0) ||

+          !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime))

+        return UString();

+      return ConvertFileTimeToString(localFileTime, true, full);

+    }

+    case kpidCRC:

+    {

+      if (prop.vt != VT_UI4)

+        break;

+      wchar_t temp[12];

+      ConvertUInt32ToHex(prop.ulVal, temp);

+      return temp;

+    }

+    case kpidAttrib:

+    {

+      if (prop.vt != VT_UI4)

+        break;

+      UInt32 a = prop.ulVal;

+      wchar_t sz[32];

+      int pos = 0;

+      for (int i = 0; i < 16; i++)

+        if (a & (1 << i) && i != 7)

+          sz[pos++] = g_WinAttrib[i];

+      sz[pos] = '\0';

+      return sz;

+    }

+    case kpidPosixAttrib:

+    {

+      if (prop.vt != VT_UI4)

+        break;

+      UString res;

+      UInt32 a = prop.ulVal;

+      wchar_t temp[16];

+

+      temp[0] = kPosixTypes[(a >> 12) & 0xF];

+      for (int i = 6; i >= 0; i -= 3)

+      {

+        temp[7 - i] = MY_ATTR_CHAR(a, i + 2, L'r');

+        temp[8 - i] = MY_ATTR_CHAR(a, i + 1, L'w');

+        temp[9 - i] = MY_ATTR_CHAR(a, i + 0, L'x');

+      }

+      if ((a & 0x800) != 0) temp[3] = ((a & (1 << 6)) ? 's' : 'S');

+      if ((a & 0x400) != 0) temp[6] = ((a & (1 << 3)) ? 's' : 'S');

+      if ((a & 0x200) != 0) temp[9] = ((a & (1 << 0)) ? 't' : 'T');

+      temp[10] = 0;

+      res = temp;

+

+      a &= ~(UInt32)0xFFFF;

+      if (a != 0)

+      {

+        ConvertUInt32ToHex(a, temp);

+        res = UString(temp) + L' ' + res;

+      }

+      return res;

+    }

+  }

+  return ConvertPropVariantToString(prop);

+}

diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h
new file mode 100755
index 0000000..05c09e7
--- /dev/null
+++ b/CPP/7zip/UI/Common/PropIDUtils.h
@@ -0,0 +1,12 @@
+// PropIDUtils.h

+

+#ifndef __PROPID_UTILS_H

+#define __PROPID_UTILS_H

+

+#include "Common/MyString.h"

+#include "Common/Types.h"

+

+void ConvertUInt32ToHex(UInt32 value, wchar_t *s);

+UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true);

+

+#endif

diff --git a/CPP/7zip/UI/Common/Property.h b/CPP/7zip/UI/Common/Property.h
new file mode 100755
index 0000000..5253d52
--- /dev/null
+++ b/CPP/7zip/UI/Common/Property.h
@@ -0,0 +1,14 @@
+// Property.h

+

+#ifndef __PROPERTY_H

+#define __PROPERTY_H

+

+#include "Common/MyString.h"

+

+struct CProperty

+{

+  UString Name;

+  UString Value;

+};

+

+#endif

diff --git a/CPP/7zip/UI/Common/SetProperties.cpp b/CPP/7zip/UI/Common/SetProperties.cpp
new file mode 100755
index 0000000..b3347ce
--- /dev/null
+++ b/CPP/7zip/UI/Common/SetProperties.cpp
@@ -0,0 +1,79 @@
+// SetProperties.cpp

+

+#include "StdAfx.h"

+

+#include "SetProperties.h"

+

+#include "Windows/PropVariant.h"

+#include "Common/MyString.h"

+#include "Common/StringToInt.h"

+#include "Common/MyCom.h"

+

+#include "../../Archive/IArchive.h"

+

+using namespace NWindows;

+using namespace NCOM;

+

+static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)

+{

+  const wchar_t *endPtr;

+  UInt64 result = ConvertStringToUInt64(s, &endPtr);

+  if (endPtr - (const wchar_t *)s != s.Length())

+    prop = s;

+  else if (result <= 0xFFFFFFFF)

+    prop = (UInt32)result;

+  else

+    prop = result;

+}

+

+HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties)

+{

+  if (properties.IsEmpty())

+    return S_OK;

+  CMyComPtr<ISetProperties> setProperties;

+  unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties);

+  if (!setProperties)

+    return S_OK;

+

+  UStringVector realNames;

+  CPropVariant *values = new CPropVariant[properties.Size()];

+  try

+  {

+    int i;

+    for(i = 0; i < properties.Size(); i++)

+    {

+      const CProperty &property = properties[i];

+      NCOM::CPropVariant propVariant;

+      UString name = property.Name;

+      if (property.Value.IsEmpty())

+      {

+        if (!name.IsEmpty())

+        {

+          wchar_t c = name[name.Length() - 1];

+          if (c == L'-')

+            propVariant = false;

+          else if (c == L'+')

+            propVariant = true;

+          if (propVariant.vt != VT_EMPTY)

+            name = name.Left(name.Length() - 1);

+        }

+      }

+      else

+        ParseNumberString(property.Value, propVariant);

+      realNames.Add(name);

+      values[i] = propVariant;

+    }

+    CRecordVector<const wchar_t *> names;

+    for(i = 0; i < realNames.Size(); i++)

+      names.Add((const wchar_t *)realNames[i]);

+    

+    RINOK(setProperties->SetProperties(&names.Front(), values, names.Size()));

+  }

+  catch(...)

+  {

+    delete []values;

+    throw;

+  }

+  delete []values;

+  return S_OK;

+}

diff --git a/CPP/7zip/UI/Common/SetProperties.h b/CPP/7zip/UI/Common/SetProperties.h
new file mode 100755
index 0000000..64c947c
--- /dev/null
+++ b/CPP/7zip/UI/Common/SetProperties.h
@@ -0,0 +1,10 @@
+// SetProperties.h

+

+#ifndef __SETPROPERTIES_H

+#define __SETPROPERTIES_H

+

+#include "Property.h"

+

+HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties);

+

+#endif

diff --git a/CPP/7zip/UI/Common/SortUtils.cpp b/CPP/7zip/UI/Common/SortUtils.cpp
new file mode 100755
index 0000000..039adfa
--- /dev/null
+++ b/CPP/7zip/UI/Common/SortUtils.cpp
@@ -0,0 +1,22 @@
+// SortUtils.cpp

+

+#include "StdAfx.h"

+

+#include "SortUtils.h"

+#include "Common/Wildcard.h"

+

+static int CompareStrings(const int *p1, const int *p2, void *param)

+{

+  const UStringVector &strings = *(const UStringVector *)param;

+  return CompareFileNames(strings[*p1], strings[*p2]);

+}

+

+void SortFileNames(const UStringVector &strings, CIntVector &indices)

+{

+  indices.Clear();

+  int numItems = strings.Size();

+  indices.Reserve(numItems);

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

+    indices.Add(i);

+  indices.Sort(CompareStrings, (void *)&strings);

+}

diff --git a/CPP/7zip/UI/Common/SortUtils.h b/CPP/7zip/UI/Common/SortUtils.h
new file mode 100755
index 0000000..4835f11
--- /dev/null
+++ b/CPP/7zip/UI/Common/SortUtils.h
@@ -0,0 +1,10 @@
+// SortUtils.h

+

+#ifndef __SORTUTLS_H

+#define __SORTUTLS_H

+

+#include "Common/MyString.h"

+

+void SortFileNames(const UStringVector &strings, CIntVector &indices);

+

+#endif

diff --git a/CPP/7zip/UI/Common/StdAfx.h b/CPP/7zip/UI/Common/StdAfx.h
new file mode 100755
index 0000000..ab2617e
--- /dev/null
+++ b/CPP/7zip/UI/Common/StdAfx.h
@@ -0,0 +1,9 @@
+// stdafx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../../Common/MyWindows.h"

+#include "../../../Common/NewHandler.h"

+

+#endif

diff --git a/CPP/7zip/UI/Common/TempFiles.cpp b/CPP/7zip/UI/Common/TempFiles.cpp
new file mode 100755
index 0000000..48fb4e7
--- /dev/null
+++ b/CPP/7zip/UI/Common/TempFiles.cpp
@@ -0,0 +1,22 @@
+// TempFiles.cpp

+

+#include "StdAfx.h"

+

+#include "TempFiles.h"

+

+#include "Windows/FileDir.h"

+#include "Windows/FileIO.h"

+

+using namespace NWindows;

+using namespace NFile;

+

+void CTempFiles::Clear()

+{

+  while(!Paths.IsEmpty())

+  {

+    NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back());

+    Paths.DeleteBack();

+  }

+}

+

+

diff --git a/CPP/7zip/UI/Common/TempFiles.h b/CPP/7zip/UI/Common/TempFiles.h
new file mode 100755
index 0000000..9e8e131
--- /dev/null
+++ b/CPP/7zip/UI/Common/TempFiles.h
@@ -0,0 +1,16 @@
+// TempFiles.h

+

+#ifndef __TEMPFILES_H

+#define __TEMPFILES_H

+

+#include "Common/MyString.h"

+

+class CTempFiles

+{

+  void Clear();

+public:

+  UStringVector Paths;

+  ~CTempFiles() { Clear(); }

+};

+

+#endif

diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
new file mode 100755
index 0000000..2e1cca0
--- /dev/null
+++ b/CPP/7zip/UI/Common/Update.cpp
@@ -0,0 +1,910 @@
+// Update.cpp

+

+#include "StdAfx.h"

+

+#include "Update.h"

+

+#include "Common/IntToString.h"

+#include "Common/StringConvert.h"

+

+#ifdef _WIN32

+#include "Windows/DLL.h"

+#endif

+

+#include "Windows/FileDir.h"

+#include "Windows/FileFind.h"

+#include "Windows/FileName.h"

+#include "Windows/PropVariant.h"

+#include "Windows/PropVariantConversions.h"

+#include "Windows/Time.h"

+

+#include "../../Common/FileStreams.h"

+

+#include "../../Compress/CopyCoder.h"

+

+#include "../Common/DirItem.h"

+#include "../Common/EnumDirItems.h"

+#include "../Common/OpenArchive.h"

+#include "../Common/UpdateProduce.h"

+

+#include "EnumDirItems.h"

+#include "SetProperties.h"

+#include "TempFiles.h"

+#include "UpdateCallback.h"

+

+static const char *kUpdateIsNotSupoorted =

+  "update operations are not supported for this archive";

+

+using namespace NWindows;

+using namespace NCOM;

+using namespace NFile;

+using namespace NName;

+

+static const wchar_t *kTempFolderPrefix = L"7zE";

+

+using namespace NUpdateArchive;

+

+class COutMultiVolStream:

+  public IOutStream,

+  public CMyUnknownImp

+{

+  int _streamIndex; // required stream

+  UInt64 _offsetPos; // offset from start of _streamIndex index

+  UInt64 _absPos;

+  UInt64 _length;

+

+  struct CSubStreamInfo

+  {

+    COutFileStream *StreamSpec;

+    CMyComPtr<IOutStream> Stream;

+    UString Name;

+    UInt64 Pos;

+    UInt64 RealSize;

+  };

+  CObjectVector<CSubStreamInfo> Streams;

+public:

+  // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;

+  CRecordVector<UInt64> Sizes;

+  UString Prefix;

+  CTempFiles *TempFiles;

+

+  void Init()

+  {

+    _streamIndex = 0;

+    _offsetPos = 0;

+    _absPos = 0;

+    _length = 0;

+  }

+

+  HRESULT Close();

+

+  MY_UNKNOWN_IMP1(IOutStream)

+

+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);

+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);

+  STDMETHOD(SetSize)(UInt64 newSize);

+};

+

+// static NSynchronization::CCriticalSection g_TempPathsCS;

+

+HRESULT COutMultiVolStream::Close()

+{

+  HRESULT res = S_OK;

+  for (int i = 0; i < Streams.Size(); i++)

+  {

+    CSubStreamInfo &s = Streams[i];

+    if (s.StreamSpec)

+    {

+      HRESULT res2 = s.StreamSpec->Close();

+      if (res2 != S_OK)

+        res = res2;

+    }

+  }

+  return res;

+}

+

+STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)

+{

+  if (processedSize != NULL)

+    *processedSize = 0;

+  while(size > 0)

+  {

+    if (_streamIndex >= Streams.Size())

+    {

+      CSubStreamInfo subStream;

+

+      wchar_t temp[16];

+      ConvertUInt32ToString(_streamIndex + 1, temp);

+      UString res = temp;

+      while (res.Length() < 3)

+        res = UString(L'0') + res;

+      UString name = Prefix + res;

+      subStream.StreamSpec = new COutFileStream;

+      subStream.Stream = subStream.StreamSpec;

+      if (!subStream.StreamSpec->Create(name, false))

+        return ::GetLastError();

+      {

+        // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);

+        TempFiles->Paths.Add(name);

+      }

+

+      subStream.Pos = 0;

+      subStream.RealSize = 0;

+      subStream.Name = name;

+      Streams.Add(subStream);

+      continue;

+    }

+    CSubStreamInfo &subStream = Streams[_streamIndex];

+

+    int index = _streamIndex;

+    if (index >= Sizes.Size())

+      index = Sizes.Size() - 1;

+    UInt64 volSize = Sizes[index];

+

+    if (_offsetPos >= volSize)

+    {

+      _offsetPos -= volSize;

+      _streamIndex++;

+      continue;

+    }

+    if (_offsetPos != subStream.Pos)

+    {

+      // CMyComPtr<IOutStream> outStream;

+      // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));

+      RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));

+      subStream.Pos = _offsetPos;

+    }

+

+    UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos);

+    UInt32 realProcessed;

+    RINOK(subStream.Stream->Write(data, curSize, &realProcessed));

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

+    size -= realProcessed;

+    subStream.Pos += realProcessed;

+    _offsetPos += realProcessed;

+    _absPos += realProcessed;

+    if (_absPos > _length)

+      _length = _absPos;

+    if (_offsetPos > subStream.RealSize)

+      subStream.RealSize = _offsetPos;

+    if (processedSize != NULL)

+      *processedSize += realProcessed;

+    if (subStream.Pos == volSize)

+    {

+      _streamIndex++;

+      _offsetPos = 0;

+    }

+    if (realProcessed == 0 && curSize != 0)

+      return E_FAIL;

+    break;

+  }

+  return S_OK;

+}

+

+STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)

+{

+  if (seekOrigin >= 3)

+    return STG_E_INVALIDFUNCTION;

+  switch(seekOrigin)

+  {

+    case STREAM_SEEK_SET:

+      _absPos = offset;

+      break;

+    case STREAM_SEEK_CUR:

+      _absPos += offset;

+      break;

+    case STREAM_SEEK_END:

+      _absPos = _length + offset;

+      break;

+  }

+  _offsetPos = _absPos;

+  if (newPosition != NULL)

+    *newPosition = _absPos;

+  _streamIndex = 0;

+  return S_OK;

+}

+

+STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize)

+{

+  if (newSize < 0)

+    return E_INVALIDARG;

+  int i = 0;

+  while (i < Streams.Size())

+  {

+    CSubStreamInfo &subStream = Streams[i++];

+    if ((UInt64)newSize < subStream.RealSize)

+    {

+      RINOK(subStream.Stream->SetSize(newSize));

+      subStream.RealSize = newSize;

+      break;

+    }

+    newSize -= subStream.RealSize;

+  }

+  while (i < Streams.Size())

+  {

+    {

+      CSubStreamInfo &subStream = Streams.Back();

+      subStream.Stream.Release();

+      NDirectory::DeleteFileAlways(subStream.Name);

+    }

+    Streams.DeleteBack();

+  }

+  _offsetPos = _absPos;

+  _streamIndex = 0;

+  _length = newSize;

+  return S_OK;

+}

+

+static const wchar_t *kDefaultArchiveType = L"7z";

+static const wchar_t *kSFXExtension =

+  #ifdef _WIN32

+    L"exe";

+  #else

+    L"";

+  #endif

+

+bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath)

+{

+  if (formatIndices.Size() > 1)

+    return false;

+  int arcTypeIndex = -1;

+  if (formatIndices.Size() != 0)

+    arcTypeIndex = formatIndices[0];

+  if (arcTypeIndex >= 0)

+    MethodMode.FormatIndex = arcTypeIndex;

+  else

+  {

+    MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath);

+    // It works incorrectly for update command if archive has some non-default extension!

+    if (MethodMode.FormatIndex < 0)

+      MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType);

+  }

+  if (MethodMode.FormatIndex < 0)

+    return false;

+  const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex];

+  if (!arcInfo.UpdateEnabled)

+    return false;

+  UString typeExt = arcInfo.GetMainExt();

+  UString ext = typeExt;

+  if (SfxMode)

+    ext = kSFXExtension;

+  ArchivePath.BaseExtension = ext;

+  ArchivePath.VolExtension = typeExt;

+  ArchivePath.ParseFromPath(arcPath);

+  for (int i = 0; i < Commands.Size(); i++)

+  {

+    CUpdateArchiveCommand &uc = Commands[i];

+    uc.ArchivePath.BaseExtension = ext;

+    uc.ArchivePath.VolExtension = typeExt;

+    uc.ArchivePath.ParseFromPath(uc.UserArchivePath);

+  }

+  return true;

+}

+

+/*

+struct CUpdateProduceCallbackImp: public IUpdateProduceCallback

+{

+  const CObjectVector<CArcItem> *_arcItems;

+  IUpdateCallbackUI *_callback;

+  

+  CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a,

+      IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {}

+  virtual HRESULT ShowDeleteFile(int arcIndex);

+};

+

+HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex)

+{

+  return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name);

+}

+*/

+

+static HRESULT Compress(

+    CCodecs *codecs,

+    const CActionSet &actionSet,

+    IInArchive *archive,

+    const CCompressionMethodMode &compressionMethod,

+    CArchivePath &archivePath,

+    const CObjectVector<CArcItem> &arcItems,

+    bool shareForWrite,

+    bool stdInMode,

+    /* const UString & stdInFileName, */

+    bool stdOutMode,

+    const CDirItems &dirItems,

+    bool sfxMode,

+    const UString &sfxModule,

+    const CRecordVector<UInt64> &volumesSizes,

+    CTempFiles &tempFiles,

+    CUpdateErrorInfo &errorInfo,

+    IUpdateCallbackUI *callback)

+{

+  CMyComPtr<IOutArchive> outArchive;

+  if (archive != NULL)

+  {

+    CMyComPtr<IInArchive> archive2 = archive;

+    HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);

+    if (result != S_OK)

+      throw kUpdateIsNotSupoorted;

+  }

+  else

+  {

+    RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive));

+

+    #ifdef EXTERNAL_CODECS

+    {

+      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;

+      outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);

+      if (setCompressCodecsInfo)

+      {

+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));

+      }

+    }

+    #endif

+  }

+  if (outArchive == 0)

+    throw kUpdateIsNotSupoorted;

+  

+  NFileTimeType::EEnum fileTimeType;

+  UInt32 value;

+  RINOK(outArchive->GetFileTimeType(&value));

+

+  switch(value)

+  {

+    case NFileTimeType::kWindows:

+    case NFileTimeType::kUnix:

+    case NFileTimeType::kDOS:

+      fileTimeType = (NFileTimeType::EEnum)value;

+      break;

+    default:

+      return E_FAIL;

+  }

+

+  CRecordVector<CUpdatePair2> updatePairs2;

+

+  {

+    CRecordVector<CUpdatePair> updatePairs;

+    GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!

+    // CUpdateProduceCallbackImp upCallback(&arcItems, callback);

+    UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */);

+  }

+

+  UInt32 numFiles = 0;

+  for (int i = 0; i < updatePairs2.Size(); i++)

+    if (updatePairs2[i].NewData)

+      numFiles++;

+  

+  RINOK(callback->SetNumFiles(numFiles));

+

+  

+  CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;

+  CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);

+  

+  updateCallbackSpec->ShareForWrite = shareForWrite;

+  updateCallbackSpec->StdInMode = stdInMode;

+  updateCallbackSpec->Callback = callback;

+  updateCallbackSpec->DirItems = &dirItems;

+  updateCallbackSpec->ArcItems = &arcItems;

+  updateCallbackSpec->UpdatePairs = &updatePairs2;

+

+  CMyComPtr<ISequentialOutStream> outStream;

+

+  if (!stdOutMode)

+  {

+    UString resultPath;

+    int pos;

+    if (!NFile::NDirectory::MyGetFullPathName(archivePath.GetFinalPath(), resultPath, pos))

+      throw 1417161;

+    NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));

+  }

+

+  COutFileStream *outStreamSpec = NULL;

+  COutMultiVolStream *volStreamSpec = NULL;

+

+  if (volumesSizes.Size() == 0)

+  {

+    if (stdOutMode)

+      outStream = new CStdOutFileStream;

+    else

+    {

+      outStreamSpec = new COutFileStream;

+      outStream = outStreamSpec;

+      bool isOK = false;

+      UString realPath;

+      for (int i = 0; i < (1 << 16); i++)

+      {

+        if (archivePath.Temp)

+        {

+          if (i > 0)

+          {

+            wchar_t s[16];

+            ConvertUInt32ToString(i, s);

+            archivePath.TempPostfix = s;

+          }

+          realPath = archivePath.GetTempPath();

+        }

+        else

+          realPath = archivePath.GetFinalPath();

+        if (outStreamSpec->Create(realPath, false))

+        {

+          tempFiles.Paths.Add(realPath);

+          isOK = true;

+          break;

+        }

+        if (::GetLastError() != ERROR_FILE_EXISTS)

+          break;

+        if (!archivePath.Temp)

+          break;

+      }

+      if (!isOK)

+      {

+        errorInfo.SystemError = ::GetLastError();

+        errorInfo.FileName = realPath;

+        errorInfo.Message = L"7-Zip cannot open file";

+        return E_FAIL;

+      }

+    }

+  }

+  else

+  {

+    if (stdOutMode)

+      return E_FAIL;

+    volStreamSpec = new COutMultiVolStream;

+    outStream = volStreamSpec;

+    volStreamSpec->Sizes = volumesSizes;

+    volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L".");

+    volStreamSpec->TempFiles = &tempFiles;

+    volStreamSpec->Init();

+

+    /*

+    updateCallbackSpec->VolumesSizes = volumesSizes;

+    updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;

+    if (!archivePath.VolExtension.IsEmpty())

+      updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;

+    */

+  }

+

+  RINOK(SetProperties(outArchive, compressionMethod.Properties));

+

+  if (sfxMode)

+  {

+    CInFileStream *sfxStreamSpec = new CInFileStream;

+    CMyComPtr<IInStream> sfxStream(sfxStreamSpec);

+    if (!sfxStreamSpec->Open(sfxModule))

+    {

+      errorInfo.SystemError = ::GetLastError();

+      errorInfo.Message = L"7-Zip cannot open SFX module";

+      errorInfo.FileName = sfxModule;

+      return E_FAIL;

+    }

+

+    CMyComPtr<ISequentialOutStream> sfxOutStream;

+    COutFileStream *outStreamSpec = NULL;

+    if (volumesSizes.Size() == 0)

+      sfxOutStream = outStream;

+    else

+    {

+      outStreamSpec = new COutFileStream;

+      sfxOutStream = outStreamSpec;

+      UString realPath = archivePath.GetFinalPath();

+      if (!outStreamSpec->Create(realPath, false))

+      {

+        errorInfo.SystemError = ::GetLastError();

+        errorInfo.FileName = realPath;

+        errorInfo.Message = L"7-Zip cannot open file";

+        return E_FAIL;

+      }

+    }

+    RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL));

+    if (outStreamSpec)

+    {

+      RINOK(outStreamSpec->Close());

+    }

+  }

+

+  HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback);

+  callback->Finilize();

+  RINOK(result);

+  if (outStreamSpec)

+    result = outStreamSpec->Close();

+  else if (volStreamSpec)

+    result = volStreamSpec->Close();

+  return result;

+}

+

+HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,

+    const CArc &arc,

+    CObjectVector<CArcItem> &arcItems)

+{

+  arcItems.Clear();

+  UInt32 numItems;

+  IInArchive *archive = arc.Archive;

+  RINOK(archive->GetNumberOfItems(&numItems));

+  arcItems.Reserve(numItems);

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

+  {

+    CArcItem ai;

+

+    RINOK(arc.GetItemPath(i, ai.Name));

+    RINOK(IsArchiveItemFolder(archive, i, ai.IsDir));

+    ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir);

+    RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined));

+

+    {

+      CPropVariant prop;

+      RINOK(archive->GetProperty(i, kpidSize, &prop));

+      ai.SizeDefined = (prop.vt != VT_EMPTY);

+      if (ai.SizeDefined)

+        ai.Size = ConvertPropVariantToUInt64(prop);

+    }

+

+    {

+      CPropVariant prop;

+      RINOK(archive->GetProperty(i, kpidTimeType, &prop));

+      if (prop.vt == VT_UI4)

+      {

+        ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal;

+        switch(ai.TimeType)

+        {

+          case NFileTimeType::kWindows:

+          case NFileTimeType::kUnix:

+          case NFileTimeType::kDOS:

+            break;

+          default:

+            return E_FAIL;

+        }

+      }

+    }

+

+    ai.IndexInServer = i;

+    arcItems.Add(ai);

+  }

+  return S_OK;

+}

+

+

+static HRESULT UpdateWithItemLists(

+    CCodecs *codecs,

+    CUpdateOptions &options,

+    IInArchive *archive,

+    const CObjectVector<CArcItem> &arcItems,

+    CDirItems &dirItems,

+    CTempFiles &tempFiles,

+    CUpdateErrorInfo &errorInfo,

+    IUpdateCallbackUI2 *callback)

+{

+  for(int i = 0; i < options.Commands.Size(); i++)

+  {

+    CUpdateArchiveCommand &command = options.Commands[i];

+    if (options.StdOutMode)

+    {

+      RINOK(callback->StartArchive(L"stdout", archive != 0));

+    }

+    else

+    {

+      RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(),

+          i == 0 && options.UpdateArchiveItself && archive != 0));

+    }

+

+    RINOK(Compress(

+        codecs,

+        command.ActionSet, archive,

+        options.MethodMode,

+        command.ArchivePath,

+        arcItems,

+        options.OpenShareForWrite,

+        options.StdInMode,

+        /* options.StdInFileName, */

+        options.StdOutMode,

+        dirItems,

+        options.SfxMode, options.SfxModule,

+        options.VolumesSizes,

+        tempFiles,

+        errorInfo, callback));

+

+    RINOK(callback->FinishArchive());

+  }

+  return S_OK;

+}

+

+#if defined(_WIN32) && !defined(UNDER_CE)

+class CCurrentDirRestorer

+{

+  UString _path;

+public:

+  CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(_path); }

+  ~CCurrentDirRestorer() { RestoreDirectory();}

+  bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(_path)); }

+};

+#endif

+

+struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback

+{

+  IUpdateCallbackUI2 *Callback;

+  HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path)

+  {

+    return Callback->ScanProgress(numFolders, numFiles, path);

+  }

+};

+

+#ifdef _WIN32

+typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)(

+  ULONG_PTR ulUIParam,

+  LPSTR lpszDelimChar,

+  LPSTR lpszFilePaths,

+  LPSTR lpszFileNames,

+  ULONG ulReserved

+);

+typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS;

+#endif

+

+HRESULT UpdateArchive(

+    CCodecs *codecs,

+    const NWildcard::CCensor &censor,

+    CUpdateOptions &options,

+    CUpdateErrorInfo &errorInfo,

+    IOpenCallbackUI *openCallback,

+    IUpdateCallbackUI2 *callback)

+{

+  if (options.StdOutMode && options.EMailMode)

+    return E_FAIL;

+

+  if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode))

+    return E_NOTIMPL;

+

+  if (options.SfxMode)

+  {

+    CProperty property;

+    property.Name = L"rsfx";

+    property.Value = L"on";

+    options.MethodMode.Properties.Add(property);

+    if (options.SfxModule.IsEmpty())

+    {

+      errorInfo.Message = L"SFX file is not specified";

+      return E_FAIL;

+    }

+    UString name = options.SfxModule;

+    #ifdef UNDER_CE

+    if (!NFind::DoesFileExist(name))

+    #else

+    if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule))

+    #endif

+    {

+      errorInfo.SystemError = ::GetLastError();

+      errorInfo.Message = L"7-Zip cannot find specified SFX module";

+      errorInfo.FileName = name;

+      return E_FAIL;

+    }

+  }

+

+

+  CArchiveLink arcLink;

+  const UString arcPath = options.ArchivePath.GetFinalPath();

+

+  if (!options.ArchivePath.OriginalPath.IsEmpty())

+  {

+    NFind::CFileInfoW fi;

+    if (fi.Find(arcPath))

+    {

+      if (fi.IsDir())

+        throw "there is no such archive";

+      if (options.VolumesSizes.Size() > 0)

+        return E_NOTIMPL;

+      CIntVector formatIndices;

+      if (options.MethodMode.FormatIndex >= 0)

+        formatIndices.Add(options.MethodMode.FormatIndex);

+      HRESULT result = arcLink.Open2(codecs, formatIndices, false, NULL, arcPath, openCallback);

+      if (result == E_ABORT)

+        return result;

+      RINOK(callback->OpenResult(arcPath, result));

+      RINOK(result);

+      if (arcLink.VolumePaths.Size() > 1)

+      {

+        errorInfo.SystemError = (DWORD)E_NOTIMPL;

+        errorInfo.Message = L"Updating for multivolume archives is not implemented";

+        return E_NOTIMPL;

+      }

+      

+      CArc &arc = arcLink.Arcs.Back();

+      arc.MTimeDefined = !fi.IsDevice;

+      arc.MTime = fi.MTime;

+    }

+  }

+  else

+  {

+    /*

+    if (archiveType.IsEmpty())

+      throw "type of archive is not specified";

+    */

+  }

+

+  CDirItems dirItems;

+  if (options.StdInMode)

+  {

+    CDirItem di;

+    di.Name = options.StdInFileName;

+    di.Size = (UInt64)(Int64)-1;

+    di.Attrib = 0;

+    NTime::GetCurUtcFileTime(di.MTime);

+    di.CTime = di.ATime = di.MTime;

+    dirItems.Items.Add(di);

+  }

+  else

+  {

+    bool needScanning = false;

+    for(int i = 0; i < options.Commands.Size(); i++)

+      if (options.Commands[i].ActionSet.NeedScanning())

+        needScanning = true;

+    if (needScanning)

+    {

+      CEnumDirItemUpdateCallback enumCallback;

+      enumCallback.Callback = callback;

+      RINOK(callback->StartScanning());

+      UStringVector errorPaths;

+      CRecordVector<DWORD> errorCodes;

+      HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes);

+      for (int i = 0; i < errorPaths.Size(); i++)

+      {

+        RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i]));

+      }

+      if (res != S_OK)

+      {

+        if (res != E_ABORT)

+          errorInfo.Message = L"Scanning error";

+        return res;

+      }

+      RINOK(callback->FinishScanning());

+    }

+  }

+

+  UString tempDirPrefix;

+  bool usesTempDir = false;

+  

+  #ifdef _WIN32

+  NDirectory::CTempDirectoryW tempDirectory;

+  if (options.EMailMode && options.EMailRemoveAfter)

+  {

+    tempDirectory.Create(kTempFolderPrefix);

+    tempDirPrefix = tempDirectory.GetPath();

+    NormalizeDirPathPrefix(tempDirPrefix);

+    usesTempDir = true;

+  }

+  #endif

+

+  CTempFiles tempFiles;

+

+  bool createTempFile = false;

+

+  bool thereIsInArchive = arcLink.IsOpen;

+

+  if (!options.StdOutMode && options.UpdateArchiveItself)

+  {

+    CArchivePath &ap = options.Commands[0].ArchivePath;

+    ap = options.ArchivePath;

+    // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty())

+    if ((thereIsInArchive || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0)

+    {

+      createTempFile = true;

+      ap.Temp = true;

+      if (!options.WorkingDir.IsEmpty())

+      {

+        ap.TempPrefix = options.WorkingDir;

+        NormalizeDirPathPrefix(ap.TempPrefix);

+      }

+    }

+  }

+

+  for(int i = 0; i < options.Commands.Size(); i++)

+  {

+    CArchivePath &ap = options.Commands[i].ArchivePath;

+    if (usesTempDir)

+    {

+      // Check it

+      ap.Prefix = tempDirPrefix;

+      // ap.Temp = true;

+      // ap.TempPrefix = tempDirPrefix;

+    }

+    if (!options.StdOutMode &&

+        (i > 0 || !createTempFile))

+    {

+      const UString &path = ap.GetFinalPath();

+      if (NFind::DoesFileOrDirExist(path))

+      {

+        errorInfo.SystemError = 0;

+        errorInfo.Message = L"The file already exists";

+        errorInfo.FileName = path;

+        return E_FAIL;

+      }

+    }

+  }

+

+  CObjectVector<CArcItem> arcItems;

+  if (thereIsInArchive)

+  {

+    RINOK(EnumerateInArchiveItems(censor, arcLink.Arcs.Back(), arcItems));

+  }

+

+  RINOK(UpdateWithItemLists(codecs, options,

+      thereIsInArchive ? arcLink.GetArchive() : 0,

+      arcItems, dirItems,

+      tempFiles, errorInfo, callback));

+

+  if (thereIsInArchive)

+  {

+    RINOK(arcLink.Close());

+    arcLink.Release();

+  }

+

+  tempFiles.Paths.Clear();

+  if (createTempFile)

+  {

+    try

+    {

+      CArchivePath &ap = options.Commands[0].ArchivePath;

+      const UString &tempPath = ap.GetTempPath();

+      if (thereIsInArchive)

+        if (!NDirectory::DeleteFileAlways(arcPath))

+        {

+          errorInfo.SystemError = ::GetLastError();

+          errorInfo.Message = L"7-Zip cannot delete the file";

+          errorInfo.FileName = arcPath;

+          return E_FAIL;

+        }

+      if (!NDirectory::MyMoveFile(tempPath, arcPath))

+      {

+        errorInfo.SystemError = ::GetLastError();

+        errorInfo.Message = L"7-Zip cannot move the file";

+        errorInfo.FileName = tempPath;

+        errorInfo.FileName2 = arcPath;

+        return E_FAIL;

+      }

+    }

+    catch(...)

+    {

+      throw;

+    }

+  }

+

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  if (options.EMailMode)

+  {

+    NDLL::CLibrary mapiLib;

+    if (!mapiLib.Load(TEXT("Mapi32.dll")))

+    {

+      errorInfo.SystemError = ::GetLastError();

+      errorInfo.Message = L"7-Zip cannot load Mapi32.dll";

+      return E_FAIL;

+    }

+    MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");

+    if (fnSend == 0)

+    {

+      errorInfo.SystemError = ::GetLastError();

+      errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function";

+      return E_FAIL;

+    }

+    UStringVector fullPaths;

+    int i;

+    for(i = 0; i < options.Commands.Size(); i++)

+    {

+      CArchivePath &ap = options.Commands[i].ArchivePath;

+      UString arcPath;

+      if (!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath))

+      {

+        errorInfo.SystemError = ::GetLastError();

+        errorInfo.Message = L"GetFullPathName error";

+        return E_FAIL;

+      }

+      fullPaths.Add(arcPath);

+    }

+    CCurrentDirRestorer curDirRestorer;

+    for(i = 0; i < fullPaths.Size(); i++)

+    {

+      UString arcPath = fullPaths[i];

+      UString fileName = ExtractFileNameFromPath(arcPath);

+      AString path = GetAnsiString(arcPath);

+      AString name = GetAnsiString(fileName);

+      // Warning!!! MAPISendDocuments function changes Current directory

+      fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);

+    }

+  }

+  #endif

+  return S_OK;

+}

diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h
new file mode 100755
index 0000000..6bc85b5
--- /dev/null
+++ b/CPP/7zip/UI/Common/Update.h
@@ -0,0 +1,175 @@
+// Update.h

+

+#ifndef __COMMON_UPDATE_H

+#define __COMMON_UPDATE_H

+

+#include "Common/Wildcard.h"

+

+#include "ArchiveOpenCallback.h"

+#include "LoadCodecs.h"

+#include "Property.h"

+#include "UpdateAction.h"

+#include "UpdateCallback.h"

+

+struct CArchivePath

+{

+  UString OriginalPath;

+

+  UString Prefix;   // path(folder) prefix including slash

+  UString Name; // base name

+  UString BaseExtension; // archive type extension or "exe" extension

+  UString VolExtension;  // archive type extension for volumes

+

+  bool Temp;

+  UString TempPrefix;  // path(folder) for temp location

+  UString TempPostfix;

+

+  CArchivePath(): Temp(false) {};

+  

+  void ParseFromPath(const UString &path)

+  {

+    OriginalPath = path;

+

+    SplitPathToParts(path, Prefix, Name);

+    int dotPos = Name.ReverseFind(L'.');

+    if (dotPos < 0)

+      return;

+    if (dotPos == Name.Length() - 1)

+    {

+      Name = Name.Left(dotPos);

+      BaseExtension.Empty();

+      return;

+    }

+    if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0)

+    {

+      BaseExtension = Name.Mid(dotPos + 1);

+      Name = Name.Left(dotPos);

+    }

+    else

+      BaseExtension.Empty();

+  }

+

+  UString GetPathWithoutExt() const

+  {

+    return Prefix + Name;

+  }

+

+  UString GetFinalPath() const

+  {

+    UString path = GetPathWithoutExt();

+    if (!BaseExtension.IsEmpty())

+      path += UString(L'.') + BaseExtension;

+    return path;

+  }

+

+  

+  UString GetTempPath() const

+  {

+    UString path = TempPrefix + Name;

+    if (!BaseExtension.IsEmpty())

+      path += UString(L'.') + BaseExtension;

+    path += L".tmp";

+    path += TempPostfix;

+    return path;

+  }

+};

+

+struct CUpdateArchiveCommand

+{

+  UString UserArchivePath;

+  CArchivePath ArchivePath;

+  NUpdateArchive::CActionSet ActionSet;

+};

+

+struct CCompressionMethodMode

+{

+  int FormatIndex;

+  CObjectVector<CProperty> Properties;

+  CCompressionMethodMode(): FormatIndex(-1) {}

+};

+

+struct CUpdateOptions

+{

+  CCompressionMethodMode MethodMode;

+

+  CObjectVector<CUpdateArchiveCommand> Commands;

+  bool UpdateArchiveItself;

+  CArchivePath ArchivePath;

+  

+  bool SfxMode;

+  UString SfxModule;

+  

+  bool OpenShareForWrite;

+

+  bool StdInMode;

+  UString StdInFileName;

+  bool StdOutMode;

+  

+  bool EMailMode;

+  bool EMailRemoveAfter;

+  UString EMailAddress;

+

+  UString WorkingDir;

+

+  bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath);

+

+  CUpdateOptions():

+    UpdateArchiveItself(true),

+    SfxMode(false),

+    StdInMode(false),

+    StdOutMode(false),

+    EMailMode(false),

+    EMailRemoveAfter(false),

+    OpenShareForWrite(false)

+      {};

+

+  void SetAddActionCommand()

+  {

+    Commands.Clear();

+    CUpdateArchiveCommand c;

+    c.ActionSet = NUpdateArchive::kAddActionSet;

+    Commands.Add(c);

+  }

+

+  CRecordVector<UInt64> VolumesSizes;

+};

+

+struct CErrorInfo

+{

+  DWORD SystemError;

+  UString FileName;

+  UString FileName2;

+  UString Message;

+  // UStringVector ErrorPaths;

+  // CRecordVector<DWORD> ErrorCodes;

+  CErrorInfo(): SystemError(0) {};

+};

+

+struct CUpdateErrorInfo: public CErrorInfo

+{

+};

+

+#define INTERFACE_IUpdateCallbackUI2(x) \

+  INTERFACE_IUpdateCallbackUI(x) \

+  virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \

+  virtual HRESULT StartScanning() x; \

+  virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) x; \

+  virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \

+  virtual HRESULT FinishScanning() x; \

+  virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \

+  virtual HRESULT FinishArchive() x; \

+

+struct IUpdateCallbackUI2: public IUpdateCallbackUI

+{

+  INTERFACE_IUpdateCallbackUI2(=0)

+};

+

+HRESULT UpdateArchive(

+    CCodecs *codecs,

+    const NWildcard::CCensor &censor,

+    CUpdateOptions &options,

+    CUpdateErrorInfo &errorInfo,

+    IOpenCallbackUI *openCallback,

+    IUpdateCallbackUI2 *callback);

+

+#endif

diff --git a/CPP/7zip/UI/Common/UpdateAction.cpp b/CPP/7zip/UI/Common/UpdateAction.cpp
new file mode 100755
index 0000000..2e3dd62
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateAction.cpp
@@ -0,0 +1,64 @@
+// UpdateAction.cpp

+

+#include "StdAfx.h"

+

+#include "UpdateAction.h"

+

+namespace NUpdateArchive {

+

+const CActionSet kAddActionSet =

+{{

+  NPairAction::kCopy,

+  NPairAction::kCopy,

+  NPairAction::kCompress,

+  NPairAction::kCompress,

+  NPairAction::kCompress,

+  NPairAction::kCompress,

+  NPairAction::kCompress

+}};

+

+const CActionSet kUpdateActionSet =

+{{

+  NPairAction::kCopy,

+  NPairAction::kCopy,

+  NPairAction::kCompress,

+  NPairAction::kCopy,

+  NPairAction::kCompress,

+  NPairAction::kCopy,

+  NPairAction::kCompress

+}};

+

+const CActionSet kFreshActionSet =

+{{

+  NPairAction::kCopy,

+  NPairAction::kCopy,

+  NPairAction::kIgnore,

+  NPairAction::kCopy,

+  NPairAction::kCompress,

+  NPairAction::kCopy,

+  NPairAction::kCompress

+}};

+

+const CActionSet kSynchronizeActionSet =

+{{

+  NPairAction::kCopy,

+  NPairAction::kIgnore,

+  NPairAction::kCompress,

+  NPairAction::kCopy,

+  NPairAction::kCompress,

+  NPairAction::kCopy,

+  NPairAction::kCompress,

+}};

+

+const CActionSet kDeleteActionSet =

+{{

+  NPairAction::kCopy,

+  NPairAction::kIgnore,

+  NPairAction::kIgnore,

+  NPairAction::kIgnore,

+  NPairAction::kIgnore,

+  NPairAction::kIgnore,

+  NPairAction::kIgnore

+}};

+

+}

diff --git a/CPP/7zip/UI/Common/UpdateAction.h b/CPP/7zip/UI/Common/UpdateAction.h
new file mode 100755
index 0000000..7ad57ce
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateAction.h
@@ -0,0 +1,57 @@
+// UpdateAction.h

+

+#ifndef __UPDATE_ACTION_H

+#define __UPDATE_ACTION_H

+

+namespace NUpdateArchive {

+

+  namespace NPairState

+  {

+    const int kNumValues = 7;

+    enum EEnum

+    {

+      kNotMasked = 0,

+      kOnlyInArchive,

+      kOnlyOnDisk,

+      kNewInArchive,

+      kOldInArchive,

+      kSameFiles,

+      kUnknowNewerFiles

+    };

+  }

+ 

+  namespace NPairAction

+  {

+    enum EEnum

+    {

+      kIgnore = 0,

+      kCopy,

+      kCompress,

+      kCompressAsAnti

+    };

+  }

+  

+  struct CActionSet

+  {

+    NPairAction::EEnum StateActions[NPairState::kNumValues];

+    bool NeedScanning() const

+    {

+      int i;

+      for (i = 0; i < NPairState::kNumValues; i++)

+        if (StateActions[i] == NPairAction::kCompress)

+          return true;

+      for (i = 1; i < NPairState::kNumValues; i++)

+        if (StateActions[i] != NPairAction::kIgnore)

+          return true;

+      return false;

+    }

+  };

+  

+  extern const CActionSet kAddActionSet;

+  extern const CActionSet kUpdateActionSet;

+  extern const CActionSet kFreshActionSet;

+  extern const CActionSet kSynchronizeActionSet;

+  extern const CActionSet kDeleteActionSet;

+}

+

+#endif

diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp
new file mode 100755
index 0000000..55c9374
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -0,0 +1,249 @@
+// UpdateCallback.cpp

+

+#include "StdAfx.h"

+

+#include "Common/ComTry.h"

+#include "Common/Defs.h"

+#include "Common/IntToString.h"

+#include "Common/StringConvert.h"

+

+#include "Windows/PropVariant.h"

+

+#include "../../Common/FileStreams.h"

+

+#include "UpdateCallback.h"

+

+using namespace NWindows;

+

+CArchiveUpdateCallback::CArchiveUpdateCallback():

+  Callback(0),

+  ShareForWrite(false),

+  StdInMode(false),

+  DirItems(0),

+  ArcItems(0),

+  UpdatePairs(0),

+  NewNames(0)

+  {}

+

+

+STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)

+{

+  COM_TRY_BEGIN

+  return Callback->SetTotal(size);

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)

+{

+  COM_TRY_BEGIN

+  return Callback->SetCompleted(completeValue);

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)

+{

+  COM_TRY_BEGIN

+  return Callback->SetRatioInfo(inSize, outSize);

+  COM_TRY_END

+}

+

+

+/*

+STATPROPSTG kProperties[] =

+{

+  { NULL, kpidPath, VT_BSTR},

+  { NULL, kpidIsDir, VT_BOOL},

+  { NULL, kpidSize, VT_UI8},

+  { NULL, kpidCTime, VT_FILETIME},

+  { NULL, kpidATime, VT_FILETIME},

+  { NULL, kpidMTime, VT_FILETIME},

+  { NULL, kpidAttrib, VT_UI4},

+  { NULL, kpidIsAnti, VT_BOOL}

+};

+

+STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **)

+{

+  return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator);

+}

+*/

+

+STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,

+      Int32 *newData, Int32 *newProps, UInt32 *indexInArchive)

+{

+  COM_TRY_BEGIN

+  RINOK(Callback->CheckBreak());

+  const CUpdatePair2 &up = (*UpdatePairs)[index];

+  if (newData != NULL) *newData = BoolToInt(up.NewData);

+  if (newProps != NULL) *newProps = BoolToInt(up.NewProps);

+  if (indexInArchive != NULL)

+  {

+    *indexInArchive = (UInt32)-1;

+    if (up.ExistInArchive())

+      *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer;

+  }

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)

+{

+  COM_TRY_BEGIN

+  const CUpdatePair2 &up = (*UpdatePairs)[index];

+  NWindows::NCOM::CPropVariant prop;

+  

+  if (propID == kpidIsAnti)

+  {

+    prop = up.IsAnti;

+    prop.Detach(value);

+    return S_OK;

+  }

+

+  if (up.IsAnti)

+  {

+    switch(propID)

+    {

+      case kpidIsDir:

+      case kpidPath:

+        break;

+      case kpidSize:

+        prop = (UInt64)0;

+        prop.Detach(value);

+        return S_OK;

+      default:

+        prop.Detach(value);

+        return S_OK;

+    }

+  }

+  

+  if (up.ExistOnDisk())

+  {

+    const CDirItem &di = DirItems->Items[up.DirIndex];

+    switch(propID)

+    {

+      case kpidPath:  prop = DirItems->GetLogPath(up.DirIndex); break;

+      case kpidIsDir:  prop = di.IsDir(); break;

+      case kpidSize:  prop = di.Size; break;

+      case kpidAttrib:  prop = di.Attrib; break;

+      case kpidCTime:  prop = di.CTime; break;

+      case kpidATime:  prop = di.ATime; break;

+      case kpidMTime:  prop = di.MTime; break;

+    }

+  }

+  else

+  {

+    if (propID == kpidPath)

+    {

+      if (up.NewNameIndex >= 0)

+      {

+        prop = (*NewNames)[up.NewNameIndex];

+        prop.Detach(value);

+        return S_OK;

+      }

+    }

+    if (up.ExistInArchive() && Archive)

+    {

+      UInt32 indexInArchive;

+      if (ArcItems == 0)

+        indexInArchive = up.ArcIndex;

+      else

+        indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer;

+      return Archive->GetProperty(indexInArchive, propID, value);

+    }

+  }

+  prop.Detach(value);

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)

+{

+  COM_TRY_BEGIN

+  const CUpdatePair2 &up = (*UpdatePairs)[index];

+  if (!up.NewData)

+    return E_FAIL;

+  

+  RINOK(Callback->CheckBreak());

+  RINOK(Callback->Finilize());

+

+  if (up.IsAnti)

+  {

+    return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true);

+  }

+  const CDirItem &di = DirItems->Items[up.DirIndex];

+  RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false));

+ 

+  if (di.IsDir())

+    return S_OK;

+

+  if (StdInMode)

+  {

+    CStdInFileStream *inStreamSpec = new CStdInFileStream;

+    CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);

+    *inStream = inStreamLoc.Detach();

+  }

+  else

+  {

+    CInFileStream *inStreamSpec = new CInFileStream;

+    CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);

+    const UString path = DirItems->GetPhyPath(up.DirIndex);

+    if (!inStreamSpec->OpenShared(path, ShareForWrite))

+    {

+      return Callback->OpenFileError(path, ::GetLastError());

+    }

+    *inStream = inStreamLoc.Detach();

+  }

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult)

+{

+  COM_TRY_BEGIN

+  return Callback->SetOperationResult(operationResult);

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)

+{

+  if (VolumesSizes.Size() == 0)

+    return S_FALSE;

+  if (index >= (UInt32)VolumesSizes.Size())

+    index = VolumesSizes.Size() - 1;

+  *size = VolumesSizes[index];

+  return S_OK;

+}

+

+STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)

+{

+  COM_TRY_BEGIN

+  wchar_t temp[16];

+  ConvertUInt32ToString(index + 1, temp);

+  UString res = temp;

+  while (res.Length() < 2)

+    res = UString(L'0') + res;

+  UString fileName = VolName;

+  fileName += L'.';

+  fileName += res;

+  fileName += VolExt;

+  COutFileStream *streamSpec = new COutFileStream;

+  CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);

+  if (!streamSpec->Create(fileName, false))

+    return ::GetLastError();

+  *volumeStream = streamLoc.Detach();

+  return S_OK;

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)

+{

+  COM_TRY_BEGIN

+  return Callback->CryptoGetTextPassword2(passwordIsDefined, password);

+  COM_TRY_END

+}

+

+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password)

+{

+  COM_TRY_BEGIN

+  return Callback->CryptoGetTextPassword(password);

+  COM_TRY_END

+}

diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h
new file mode 100755
index 0000000..2785ee9
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateCallback.h
@@ -0,0 +1,74 @@
+// UpdateCallback.h

+

+#ifndef __UPDATECALLBACK_H

+#define __UPDATECALLBACK_H

+

+#include "Common/MyCom.h"

+#include "Common/MyString.h"

+

+#include "../../IPassword.h"

+#include "../../ICoder.h"

+

+#include "../Common/UpdatePair.h"

+#include "../Common/UpdateProduce.h"

+

+#define INTERFACE_IUpdateCallbackUI(x) \

+  virtual HRESULT SetTotal(UInt64 size) x; \

+  virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \

+  virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \

+  virtual HRESULT CheckBreak() x; \

+  virtual HRESULT Finilize() x; \

+  virtual HRESULT SetNumFiles(UInt64 numFiles) x; \

+  virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \

+  virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \

+  virtual HRESULT SetOperationResult(Int32 operationResult) x; \

+  virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \

+  virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \

+  /* virtual HRESULT ShowDeleteFile(const wchar_t *name) x; */ \

+  /* virtual HRESULT CloseProgress() { return S_OK; }; */

+

+struct IUpdateCallbackUI

+{

+  INTERFACE_IUpdateCallbackUI(=0)

+};

+

+class CArchiveUpdateCallback:

+  public IArchiveUpdateCallback2,

+  public ICryptoGetTextPassword2,

+  public ICryptoGetTextPassword,

+  public ICompressProgressInfo,

+  public CMyUnknownImp

+{

+public:

+  MY_UNKNOWN_IMP4(

+      IArchiveUpdateCallback2,

+      ICryptoGetTextPassword2,

+      ICryptoGetTextPassword,

+      ICompressProgressInfo)

+

+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);

+

+  INTERFACE_IArchiveUpdateCallback2(;)

+

+  STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);

+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);

+

+public:

+  CRecordVector<UInt64> VolumesSizes;

+  UString VolName;

+  UString VolExt;

+

+  IUpdateCallbackUI *Callback;

+

+  bool ShareForWrite;

+  bool StdInMode;

+  const CDirItems *DirItems;

+  const CObjectVector<CArcItem> *ArcItems;

+  const CRecordVector<CUpdatePair2> *UpdatePairs;

+  const UStringVector *NewNames;

+  CMyComPtr<IInArchive> Archive;

+

+  CArchiveUpdateCallback();

+};

+

+#endif

diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp
new file mode 100755
index 0000000..812bff8
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdatePair.cpp
@@ -0,0 +1,158 @@
+// UpdatePair.cpp

+

+#include "StdAfx.h"

+

+#include <time.h>

+

+#include "Common/Defs.h"

+#include "Common/Wildcard.h"

+

+#include "Windows/Time.h"

+

+#include "SortUtils.h"

+#include "UpdatePair.h"

+

+using namespace NWindows;

+using namespace NTime;

+

+static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2)

+{

+  switch(fileTimeType)

+  {

+    case NFileTimeType::kWindows:

+      return ::CompareFileTime(&time1, &time2);

+    case NFileTimeType::kUnix:

+      {

+        UInt32 unixTime1, unixTime2;

+        FileTimeToUnixTime(time1, unixTime1);

+        FileTimeToUnixTime(time2, unixTime2);

+        return MyCompare(unixTime1, unixTime2);

+      }

+    case NFileTimeType::kDOS:

+      {

+        UInt32 dosTime1, dosTime2;

+        FileTimeToDosTime(time1, dosTime1);

+        FileTimeToDosTime(time2, dosTime2);

+        return MyCompare(dosTime1, dosTime2);

+      }

+  }

+  throw 4191618;

+}

+

+static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:";

+static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):";

+

+static void ThrowError(const UString &message, const UString &s1, const UString &s2)

+{

+  UString m = message;

+  m += L'\n';

+  m += s1;

+  m += L'\n';

+  m += s2;

+  throw m;

+}

+

+static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices)

+{

+  for(int i = 0; i + 1 < indices.Size(); i++)

+    if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0)

+      ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]);

+}

+

+void GetUpdatePairInfoList(

+    const CDirItems &dirItems,

+    const CObjectVector<CArcItem> &arcItems,

+    NFileTimeType::EEnum fileTimeType,

+    CRecordVector<CUpdatePair> &updatePairs)

+{

+  CIntVector dirIndices, arcIndices;

+  

+  int numDirItems = dirItems.Items.Size();

+  int numArcItems = arcItems.Size();

+  

+  

+  {

+    UStringVector arcNames;

+    arcNames.Reserve(numArcItems);

+    for (int i = 0; i < numArcItems; i++)

+      arcNames.Add(arcItems[i].Name);

+    SortFileNames(arcNames, arcIndices);

+    TestDuplicateString(arcNames, arcIndices);

+  }

+

+  UStringVector dirNames;

+  {

+    dirNames.Reserve(numDirItems);

+    for (int i = 0; i < numDirItems; i++)

+      dirNames.Add(dirItems.GetLogPath(i));

+    SortFileNames(dirNames, dirIndices);

+    TestDuplicateString(dirNames, dirIndices);

+  }

+  

+  int dirIndex = 0, arcIndex = 0;

+  while (dirIndex < numDirItems && arcIndex < numArcItems)

+  {

+    CUpdatePair pair;

+    int dirIndex2 = dirIndices[dirIndex];

+    int arcIndex2 = arcIndices[arcIndex];

+    const CDirItem &di = dirItems.Items[dirIndex2];

+    const CArcItem &ai = arcItems[arcIndex2];

+    int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name);

+    if (compareResult < 0)

+    {

+      pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;

+      pair.DirIndex = dirIndex2;

+      dirIndex++;

+    }

+    else if (compareResult > 0)

+    {

+      pair.State = ai.Censored ?

+          NUpdateArchive::NPairState::kOnlyInArchive:

+          NUpdateArchive::NPairState::kNotMasked;

+      pair.ArcIndex = arcIndex2;

+      arcIndex++;

+    }

+    else

+    {

+      if (!ai.Censored)

+        ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name);

+      pair.DirIndex = dirIndex2;

+      pair.ArcIndex = arcIndex2;

+      switch (ai.MTimeDefined ? MyCompareTime(

+          ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType,

+          di.MTime, ai.MTime): 0)

+      {

+        case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break;

+        case 1:  pair.State = NUpdateArchive::NPairState::kOldInArchive; break;

+        default:

+          pair.State = (ai.SizeDefined && di.Size == ai.Size) ?

+              NUpdateArchive::NPairState::kSameFiles :

+              NUpdateArchive::NPairState::kUnknowNewerFiles;

+      }

+      dirIndex++;

+      arcIndex++;

+    }

+    updatePairs.Add(pair);

+  }

+

+  for (; dirIndex < numDirItems; dirIndex++)

+  {

+    CUpdatePair pair;

+    pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;

+    pair.DirIndex = dirIndices[dirIndex];

+    updatePairs.Add(pair);

+  }

+  

+  for (; arcIndex < numArcItems; arcIndex++)

+  {

+    CUpdatePair pair;

+    int arcIndex2 = arcIndices[arcIndex];

+    pair.State = arcItems[arcIndex2].Censored ?

+        NUpdateArchive::NPairState::kOnlyInArchive:

+        NUpdateArchive::NPairState::kNotMasked;

+    pair.ArcIndex = arcIndex2;

+    updatePairs.Add(pair);

+  }

+

+  updatePairs.ReserveDown();

+}

diff --git a/CPP/7zip/UI/Common/UpdatePair.h b/CPP/7zip/UI/Common/UpdatePair.h
new file mode 100755
index 0000000..5ee2665
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdatePair.h
@@ -0,0 +1,25 @@
+// UpdatePair.h

+

+#ifndef __UPDATE_PAIR_H

+#define __UPDATE_PAIR_H

+

+#include "DirItem.h"

+#include "UpdateAction.h"

+

+#include "../../Archive/IArchive.h"

+

+struct CUpdatePair

+{

+  NUpdateArchive::NPairState::EEnum State;

+  int ArcIndex;

+  int DirIndex;

+  CUpdatePair(): ArcIndex(-1), DirIndex(-1) {}

+};

+

+void GetUpdatePairInfoList(

+    const CDirItems &dirItems,

+    const CObjectVector<CArcItem> &arcItems,

+    NFileTimeType::EEnum fileTimeType,

+    CRecordVector<CUpdatePair> &updatePairs);

+

+#endif

diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp
new file mode 100755
index 0000000..3ba677d
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateProduce.cpp
@@ -0,0 +1,58 @@
+// UpdateProduce.cpp

+

+#include "StdAfx.h"

+

+#include "UpdateProduce.h"

+

+using namespace NUpdateArchive;

+

+static const char *kUpdateActionSetCollision = "Internal collision in update action set";

+

+void UpdateProduce(

+    const CRecordVector<CUpdatePair> &updatePairs,

+    const CActionSet &actionSet,

+    CRecordVector<CUpdatePair2> &operationChain,

+    IUpdateProduceCallback *callback)

+{

+  for (int i = 0; i < updatePairs.Size(); i++)

+  {

+    const CUpdatePair &pair = updatePairs[i];

+

+    CUpdatePair2 up2;

+    up2.IsAnti = false;

+    up2.DirIndex = pair.DirIndex;

+    up2.ArcIndex = pair.ArcIndex;

+    up2.NewData = up2.NewProps = true;

+    

+    switch(actionSet.StateActions[pair.State])

+    {

+      case NPairAction::kIgnore:

+        /*

+        if (pair.State != NPairState::kOnlyOnDisk)

+          IgnoreArchiveItem(m_ArchiveItems[pair.ArcIndex]);

+        // cout << "deleting";

+        */

+        if (callback)

+          callback->ShowDeleteFile(pair.ArcIndex);

+        continue;

+

+      case NPairAction::kCopy:

+        if (pair.State == NPairState::kOnlyOnDisk)

+          throw kUpdateActionSetCollision;

+        up2.NewData = up2.NewProps = false;

+        break;

+      

+      case NPairAction::kCompress:

+        if (pair.State == NPairState::kOnlyInArchive ||

+            pair.State == NPairState::kNotMasked)

+          throw kUpdateActionSetCollision;

+        break;

+      

+      case NPairAction::kCompressAsAnti:

+        up2.IsAnti = true;

+        break;

+    }

+    operationChain.Add(up2);

+  }

+  operationChain.ReserveDown();

+}

diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h
new file mode 100755
index 0000000..c511caf
--- /dev/null
+++ b/CPP/7zip/UI/Common/UpdateProduce.h
@@ -0,0 +1,35 @@
+// UpdateProduce.h

+

+#ifndef __UPDATE_PRODUCE_H

+#define __UPDATE_PRODUCE_H

+

+#include "UpdatePair.h"

+

+struct CUpdatePair2

+{

+  bool NewData;

+  bool NewProps;

+  bool IsAnti;

+  

+  int DirIndex;

+  int ArcIndex;

+  int NewNameIndex;

+

+  bool ExistOnDisk() const { return DirIndex != -1; }

+  bool ExistInArchive() const { return ArcIndex != -1; }

+

+  CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {}

+};

+

+struct IUpdateProduceCallback

+{

+  virtual HRESULT ShowDeleteFile(int arcIndex) = 0;

+};

+

+void UpdateProduce(

+    const CRecordVector<CUpdatePair> &updatePairs,

+    const NUpdateArchive::CActionSet &actionSet,

+    CRecordVector<CUpdatePair2> &operationChain,

+    IUpdateProduceCallback *callback);

+

+#endif

diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp
new file mode 100755
index 0000000..2989632
--- /dev/null
+++ b/CPP/7zip/UI/Common/WorkDir.cpp
@@ -0,0 +1,59 @@
+// WorkDir.cpp

+

+#include "StdAfx.h"

+

+#include "Common/StringConvert.h"

+#include "Common/Wildcard.h"

+

+#include "Windows/FileDir.h"

+#include "Windows/FileName.h"

+

+#include "WorkDir.h"

+

+using namespace NWindows;

+using namespace NFile;

+

+UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path)

+{

+  NWorkDir::NMode::EEnum mode = workDirInfo.Mode;

+  #ifndef UNDER_CE

+  if (workDirInfo.ForRemovableOnly)

+  {

+    mode = NWorkDir::NMode::kCurrent;

+    UString prefix = path.Left(3);

+    if (prefix[1] == L':' && prefix[2] == L'\\')

+    {

+      UINT driveType = GetDriveType(GetSystemString(prefix, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP));

+      if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE)

+        mode = workDirInfo.Mode;

+    }

+    /*

+    CParsedPath parsedPath;

+    parsedPath.ParsePath(archiveName);

+    UINT driveType = GetDriveType(parsedPath.Prefix);

+    if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE))

+      mode = NZipSettings::NWorkDir::NMode::kCurrent;

+    */

+  }

+  #endif

+  switch(mode)

+  {

+    case NWorkDir::NMode::kCurrent:

+    {

+      return ExtractDirPrefixFromPath(path);

+    }

+    case NWorkDir::NMode::kSpecified:

+    {

+      UString tempDir = workDirInfo.Path;

+      NName::NormalizeDirPathPrefix(tempDir);

+      return tempDir;

+    }

+    default:

+    {

+      UString tempDir;

+      if (!NDirectory::MyGetTempPath(tempDir))

+        throw 141717;

+      return tempDir;

+    }

+  }

+}

diff --git a/CPP/7zip/UI/Common/WorkDir.h b/CPP/7zip/UI/Common/WorkDir.h
new file mode 100755
index 0000000..8208f3a
--- /dev/null
+++ b/CPP/7zip/UI/Common/WorkDir.h
@@ -0,0 +1,10 @@
+// WorkDir.h

+

+#ifndef __WORKDIR_H

+#define __WORKDIR_H

+

+#include "ZipRegistry.h"

+

+UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path);

+

+#endif

diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h
new file mode 100755
index 0000000..1760d9b
--- /dev/null
+++ b/CPP/7zip/UI/Common/ZipRegistry.h
@@ -0,0 +1,105 @@
+// ZipRegistry.h

+

+#ifndef __ZIP_REGISTRY_H

+#define __ZIP_REGISTRY_H

+

+#include "Common/MyString.h"

+#include "Common/Types.h"

+

+#include "ExtractMode.h"

+

+namespace NExtract

+{

+  struct CInfo

+  {

+    NPathMode::EEnum PathMode;

+    NOverwriteMode::EEnum OverwriteMode;

+    bool ShowPassword;

+    UStringVector Paths;

+

+    void Save() const;

+    void Load();

+  };

+}

+

+namespace NCompression

+{

+  struct CFormatOptions

+  {

+    UInt32 Level;

+    UInt32 Dictionary;

+    UInt32 Order;

+    UInt32 BlockLogSize;

+    UInt32 NumThreads;

+    

+    CSysString FormatID;

+    UString Method;

+    UString Options;

+    UString EncryptionMethod;

+

+    void ResetForLevelChange()

+    {

+      BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1);

+      Method.Empty();

+      // Options.Empty();

+      // EncryptionMethod.Empty();

+    }

+    CFormatOptions() { ResetForLevelChange(); }

+  };

+

+  struct CInfo

+  {

+    UInt32 Level;

+    bool ShowPassword;

+    bool EncryptHeaders;

+    UString ArcType;

+    UStringVector ArcPaths;

+

+    CObjectVector<CFormatOptions> Formats;

+

+    void Save() const;

+    void Load();

+  };

+}

+

+namespace NWorkDir

+{

+  namespace NMode

+  {

+    enum EEnum

+    {

+      kSystem,

+      kCurrent,

+      kSpecified

+    };

+  }

+  struct CInfo

+  {

+    NMode::EEnum Mode;

+    UString Path;

+    bool ForRemovableOnly;

+

+    void SetForRemovableOnlyDefault() { ForRemovableOnly = true; }

+    void SetDefault()

+    {

+      Mode = NMode::kSystem;

+      Path.Empty();

+      SetForRemovableOnlyDefault();

+    }

+

+    void Save() const;

+    void Load();

+  };

+}

+

+

+struct CContextMenuInfo

+{

+  bool Cascaded;

+  UInt32 Flags;

+

+  void Save() const;

+  void Load();

+};

+

+#endif

diff --git a/CPP/7zip/UI/Console/BenchCon.cpp b/CPP/7zip/UI/Console/BenchCon.cpp
new file mode 100755
index 0000000..a31d8e0
--- /dev/null
+++ b/CPP/7zip/UI/Console/BenchCon.cpp
@@ -0,0 +1,297 @@
+// BenchCon.cpp

+

+#include "StdAfx.h"

+

+#include "../../../Common/IntToString.h"

+#include "../../../Common/MyCom.h"

+

+#if !defined(_7ZIP_ST) || defined(_WIN32)

+#include "../../../Windows/System.h"

+#endif

+

+#include "../Common/Bench.h"

+

+#include "BenchCon.h"

+#include "ConsoleClose.h"

+

+struct CTotalBenchRes

+{

+  UInt64 NumIterations;

+  UInt64 Rating;

+  UInt64 Usage;

+  UInt64 RPU;

+  void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; }

+  void Normalize()

+  {

+    if (NumIterations == 0)

+      return;

+    Rating /= NumIterations;

+    Usage /= NumIterations;

+    RPU /= NumIterations;

+    NumIterations = 1;

+  }

+  void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2)

+  {

+    Rating = (r1.Rating + r2.Rating) / 2;

+    Usage = (r1.Usage + r2.Usage) / 2;

+    RPU = (r1.RPU + r2.RPU) / 2;

+    NumIterations = (r1.NumIterations + r2.NumIterations) / 2;

+  }

+};

+

+struct CBenchCallback: public IBenchCallback

+{

+  CTotalBenchRes EncodeRes;

+  CTotalBenchRes DecodeRes;

+  FILE *f;

+  void Init() { EncodeRes.Init(); DecodeRes.Init(); }

+  void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); }

+  UInt32 dictionarySize;

+  HRESULT SetEncodeResult(const CBenchInfo &info, bool final);

+  HRESULT SetDecodeResult(const CBenchInfo &info, bool final);

+};

+

+static void NormalizeVals(UInt64 &v1, UInt64 &v2)

+{

+  while (v1 > 1000000)

+  {

+    v1 >>= 1;

+    v2 >>= 1;

+  }

+}

+

+static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)

+{

+  UInt64 elTime = elapsedTime;

+  NormalizeVals(freq, elTime);

+  if (elTime == 0)

+    elTime = 1;

+  return value * freq / elTime;

+}

+

+static void PrintNumber(FILE *f, UInt64 value, int size)

+{

+  char s[32];

+  ConvertUInt64ToString(value, s);

+  fprintf(f, " ");

+  for (int len = (int)strlen(s); len < size; len++)

+    fprintf(f, " ");

+  fputs(s, f);

+}

+

+static void PrintRating(FILE *f, UInt64 rating)

+{

+  PrintNumber(f, rating / 1000000, 6);

+}

+

+static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating)

+{

+  PrintNumber(f, (usage + 5000) / 10000, 5);

+  PrintRating(f, rpu);

+  PrintRating(f, rating);

+}

+

+

+static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res)

+{

+  UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq);

+  PrintNumber(f, speed / 1024, 7);

+  UInt64 usage = GetUsage(info);

+  UInt64 rpu = GetRatingPerUsage(info, rating);

+  PrintResults(f, usage, rpu, rating);

+  res.NumIterations++;

+  res.RPU += rpu;

+  res.Rating += rating;

+  res.Usage += usage;

+}

+

+static void PrintTotals(FILE *f, const CTotalBenchRes &res)

+{

+  fprintf(f, "       ");

+  PrintResults(f, res.Usage, res.RPU, res.Rating);

+}

+

+

+HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final)

+{

+  if (NConsoleClose::TestBreakSignal())

+    return E_ABORT;

+  if (final)

+  {

+    UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize);

+    PrintResults(f, info, rating, EncodeRes);

+  }

+  return S_OK;

+}

+

+static const char *kSep = "  | ";

+

+

+HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final)

+{

+  if (NConsoleClose::TestBreakSignal())

+    return E_ABORT;

+  if (final)

+  {

+    UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations);

+    fputs(kSep, f);

+    CBenchInfo info2 = info;

+    info2.UnpackSize *= info2.NumIterations;

+    info2.PackSize *= info2.NumIterations;

+    info2.NumIterations = 1;

+    PrintResults(f, info2, rating, DecodeRes);

+  }

+  return S_OK;

+}

+

+static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads)

+{

+  fprintf(f, "\nRAM %s ", sizeString);

+  PrintNumber(f, (size >> 20), 5);

+  fprintf(f, " MB,  # %s %3d", threadsString, (unsigned int)numThreads);

+}

+

+HRESULT LzmaBenchCon(

+  DECL_EXTERNAL_CODECS_LOC_VARS

+  FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)

+{

+  if (!CrcInternalTest())

+    return S_FALSE;

+  #ifndef _7ZIP_ST

+  UInt64 ramSize = NWindows::NSystem::GetRamSize();  //

+  UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();

+  PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);

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

+    numThreads = numCPUs;

+  if (numThreads > 1)

+    numThreads &= ~1;

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

+  {

+    int dicSizeLog;

+    for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)

+      if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)

+        break;

+    dictionary = (1 << dicSizeLog);

+  }

+  #else

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

+    dictionary = (1 << 22);

+  numThreads = 1;

+  #endif

+

+  PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads:   ", numThreads);

+

+  CBenchCallback callback;

+  callback.Init();

+  callback.f = f;

+  

+  fprintf(f, "\n\nDict        Compressing          |        Decompressing\n   ");

+  int j;

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

+  {

+    fprintf(f, "   Speed Usage    R/U Rating");

+    if (j == 0)

+      fputs(kSep, f);

+  }

+  fprintf(f, "\n   ");

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

+  {

+    fprintf(f, "    KB/s     %%   MIPS   MIPS");

+    if (j == 0)

+      fputs(kSep, f);

+  }

+  fprintf(f, "\n\n");

+  for (UInt32 i = 0; i < numIterations; i++)

+  {

+    const int kStartDicLog = 22;

+    int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog;

+    while (((UInt32)1 << pow) > dictionary)

+      pow--;

+    for (; ((UInt32)1 << pow) <= dictionary; pow++)

+    {

+      fprintf(f, "%2d:", pow);

+      callback.dictionarySize = (UInt32)1 << pow;

+      HRESULT res = LzmaBench(

+        EXTERNAL_CODECS_LOC_VARS

+        numThreads, callback.dictionarySize, &callback);

+      fprintf(f, "\n");

+      RINOK(res);

+    }

+  }

+  callback.Normalize();

+  fprintf(f, "----------------------------------------------------------------\nAvr:");

+  PrintTotals(f, callback.EncodeRes);

+  fprintf(f, "     ");

+  PrintTotals(f, callback.DecodeRes);

+  fprintf(f, "\nTot:");

+  CTotalBenchRes midRes;

+  midRes.SetMid(callback.EncodeRes, callback.DecodeRes);

+  PrintTotals(f, midRes);

+  fprintf(f, "\n");

+  return S_OK;

+}

+

+struct CTempValues

+{

+  UInt64 *Values;

+  CTempValues(UInt32 num) { Values = new UInt64[num]; }

+  ~CTempValues() { delete []Values; }

+};

+

+HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)

+{

+  if (!CrcInternalTest())

+    return S_FALSE;

+

+  #ifndef _7ZIP_ST

+  UInt64 ramSize = NWindows::NSystem::GetRamSize();

+  UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();

+  PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);

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

+    numThreads = numCPUs;

+  #else

+  numThreads = 1;

+  #endif

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

+    dictionary = (1 << 24);

+

+  CTempValues speedTotals(numThreads);

+  fprintf(f, "\n\nSize");

+  for (UInt32 ti = 0; ti < numThreads; ti++)

+  {

+    fprintf(f, " %5d", ti + 1);

+    speedTotals.Values[ti] = 0;

+  }

+  fprintf(f, "\n\n");

+

+  UInt64 numSteps = 0;

+  for (UInt32 i = 0; i < numIterations; i++)

+  {

+    for (int pow = 10; pow < 32; pow++)

+    {

+      UInt32 bufSize = (UInt32)1 << pow;

+      if (bufSize > dictionary)

+        break;

+      fprintf(f, "%2d: ", pow);

+      UInt64 speed;

+      for (UInt32 ti = 0; ti < numThreads; ti++)

+      {

+        if (NConsoleClose::TestBreakSignal())

+          return E_ABORT;

+        RINOK(CrcBench(ti + 1, bufSize, speed));

+        PrintNumber(f, (speed >> 20), 5);

+        speedTotals.Values[ti] += speed;

+      }

+      fprintf(f, "\n");

+      numSteps++;

+    }

+  }

+  if (numSteps != 0)

+  {

+    fprintf(f, "\nAvg:");

+    for (UInt32 ti = 0; ti < numThreads; ti++)

+      PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5);

+    fprintf(f, "\n");

+  }

+  return S_OK;

+}

diff --git a/CPP/7zip/UI/Console/BenchCon.h b/CPP/7zip/UI/Console/BenchCon.h
new file mode 100755
index 0000000..c5eafbf
--- /dev/null
+++ b/CPP/7zip/UI/Console/BenchCon.h
@@ -0,0 +1,16 @@
+// BenchCon.h

+

+#ifndef __BENCH_CON_H

+#define __BENCH_CON_H

+

+#include <stdio.h>

+

+#include "../../Common/CreateCoder.h"

+

+HRESULT LzmaBenchCon(

+    DECL_EXTERNAL_CODECS_LOC_VARS

+    FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary);

+

+HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary);

+

+#endif

diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp
new file mode 100755
index 0000000..9fbad17
--- /dev/null
+++ b/CPP/7zip/UI/Console/ConsoleClose.cpp
@@ -0,0 +1,73 @@
+// ConsoleClose.cpp

+

+#include "StdAfx.h"

+

+#include "ConsoleClose.h"

+

+static int g_BreakCounter = 0;

+static const int kBreakAbortThreshold = 2;

+

+namespace NConsoleClose {

+

+#if !defined(UNDER_CE) && defined(_WIN32)

+static BOOL WINAPI HandlerRoutine(DWORD ctrlType)

+{

+  if (ctrlType == CTRL_LOGOFF_EVENT)

+  {

+    // printf("\nCTRL_LOGOFF_EVENT\n");

+    return TRUE;

+  }

+

+  g_BreakCounter++;

+  if (g_BreakCounter < kBreakAbortThreshold)

+    return TRUE;

+  return FALSE;

+  /*

+  switch(ctrlType)

+  {

+    case CTRL_C_EVENT:

+    case CTRL_BREAK_EVENT:

+      if (g_BreakCounter < kBreakAbortThreshold)

+      return TRUE;

+  }

+  return FALSE;

+  */

+}

+#endif

+

+bool TestBreakSignal()

+{

+  #ifdef UNDER_CE

+  return false;

+  #else

+  /*

+  if (g_BreakCounter > 0)

+    return true;

+  */

+  return (g_BreakCounter > 0);

+  #endif

+}

+

+void CheckCtrlBreak()

+{

+  if (TestBreakSignal())

+    throw CCtrlBreakException();

+}

+

+CCtrlHandlerSetter::CCtrlHandlerSetter()

+{

+  #if !defined(UNDER_CE) && defined(_WIN32)

+  if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE))

+    throw "SetConsoleCtrlHandler fails";

+  #endif

+}

+

+CCtrlHandlerSetter::~CCtrlHandlerSetter()

+{

+  #if !defined(UNDER_CE) && defined(_WIN32)

+  if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE))

+    throw "SetConsoleCtrlHandler fails";

+  #endif

+}

+

+}

diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h
new file mode 100755
index 0000000..7101018
--- /dev/null
+++ b/CPP/7zip/UI/Console/ConsoleClose.h
@@ -0,0 +1,24 @@
+// ConsoleCloseUtils.h

+

+#ifndef __CONSOLECLOSEUTILS_H

+#define __CONSOLECLOSEUTILS_H

+

+namespace NConsoleClose {

+

+bool TestBreakSignal();

+

+class CCtrlHandlerSetter

+{

+public:

+  CCtrlHandlerSetter();

+  virtual ~CCtrlHandlerSetter();

+};

+

+class CCtrlBreakException

+{};

+

+void CheckCtrlBreak();

+

+}

+

+#endif

diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
new file mode 100755
index 0000000..278b069
--- /dev/null
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
@@ -0,0 +1,228 @@
+// ExtractCallbackConsole.h

+

+#include "StdAfx.h"

+

+#include "ExtractCallbackConsole.h"

+#include "UserInputUtils.h"

+#include "ConsoleClose.h"

+

+#include "Common/Wildcard.h"

+

+#include "Windows/FileDir.h"

+#include "Windows/FileFind.h"

+#include "Windows/Time.h"

+#include "Windows/Defs.h"

+#include "Windows/PropVariant.h"

+#include "Windows/Error.h"

+#include "Windows/PropVariantConversions.h"

+

+#include "../../Common/FilePathAutoRename.h"

+

+#include "../Common/ExtractingFilePath.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NDirectory;

+

+static const char *kTestString    =  "Testing     ";

+static const char *kExtractString =  "Extracting  ";

+static const char *kSkipString   =  "Skipping    ";

+

+// static const char *kCantAutoRename = "can not create file with auto name\n";

+// static const char *kCantRenameFile = "can not rename existing file\n";

+// static const char *kCantDeleteOutputFile = "can not delete output file ";

+static const char *kError = "ERROR: ";

+static const char *kMemoryExceptionMessage = "Can't allocate required memory!";

+

+static const char *kProcessing = "Processing archive: ";

+static const char *kEverythingIsOk = "Everything is Ok";

+static const char *kNoFiles = "No files to process";

+

+static const char *kUnsupportedMethod = "Unsupported Method";

+static const char *kCrcFailed = "CRC Failed";

+static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";

+static const char *kDataError = "Data Error";

+static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";

+static const char *kUnknownError = "Unknown Error";

+

+STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64)

+{

+  if (NConsoleClose::TestBreakSignal())

+    return E_ABORT;

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *)

+{

+  if (NConsoleClose::TestBreakSignal())

+    return E_ABORT;

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackConsole::AskOverwrite(

+    const wchar_t *existName, const FILETIME *, const UInt64 *,

+    const wchar_t *newName, const FILETIME *, const UInt64 *,

+    Int32 *answer)

+{

+  (*OutStream) << "file " << existName <<

+    "\nalready exists. Overwrite with " << endl;

+  (*OutStream) << newName;

+  

+  NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream);

+  

+  switch(overwriteAnswer)

+  {

+    case NUserAnswerMode::kQuit:  return E_ABORT;

+    case NUserAnswerMode::kNo:     *answer = NOverwriteAnswer::kNo; break;

+    case NUserAnswerMode::kNoAll:  *answer = NOverwriteAnswer::kNoToAll; break;

+    case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break;

+    case NUserAnswerMode::kYes:    *answer = NOverwriteAnswer::kYes; break;

+    case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break;

+    default: return E_FAIL;

+  }

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position)

+{

+  switch (askExtractMode)

+  {

+    case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractString; break;

+    case NArchive::NExtract::NAskMode::kTest:    (*OutStream) << kTestString; break;

+    case NArchive::NExtract::NAskMode::kSkip:    (*OutStream) << kSkipString; break;

+  };

+  (*OutStream) << name;

+  if (position != 0)

+    (*OutStream) << " <" << *position << ">";

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)

+{

+  (*OutStream) << message << endl;

+  NumFileErrorsInCurrentArchive++;

+  NumFileErrors++;

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted)

+{

+  switch(operationResult)

+  {

+    case NArchive::NExtract::NOperationResult::kOK:

+      break;

+    default:

+    {

+      NumFileErrorsInCurrentArchive++;

+      NumFileErrors++;

+      (*OutStream) << "     ";

+      switch(operationResult)

+      {

+        case NArchive::NExtract::NOperationResult::kUnSupportedMethod:

+          (*OutStream) << kUnsupportedMethod;

+          break;

+        case NArchive::NExtract::NOperationResult::kCRCError:

+          (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed);

+          break;

+        case NArchive::NExtract::NOperationResult::kDataError:

+          (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError);

+          break;

+        default:

+          (*OutStream) << kUnknownError;

+      }

+    }

+  }

+  (*OutStream) << endl;

+  return S_OK;

+}

+

+#ifndef _NO_CRYPTO

+

+HRESULT CExtractCallbackConsole::SetPassword(const UString &password)

+{

+  PasswordIsDefined = true;

+  Password = password;

+  return S_OK;

+}

+

+STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)

+{

+  if (!PasswordIsDefined)

+  {

+    Password = GetPassword(OutStream);

+    PasswordIsDefined = true;

+  }

+  return StringToBstr(Password, password);

+}

+

+#endif

+

+HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name)

+{

+  NumArchives++;

+  NumFileErrorsInCurrentArchive = 0;

+  (*OutStream) << endl << kProcessing << name << endl;

+  return S_OK;

+}

+

+HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted)

+{

+  (*OutStream) << endl;

+  if (result != S_OK)

+  {

+    (*OutStream) << "Error: ";

+    if (result == S_FALSE)

+    {

+      (*OutStream) << (encrypted ?

+        "Can not open encrypted archive. Wrong password?" :

+        "Can not open file as archive");

+    }

+    else

+    {

+      if (result == E_OUTOFMEMORY)

+        (*OutStream) << "Can't allocate required memory";

+      else

+        (*OutStream) << NError::MyFormatMessage(result);

+    }

+    (*OutStream) << endl;

+    NumArchiveErrors++;

+  }

+  return S_OK;

+}

+  

+HRESULT CExtractCallbackConsole::ThereAreNoFiles()

+{

+  (*OutStream) << endl << kNoFiles << endl;

+  return S_OK;

+}

+

+HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)

+{

+  if (result == S_OK)

+  {

+    (*OutStream) << endl;

+    if (NumFileErrorsInCurrentArchive == 0)

+      (*OutStream) << kEverythingIsOk << endl;

+    else

+    {

+      NumArchiveErrors++;

+      (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl;

+    }

+  }

+  if (result == S_OK)

+    return result;

+  NumArchiveErrors++;

+  if (result == E_ABORT || result == ERROR_DISK_FULL)

+    return result;

+  (*OutStream) << endl << kError;

+  if (result == E_OUTOFMEMORY)

+    (*OutStream) << kMemoryExceptionMessage;

+  else

+  {

+    UString message;

+    NError::MyFormatMessage(result, message);

+    (*OutStream) << message;

+  }

+  (*OutStream) << endl;

+  return S_OK;

+}

diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
new file mode 100755
index 0000000..7086527
--- /dev/null
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
@@ -0,0 +1,73 @@
+// ExtractCallbackConsole.h

+

+#ifndef __EXTRACTCALLBACKCONSOLE_H

+#define __EXTRACTCALLBACKCONSOLE_H

+

+#include "Common/MyString.h"

+#include "Common/StdOutStream.h"

+#include "../../Common/FileStreams.h"

+#include "../../IPassword.h"

+#include "../../Archive/IArchive.h"

+#include "../Common/ArchiveExtractCallback.h"

+

+class CExtractCallbackConsole:

+  public IExtractCallbackUI,

+  #ifndef _NO_CRYPTO

+  public ICryptoGetTextPassword,

+  #endif

+  public CMyUnknownImp

+{

+public:

+  MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)

+  #ifndef _NO_CRYPTO

+  MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)

+  #endif

+  MY_QUERYINTERFACE_END

+  MY_ADDREF_RELEASE

+

+  STDMETHOD(SetTotal)(UInt64 total);

+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);

+

+  // IFolderArchiveExtractCallback

+  STDMETHOD(AskOverwrite)(

+      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,

+      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,

+      Int32 *answer);

+  STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);

+

+  STDMETHOD(MessageError)(const wchar_t *message);

+  STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);

+

+  HRESULT BeforeOpen(const wchar_t *name);

+  HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);

+  HRESULT ThereAreNoFiles();

+  HRESULT ExtractResult(HRESULT result);

+

+ 

+  #ifndef _NO_CRYPTO

+  HRESULT SetPassword(const UString &password);

+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);

+

+  bool PasswordIsDefined;

+  UString Password;

+

+  #endif

+  

+  UInt64 NumArchives;

+  UInt64 NumArchiveErrors;

+  UInt64 NumFileErrors;

+  UInt64 NumFileErrorsInCurrentArchive;

+

+  CStdOutStream *OutStream;

+

+  void Init()

+  {

+    NumArchives = 0;

+    NumArchiveErrors = 0;

+    NumFileErrors = 0;

+    NumFileErrorsInCurrentArchive = 0;

+  }

+

+};

+

+#endif

diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
new file mode 100755
index 0000000..298adbd
--- /dev/null
+++ b/CPP/7zip/UI/Console/List.cpp
@@ -0,0 +1,654 @@
+// List.cpp

+

+#include "StdAfx.h"

+

+#include "Common/IntToString.h"

+#include "Common/MyCom.h"

+#include "Common/StdOutStream.h"

+#include "Common/StringConvert.h"

+

+#include "Windows/Error.h"

+#include "Windows/FileDir.h"

+#include "Windows/PropVariant.h"

+#include "Windows/PropVariantConversions.h"

+

+#include "../../Archive/IArchive.h"

+

+#include "../Common/OpenArchive.h"

+#include "../Common/PropIDUtils.h"

+

+#include "ConsoleClose.h"

+#include "List.h"

+#include "OpenCallbackConsole.h"

+

+using namespace NWindows;

+

+struct CPropIdToName

+{

+  PROPID PropID;

+  const wchar_t *Name;

+};

+

+static const CPropIdToName kPropIdToName[] =

+{

+  { kpidPath, L"Path" },

+  { kpidName, L"Name" },

+  { kpidIsDir, L"Folder" },

+  { kpidSize, L"Size" },

+  { kpidPackSize, L"Packed Size" },

+  { kpidAttrib, L"Attributes" },

+  { kpidCTime, L"Created" },

+  { kpidATime, L"Accessed" },

+  { kpidMTime, L"Modified" },

+  { kpidSolid, L"Solid" },

+  { kpidCommented, L"Commented" },

+  { kpidEncrypted, L"Encrypted" },

+  { kpidSplitBefore, L"Split Before" },

+  { kpidSplitAfter, L"Split After" },

+  { kpidDictionarySize, L"Dictionary Size" },

+  { kpidCRC, L"CRC" },

+  { kpidType, L"Type" },

+  { kpidIsAnti, L"Anti" },

+  { kpidMethod, L"Method" },

+  { kpidHostOS, L"Host OS" },

+  { kpidFileSystem, L"File System" },

+  { kpidUser, L"User" },

+  { kpidGroup, L"Group" },

+  { kpidBlock, L"Block" },

+  { kpidComment, L"Comment" },

+  { kpidPosition, L"Position" },

+  { kpidPrefix, L"Prefix" },

+  { kpidNumSubDirs, L"Folders" },

+  { kpidNumSubFiles, L"Files" },

+  { kpidUnpackVer, L"Version" },

+  { kpidVolume, L"Volume" },

+  { kpidIsVolume, L"Multivolume" },

+  { kpidOffset, L"Offset" },

+  { kpidLinks, L"Links" },

+  { kpidNumBlocks, L"Blocks" },

+  { kpidNumVolumes, L"Volumes" },

+

+  { kpidBit64, L"64-bit" },

+  { kpidBigEndian, L"Big-endian" },

+  { kpidCpu, L"CPU" },

+  { kpidPhySize, L"Physical Size" },

+  { kpidHeadersSize, L"Headers Size" },

+  { kpidChecksum, L"Checksum" },

+  { kpidCharacts, L"Characteristics" },

+  { kpidVa, L"Virtual Address" },

+  { kpidId, L"ID" },

+  { kpidShortName, L"Short Name" },

+  { kpidCreatorApp, L"Creator Application"},

+  { kpidSectorSize, L"Sector Size" },

+  { kpidPosixAttrib, L"Mode" },

+  { kpidLink, L"Link" },

+  { kpidError, L"Error" },

+

+  { kpidTotalSize, L"Total Size" },

+  { kpidFreeSpace, L"Free Space" },

+  { kpidClusterSize, L"Cluster Size" },

+  { kpidVolumeName, L"Label" }

+};

+

+static const char kEmptyAttribChar = '.';

+

+static const char *kListing = "Listing archive: ";

+static const wchar_t *kFilesMessage = L"files";

+static const wchar_t *kDirsMessage = L"folders";

+

+static void GetAttribString(DWORD wa, bool isDir, char *s)

+{

+  s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar;

+  s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar;

+  s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar;

+  s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar;

+  s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar;

+  s[5] = '\0';

+}

+

+enum EAdjustment

+{

+  kLeft,

+  kCenter,

+  kRight

+};

+

+struct CFieldInfo

+{

+  PROPID PropID;

+  UString Name;

+  EAdjustment TitleAdjustment;

+  EAdjustment TextAdjustment;

+  int PrefixSpacesWidth;

+  int Width;

+};

+

+struct CFieldInfoInit

+{

+  PROPID PropID;

+  const wchar_t *Name;

+  EAdjustment TitleAdjustment;

+  EAdjustment TextAdjustment;

+  int PrefixSpacesWidth;

+  int Width;

+};

+

+static CFieldInfoInit kStandardFieldTable[] =

+{

+  { kpidMTime, L"   Date      Time", kLeft, kLeft, 0, 19 },

+  { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 },

+  { kpidSize, L"Size", kRight, kRight, 1, 12 },

+  { kpidPackSize, L"Compressed", kRight, kRight, 1, 12 },

+  { kpidPath, L"Name", kLeft, kLeft, 2, 24 }

+};

+

+static void PrintSpaces(int numSpaces)

+{

+  for (int i = 0; i < numSpaces; i++)

+    g_StdOut << ' ';

+}

+

+static void PrintString(EAdjustment adjustment, int width, const UString &textString)

+{

+  const int numSpaces = width - textString.Length();

+  int numLeftSpaces = 0;

+  switch (adjustment)

+  {

+    case kLeft:

+      numLeftSpaces = 0;

+      break;

+    case kCenter:

+      numLeftSpaces = numSpaces / 2;

+      break;

+    case kRight:

+      numLeftSpaces = numSpaces;

+      break;

+  }

+  PrintSpaces(numLeftSpaces);

+  g_StdOut << textString;

+  PrintSpaces(numSpaces - numLeftSpaces);

+}

+

+class CFieldPrinter

+{

+  CObjectVector<CFieldInfo> _fields;

+public:

+  void Clear() { _fields.Clear(); }

+  void Init(const CFieldInfoInit *standardFieldTable, int numItems);

+  HRESULT Init(IInArchive *archive);

+  void PrintTitle();

+  void PrintTitleLines();

+  HRESULT PrintItemInfo(const CArc &arc, UInt32 index, bool techMode);

+  HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,

+      const UInt64 *size, const UInt64 *compressedSize);

+};

+

+void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)

+{

+  Clear();

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

+  {

+    CFieldInfo fieldInfo;

+    const CFieldInfoInit &fieldInfoInit = standardFieldTable[i];

+    fieldInfo.PropID = fieldInfoInit.PropID;

+    fieldInfo.Name = fieldInfoInit.Name;

+    fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment;

+    fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment;

+    fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth;

+    fieldInfo.Width = fieldInfoInit.Width;

+    _fields.Add(fieldInfo);

+  }

+}

+

+static UString GetPropName(PROPID propID, BSTR name)

+{

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

+  {

+    const CPropIdToName &propIdToName = kPropIdToName[i];

+    if (propIdToName.PropID == propID)

+      return propIdToName.Name;

+  }

+  if (name)

+    return name;

+  wchar_t s[16];

+  ConvertUInt32ToString(propID, s);

+  return s;

+}

+

+HRESULT CFieldPrinter::Init(IInArchive *archive)

+{

+  Clear();

+  UInt32 numProps;

+  RINOK(archive->GetNumberOfProperties(&numProps));

+  for (UInt32 i = 0; i < numProps; i++)

+  {

+    CMyComBSTR name;

+    PROPID propID;

+    VARTYPE vt;

+    RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt));

+    CFieldInfo fieldInfo;

+    fieldInfo.PropID = propID;

+    fieldInfo.Name = GetPropName(propID, name);

+    _fields.Add(fieldInfo);

+  }

+  return S_OK;

+}

+

+void CFieldPrinter::PrintTitle()

+{

+  for (int i = 0; i < _fields.Size(); i++)

+  {

+    const CFieldInfo &fieldInfo = _fields[i];

+    PrintSpaces(fieldInfo.PrefixSpacesWidth);

+    PrintString(fieldInfo.TitleAdjustment,

+      ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name);

+  }

+}

+

+void CFieldPrinter::PrintTitleLines()

+{

+  for (int i = 0; i < _fields.Size(); i++)

+  {

+    const CFieldInfo &fieldInfo = _fields[i];

+    PrintSpaces(fieldInfo.PrefixSpacesWidth);

+    for (int i = 0; i < fieldInfo.Width; i++)

+      g_StdOut << '-';

+  }

+}

+

+

+static BOOL IsFileTimeZero(CONST FILETIME *lpFileTime)

+{

+  return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0);

+}

+

+static const char *kEmptyTimeString = "                   ";

+static void PrintTime(const NCOM::CPropVariant &prop)

+{

+  if (prop.vt != VT_FILETIME)

+    throw "incorrect item";

+  if (IsFileTimeZero(&prop.filetime))

+    g_StdOut << kEmptyTimeString;

+  else

+  {

+    FILETIME localFileTime;

+    if (!FileTimeToLocalFileTime(&prop.filetime, &localFileTime))

+      throw "FileTimeToLocalFileTime error";

+    char s[32];

+    if (ConvertFileTimeToString(localFileTime, s, true, true))

+      g_StdOut << s;

+    else

+      g_StdOut << kEmptyTimeString;

+  }

+}

+

+HRESULT CFieldPrinter::PrintItemInfo(const CArc &arc, UInt32 index, bool techMode)

+{

+  /*

+  if (techMode)

+  {

+    g_StdOut << "Index = ";

+    g_StdOut << (UInt64)index;

+    g_StdOut << endl;

+  }

+  */

+  for (int i = 0; i < _fields.Size(); i++)

+  {

+    const CFieldInfo &fieldInfo = _fields[i];

+    if (!techMode)

+      PrintSpaces(fieldInfo.PrefixSpacesWidth);

+

+    NCOM::CPropVariant prop;

+    if (fieldInfo.PropID == kpidPath)

+    {

+      UString s;

+      RINOK(arc.GetItemPath(index, s));

+      prop = s;

+    }

+    else

+    {

+      RINOK(arc.Archive->GetProperty(index, fieldInfo.PropID, &prop));

+    }

+    if (techMode)

+    {

+      g_StdOut << fieldInfo.Name << " = ";

+    }

+    int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width;

+    if (fieldInfo.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4))

+    {

+      UInt32 attrib = (prop.vt == VT_EMPTY) ? 0 : prop.ulVal;

+      bool isFolder;

+      RINOK(IsArchiveItemFolder(arc.Archive, index, isFolder));

+      char s[8];

+      GetAttribString(attrib, isFolder, s);

+      g_StdOut << s;

+    }

+    else if (prop.vt == VT_EMPTY)

+    {

+      if (!techMode)

+        PrintSpaces(width);

+    }

+    else if (fieldInfo.PropID == kpidMTime)

+    {

+      PrintTime(prop);

+    }

+    else if (prop.vt == VT_BSTR)

+    {

+      if (techMode)

+        g_StdOut << prop.bstrVal;

+      else

+        PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal);

+    }

+    else

+    {

+      UString s = ConvertPropertyToString(prop, fieldInfo.PropID);

+      s.Replace(wchar_t(0xA), L' ');

+      s.Replace(wchar_t(0xD), L' ');

+

+      if (techMode)

+        g_StdOut << s;

+      else

+        PrintString(fieldInfo.TextAdjustment, width, s);

+    }

+    if (techMode)

+      g_StdOut << endl;

+  }

+  return S_OK;

+}

+

+static void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value)

+{

+  wchar_t textString[32] = { 0 };

+  if (value != NULL)

+    ConvertUInt64ToString(*value, textString);

+  PrintString(adjustment, width, textString);

+}

+

+

+HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,

+    const UInt64 *size, const UInt64 *compressedSize)

+{

+  for (int i = 0; i < _fields.Size(); i++)

+  {

+    const CFieldInfo &fieldInfo = _fields[i];

+    PrintSpaces(fieldInfo.PrefixSpacesWidth);

+    NCOM::CPropVariant prop;

+    if (fieldInfo.PropID == kpidSize)

+      PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size);

+    else if (fieldInfo.PropID == kpidPackSize)

+      PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize);

+    else if (fieldInfo.PropID == kpidPath)

+    {

+      wchar_t textString[32];

+      ConvertUInt64ToString(numFiles, textString);

+      UString temp = textString;

+      temp += L" ";

+      temp += kFilesMessage;

+      temp += L", ";

+      ConvertUInt64ToString(numDirs, textString);

+      temp += textString;

+      temp += L" ";

+      temp += kDirsMessage;

+      PrintString(fieldInfo.TextAdjustment, 0, temp);

+    }

+    else

+      PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L"");

+  }

+  return S_OK;

+}

+

+bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value)

+{

+  NCOM::CPropVariant prop;

+  if (archive->GetProperty(index, propID, &prop) != S_OK)

+    throw "GetPropertyValue error";

+  if (prop.vt == VT_EMPTY)

+    return false;

+  value = ConvertPropVariantToUInt64(prop);

+  return true;

+}

+

+static void PrintPropPair(const wchar_t *name, const wchar_t *value)

+{

+  g_StdOut << name << " = " << value << endl;

+}

+

+HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,

+    bool stdInMode,

+    UStringVector &arcPaths, UStringVector &arcPathsFull,

+    const NWildcard::CCensorNode &wildcardCensor,

+    bool enableHeaders, bool techMode,

+    #ifndef _NO_CRYPTO

+    bool &passwordEnabled, UString &password,

+    #endif

+    UInt64 &numErrors)

+{

+  numErrors = 0;

+  CFieldPrinter fieldPrinter;

+  if (!techMode)

+    fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));

+

+  UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;

+  UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;

+  int numArcs = /* stdInMode ? 1 : */ arcPaths.Size();

+  for (int i = 0; i < numArcs; i++)

+  {

+    const UString &archiveName = arcPaths[i];

+    UInt64 arcPackSize = 0;

+    if (!stdInMode)

+    {

+      NFile::NFind::CFileInfoW fi;

+      if (!fi.Find(archiveName) || fi.IsDir())

+      {

+        g_StdOut << endl << "Error: " << archiveName << " is not file" << endl;

+        numErrors++;

+        continue;

+      }

+      arcPackSize = fi.Size;

+    }

+

+    CArchiveLink archiveLink;

+

+    COpenCallbackConsole openCallback;

+    openCallback.OutStream = &g_StdOut;

+

+    #ifndef _NO_CRYPTO

+

+    openCallback.PasswordIsDefined = passwordEnabled;

+    openCallback.Password = password;

+

+    #endif

+

+    HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archiveName, &openCallback);

+    if (result != S_OK)

+    {

+      if (result == E_ABORT)

+        return result;

+      g_StdOut << endl << "Error: " << archiveName << ": ";

+      if (result == S_FALSE)

+      {

+        #ifndef _NO_CRYPTO

+        if (openCallback.Open_WasPasswordAsked())

+          g_StdOut << "Can not open encrypted archive. Wrong password?";

+        else

+        #endif

+          g_StdOut << "Can not open file as archive";

+      }

+      else if (result == E_OUTOFMEMORY)

+        g_StdOut << "Can't allocate required memory";

+      else

+        g_StdOut << NError::MyFormatMessage(result);

+      g_StdOut << endl;

+      numErrors++;

+      continue;

+    }

+

+    if (!stdInMode)

+    for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)

+    {

+      int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);

+      if (index >= 0 && index > i)

+      {

+        arcPaths.Delete(index);

+        arcPathsFull.Delete(index);

+        numArcs = arcPaths.Size();

+      }

+    }

+

+    if (enableHeaders)

+    {

+      g_StdOut << endl << kListing << archiveName << endl << endl;

+

+      for (int i = 0; i < archiveLink.Arcs.Size(); i++)

+      {

+        const CArc &arc = archiveLink.Arcs[i];

+        

+        g_StdOut << "--\n";

+        PrintPropPair(L"Path", arc.Path);

+        PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name);

+        if (!arc.ErrorMessage.IsEmpty())

+          PrintPropPair(L"Error", arc.ErrorMessage);

+        UInt32 numProps;

+        IInArchive *archive = arc.Archive;

+        if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK)

+        {

+          for (UInt32 j = 0; j < numProps; j++)

+          {

+            CMyComBSTR name;

+            PROPID propID;

+            VARTYPE vt;

+            RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt));

+            NCOM::CPropVariant prop;

+            RINOK(archive->GetArchiveProperty(propID, &prop));

+            UString s = ConvertPropertyToString(prop, propID);

+            if (!s.IsEmpty())

+              PrintPropPair(GetPropName(propID, name), s);

+          }

+        }

+        if (i != archiveLink.Arcs.Size() - 1)

+        {

+          UInt32 numProps;

+          g_StdOut << "----\n";

+          if (archive->GetNumberOfProperties(&numProps) == S_OK)

+          {

+            UInt32 mainIndex = archiveLink.Arcs[i + 1].SubfileIndex;

+            for (UInt32 j = 0; j < numProps; j++)

+            {

+              CMyComBSTR name;

+              PROPID propID;

+              VARTYPE vt;

+              RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt));

+              NCOM::CPropVariant prop;

+              RINOK(archive->GetProperty(mainIndex, propID, &prop));

+              UString s = ConvertPropertyToString(prop, propID);

+              if (!s.IsEmpty())

+                PrintPropPair(GetPropName(propID, name), s);

+            }

+          }

+        }

+        

+      }

+      g_StdOut << endl;

+      if (techMode)

+        g_StdOut << "----------\n";

+    }

+

+    if (enableHeaders && !techMode)

+    {

+      fieldPrinter.PrintTitle();

+      g_StdOut << endl;

+      fieldPrinter.PrintTitleLines();

+      g_StdOut << endl;

+    }

+

+    const CArc &arc = archiveLink.Arcs.Back();

+    IInArchive *archive = arc.Archive;

+    if (techMode)

+    {

+      RINOK(fieldPrinter.Init(archive));

+    }

+    UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0;

+    UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;

+    UInt32 numItems;

+    RINOK(archive->GetNumberOfItems(&numItems));

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

+    {

+      if (NConsoleClose::TestBreakSignal())

+        return E_ABORT;

+

+      UString filePath;

+      HRESULT res = arc.GetItemPath(i, filePath);

+      if (stdInMode && res == E_INVALIDARG)

+        break;

+      RINOK(res);

+

+      bool isFolder;

+      RINOK(IsArchiveItemFolder(archive, i, isFolder));

+      if (!wildcardCensor.CheckPath(filePath, !isFolder))

+        continue;

+      

+      fieldPrinter.PrintItemInfo(arc, i, techMode);

+      

+      UInt64 packSize, unpackSize;

+      if (!GetUInt64Value(archive, i, kpidSize, unpackSize))

+        unpackSize = 0;

+      else

+        totalUnPackSizePointer = &totalUnPackSize;

+      if (!GetUInt64Value(archive, i, kpidPackSize, packSize))

+        packSize = 0;

+      else

+        totalPackSizePointer = &totalPackSize;

+      

+      g_StdOut << endl;

+

+      if (isFolder)

+        numDirs++;

+      else

+        numFiles++;

+      totalPackSize += packSize;

+      totalUnPackSize += unpackSize;

+    }

+

+    if (!stdInMode && totalPackSizePointer == 0)

+    {

+      if (archiveLink.VolumePaths.Size() != 0)

+        arcPackSize += archiveLink.VolumesSize;

+      totalPackSize = (numFiles == 0) ? 0 : arcPackSize;

+      totalPackSizePointer = &totalPackSize;

+    }

+    if (totalUnPackSizePointer == 0 && numFiles == 0)

+    {

+      totalUnPackSize = 0;

+      totalUnPackSizePointer = &totalUnPackSize;

+    }

+    if (enableHeaders && !techMode)

+    {

+      fieldPrinter.PrintTitleLines();

+      g_StdOut << endl;

+      fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer);

+      g_StdOut << endl;

+    }

+    if (totalPackSizePointer != 0)

+    {

+      totalPackSizePointer2 = &totalPackSize2;

+      totalPackSize2 += totalPackSize;

+    }

+    if (totalUnPackSizePointer != 0)

+    {

+      totalUnPackSizePointer2 = &totalUnPackSize2;

+      totalUnPackSize2 += totalUnPackSize;

+    }

+    numFiles2 += numFiles;

+    numDirs2 += numDirs;

+  }

+  if (enableHeaders && !techMode && numArcs > 1)

+  {

+    g_StdOut << endl;

+    fieldPrinter.PrintTitleLines();

+    g_StdOut << endl;

+    fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2);

+    g_StdOut << endl;

+    g_StdOut << "Archives: " << numArcs << endl;

+  }

+  return S_OK;

+}

diff --git a/CPP/7zip/UI/Console/List.h b/CPP/7zip/UI/Console/List.h
new file mode 100755
index 0000000..7ea02cc
--- /dev/null
+++ b/CPP/7zip/UI/Console/List.h
@@ -0,0 +1,20 @@
+// List.h

+

+#ifndef __LIST_H

+#define __LIST_H

+

+#include "Common/Wildcard.h"

+#include "../Common/LoadCodecs.h"

+

+HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,

+    bool stdInMode,

+    UStringVector &archivePaths, UStringVector &archivePathsFull,

+    const NWildcard::CCensorNode &wildcardCensor,

+    bool enableHeaders, bool techMode,

+    #ifndef _NO_CRYPTO

+    bool &passwordEnabled, UString &password,

+    #endif

+    UInt64 &errors);

+

+#endif

+

diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
new file mode 100755
index 0000000..8946772
--- /dev/null
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -0,0 +1,598 @@
+// Main.cpp

+

+#include "StdAfx.h"

+

+#if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES)

+#include "../../../../C/Alloc.h"

+#endif

+

+#include "Common/MyInitGuid.h"

+

+#include "Common/CommandLineParser.h"

+#include "Common/IntToString.h"

+#include "Common/MyException.h"

+#include "Common/StdOutStream.h"

+#include "Common/StringConvert.h"

+#include "Common/StringToInt.h"

+

+#include "Windows/Error.h"

+#ifdef _WIN32

+#include "Windows/MemoryLock.h"

+#endif

+

+#include "../Common/ArchiveCommandLine.h"

+#include "../Common/ExitCode.h"

+#include "../Common/Extract.h"

+#ifdef EXTERNAL_CODECS

+#include "../Common/LoadCodecs.h"

+#endif

+

+#include "BenchCon.h"

+#include "ExtractCallbackConsole.h"

+#include "List.h"

+#include "OpenCallbackConsole.h"

+#include "UpdateCallbackConsole.h"

+

+#include "../../MyVersion.h"

+

+using namespace NWindows;

+using namespace NFile;

+using namespace NCommandLineParser;

+

+HINSTANCE g_hInstance = 0;

+extern CStdOutStream *g_StdStream;

+

+static const char *kCopyrightString = "\n7-Zip"

+#ifndef EXTERNAL_CODECS

+" (A)"

+#endif

+

+#ifdef _WIN64

+" [64]"

+#endif

+

+" " MY_VERSION_COPYRIGHT_DATE "\n";

+

+static const char *kHelpString =

+    "\nUsage: 7z"

+#ifdef _NO_CRYPTO

+    "r"

+#else

+#ifndef EXTERNAL_CODECS

+    "a"

+#endif

+#endif

+    " <command> [<switches>...] <archive_name> [<file_names>...]\n"

+    "       [<@listfiles...>]\n"

+    "\n"

+    "<Commands>\n"

+    "  a: Add files to archive\n"

+    "  b: Benchmark\n"

+    "  d: Delete files from archive\n"

+    "  e: Extract files from archive (without using directory names)\n"

+    "  l: List contents of archive\n"

+//    "  l[a|t][f]: List contents of archive\n"

+//    "    a - with Additional fields\n"

+//    "    t - with all fields\n"

+//    "    f - with Full pathnames\n"

+    "  t: Test integrity of archive\n"

+    "  u: Update files to archive\n"

+    "  x: eXtract files with full paths\n"

+    "<Switches>\n"

+    "  -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n"

+    "  -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n"

+    "  -bd: Disable percentage indicator\n"

+    "  -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n"

+    "  -m{Parameters}: set compression Method\n"

+    "  -o{Directory}: set Output directory\n"

+    #ifndef _NO_CRYPTO

+    "  -p{Password}: set Password\n"

+    #endif

+    "  -r[-|0]: Recurse subdirectories\n"

+    "  -scs{UTF-8 | WIN | DOS}: set charset for list files\n"

+    "  -sfx[{name}]: Create SFX archive\n"

+    "  -si[{name}]: read data from stdin\n"

+    "  -slt: show technical information for l (List) command\n"

+    "  -so: write data to stdout\n"

+    "  -ssc[-]: set sensitive case mode\n"

+    "  -ssw: compress shared files\n"

+    "  -t{Type}: Set type of archive\n"

+    "  -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n"

+    "  -v{Size}[b|k|m|g]: Create volumes\n"

+    "  -w[{path}]: assign Work directory. Empty path means a temporary directory\n"

+    "  -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n"

+    "  -y: assume Yes on all queries\n";

+

+// ---------------------------

+// exception messages

+

+static const char *kEverythingIsOk = "Everything is Ok";

+static const char *kUserErrorMessage = "Incorrect command line";

+static const char *kNoFormats = "7-Zip cannot find the code that works with archives.";

+static const char *kUnsupportedArcTypeMessage = "Unsupported archive type";

+

+static const wchar_t *kDefaultSfxModule = L"7zCon.sfx";

+

+static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code)

+{

+  s << message << endl;

+  throw code;

+}

+

+static void PrintHelpAndExit(CStdOutStream &s)

+{

+  s << kHelpString;

+  ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError);

+}

+

+#ifndef _WIN32

+static void GetArguments(int numArgs, const char *args[], UStringVector &parts)

+{

+  parts.Clear();

+  for (int i = 0; i < numArgs; i++)

+  {

+    UString s = MultiByteToUnicodeString(args[i]);

+    parts.Add(s);

+  }

+}

+#endif

+

+static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp)

+{

+  s << kCopyrightString;

+  // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n";

+  if (needHelp)

+    s << kHelpString;

+}

+

+#ifdef EXTERNAL_CODECS

+static void PrintString(CStdOutStream &stdStream, const AString &s, int size)

+{

+  int len = s.Length();

+  stdStream << s;

+  for (int i = len; i < size; i++)

+    stdStream << ' ';

+}

+#endif

+

+static void PrintString(CStdOutStream &stdStream, const UString &s, int size)

+{

+  int len = s.Length();

+  stdStream << s;

+  for (int i = len; i < size; i++)

+    stdStream << ' ';

+}

+

+static inline char GetHex(Byte value)

+{

+  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));

+}

+

+int Main2(

+  #ifndef _WIN32

+  int numArgs, const char *args[]

+  #endif

+)

+{

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  SetFileApisToOEM();

+  #endif

+  

+  UStringVector commandStrings;

+  #ifdef _WIN32

+  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);

+  #else

+  GetArguments(numArgs, args, commandStrings);

+  #endif

+

+  if (commandStrings.Size() == 1)

+  {

+    ShowCopyrightAndHelp(g_StdOut, true);

+    return 0;

+  }

+  commandStrings.Delete(0);

+

+  CArchiveCommandLineOptions options;

+

+  CArchiveCommandLineParser parser;

+

+  parser.Parse1(commandStrings, options);

+

+  if (options.HelpMode)

+  {

+    ShowCopyrightAndHelp(g_StdOut, true);

+    return 0;

+  }

+

+  #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)

+  if (options.LargePages)

+  {

+    SetLargePageSize();

+    NSecurity::EnableLockMemoryPrivilege();

+  }

+  #endif

+

+  CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut;

+  g_StdStream = &stdStream;

+

+  if (options.EnableHeaders)

+    ShowCopyrightAndHelp(stdStream, false);

+

+  parser.Parse2(options);

+

+  CCodecs *codecs = new CCodecs;

+  CMyComPtr<

+    #ifdef EXTERNAL_CODECS

+    ICompressCodecsInfo

+    #else

+    IUnknown

+    #endif

+    > compressCodecsInfo = codecs;

+  HRESULT result = codecs->Load();

+  if (result != S_OK)

+    throw CSystemException(result);

+

+  bool isExtractGroupCommand = options.Command.IsFromExtractGroup();

+

+  if (codecs->Formats.Size() == 0 &&

+        (isExtractGroupCommand ||

+        options.Command.CommandType == NCommandType::kList ||

+        options.Command.IsFromUpdateGroup()))

+    throw kNoFormats;

+

+  CIntVector formatIndices;

+  if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices))

+    throw kUnsupportedArcTypeMessage;

+

+  if (options.Command.CommandType == NCommandType::kInfo)

+  {

+    stdStream << endl << "Formats:" << endl;

+    int i;

+    for (i = 0; i < codecs->Formats.Size(); i++)

+    {

+      const CArcInfoEx &arc = codecs->Formats[i];

+      #ifdef EXTERNAL_CODECS

+      if (arc.LibIndex >= 0)

+      {

+        char s[16];

+        ConvertUInt32ToString(arc.LibIndex, s);

+        PrintString(stdStream, s, 2);

+      }

+      else

+      #endif

+        stdStream << "  ";

+      stdStream << ' ';

+      stdStream << (char)(arc.UpdateEnabled ? 'C' : ' ');

+      stdStream << (char)(arc.KeepName ? 'K' : ' ');

+      stdStream << "  ";

+      PrintString(stdStream, arc.Name, 6);

+      stdStream << "  ";

+      UString s;

+      for (int t = 0; t < arc.Exts.Size(); t++)

+      {

+        const CArcExtInfo &ext = arc.Exts[t];

+        s += ext.Ext;

+        if (!ext.AddExt.IsEmpty())

+        {

+          s += L" (";

+          s += ext.AddExt;

+          s += L')';

+        }

+        s += L' ';

+      }

+      PrintString(stdStream, s, 14);

+      stdStream << "  ";

+      const CByteBuffer &sig = arc.StartSignature;

+      for (size_t j = 0; j < sig.GetCapacity(); j++)

+      {

+        Byte b = sig[j];

+        if (b > 0x20 && b < 0x80)

+        {

+          stdStream << (char)b;

+        }

+        else

+        {

+          stdStream << GetHex((Byte)((b >> 4) & 0xF));

+          stdStream << GetHex((Byte)(b & 0xF));

+        }

+        stdStream << ' ';

+      }

+      stdStream << endl;

+    }

+    stdStream << endl << "Codecs:" << endl;

+

+    #ifdef EXTERNAL_CODECS

+    UInt32 numMethods;

+    if (codecs->GetNumberOfMethods(&numMethods) == S_OK)

+    for (UInt32 j = 0; j < numMethods; j++)

+    {

+      int libIndex = codecs->GetCodecLibIndex(j);

+      if (libIndex >= 0)

+      {

+        char s[16];

+        ConvertUInt32ToString(libIndex, s);

+        PrintString(stdStream, s, 2);

+      }

+      else

+        stdStream << "  ";

+      stdStream << ' ';

+      stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' ');

+      UInt64 id;

+      stdStream << "  ";

+      HRESULT res = codecs->GetCodecId(j, id);

+      if (res != S_OK)

+        id = (UInt64)(Int64)-1;

+      char s[32];

+      ConvertUInt64ToString(id, s, 16);

+      PrintString(stdStream, s, 8);

+      stdStream << "  ";

+      PrintString(stdStream, codecs->GetCodecName(j), 11);

+      stdStream << endl;

+      /*

+      if (res != S_OK)

+        throw "incorrect Codec ID";

+      */

+    }

+    #endif

+    return S_OK;

+  }

+  else if (options.Command.CommandType == NCommandType::kBenchmark)

+  {

+    if (options.Method.CompareNoCase(L"CRC") == 0)

+    {

+      HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);

+      if (res != S_OK)

+      {

+        if (res == S_FALSE)

+        {

+          stdStream << "\nCRC Error\n";

+          return NExitCode::kFatalError;

+        }

+        throw CSystemException(res);

+      }

+    }

+    else

+    {

+      HRESULT res;

+      #ifdef EXTERNAL_CODECS

+      CObjectVector<CCodecInfoEx> externalCodecs;

+      res = LoadExternalCodecs(compressCodecsInfo, externalCodecs);

+      if (res != S_OK)

+        throw CSystemException(res);

+      #endif

+      res = LzmaBenchCon(

+          #ifdef EXTERNAL_CODECS

+          compressCodecsInfo, &externalCodecs,

+          #endif

+        (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);

+      if (res != S_OK)

+      {

+        if (res == S_FALSE)

+        {

+          stdStream << "\nDecoding Error\n";

+          return NExitCode::kFatalError;

+        }

+        throw CSystemException(res);

+      }

+    }

+  }

+  else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)

+  {

+    if (isExtractGroupCommand)

+    {

+      CExtractCallbackConsole *ecs = new CExtractCallbackConsole;

+      CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;

+

+      ecs->OutStream = &stdStream;

+

+      #ifndef _NO_CRYPTO

+      ecs->PasswordIsDefined = options.PasswordEnabled;

+      ecs->Password = options.Password;

+      #endif

+

+      ecs->Init();

+

+      COpenCallbackConsole openCallback;

+      openCallback.OutStream = &stdStream;

+

+      #ifndef _NO_CRYPTO

+      openCallback.PasswordIsDefined = options.PasswordEnabled;

+      openCallback.Password = options.Password;

+      #endif

+

+      CExtractOptions eo;

+      eo.StdInMode = options.StdInMode;

+      eo.StdOutMode = options.StdOutMode;

+      eo.PathMode = options.Command.GetPathMode();

+      eo.TestMode = options.Command.IsTestMode();

+      eo.OverwriteMode = options.OverwriteMode;

+      eo.OutputDir = options.OutputDir;

+      eo.YesToAll = options.YesToAll;

+      eo.CalcCrc = options.CalcCrc;

+      #if !defined(_7ZIP_ST) && !defined(_SFX)

+      eo.Properties = options.ExtractProperties;

+      #endif

+      UString errorMessage;

+      CDecompressStat stat;

+      HRESULT result = DecompressArchives(

+          codecs,

+          formatIndices,

+          options.ArchivePathsSorted,

+          options.ArchivePathsFullSorted,

+          options.WildcardCensor.Pairs.Front().Head,

+          eo, &openCallback, ecs, errorMessage, stat);

+      if (!errorMessage.IsEmpty())

+      {

+        stdStream << endl << "Error: " << errorMessage;

+        if (result == S_OK)

+          result = E_FAIL;

+      }

+

+      stdStream << endl;

+      if (ecs->NumArchives > 1)

+        stdStream << "Archives: " << ecs->NumArchives << endl;

+      if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0)

+      {

+        if (ecs->NumArchives > 1)

+        {

+          stdStream << endl;

+          if (ecs->NumArchiveErrors != 0)

+            stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl;

+          if (ecs->NumFileErrors != 0)

+            stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl;

+        }

+        if (result != S_OK)

+          throw CSystemException(result);

+        return NExitCode::kFatalError;

+      }

+      if (result != S_OK)

+        throw CSystemException(result);

+      if (stat.NumFolders != 0)

+        stdStream << "Folders: " << stat.NumFolders << endl;

+      if (stat.NumFiles != 1 || stat.NumFolders != 0)

+          stdStream << "Files: " << stat.NumFiles << endl;

+      stdStream

+           << "Size:       " << stat.UnpackSize << endl

+           << "Compressed: " << stat.PackSize << endl;

+      if (options.CalcCrc)

+      {

+        char s[16];

+        ConvertUInt32ToHexWithZeros(stat.CrcSum, s);

+        stdStream << "CRC: " << s << endl;

+      }

+    }

+    else

+    {

+      UInt64 numErrors = 0;

+      HRESULT result = ListArchives(

+          codecs,

+          formatIndices,

+          options.StdInMode,

+          options.ArchivePathsSorted,

+          options.ArchivePathsFullSorted,

+          options.WildcardCensor.Pairs.Front().Head,

+          options.EnableHeaders,

+          options.TechMode,

+          #ifndef _NO_CRYPTO

+          options.PasswordEnabled,

+          options.Password,

+          #endif

+          numErrors);

+      if (numErrors > 0)

+      {

+        g_StdOut << endl << "Errors: " << numErrors;

+        return NExitCode::kFatalError;

+      }

+      if (result != S_OK)

+        throw CSystemException(result);

+    }

+  }

+  else if (options.Command.IsFromUpdateGroup())

+  {

+    CUpdateOptions &uo = options.UpdateOptions;

+    if (uo.SfxMode && uo.SfxModule.IsEmpty())

+      uo.SfxModule = kDefaultSfxModule;

+

+    COpenCallbackConsole openCallback;

+    openCallback.OutStream = &stdStream;

+

+    #ifndef _NO_CRYPTO

+    bool passwordIsDefined =

+        options.PasswordEnabled && !options.Password.IsEmpty();

+    openCallback.PasswordIsDefined = passwordIsDefined;

+    openCallback.Password = options.Password;

+    #endif

+

+    CUpdateCallbackConsole callback;

+    callback.EnablePercents = options.EnablePercents;

+

+    #ifndef _NO_CRYPTO

+    callback.PasswordIsDefined = passwordIsDefined;

+    callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty();

+    callback.Password = options.Password;

+    #endif

+    callback.StdOutMode = uo.StdOutMode;

+    callback.Init(&stdStream);

+

+    CUpdateErrorInfo errorInfo;

+

+    if (!uo.Init(codecs, formatIndices, options.ArchiveName))

+      throw kUnsupportedArcTypeMessage;

+    HRESULT result = UpdateArchive(codecs,

+        options.WildcardCensor, uo,

+        errorInfo, &openCallback, &callback);

+

+    int exitCode = NExitCode::kSuccess;

+    if (callback.CantFindFiles.Size() > 0)

+    {

+      stdStream << endl;

+      stdStream << "WARNINGS for files:" << endl << endl;

+      int numErrors = callback.CantFindFiles.Size();

+      for (int i = 0; i < numErrors; i++)

+      {

+        stdStream << callback.CantFindFiles[i] << " : ";

+        stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl;

+      }

+      stdStream << "----------------" << endl;

+      stdStream << "WARNING: Cannot find " << numErrors << " file";

+      if (numErrors > 1)

+        stdStream << "s";

+      stdStream << endl;

+      exitCode = NExitCode::kWarning;

+    }

+

+    if (result != S_OK)

+    {

+      UString message;

+      if (!errorInfo.Message.IsEmpty())

+      {

+        message += errorInfo.Message;

+        message += L"\n";

+      }

+      if (!errorInfo.FileName.IsEmpty())

+      {

+        message += errorInfo.FileName;

+        message += L"\n";

+      }

+      if (!errorInfo.FileName2.IsEmpty())

+      {

+        message += errorInfo.FileName2;

+        message += L"\n";

+      }

+      if (errorInfo.SystemError != 0)

+      {

+        message += NError::MyFormatMessageW(errorInfo.SystemError);

+        message += L"\n";

+      }

+      if (!message.IsEmpty())

+        stdStream << L"\nError:\n" << message;

+      throw CSystemException(result);

+    }

+    int numErrors = callback.FailedFiles.Size();

+    if (numErrors == 0)

+    {

+      if (callback.CantFindFiles.Size() == 0)

+        stdStream << kEverythingIsOk << endl;

+    }

+    else

+    {

+      stdStream << endl;

+      stdStream << "WARNINGS for files:" << endl << endl;

+      for (int i = 0; i < numErrors; i++)

+      {

+        stdStream << callback.FailedFiles[i] << " : ";

+        stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl;

+      }

+      stdStream << "----------------" << endl;

+      stdStream << "WARNING: Cannot open " << numErrors << " file";

+      if (numErrors > 1)

+        stdStream << "s";

+      stdStream << endl;

+      exitCode = NExitCode::kWarning;

+    }

+    return exitCode;

+  }

+  else

+    PrintHelpAndExit(stdStream);

+  return 0;

+}

diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp
new file mode 100755
index 0000000..b6681b4
--- /dev/null
+++ b/CPP/7zip/UI/Console/MainAr.cpp
@@ -0,0 +1,125 @@
+// MainAr.cpp

+

+#include "StdAfx.h"

+

+#include "Common/MyException.h"

+#include "Common/StdOutStream.h"

+

+#include "Windows/Error.h"

+#include "Windows/NtCheck.h"

+

+#include "../Common/ArchiveCommandLine.h"

+#include "../Common/ExitCode.h"

+

+#include "ConsoleClose.h"

+

+using namespace NWindows;

+

+CStdOutStream *g_StdStream = 0;

+

+extern int Main2(

+  #ifndef _WIN32

+  int numArgs, const char *args[]

+  #endif

+);

+

+static const char *kExceptionErrorMessage = "\n\nError:\n";

+static const char *kUserBreak  = "\nBreak signaled\n";

+static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n";

+static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n";

+static const char *kInternalExceptionMessage = "\n\nInternal Error #";

+

+#define NT_CHECK_FAIL_ACTION (*g_StdStream) << "Unsupported Windows version"; return NExitCode::kFatalError;

+

+int MY_CDECL main

+(

+  #ifndef _WIN32

+  int numArgs, const char *args[]

+  #endif

+)

+{

+  g_StdStream = &g_StdOut;

+

+  NT_CHECK

+

+  NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;

+  int res = 0;

+  try

+  {

+    res = Main2(

+    #ifndef _WIN32

+    numArgs, args

+    #endif

+    );

+  }

+  catch(const CNewException &)

+  {

+    (*g_StdStream) << kMemoryExceptionMessage;

+    return (NExitCode::kMemoryError);

+  }

+  catch(const NConsoleClose::CCtrlBreakException &)

+  {

+    (*g_StdStream) << endl << kUserBreak;

+    return (NExitCode::kUserBreak);

+  }

+  catch(const CArchiveCommandLineException &e)

+  {

+    (*g_StdStream) << kExceptionErrorMessage << e << endl;

+    return (NExitCode::kUserError);

+  }

+  catch(const CSystemException &systemError)

+  {

+    if (systemError.ErrorCode == E_OUTOFMEMORY)

+    {

+      (*g_StdStream) << kMemoryExceptionMessage;

+      return (NExitCode::kMemoryError);

+    }

+    if (systemError.ErrorCode == E_ABORT)

+    {

+      (*g_StdStream) << endl << kUserBreak;

+      return (NExitCode::kUserBreak);

+    }

+    UString message;

+    NError::MyFormatMessage(systemError.ErrorCode, message);

+    (*g_StdStream) << endl << endl << "System error:" << endl << message << endl;

+    return (NExitCode::kFatalError);

+  }

+  catch(NExitCode::EEnum &exitCode)

+  {

+    (*g_StdStream) << kInternalExceptionMessage << exitCode << endl;

+    return (exitCode);

+  }

+  /*

+  catch(const NExitCode::CMultipleErrors &multipleErrors)

+  {

+    (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl;

+    return (NExitCode::kFatalError);

+  }

+  */

+  catch(const UString &s)

+  {

+    (*g_StdStream) << kExceptionErrorMessage << s << endl;

+    return (NExitCode::kFatalError);

+  }

+  catch(const AString &s)

+  {

+    (*g_StdStream) << kExceptionErrorMessage << s << endl;

+    return (NExitCode::kFatalError);

+  }

+  catch(const char *s)

+  {

+    (*g_StdStream) << kExceptionErrorMessage << s << endl;

+    return (NExitCode::kFatalError);

+  }

+  catch(int t)

+  {

+    (*g_StdStream) << kInternalExceptionMessage << t << endl;

+    return (NExitCode::kFatalError);

+  }

+  catch(...)

+  {

+    (*g_StdStream) << kUnknownExceptionMessage;

+    return (NExitCode::kFatalError);

+  }

+  return  res;

+}

diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
new file mode 100755
index 0000000..986a592
--- /dev/null
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
@@ -0,0 +1,58 @@
+// OpenCallbackConsole.cpp

+

+#include "StdAfx.h"

+

+#include "OpenCallbackConsole.h"

+

+#include "ConsoleClose.h"

+#include "UserInputUtils.h"

+

+HRESULT COpenCallbackConsole::Open_CheckBreak()

+{

+  if (NConsoleClose::TestBreakSignal())

+    return E_ABORT;

+  return S_OK;

+}

+

+HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *)

+{

+  return Open_CheckBreak();

+}

+

+HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *)

+{

+  return Open_CheckBreak();

+}

+ 

+#ifndef _NO_CRYPTO

+

+HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password)

+{

+  PasswordWasAsked = true;

+  RINOK(Open_CheckBreak());

+  if (!PasswordIsDefined)

+  {

+    Password = GetPassword(OutStream);

+    PasswordIsDefined = true;

+  }

+  return StringToBstr(Password, password);

+}

+

+HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password)

+{

+  if (PasswordIsDefined)

+    password = Password;

+  return S_OK;

+}

+

+bool COpenCallbackConsole::Open_WasPasswordAsked()

+{

+  return PasswordWasAsked;

+}

+

+void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag()

+{

+  PasswordWasAsked = false;

+}

+

+#endif

diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h
new file mode 100755
index 0000000..99e8c04
--- /dev/null
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.h
@@ -0,0 +1,24 @@
+// OpenCallbackConsole.h

+

+#ifndef __OPENCALLBACKCONSOLE_H

+#define __OPENCALLBACKCONSOLE_H

+

+#include "Common/StdOutStream.h"

+#include "../Common/ArchiveOpenCallback.h"

+

+class COpenCallbackConsole: public IOpenCallbackUI

+{

+public:

+  INTERFACE_IOpenCallbackUI(;)

+  

+  CStdOutStream *OutStream;

+

+  #ifndef _NO_CRYPTO

+  bool PasswordIsDefined;

+  bool PasswordWasAsked;

+  UString Password;

+  COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {}

+  #endif

+};

+

+#endif

diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp
new file mode 100755
index 0000000..111ae25
--- /dev/null
+++ b/CPP/7zip/UI/Console/PercentPrinter.cpp
@@ -0,0 +1,90 @@
+// PercentPrinter.cpp

+

+#include "StdAfx.h"

+

+#include "Common/IntToString.h"

+#include "Common/MyString.h"

+

+#include "PercentPrinter.h"

+

+const int kPaddingSize = 2;

+const int kPercentsSize = 4;

+const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize;

+

+static void ClearPrev(char *p, int num)

+{

+  int i;

+  for (i = 0; i < num; i++) *p++ = '\b';

+  for (i = 0; i < num; i++) *p++ = ' ';

+  for (i = 0; i < num; i++) *p++ = '\b';

+  *p = '\0';

+}

+

+void CPercentPrinter::ClosePrint()

+{

+  if (m_NumExtraChars == 0)

+    return;

+  char s[kMaxExtraSize * 3 + 1];

+  ClearPrev(s, m_NumExtraChars);

+  (*OutStream) << s;

+  m_NumExtraChars = 0;

+}

+

+void CPercentPrinter::PrintString(const char *s)

+{

+  ClosePrint();

+  (*OutStream) << s;

+}

+

+void CPercentPrinter::PrintString(const wchar_t *s)

+{

+  ClosePrint();

+  (*OutStream) << s;

+}

+

+void CPercentPrinter::PrintNewLine()

+{

+  ClosePrint();

+  (*OutStream) << "\n";

+}

+

+void CPercentPrinter::RePrintRatio()

+{

+  char s[32];

+  ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s);

+  int size = (int)strlen(s);

+  s[size++] = '%';

+  s[size] = '\0';

+

+  int extraSize = kPaddingSize + MyMax(size, kPercentsSize);

+  if (extraSize < m_NumExtraChars)

+    extraSize = m_NumExtraChars;

+

+  char fullString[kMaxExtraSize * 3];

+  char *p = fullString;

+  int i;

+  if (m_NumExtraChars == 0)

+  {

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

+      *p++ = ' ';

+    m_NumExtraChars = extraSize;

+  }

+

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

+    *p++ = '\b';

+  m_NumExtraChars = extraSize;

+  for (; size < m_NumExtraChars; size++)

+    *p++ = ' ';

+  MyStringCopy(p, s);

+  (*OutStream) << fullString;

+  OutStream->Flush();

+  m_PrevValue = m_CurValue;

+}

+

+void CPercentPrinter::PrintRatio()

+{

+  if (m_CurValue < m_PrevValue + m_MinStepSize &&

+      m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0)

+    return;

+  RePrintRatio();

+}

diff --git a/CPP/7zip/UI/Console/PercentPrinter.h b/CPP/7zip/UI/Console/PercentPrinter.h
new file mode 100755
index 0000000..212e11e
--- /dev/null
+++ b/CPP/7zip/UI/Console/PercentPrinter.h
@@ -0,0 +1,31 @@
+// PercentPrinter.h

+

+#ifndef __PERCENTPRINTER_H

+#define __PERCENTPRINTER_H

+

+#include "Common/Types.h"

+#include "Common/StdOutStream.h"

+

+class CPercentPrinter

+{

+  UInt64 m_MinStepSize;

+  UInt64 m_PrevValue;

+  UInt64 m_CurValue;

+  UInt64 m_Total;

+  int m_NumExtraChars;

+public:

+  CStdOutStream *OutStream;

+

+  CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize),

+      m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {}

+  void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; }

+  void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; }

+  void PrintString(const char *s);

+  void PrintString(const wchar_t *s);

+  void PrintNewLine();

+  void ClosePrint();

+  void RePrintRatio();

+  void PrintRatio();

+};

+

+#endif

diff --git a/CPP/7zip/UI/Console/StdAfx.cpp b/CPP/7zip/UI/Console/StdAfx.cpp
new file mode 100755
index 0000000..c6d3b1f
--- /dev/null
+++ b/CPP/7zip/UI/Console/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp

+

+#include "StdAfx.h"

diff --git a/CPP/7zip/UI/Console/StdAfx.h b/CPP/7zip/UI/Console/StdAfx.h
new file mode 100755
index 0000000..a4e6173
--- /dev/null
+++ b/CPP/7zip/UI/Console/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../../../Common/MyWindows.h"

+#include "../../../Common/NewHandler.h"

+

+#endif

diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
new file mode 100755
index 0000000..c482676
--- /dev/null
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
@@ -0,0 +1,261 @@
+// UpdateCallbackConsole.cpp

+

+#include "StdAfx.h"

+

+#include "UpdateCallbackConsole.h"

+

+#include "Windows/Error.h"

+#ifndef _7ZIP_ST

+#include "Windows/Synchronization.h"

+#endif

+

+#include "ConsoleClose.h"

+#include "UserInputUtils.h"

+

+using namespace NWindows;

+

+#ifndef _7ZIP_ST

+static NSynchronization::CCriticalSection g_CriticalSection;

+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);

+#else

+#define MT_LOCK

+#endif

+

+static const wchar_t *kEmptyFileAlias = L"[Content]";

+

+static const char *kCreatingArchiveMessage = "Creating archive ";

+static const char *kUpdatingArchiveMessage = "Updating archive ";

+static const char *kScanningMessage = "Scanning";

+

+

+HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result)

+{

+  (*OutStream) << endl;

+  if (result != S_OK)

+    (*OutStream) << "Error: " << name << " is not supported archive" << endl;

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::StartScanning()

+{

+  (*OutStream) << kScanningMessage;

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */)

+{

+  return CheckBreak();

+}

+

+HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError)

+{

+  CantFindFiles.Add(name);

+  CantFindCodes.Add(systemError);

+  // m_PercentPrinter.ClosePrint();

+  if (!m_WarningsMode)

+  {

+    (*OutStream) << endl << endl;

+    m_PercentPrinter.PrintNewLine();

+    m_WarningsMode = true;

+  }

+  m_PercentPrinter.PrintString(name);

+  m_PercentPrinter.PrintString(":  WARNING: ");

+  m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));

+  m_PercentPrinter.PrintNewLine();

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::FinishScanning()

+{

+  (*OutStream) << endl << endl;

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)

+{

+  if(updating)

+    (*OutStream) << kUpdatingArchiveMessage;

+  else

+    (*OutStream) << kCreatingArchiveMessage;

+  if (name != 0)

+    (*OutStream) << name;

+  else

+    (*OutStream) << "StdOut";

+  (*OutStream) << endl << endl;

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::FinishArchive()

+{

+  (*OutStream) << endl;

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::CheckBreak()

+{

+  if (NConsoleClose::TestBreakSignal())

+    return E_ABORT;

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::Finilize()

+{

+  MT_LOCK

+  if (m_NeedBeClosed)

+  {

+    if (EnablePercents)

+    {

+      m_PercentPrinter.ClosePrint();

+    }

+    if (!StdOutMode && m_NeedNewLine)

+    {

+      m_PercentPrinter.PrintNewLine();

+      m_NeedNewLine = false;

+    }

+    m_NeedBeClosed = false;

+  }

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */)

+{

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)

+{

+  MT_LOCK

+  if (EnablePercents)

+    m_PercentPrinter.SetTotal(size);

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)

+{

+  MT_LOCK

+  if (completeValue != NULL)

+  {

+    if (EnablePercents)

+    {

+      m_PercentPrinter.SetRatio(*completeValue);

+      m_PercentPrinter.PrintRatio();

+      m_NeedBeClosed = true;

+    }

+  }

+  if (NConsoleClose::TestBreakSignal())

+    return E_ABORT;

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)

+{

+  if (NConsoleClose::TestBreakSignal())

+    return E_ABORT;

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti)

+{

+  MT_LOCK

+  if (StdOutMode)

+    return S_OK;

+  if(isAnti)

+    m_PercentPrinter.PrintString("Anti item    ");

+  else

+    m_PercentPrinter.PrintString("Compressing  ");

+  if (name[0] == 0)

+    name = kEmptyFileAlias;

+  m_PercentPrinter.PrintString(name);

+  if (EnablePercents)

+    m_PercentPrinter.RePrintRatio();

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError)

+{

+  MT_LOCK

+  FailedCodes.Add(systemError);

+  FailedFiles.Add(name);

+  // if (systemError == ERROR_SHARING_VIOLATION)

+  {

+    m_PercentPrinter.ClosePrint();

+    m_PercentPrinter.PrintNewLine();

+    m_PercentPrinter.PrintString("WARNING: ");

+    m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));

+    return S_FALSE;

+  }

+  // return systemError;

+}

+

+HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 )

+{

+  m_NeedBeClosed = true;

+  m_NeedNewLine = true;

+  return S_OK;

+}

+

+HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)

+{

+  *password = NULL;

+

+  #ifdef _NO_CRYPTO

+

+  *passwordIsDefined = false;

+  return S_OK;

+  

+  #else

+  

+  if (!PasswordIsDefined)

+  {

+    if (AskPassword)

+    {

+      Password = GetPassword(OutStream);

+      PasswordIsDefined = true;

+    }

+  }

+  *passwordIsDefined = BoolToInt(PasswordIsDefined);

+  return StringToBstr(Password, password);

+  

+  #endif

+}

+

+HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)

+{

+  *password = NULL;

+

+  #ifdef _NO_CRYPTO

+

+  return E_NOTIMPL;

+  

+  #else

+  

+  if (!PasswordIsDefined)

+  {

+    {

+      Password = GetPassword(OutStream);

+      PasswordIsDefined = true;

+    }

+  }

+  return StringToBstr(Password, password);

+  

+  #endif

+}

+

+/*

+HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name)

+{

+  // MT_LOCK

+  if (StdOutMode)

+    return S_OK;

+  RINOK(Finilize());

+  m_PercentPrinter.PrintString("Deleting  ");

+  if (name[0] == 0)

+    name = kEmptyFileAlias;

+  m_PercentPrinter.PrintString(name);

+  if (EnablePercents)

+    m_PercentPrinter.RePrintRatio();

+  m_NeedBeClosed = true;

+  m_NeedNewLine = true;

+  return S_OK;

+}

+*/

diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
new file mode 100755
index 0000000..59581f3
--- /dev/null
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
@@ -0,0 +1,62 @@
+// UpdateCallbackConsole.h

+

+#ifndef __UPDATE_CALLBACK_CONSOLE_H

+#define __UPDATE_CALLBACK_CONSOLE_H

+

+#include "Common/StdOutStream.h"

+

+#include "../Common/Update.h"

+

+#include "PercentPrinter.h"

+

+class CUpdateCallbackConsole: public IUpdateCallbackUI2

+{

+  CPercentPrinter m_PercentPrinter;

+  bool m_NeedBeClosed;

+  bool m_NeedNewLine;

+

+  bool m_WarningsMode;

+

+  CStdOutStream *OutStream;

+public:

+  bool EnablePercents;

+  bool StdOutMode;

+

+  #ifndef _NO_CRYPTO

+  bool PasswordIsDefined;

+  UString Password;

+  bool AskPassword;

+  #endif

+

+  CUpdateCallbackConsole():

+      m_PercentPrinter(1 << 16),

+      #ifndef _NO_CRYPTO

+      PasswordIsDefined(false),

+      AskPassword(false),

+      #endif

+      StdOutMode(false),

+      EnablePercents(true),

+      m_WarningsMode(false)

+      {}

+  

+  ~CUpdateCallbackConsole() { Finilize(); }

+  void Init(CStdOutStream *outStream)

+  {

+    m_NeedBeClosed = false;

+    m_NeedNewLine = false;

+    FailedFiles.Clear();

+    FailedCodes.Clear();

+    OutStream = outStream;

+    m_PercentPrinter.OutStream = outStream;

+  }

+

+  INTERFACE_IUpdateCallbackUI2(;)

+

+  UStringVector FailedFiles;

+  CRecordVector<HRESULT> FailedCodes;

+

+  UStringVector CantFindFiles;

+  CRecordVector<HRESULT> CantFindCodes;

+};

+

+#endif

diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp
new file mode 100755
index 0000000..68481c2
--- /dev/null
+++ b/CPP/7zip/UI/Console/UserInputUtils.cpp
@@ -0,0 +1,87 @@
+// UserInputUtils.cpp

+

+#include "StdAfx.h"

+

+#include "Common/StdInStream.h"

+#include "Common/StringConvert.h"

+

+#include "UserInputUtils.h"

+

+static const char kYes = 'Y';

+static const char kNo = 'N';

+static const char kYesAll = 'A';

+static const char kNoAll = 'S';

+static const char kAutoRenameAll = 'U';

+static const char kQuit = 'Q';

+

+static const char *kFirstQuestionMessage = "?\n";

+static const char *kHelpQuestionMessage =

+  "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? ";

+

+// return true if pressed Quite;

+

+NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)

+{

+  (*outStream) << kFirstQuestionMessage;

+  for (;;)

+  {

+    (*outStream) << kHelpQuestionMessage;

+    outStream->Flush();

+    AString scannedString = g_StdIn.ScanStringUntilNewLine();

+    scannedString.Trim();

+    if (!scannedString.IsEmpty())

+      switch(

+        ::MyCharUpper(

+        #ifdef UNDER_CE

+        (wchar_t)

+        #endif

+        scannedString[0]))

+      {

+        case kYes:

+          return NUserAnswerMode::kYes;

+        case kNo:

+          return NUserAnswerMode::kNo;

+        case kYesAll:

+          return NUserAnswerMode::kYesAll;

+        case kNoAll:

+          return NUserAnswerMode::kNoAll;

+        case kAutoRenameAll:

+          return NUserAnswerMode::kAutoRenameAll;

+        case kQuit:

+          return NUserAnswerMode::kQuit;

+      }

+  }

+}

+

+#ifdef _WIN32

+#ifndef UNDER_CE

+#define MY_DISABLE_ECHO

+#endif

+#endif

+

+UString GetPassword(CStdOutStream *outStream)

+{

+  (*outStream) << "\nEnter password"

+      #ifdef MY_DISABLE_ECHO

+      " (will not be echoed)"

+      #endif

+      ":";

+  outStream->Flush();

+

+  #ifdef MY_DISABLE_ECHO

+  HANDLE console = GetStdHandle(STD_INPUT_HANDLE);

+  bool wasChanged = false;

+  DWORD mode = 0;

+  if (console != INVALID_HANDLE_VALUE && console != 0)

+    if (GetConsoleMode(console, &mode))

+      wasChanged = (SetConsoleMode(console, mode & ~ENABLE_ECHO_INPUT) != 0);

+  UString res = g_StdIn.ScanUStringUntilNewLine();

+  if (wasChanged)

+    SetConsoleMode(console, mode);

+  (*outStream) << "\n";

+  outStream->Flush();

+  return res;

+  #else

+  return g_StdIn.ScanUStringUntilNewLine();

+  #endif

+}

diff --git a/CPP/7zip/UI/Console/UserInputUtils.h b/CPP/7zip/UI/Console/UserInputUtils.h
new file mode 100755
index 0000000..3740ad7
--- /dev/null
+++ b/CPP/7zip/UI/Console/UserInputUtils.h
@@ -0,0 +1,24 @@
+// UserInputUtils.h

+

+#ifndef __USERINPUTUTILS_H

+#define __USERINPUTUTILS_H

+

+#include "Common/StdOutStream.h"

+

+namespace NUserAnswerMode {

+

+enum EEnum

+{

+  kYes,

+  kNo,

+  kYesAll,

+  kNoAll,

+  kAutoRenameAll,

+  kQuit

+};

+}

+

+NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream);

+UString GetPassword(CStdOutStream *outStream);

+

+#endif

diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile
new file mode 100755
index 0000000..0d40eb5
--- /dev/null
+++ b/CPP/7zip/UI/Console/makefile
@@ -0,0 +1,124 @@
+PROG = 7z.exe

+MY_CONSOLE = 1

+CFLAGS = $(CFLAGS) -I ../../../  \

+  -DEXTERNAL_CODECS \

+

+!IFNDEF UNDER_CE

+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE

+!ENDIF

+

+

+CONSOLE_OBJS = \

+  $O\ConsoleClose.obj \

+  $O\ExtractCallbackConsole.obj \

+  $O\List.obj \

+  $O\BenchCon.obj \

+  $O\Main.obj \

+  $O\MainAr.obj \

+  $O\OpenCallbackConsole.obj \

+  $O\PercentPrinter.obj \

+  $O\UpdateCallbackConsole.obj \

+  $O\UserInputUtils.obj \

+

+COMMON_OBJS = \

+  $O\CommandLineParser.obj \

+  $O\CRC.obj \

+  $O\IntToString.obj \

+  $O\ListFileUtils.obj \

+  $O\NewHandler.obj \

+  $O\StdInStream.obj \

+  $O\StdOutStream.obj \

+  $O\MyString.obj \

+  $O\StringConvert.obj \

+  $O\StringToInt.obj \

+  $O\UTFConvert.obj \

+  $O\MyVector.obj \

+  $O\Wildcard.obj \

+

+WIN_OBJS = \

+  $O\DLL.obj \

+  $O\Error.obj \

+  $O\FileDir.obj \

+  $O\FileFind.obj \

+  $O\FileIO.obj \

+  $O\FileName.obj \

+  $O\MemoryLock.obj \

+  $O\PropVariant.obj \

+  $O\PropVariantConversions.obj \

+  $O\Registry.obj \

+  $O\System.obj \

+  $O\Time.obj \

+

+7ZIP_COMMON_OBJS = \

+  $O\CreateCoder.obj \

+  $O\FilePathAutoRename.obj \

+  $O\FileStreams.obj \

+  $O\FilterCoder.obj \

+  $O\ProgressUtils.obj \

+  $O\StreamUtils.obj \

+

+UI_COMMON_OBJS = \

+  $O\ArchiveCommandLine.obj \

+  $O\ArchiveExtractCallback.obj \

+  $O\ArchiveOpenCallback.obj \

+  $O\DefaultName.obj \

+  $O\EnumDirItems.obj \

+  $O\Extract.obj \

+  $O\ExtractingFilePath.obj \

+  $O\Bench.obj \

+  $O\LoadCodecs.obj \

+  $O\OpenArchive.obj \

+  $O\PropIDUtils.obj \

+  $O\SetProperties.obj \

+  $O\SortUtils.obj \

+  $O\TempFiles.obj \

+  $O\Update.obj \

+  $O\UpdateAction.obj \

+  $O\UpdateCallback.obj \

+  $O\UpdatePair.obj \

+  $O\UpdateProduce.obj \

+  $O\WorkDir.obj \

+

+AR_COMMON_OBJS = \

+  $O\OutStreamWithCRC.obj \

+

+C_OBJS = \

+  $O\Alloc.obj \

+  $O\CpuArch.obj \

+  $O\Threads.obj \

+

+!include "../../Crc.mak"

+

+OBJS = \

+  $O\StdAfx.obj \

+  $(CONSOLE_OBJS) \

+  $(COMMON_OBJS) \

+  $(WIN_OBJS) \

+  $(7ZIP_COMMON_OBJS) \

+  $(UI_COMMON_OBJS) \

+  $(AR_COMMON_OBJS) \

+  $O\CopyCoder.obj \

+  $(C_OBJS) \

+  $(ASM_OBJS) \

+  $O\resource.res

+

+!include "../../../Build.mak"

+

+$(CONSOLE_OBJS): $(*B).cpp

+	$(COMPL)

+$(COMMON_OBJS): ../../../Common/$(*B).cpp

+	$(COMPL)

+$(WIN_OBJS): ../../../Windows/$(*B).cpp

+	$(COMPL)

+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp

+	$(COMPL)

+$(UI_COMMON_OBJS): ../Common/$(*B).cpp

+	$(COMPL)

+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp

+	$(COMPL)

+$O\CopyCoder.obj: ../../Compress/$(*B).cpp

+	$(COMPL)

+$(C_OBJS): ../../../../C/$(*B).c

+	$(COMPL_O2)

+

+!include "../../Asm.mak"

diff --git a/CPP/7zip/UI/Console/resource.rc b/CPP/7zip/UI/Console/resource.rc
new file mode 100755
index 0000000..20dfee1
--- /dev/null
+++ b/CPP/7zip/UI/Console/resource.rc
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"

+

+MY_VERSION_INFO_APP("7-Zip Console", "7z")

diff --git a/CPP/Build.mak b/CPP/Build.mak
new file mode 100755
index 0000000..81ac79d
--- /dev/null
+++ b/CPP/Build.mak
@@ -0,0 +1,94 @@
+LIBS = $(LIBS) oleaut32.lib ole32.lib

+

+!IFDEF CPU

+!IFNDEF NO_BUFFEROVERFLOWU

+LIBS = $(LIBS) bufferoverflowU.lib

+!ENDIF

+!ENDIF

+

+

+!IFNDEF O

+!IFDEF CPU

+O=$(CPU)

+!ELSE

+O=O

+!ENDIF

+!ENDIF

+

+!IF "$(CPU)" == "AMD64"

+MY_ML = ml64 -Dx64

+!ELSEIF "$(CPU)" == "ARM"

+MY_ML = armasm

+!ELSE

+MY_ML = ml

+!ENDIF

+

+

+!IFDEF UNDER_CE

+RFLAGS = $(RFLAGS) -dUNDER_CE

+!IFDEF MY_CONSOLE

+LFLAGS = $(LFLAGS) /ENTRY:mainACRTStartup

+!ENDIF

+!ELSE

+!IFNDEF NEW_COMPILER

+LFLAGS = $(LFLAGS) -OPT:NOWIN98

+!ENDIF

+CFLAGS = $(CFLAGS) -Gr

+LIBS = $(LIBS) user32.lib advapi32.lib shell32.lib

+!ENDIF

+

+!IF "$(CPU)" == "ARM"

+COMPL_ASM = $(MY_ML) $** $O/$(*B).obj

+!ELSE

+COMPL_ASM = $(MY_ML) -c -Fo$O/ $**

+!ENDIF

+

+CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -WX -EHsc -Gy -GR-

+

+!IFDEF MY_STATIC_LINK

+!IFNDEF MY_SINGLE_THREAD

+CFLAGS = $(CFLAGS) -MT

+!ENDIF

+!ELSE

+CFLAGS = $(CFLAGS) -MD

+!ENDIF

+

+!IFDEF NEW_COMPILER

+CFLAGS = $(CFLAGS) -W4 -GS- -Zc:forScope

+!ELSE

+CFLAGS = $(CFLAGS) -W3

+!ENDIF

+

+CFLAGS_O1 = $(CFLAGS) -O1

+CFLAGS_O2 = $(CFLAGS) -O2

+

+LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF

+

+!IFDEF DEF_FILE

+LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE)

+!ENDIF

+

+PROGPATH = $O\$(PROG)

+

+COMPL_O1   = $(CC) $(CFLAGS_O1) $**

+COMPL_O2   = $(CC) $(CFLAGS_O2) $**

+COMPL_PCH  = $(CC) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $**

+COMPL      = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $**

+

+all: $(PROGPATH)

+

+clean:

+	-del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch

+

+$O:

+	if not exist "$O" mkdir "$O"

+

+$(PROGPATH): $O $(OBJS) $(DEF_FILE)

+	link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)

+

+!IFNDEF NO_DEFAULT_RES

+$O\resource.res: $(*B).rc

+	rc $(RFLAGS) -fo$@ $**

+!ENDIF

+$O\StdAfx.obj: $(*B).cpp

+	$(COMPL_PCH)

diff --git a/CPP/Common/AutoPtr.h b/CPP/Common/AutoPtr.h
new file mode 100755
index 0000000..e53fb7f
--- /dev/null
+++ b/CPP/Common/AutoPtr.h
@@ -0,0 +1,35 @@
+// Common/AutoPtr.h

+

+#ifndef __COMMON_AUTOPTR_H

+#define __COMMON_AUTOPTR_H

+

+template<class T> class CMyAutoPtr

+{

+  T *_p;

+public:

+  CMyAutoPtr(T *p = 0) : _p(p) {}

+  CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {}

+  CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p)

+  {

+    reset(p.release());

+    return (*this);

+  }

+  ~CMyAutoPtr() { delete _p; }

+  T& operator*() const { return *_p; }

+  // T* operator->() const { return (&**this); }

+  T* get() const { return _p; }

+  T* release()

+  {

+    T *tmp = _p;

+    _p = 0;

+    return tmp;

+  }

+  void reset(T* p = 0)

+  {

+    if (p != _p)

+      delete _p;

+    _p = p;

+  }

+};

+

+#endif

diff --git a/CPP/Common/Buffer.h b/CPP/Common/Buffer.h
new file mode 100755
index 0000000..defe943
--- /dev/null
+++ b/CPP/Common/Buffer.h
@@ -0,0 +1,77 @@
+// Common/Buffer.h

+

+#ifndef __COMMON_BUFFER_H

+#define __COMMON_BUFFER_H

+

+#include "Defs.h"

+

+template <class T> class CBuffer

+{

+protected:

+  size_t _capacity;

+  T *_items;

+public:

+  void Free()

+  {

+    delete []_items;

+    _items = 0;

+    _capacity = 0;

+  }

+  CBuffer(): _capacity(0), _items(0) {};

+  CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; }

+  CBuffer(size_t size): _items(0), _capacity(0) {  SetCapacity(size); }

+  virtual ~CBuffer() { delete []_items; }

+  operator T *() { return _items; };

+  operator const T *() const { return _items; };

+  size_t GetCapacity() const { return  _capacity; }

+  void SetCapacity(size_t newCapacity)

+  {

+    if (newCapacity == _capacity)

+      return;

+    T *newBuffer;

+    if (newCapacity > 0)

+    {

+      newBuffer = new T[newCapacity];

+      if (_capacity > 0)

+        memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T));

+    }

+    else

+      newBuffer = 0;

+    delete []_items;

+    _items = newBuffer;

+    _capacity = newCapacity;

+  }

+  CBuffer& operator=(const CBuffer &buffer)

+  {

+    Free();

+    if (buffer._capacity > 0)

+    {

+      SetCapacity(buffer._capacity);

+      memmove(_items, buffer._items, buffer._capacity * sizeof(T));

+    }

+    return *this;

+  }

+};

+

+template <class T>

+bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2)

+{

+  if (b1.GetCapacity() != b2.GetCapacity())

+    return false;

+  for (size_t i = 0; i < b1.GetCapacity(); i++)

+    if (b1[i] != b2[i])

+      return false;

+  return true;

+}

+

+template <class T>

+bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)

+{

+  return !(b1 == b2);

+}

+

+typedef CBuffer<char> CCharBuffer;

+typedef CBuffer<wchar_t> CWCharBuffer;

+typedef CBuffer<unsigned char> CByteBuffer;

+

+#endif

diff --git a/CPP/Common/CRC.cpp b/CPP/Common/CRC.cpp
new file mode 100755
index 0000000..6ac52c4
--- /dev/null
+++ b/CPP/Common/CRC.cpp
@@ -0,0 +1,7 @@
+// Common/CRC.cpp

+

+#include "StdAfx.h"

+

+#include "../../C/7zCrc.h"

+

+struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit;

diff --git a/CPP/Common/C_FileIO.cpp b/CPP/Common/C_FileIO.cpp
new file mode 100755
index 0000000..0e5647f
--- /dev/null
+++ b/CPP/Common/C_FileIO.cpp
@@ -0,0 +1,88 @@
+// Common/C_FileIO.h

+

+#include "C_FileIO.h"

+

+#include <fcntl.h>

+#include <unistd.h>

+

+namespace NC {

+namespace NFile {

+namespace NIO {

+

+bool CFileBase::OpenBinary(const char *name, int flags)

+{

+  #ifdef O_BINARY

+  flags |= O_BINARY;

+  #endif

+  Close();

+  _handle = ::open(name, flags, 0666);

+  return _handle != -1;

+}

+

+bool CFileBase::Close()

+{

+  if (_handle == -1)

+    return true;

+  if (close(_handle) != 0)

+    return false;

+  _handle = -1;

+  return true;

+}

+

+bool CFileBase::GetLength(UInt64 &length) const

+{

+  off_t curPos = Seek(0, SEEK_CUR);

+  off_t lengthTemp = Seek(0, SEEK_END);

+  Seek(curPos, SEEK_SET);

+  length = (UInt64)lengthTemp;

+  return true;

+}

+

+off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const

+{

+  return ::lseek(_handle, distanceToMove, moveMethod);

+}

+

+/////////////////////////

+// CInFile

+

+bool CInFile::Open(const char *name)

+{

+  return CFileBase::OpenBinary(name, O_RDONLY);

+}

+

+bool CInFile::OpenShared(const char *name, bool)

+{

+  return Open(name);

+}

+

+ssize_t CInFile::Read(void *data, size_t size)

+{

+  return read(_handle, data, size);

+}

+

+/////////////////////////

+// COutFile

+

+bool COutFile::Create(const char *name, bool createAlways)

+{

+  if (createAlways)

+  {

+    Close();

+    _handle = ::creat(name, 0666);

+    return _handle != -1;

+  }

+  return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY);

+}

+

+bool COutFile::Open(const char *name, DWORD creationDisposition)

+{

+  return Create(name, false);

+}

+

+ssize_t COutFile::Write(const void *data, size_t size)

+{

+  return write(_handle, data, size);

+}

+

+}}}

diff --git a/CPP/Common/C_FileIO.h b/CPP/Common/C_FileIO.h
new file mode 100755
index 0000000..3f8cbca
--- /dev/null
+++ b/CPP/Common/C_FileIO.h
@@ -0,0 +1,47 @@
+// Common/C_FileIO.h

+

+#ifndef __COMMON_C_FILEIO_H

+#define __COMMON_C_FILEIO_H

+

+#include <stdio.h>

+#include <sys/types.h>

+

+#include "Types.h"

+#include "MyWindows.h"

+

+namespace NC {

+namespace NFile {

+namespace NIO {

+

+class CFileBase

+{

+protected:

+  int _handle;

+  bool OpenBinary(const char *name, int flags);

+public:

+  CFileBase(): _handle(-1) {};

+  ~CFileBase() { Close(); }

+  bool Close();

+  bool GetLength(UInt64 &length) const;

+  off_t Seek(off_t distanceToMove, int moveMethod) const;

+};

+

+class CInFile: public CFileBase

+{

+public:

+  bool Open(const char *name);

+  bool OpenShared(const char *name, bool shareForWrite);

+  ssize_t Read(void *data, size_t size);

+};

+

+class COutFile: public CFileBase

+{

+public:

+  bool Create(const char *name, bool createAlways);

+  bool Open(const char *name, DWORD creationDisposition);

+  ssize_t Write(const void *data, size_t size);

+};

+

+}}}

+

+#endif

diff --git a/CPP/Common/ComTry.h b/CPP/Common/ComTry.h
new file mode 100755
index 0000000..b2b3029
--- /dev/null
+++ b/CPP/Common/ComTry.h
@@ -0,0 +1,17 @@
+// ComTry.h

+

+#ifndef __COM_TRY_H

+#define __COM_TRY_H

+

+#include "MyWindows.h"

+// #include "Exception.h"

+// #include "NewHandler.h"

+

+#define COM_TRY_BEGIN try {

+#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; }

+  

+  // catch(const CNewException &) { return E_OUTOFMEMORY; }

+  // catch(const CSystemException &e) { return e.ErrorCode; }

+  // catch(...) { return E_FAIL; }

+

+#endif

diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp
new file mode 100755
index 0000000..028f4f8
--- /dev/null
+++ b/CPP/Common/CommandLineParser.cpp
@@ -0,0 +1,229 @@
+// CommandLineParser.cpp

+

+#include "StdAfx.h"

+

+#include "CommandLineParser.h"

+

+namespace NCommandLineParser {

+

+bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)

+{

+  dest1.Empty();

+  dest2.Empty();

+  bool quoteMode = false;

+  int i;

+  for (i = 0; i < src.Length(); i++)

+  {

+    wchar_t c = src[i];

+    if (c == L' ' && !quoteMode)

+    {

+      dest2 = src.Mid(i + 1);

+      return i != 0;

+    }

+    if (c == L'\"')

+      quoteMode = !quoteMode;

+    else

+      dest1 += c;

+  }

+  return i != 0;

+}

+

+void SplitCommandLine(const UString &s, UStringVector &parts)

+{

+  UString sTemp = s;

+  sTemp.Trim();

+  parts.Clear();

+  for (;;)

+  {

+    UString s1, s2;

+    if (SplitCommandLine(sTemp, s1, s2))

+      parts.Add(s1);

+    if (s2.IsEmpty())

+      break;

+    sTemp = s2;

+  }

+}

+

+

+static const wchar_t kSwitchID1 = '-';

+// static const wchar_t kSwitchID2 = '/';

+

+static const wchar_t kSwitchMinus = '-';

+static const wchar_t *kStopSwitchParsing = L"--";

+

+static bool IsItSwitchChar(wchar_t c)

+{

+  return (c == kSwitchID1 /*|| c == kSwitchID2 */);

+}

+

+CParser::CParser(int numSwitches):

+  _numSwitches(numSwitches)

+{

+  _switches = new CSwitchResult[_numSwitches];

+}

+

+CParser::~CParser()

+{

+  delete []_switches;

+}

+

+void CParser::ParseStrings(const CSwitchForm *switchForms,

+  const UStringVector &commandStrings)

+{

+  int numCommandStrings = commandStrings.Size();

+  bool stopSwitch = false;

+  for (int i = 0; i < numCommandStrings; i++)

+  {

+    const UString &s = commandStrings[i];

+    if (stopSwitch)

+      NonSwitchStrings.Add(s);

+    else

+      if (s == kStopSwitchParsing)

+        stopSwitch = true;

+      else

+        if (!ParseString(s, switchForms))

+          NonSwitchStrings.Add(s);

+  }

+}

+

+// if string contains switch then function updates switch structures

+// out: (string is a switch)

+bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)

+{

+  int len = s.Length();

+  if (len == 0)

+    return false;

+  int pos = 0;

+  if (!IsItSwitchChar(s[pos]))

+    return false;

+  while (pos < len)

+  {

+    if (IsItSwitchChar(s[pos]))

+      pos++;

+    const int kNoLen = -1;

+    int matchedSwitchIndex = 0; // GCC Warning

+    int maxLen = kNoLen;

+    for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++)

+    {

+      int switchLen = MyStringLen(switchForms[switchIndex].IDString);

+      if (switchLen <= maxLen || pos + switchLen > len)

+        continue;

+

+      UString temp = s + pos;

+      temp = temp.Left(switchLen);

+      if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0)

+      // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0)

+      {

+        matchedSwitchIndex = switchIndex;

+        maxLen = switchLen;

+      }

+    }

+    if (maxLen == kNoLen)

+      throw "maxLen == kNoLen";

+    CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex];

+    const CSwitchForm &switchForm = switchForms[matchedSwitchIndex];

+    if ((!switchForm.Multi) && matchedSwitch.ThereIs)

+      throw "switch must be single";

+    matchedSwitch.ThereIs = true;

+    pos += maxLen;

+    int tailSize = len - pos;

+    NSwitchType::EEnum type = switchForm.Type;

+    switch(type)

+    {

+      case NSwitchType::kPostMinus:

+        {

+          if (tailSize == 0)

+            matchedSwitch.WithMinus = false;

+          else

+          {

+            matchedSwitch.WithMinus = (s[pos] == kSwitchMinus);

+            if (matchedSwitch.WithMinus)

+              pos++;

+          }

+          break;

+        }

+      case NSwitchType::kPostChar:

+        {

+          if (tailSize < switchForm.MinLen)

+            throw "switch is not full";

+          UString set = switchForm.PostCharSet;

+          const int kEmptyCharValue = -1;

+          if (tailSize == 0)

+            matchedSwitch.PostCharIndex = kEmptyCharValue;

+          else

+          {

+            int index = set.Find(s[pos]);

+            if (index < 0)

+              matchedSwitch.PostCharIndex =  kEmptyCharValue;

+            else

+            {

+              matchedSwitch.PostCharIndex = index;

+              pos++;

+            }

+          }

+          break;

+        }

+      case NSwitchType::kLimitedPostString:

+      case NSwitchType::kUnLimitedPostString:

+        {

+          int minLen = switchForm.MinLen;

+          if (tailSize < minLen)

+            throw "switch is not full";

+          if (type == NSwitchType::kUnLimitedPostString)

+          {

+            matchedSwitch.PostStrings.Add(s.Mid(pos));

+            return true;

+          }

+          int maxLen = switchForm.MaxLen;

+          UString stringSwitch = s.Mid(pos, minLen);

+          pos += minLen;

+          for (int i = minLen; i < maxLen && pos < len; i++, pos++)

+          {

+            wchar_t c = s[pos];

+            if (IsItSwitchChar(c))

+              break;

+            stringSwitch += c;

+          }

+          matchedSwitch.PostStrings.Add(stringSwitch);

+          break;

+        }

+      case NSwitchType::kSimple:

+          break;

+    }

+  }

+  return true;

+}

+

+const CSwitchResult& CParser::operator[](size_t index) const

+{

+  return _switches[index];

+}

+

+/////////////////////////////////

+// Command parsing procedures

+

+int ParseCommand(int numCommandForms, const CCommandForm *commandForms,

+    const UString &commandString, UString &postString)

+{

+  for (int i = 0; i < numCommandForms; i++)

+  {

+    const UString id = commandForms[i].IDString;

+    if (commandForms[i].PostStringMode)

+    {

+      if (commandString.Find(id) == 0)

+      {

+        postString = commandString.Mid(id.Length());

+        return i;

+      }

+    }

+    else

+      if (commandString == id)

+      {

+        postString.Empty();

+        return i;

+      }

+  }

+  return -1;

+}

+   

+}

diff --git a/CPP/Common/CommandLineParser.h b/CPP/Common/CommandLineParser.h
new file mode 100755
index 0000000..ec079e3
--- /dev/null
+++ b/CPP/Common/CommandLineParser.h
@@ -0,0 +1,72 @@
+// Common/CommandLineParser.h

+

+#ifndef __COMMON_COMMAND_LINE_PARSER_H

+#define __COMMON_COMMAND_LINE_PARSER_H

+

+#include "MyString.h"

+

+namespace NCommandLineParser {

+

+bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2);

+void SplitCommandLine(const UString &s, UStringVector &parts);

+

+namespace NSwitchType {

+  enum EEnum

+  {

+    kSimple,

+    kPostMinus,

+    kLimitedPostString,

+    kUnLimitedPostString,

+    kPostChar

+  };

+}

+

+struct CSwitchForm

+{

+  const wchar_t *IDString;

+  NSwitchType::EEnum Type;

+  bool Multi;

+  int MinLen;

+  int MaxLen;

+  const wchar_t *PostCharSet;

+};

+

+struct CSwitchResult

+{

+  bool ThereIs;

+  bool WithMinus;

+  UStringVector PostStrings;

+  int PostCharIndex;

+  CSwitchResult(): ThereIs(false) {};

+};

+  

+class CParser

+{

+  int _numSwitches;

+  CSwitchResult *_switches;

+  bool ParseString(const UString &s, const CSwitchForm *switchForms);

+public:

+  UStringVector NonSwitchStrings;

+  CParser(int numSwitches);

+  ~CParser();

+  void ParseStrings(const CSwitchForm *switchForms,

+    const UStringVector &commandStrings);

+  const CSwitchResult& operator[](size_t index) const;

+};

+

+/////////////////////////////////

+// Command parsing procedures

+

+struct CCommandForm

+{

+  const wchar_t *IDString;

+  bool PostStringMode;

+};

+

+// Returns: Index of form and postString; -1, if there is no match

+int ParseCommand(int numCommandForms, const CCommandForm *commandForms,

+    const UString &commandString, UString &postString);

+

+}

+

+#endif

diff --git a/CPP/Common/Defs.h b/CPP/Common/Defs.h
new file mode 100755
index 0000000..69b8ece
--- /dev/null
+++ b/CPP/Common/Defs.h
@@ -0,0 +1,20 @@
+// Common/Defs.h

+

+#ifndef __COMMON_DEFS_H

+#define __COMMON_DEFS_H

+

+template <class T> inline T MyMin(T a, T b)

+  {  return a < b ? a : b; }

+template <class T> inline T MyMax(T a, T b)

+  {  return a > b ? a : b; }

+

+template <class T> inline int MyCompare(T a, T b)

+  {  return a < b ? -1 : (a == b ? 0 : 1); }

+

+inline int BoolToInt(bool value)

+  { return (value ? 1: 0); }

+

+inline bool IntToBool(int value)

+  { return (value != 0); }

+

+#endif

diff --git a/CPP/Common/DynamicBuffer.h b/CPP/Common/DynamicBuffer.h
new file mode 100755
index 0000000..2bd80ac
--- /dev/null
+++ b/CPP/Common/DynamicBuffer.h
@@ -0,0 +1,50 @@
+// Common/DynamicBuffer.h

+

+#ifndef __COMMON_DYNAMIC_BUFFER_H

+#define __COMMON_DYNAMIC_BUFFER_H

+

+#include "Buffer.h"

+

+template <class T> class CDynamicBuffer: public CBuffer<T>

+{

+  void GrowLength(size_t size)

+  {

+    size_t delta;

+    if (this->_capacity > 64)

+      delta = this->_capacity / 4;

+    else if (this->_capacity > 8)

+      delta = 16;

+    else

+      delta = 4;

+    delta = MyMax(delta, size);

+    size_t newCap = this->_capacity + delta;

+    if (newCap < delta)

+      newCap = this->_capacity + size;

+    SetCapacity(newCap);

+  }

+public:

+  CDynamicBuffer(): CBuffer<T>() {};

+  CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {};

+  CDynamicBuffer(size_t size): CBuffer<T>(size) {};

+  CDynamicBuffer& operator=(const CDynamicBuffer &buffer)

+  {

+    this->Free();

+    if (buffer._capacity > 0)

+    {

+      SetCapacity(buffer._capacity);

+      memmove(this->_items, buffer._items, buffer._capacity * sizeof(T));

+    }

+    return *this;

+  }

+  void EnsureCapacity(size_t capacity)

+  {

+    if (this->_capacity < capacity)

+      GrowLength(capacity - this->_capacity);

+  }

+};

+

+typedef CDynamicBuffer<char> CCharDynamicBuffer;

+typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer;

+typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer;

+

+#endif

diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp
new file mode 100755
index 0000000..312e9f0
--- /dev/null
+++ b/CPP/Common/IntToString.cpp
@@ -0,0 +1,77 @@
+// Common/IntToString.cpp

+

+#include "StdAfx.h"

+

+#include "IntToString.h"

+

+void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base)

+{

+  if (base < 2 || base > 36)

+  {

+    *s = '\0';

+    return;

+  }

+  char temp[72];

+  int pos = 0;

+  do

+  {

+    int delta = (int)(value % base);

+    temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10)));

+    value /= base;

+  }

+  while (value != 0);

+  do

+    *s++ = temp[--pos];

+  while (pos > 0);

+  *s = '\0';

+}

+

+void ConvertUInt64ToString(UInt64 value, wchar_t *s)

+{

+  wchar_t temp[32];

+  int pos = 0;

+  do

+  {

+    temp[pos++] = (wchar_t)(L'0' + (int)(value % 10));

+    value /= 10;

+  }

+  while (value != 0);

+  do

+    *s++ = temp[--pos];

+  while (pos > 0);

+  *s = L'\0';

+}

+

+void ConvertUInt32ToString(UInt32 value, char *s) { ConvertUInt64ToString(value, s); }

+void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s); }

+

+void ConvertInt64ToString(Int64 value, char *s)

+{

+  if (value < 0)

+  {

+    *s++ = '-';

+    value = -value;

+  }

+  ConvertUInt64ToString(value, s);

+}

+

+void ConvertInt64ToString(Int64 value, wchar_t *s)

+{

+  if (value < 0)

+  {

+    *s++ = L'-';

+    value = -value;

+  }

+  ConvertUInt64ToString(value, s);

+}

+

+void ConvertUInt32ToHexWithZeros(UInt32 value, char *s)

+{

+  for (int i = 0; i < 8; i++)

+  {

+    int t = value & 0xF;

+    value >>= 4;

+    s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

+  }

+  s[8] = '\0';

+}

diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h
new file mode 100755
index 0000000..c57fd6a
--- /dev/null
+++ b/CPP/Common/IntToString.h
@@ -0,0 +1,19 @@
+// Common/IntToString.h

+

+#ifndef __COMMON_INT_TO_STRING_H

+#define __COMMON_INT_TO_STRING_H

+

+#include <stddef.h>

+#include "Types.h"

+

+void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10);

+void ConvertUInt64ToString(UInt64 value, wchar_t *s);

+void ConvertInt64ToString(Int64 value, char *s);

+void ConvertInt64ToString(Int64 value, wchar_t *s);

+

+void ConvertUInt32ToString(UInt32 value, char *s);

+void ConvertUInt32ToString(UInt32 value, wchar_t *s);

+

+void ConvertUInt32ToHexWithZeros(UInt32 value, char *s);

+

+#endif

diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp
new file mode 100755
index 0000000..ff61b02
--- /dev/null
+++ b/CPP/Common/ListFileUtils.cpp
@@ -0,0 +1,75 @@
+// Common/ListFileUtils.cpp

+

+#include "StdAfx.h"

+

+#include "MyWindows.h"

+#include "../Windows/FileIO.h"

+

+#include "ListFileUtils.h"

+#include "StringConvert.h"

+#include "UTFConvert.h"

+

+static const char kQuoteChar     = '\"';

+static void RemoveQuote(UString &s)

+{

+  if (s.Length() >= 2)

+    if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar)

+      s = s.Mid(1, s.Length() - 2);

+}

+

+bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage)

+{

+  NWindows::NFile::NIO::CInFile file;

+  if (!file.Open(fileName))

+    return false;

+  UInt64 length;

+  if (!file.GetLength(length))

+    return false;

+  if (length > ((UInt32)1 << 31))

+    return false;

+  AString s;

+  char *p = s.GetBuffer((int)length + 1);

+  UInt32 processed;

+  if (!file.Read(p, (UInt32)length, processed))

+    return false;

+  p[(UInt32)length] = 0;

+  s.ReleaseBuffer();

+  file.Close();

+

+  UString u;

+  #ifdef CP_UTF8

+  if (codePage == CP_UTF8)

+  {

+    if (!ConvertUTF8ToUnicode(s, u))

+      return false;

+  }

+  else

+  #endif

+    u = MultiByteToUnicodeString(s, codePage);

+  if (!u.IsEmpty())

+  {

+    if (u[0] == 0xFEFF)

+      u.Delete(0);

+  }

+

+  UString t;

+  for (int i = 0; i < u.Length(); i++)

+  {

+    wchar_t c = u[i];

+    if (c == L'\n' || c == 0xD)

+    {

+      t.Trim();

+      RemoveQuote(t);

+      if (!t.IsEmpty())

+        resultStrings.Add(t);

+      t.Empty();

+    }

+    else

+      t += c;

+  }

+  t.Trim();

+  RemoveQuote(t);

+  if (!t.IsEmpty())

+    resultStrings.Add(t);

+  return true;

+}

diff --git a/CPP/Common/ListFileUtils.h b/CPP/Common/ListFileUtils.h
new file mode 100755
index 0000000..64f2199
--- /dev/null
+++ b/CPP/Common/ListFileUtils.h
@@ -0,0 +1,11 @@
+// Common/ListFileUtils.h

+

+#ifndef __COMMON_LISTFILEUTILS_H

+#define __COMMON_LISTFILEUTILS_H

+

+#include "MyString.h"

+#include "Types.h"

+

+bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP);

+

+#endif

diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h
new file mode 100755
index 0000000..d04fa4c
--- /dev/null
+++ b/CPP/Common/MyCom.h
@@ -0,0 +1,225 @@
+// MyCom.h

+

+#ifndef __MYCOM_H

+#define __MYCOM_H

+

+#include "MyWindows.h"

+

+#ifndef RINOK

+#define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; }

+#endif

+

+template <class T>

+class CMyComPtr

+{

+  T* _p;

+public:

+  // typedef T _PtrClass;

+  CMyComPtr() { _p = NULL;}

+  CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); }

+  CMyComPtr(const CMyComPtr<T>& lp)

+  {

+    if ((_p = lp._p) != NULL)

+      _p->AddRef();

+  }

+  ~CMyComPtr() { if (_p) _p->Release(); }

+  void Release() { if (_p) { _p->Release(); _p = NULL; } }

+  operator T*() const {  return (T*)_p;  }

+  // T& operator*() const {  return *_p; }

+  T** operator&() { return &_p; }

+  T* operator->() const { return _p; }

+  T* operator=(T* p)

+  {

+    if (p != 0)

+      p->AddRef();

+    if (_p)

+      _p->Release();

+    _p = p;

+    return p;

+  }

+  T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }

+  bool operator!() const { return (_p == NULL); }

+  // bool operator==(T* pT) const {  return _p == pT; }

+  // Compare two objects for equivalence

+  void Attach(T* p2)

+  {

+    Release();

+    _p = p2;

+  }

+  T* Detach()

+  {

+    T* pt = _p;

+    _p = NULL;

+    return pt;

+  }

+  #ifdef _WIN32

+  HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)

+  {

+    return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);

+  }

+  #endif

+  /*

+  HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)

+  {

+    CLSID clsid;

+    HRESULT hr = CLSIDFromProgID(szProgID, &clsid);

+    ATLASSERT(_p == NULL);

+    if (SUCCEEDED(hr))

+      hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);

+    return hr;

+  }

+  */

+  template <class Q>

+  HRESULT QueryInterface(REFGUID iid, Q** pp) const

+  {

+    return _p->QueryInterface(iid, (void**)pp);

+  }

+};

+

+//////////////////////////////////////////////////////////

+

+inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)

+{

+  *bstr = ::SysAllocString(src);

+  return (*bstr != 0) ? S_OK : E_OUTOFMEMORY;

+}

+

+class CMyComBSTR

+{

+public:

+  BSTR m_str;

+  CMyComBSTR(): m_str(NULL) {}

+  CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }

+  // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }

+  // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize);  }

+  CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }

+  /*

+  CMyComBSTR(REFGUID src)

+  {

+    LPOLESTR szGuid;

+    StringFromCLSID(src, &szGuid);

+    m_str = ::SysAllocString(szGuid);

+    CoTaskMemFree(szGuid);

+  }

+  */

+  ~CMyComBSTR() { ::SysFreeString(m_str); }

+  CMyComBSTR& operator=(const CMyComBSTR& src)

+  {

+    if (m_str != src.m_str)

+    {

+      if (m_str)

+        ::SysFreeString(m_str);

+      m_str = src.MyCopy();

+    }

+    return *this;

+  }

+  CMyComBSTR& operator=(LPCOLESTR src)

+  {

+    ::SysFreeString(m_str);

+    m_str = ::SysAllocString(src);

+    return *this;

+  }

+  unsigned int Length() const { return ::SysStringLen(m_str); }

+  operator BSTR() const { return m_str; }

+  BSTR* operator&() { return &m_str; }

+  BSTR MyCopy() const

+  {

+    int byteLen = ::SysStringByteLen(m_str);

+    BSTR res = ::SysAllocStringByteLen(NULL, byteLen);

+    memcpy(res, m_str, byteLen);

+    return res;

+  }

+  /*

+  void Attach(BSTR src) { m_str = src; }

+  BSTR Detach()

+  {

+    BSTR s = m_str;

+    m_str = NULL;

+    return s;

+  }

+  */

+  void Empty()

+  {

+    ::SysFreeString(m_str);

+    m_str = NULL;

+  }

+  bool operator!() const {  return (m_str == NULL); }

+};

+

+//////////////////////////////////////////////////////////

+

+class CMyUnknownImp

+{

+public:

+  ULONG __m_RefCount;

+  CMyUnknownImp(): __m_RefCount(0) {}

+};

+

+#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \

+    (REFGUID iid, void **outObject) {

+

+#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \

+    { *outObject = (void *)(i *)this; AddRef(); return S_OK; }

+

+#define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \

+    { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; }

+

+#define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \

+    MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \

+    MY_QUERYINTERFACE_ENTRY(i)

+

+#define MY_QUERYINTERFACE_END return E_NOINTERFACE; }

+

+#define MY_ADDREF_RELEASE \

+STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \

+STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0)  \

+  return __m_RefCount; delete this; return 0; }

+

+#define MY_UNKNOWN_IMP_SPEC(i) \

+  MY_QUERYINTERFACE_BEGIN \

+  i \

+  MY_QUERYINTERFACE_END \

+  MY_ADDREF_RELEASE

+

+

+#define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \

+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \

+  MY_QUERYINTERFACE_END \

+  MY_ADDREF_RELEASE

+

+#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \

+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \

+  MY_QUERYINTERFACE_ENTRY(i) \

+  )

+

+#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \

+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \

+  MY_QUERYINTERFACE_ENTRY(i1) \

+  MY_QUERYINTERFACE_ENTRY(i2) \

+  )

+

+#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \

+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \

+  MY_QUERYINTERFACE_ENTRY(i1) \

+  MY_QUERYINTERFACE_ENTRY(i2) \

+  MY_QUERYINTERFACE_ENTRY(i3) \

+  )

+

+#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \

+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \

+  MY_QUERYINTERFACE_ENTRY(i1) \

+  MY_QUERYINTERFACE_ENTRY(i2) \

+  MY_QUERYINTERFACE_ENTRY(i3) \

+  MY_QUERYINTERFACE_ENTRY(i4) \

+  )

+

+#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \

+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \

+  MY_QUERYINTERFACE_ENTRY(i1) \

+  MY_QUERYINTERFACE_ENTRY(i2) \

+  MY_QUERYINTERFACE_ENTRY(i3) \

+  MY_QUERYINTERFACE_ENTRY(i4) \

+  MY_QUERYINTERFACE_ENTRY(i5) \

+  )

+

+#endif

diff --git a/CPP/Common/MyException.h b/CPP/Common/MyException.h
new file mode 100755
index 0000000..cd9fe69
--- /dev/null
+++ b/CPP/Common/MyException.h
@@ -0,0 +1,14 @@
+// Common/Exception.h

+

+#ifndef __COMMON_EXCEPTION_H

+#define __COMMON_EXCEPTION_H

+

+#include "MyWindows.h"

+

+struct CSystemException

+{

+  HRESULT ErrorCode;

+  CSystemException(HRESULT errorCode): ErrorCode(errorCode) {}

+};

+

+#endif

diff --git a/CPP/Common/MyGuidDef.h b/CPP/Common/MyGuidDef.h
new file mode 100755
index 0000000..da73d0a
--- /dev/null
+++ b/CPP/Common/MyGuidDef.h
@@ -0,0 +1,54 @@
+// Common/MyGuidDef.h

+

+#ifndef GUID_DEFINED

+#define GUID_DEFINED

+

+#include "Types.h"

+

+typedef struct {

+  UInt32 Data1;

+  UInt16 Data2;

+  UInt16 Data3;

+  unsigned char Data4[8];

+} GUID;

+

+#ifdef __cplusplus

+#define REFGUID const GUID &

+#else

+#define REFGUID const GUID *

+#endif

+

+#define REFCLSID REFGUID

+#define REFIID REFGUID

+

+#ifdef __cplusplus

+inline int operator==(REFGUID g1, REFGUID g2)

+{

+  for (int i = 0; i < (int)sizeof(g1); i++)

+    if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i])

+      return 0;

+  return 1;

+}

+inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); }

+#endif

+

+#ifdef __cplusplus

+  #define MY_EXTERN_C extern "C"

+#else

+  #define MY_EXTERN_C extern

+#endif

+

+#endif

+

+

+#ifdef DEFINE_GUID

+#undef DEFINE_GUID

+#endif

+

+#ifdef INITGUID

+  #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \

+    MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }

+#else

+  #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \

+    MY_EXTERN_C const GUID name

+#endif

diff --git a/CPP/Common/MyInitGuid.h b/CPP/Common/MyInitGuid.h
new file mode 100755
index 0000000..98d1705
--- /dev/null
+++ b/CPP/Common/MyInitGuid.h
@@ -0,0 +1,22 @@
+// Common/MyInitGuid.h

+

+#ifndef __COMMON_MY_INITGUID_H

+#define __COMMON_MY_INITGUID_H

+

+#ifdef _WIN32

+#ifdef UNDER_CE

+#include <basetyps.h>

+#endif

+#include <initguid.h>

+#ifdef UNDER_CE

+DEFINE_GUID(IID_IUnknown,

+0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);

+#endif

+#else

+#define INITGUID

+#include "MyGuidDef.h"

+DEFINE_GUID(IID_IUnknown,

+0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);

+#endif

+

+#endif

diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp
new file mode 100755
index 0000000..1a25c9e
--- /dev/null
+++ b/CPP/Common/MyString.cpp
@@ -0,0 +1,200 @@
+// Common/MyString.cpp

+

+#include "StdAfx.h"

+

+#ifndef _WIN32

+#include <ctype.h>

+#endif

+

+#ifndef _UNICODE

+#include "StringConvert.h"

+#endif

+

+#include "MyString.h"

+

+

+#ifdef _WIN32

+

+#ifndef _UNICODE

+

+wchar_t MyCharUpper(wchar_t c)

+{

+  if (c == 0)

+    return 0;

+  wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c);

+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)

+    return (wchar_t)(unsigned int)(UINT_PTR)res;

+  const int kBufferSize = 4;

+  char s[kBufferSize + 1];

+  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);

+  if (numChars == 0 || numChars > kBufferSize)

+    return c;

+  s[numChars] = 0;

+  ::CharUpperA(s);

+  ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);

+  return c;

+}

+

+wchar_t MyCharLower(wchar_t c)

+{

+  if (c == 0)

+    return 0;

+  wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c);

+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)

+    return (wchar_t)(unsigned int)(UINT_PTR)res;

+  const int kBufferSize = 4;

+  char s[kBufferSize + 1];

+  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);

+  if (numChars == 0 || numChars > kBufferSize)

+    return c;

+  s[numChars] = 0;

+  ::CharLowerA(s);

+  ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);

+  return c;

+}

+

+wchar_t * MyStringUpper(wchar_t *s)

+{

+  if (s == 0)

+    return 0;

+  wchar_t *res = CharUpperW(s);

+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)

+    return res;

+  AString a = UnicodeStringToMultiByte(s);

+  a.MakeUpper();

+  return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));

+}

+

+wchar_t * MyStringLower(wchar_t *s)

+{

+  if (s == 0)

+    return 0;

+  wchar_t *res = CharLowerW(s);

+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)

+    return res;

+  AString a = UnicodeStringToMultiByte(s);

+  a.MakeLower();

+  return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));

+}

+

+#endif

+

+/*

+inline int ConvertCompareResult(int r) { return r - 2; }

+

+int MyStringCollate(const wchar_t *s1, const wchar_t *s2)

+{

+  int res = CompareStringW(

+        LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1);

+  #ifdef _UNICODE

+  return ConvertCompareResult(res);

+  #else

+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)

+    return ConvertCompareResult(res);

+  return MyStringCollate(UnicodeStringToMultiByte(s1),

+        UnicodeStringToMultiByte(s2));

+  #endif

+}

+

+#ifndef UNDER_CE

+int MyStringCollate(const char *s1, const char *s2)

+{

+  return ConvertCompareResult(CompareStringA(

+    LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1));

+}

+

+int MyStringCollateNoCase(const char *s1, const char *s2)

+{

+  return ConvertCompareResult(CompareStringA(

+    LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1));

+}

+#endif

+

+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)

+{

+  int res = CompareStringW(

+        LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1);

+  #ifdef _UNICODE

+  return ConvertCompareResult(res);

+  #else

+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)

+    return ConvertCompareResult(res);

+  return MyStringCollateNoCase(UnicodeStringToMultiByte(s1),

+      UnicodeStringToMultiByte(s2));

+  #endif

+}

+*/

+

+#else

+

+wchar_t MyCharUpper(wchar_t c)

+{

+  return toupper(c);

+}

+

+/*

+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)

+{

+  for (;;)

+  {

+    wchar_t c1 = *s1++;

+    wchar_t c2 = *s2++;

+    wchar_t u1 = MyCharUpper(c1);

+    wchar_t u2 = MyCharUpper(c2);

+

+    if (u1 < u2) return -1;

+    if (u1 > u2) return 1;

+    if (u1 == 0) return 0;

+  }

+}

+*/

+

+#endif

+

+int MyStringCompare(const char *s1, const char *s2)

+{

+  for (;;)

+  {

+    unsigned char c1 = (unsigned char)*s1++;

+    unsigned char c2 = (unsigned char)*s2++;

+    if (c1 < c2) return -1;

+    if (c1 > c2) return 1;

+    if (c1 == 0) return 0;

+  }

+}

+

+int MyStringCompare(const wchar_t *s1, const wchar_t *s2)

+{

+  for (;;)

+  {

+    wchar_t c1 = *s1++;

+    wchar_t c2 = *s2++;

+    if (c1 < c2) return -1;

+    if (c1 > c2) return 1;

+    if (c1 == 0) return 0;

+  }

+}

+

+int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2)

+{

+  for (;;)

+  {

+    wchar_t c1 = *s1++;

+    wchar_t c2 = *s2++;

+    if (c1 != c2)

+    {

+      wchar_t u1 = MyCharUpper(c1);

+      wchar_t u2 = MyCharUpper(c2);

+      if (u1 < u2) return -1;

+      if (u1 > u2) return 1;

+    }

+    if (c1 == 0) return 0;

+  }

+}

+

+/*

+int MyStringCompareNoCase(const char *s1, const char *s2)

+{

+  return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));

+}

+*/

diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h
new file mode 100755
index 0000000..ede2573
--- /dev/null
+++ b/CPP/Common/MyString.h
@@ -0,0 +1,625 @@
+// Common/String.h

+

+#ifndef __COMMON_STRING_H

+#define __COMMON_STRING_H

+

+#include <string.h>

+

+#include "MyVector.h"

+

+template <class T>

+inline int MyStringLen(const T *s)

+{

+  int i;

+  for (i = 0; s[i] != '\0'; i++);

+  return i;

+}

+

+template <class T>

+inline T * MyStringCopy(T *dest, const T *src)

+{

+  T *destStart = dest;

+  while ((*dest++ = *src++) != 0);

+  return destStart;

+}

+

+inline wchar_t* MyStringGetNextCharPointer(wchar_t *p)

+  { return (p + 1); }

+inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p)

+  { return (p + 1); }

+inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p)

+  { return (p - 1); }

+inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p)

+  { return (p - 1); }

+

+#ifdef _WIN32

+

+inline const char* MyStringGetNextCharPointer(const char *p)

+{

+  #ifdef UNDER_CE

+  return p + 1;

+  #else

+  return CharNextA(p);

+  #endif

+}

+

+inline const char* MyStringGetPrevCharPointer(const char *base, const char *p)

+  { return CharPrevA(base, p); }

+

+inline char MyCharUpper(char c)

+  { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }

+#ifdef _UNICODE

+inline wchar_t MyCharUpper(wchar_t c)

+  { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); }

+#else

+wchar_t MyCharUpper(wchar_t c);

+#endif

+

+#ifdef _UNICODE

+inline wchar_t MyCharLower(wchar_t c)

+  { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); }

+#else

+wchar_t MyCharLower(wchar_t c);

+#endif

+

+inline char MyCharLower(char c)

+#ifdef UNDER_CE

+  { return (char)MyCharLower((wchar_t)c); }

+#else

+  { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }

+#endif

+

+inline char * MyStringUpper(char *s) { return CharUpperA(s); }

+#ifdef _UNICODE

+inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }

+#else

+wchar_t * MyStringUpper(wchar_t *s);

+#endif

+

+inline char * MyStringLower(char *s) { return CharLowerA(s); }

+#ifdef _UNICODE

+inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }

+#else

+wchar_t * MyStringLower(wchar_t *s);

+#endif

+

+#else // Standard-C

+wchar_t MyCharUpper(wchar_t c);

+#endif

+

+//////////////////////////////////////

+// Compare

+

+/*

+#ifndef UNDER_CE

+int MyStringCollate(const char *s1, const char *s2);

+int MyStringCollateNoCase(const char *s1, const char *s2);

+#endif

+int MyStringCollate(const wchar_t *s1, const wchar_t *s2);

+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2);

+*/

+

+int MyStringCompare(const char *s1, const char  *s2);

+int MyStringCompare(const wchar_t *s1, const wchar_t *s2);

+

+// int MyStringCompareNoCase(const char *s1, const char  *s2);

+int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2);

+

+template <class T>

+class CStringBase

+{

+  void TrimLeftWithCharSet(const CStringBase &charSet)

+  {

+    const T *p = _chars;

+    while (charSet.Find(*p) >= 0 && (*p != 0))

+      p = GetNextCharPointer(p);

+    Delete(0, (int)(p - _chars));

+  }

+  void TrimRightWithCharSet(const CStringBase &charSet)

+  {

+    const T *p = _chars;

+    const T *pLast = NULL;

+    while (*p != 0)

+    {

+      if (charSet.Find(*p) >= 0)

+      {

+        if (pLast == NULL)

+          pLast = p;

+      }

+      else

+        pLast = NULL;

+      p = GetNextCharPointer(p);

+    }

+    if (pLast != NULL)

+    {

+      int i = (int)(pLast - _chars);

+      Delete(i, _length - i);

+    }

+

+  }

+  void MoveItems(int destIndex, int srcIndex)

+  {

+    memmove(_chars + destIndex, _chars + srcIndex,

+        sizeof(T) * (_length - srcIndex + 1));

+  }

+  

+  void InsertSpace(int &index, int size)

+  {

+    CorrectIndex(index);

+    GrowLength(size);

+    MoveItems(index + size, index);

+  }

+

+  static const T *GetNextCharPointer(const T *p)

+    { return MyStringGetNextCharPointer(p); }

+  static const T *GetPrevCharPointer(const T *base, const T *p)

+    { return MyStringGetPrevCharPointer(base, p); }

+protected:

+  T *_chars;

+  int _length;

+  int _capacity;

+  

+  void SetCapacity(int newCapacity)

+  {

+    int realCapacity = newCapacity + 1;

+    if (realCapacity == _capacity)

+      return;

+    /*

+    const int kMaxStringSize = 0x20000000;

+    if (newCapacity > kMaxStringSize || newCapacity < _length)

+      throw 1052337;

+    */

+    T *newBuffer = new T[realCapacity];

+    if (_capacity > 0)

+    {

+      for (int i = 0; i < _length; i++)

+        newBuffer[i] = _chars[i];

+      delete []_chars;

+    }

+    _chars = newBuffer;

+    _chars[_length] = 0;

+    _capacity = realCapacity;

+  }

+

+  void GrowLength(int n)

+  {

+    int freeSize = _capacity - _length - 1;

+    if (n <= freeSize)

+      return;

+    int delta;

+    if (_capacity > 64)

+      delta = _capacity / 2;

+    else if (_capacity > 8)

+      delta = 16;

+    else

+      delta = 4;

+    if (freeSize + delta < n)

+      delta = n - freeSize;

+    SetCapacity(_capacity + delta);

+  }

+

+  void CorrectIndex(int &index) const

+  {

+    if (index > _length)

+      index = _length;

+  }

+

+public:

+  CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); }

+  CStringBase(T c):  _chars(0), _length(0), _capacity(0)

+  {

+    SetCapacity(1);

+    _chars[0] = c;

+    _chars[1] = 0;

+    _length = 1;

+  }

+  CStringBase(const T *chars): _chars(0), _length(0), _capacity(0)

+  {

+    int length = MyStringLen(chars);

+    SetCapacity(length);

+    MyStringCopy(_chars, chars); // can be optimized by memove()

+    _length = length;

+  }

+  CStringBase(const CStringBase &s):  _chars(0), _length(0), _capacity(0)

+  {

+    SetCapacity(s._length);

+    MyStringCopy(_chars, s._chars);

+    _length = s._length;

+  }

+  ~CStringBase() {  delete []_chars; }

+

+  operator const T*() const { return _chars;}

+

+  T Back() const { return _chars[_length - 1]; }

+

+  // The minimum size of the character buffer in characters.

+  // This value does not include space for a null terminator.

+  T* GetBuffer(int minBufLength)

+  {

+    if (minBufLength >= _capacity)

+      SetCapacity(minBufLength);

+    return _chars;

+  }

+  void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }

+  void ReleaseBuffer(int newLength)

+  {

+    /*

+    if (newLength >= _capacity)

+      throw 282217;

+    */

+    _chars[newLength] = 0;

+    _length = newLength;

+  }

+

+  CStringBase& operator=(T c)

+  {

+    Empty();

+    SetCapacity(1);

+    _chars[0] = c;

+    _chars[1] = 0;

+    _length = 1;

+    return *this;

+  }

+  CStringBase& operator=(const T *chars)

+  {

+    Empty();

+    int length = MyStringLen(chars);

+    SetCapacity(length);

+    MyStringCopy(_chars, chars);

+    _length = length;

+    return *this;

+  }

+  CStringBase& operator=(const CStringBase& s)

+  {

+    if (&s == this)

+      return *this;

+    Empty();

+    SetCapacity(s._length);

+    MyStringCopy(_chars, s._chars);

+    _length = s._length;

+    return *this;

+  }

+  

+  CStringBase& operator+=(T c)

+  {

+    GrowLength(1);

+    _chars[_length] = c;

+    _chars[++_length] = 0;

+    return *this;

+  }

+  CStringBase& operator+=(const T *s)

+  {

+    int len = MyStringLen(s);

+    GrowLength(len);

+    MyStringCopy(_chars + _length, s);

+    _length += len;

+    return *this;

+  }

+  CStringBase& operator+=(const CStringBase &s)

+  {

+    GrowLength(s._length);

+    MyStringCopy(_chars + _length, s._chars);

+    _length += s._length;

+    return *this;

+  }

+  void Empty()

+  {

+    _length = 0;

+    _chars[0] = 0;

+  }

+  int Length() const { return _length; }

+  bool IsEmpty() const { return (_length == 0); }

+

+  CStringBase Mid(int startIndex) const

+    { return Mid(startIndex, _length - startIndex); }

+  CStringBase Mid(int startIndex, int count) const

+  {

+    if (startIndex + count > _length)

+      count = _length - startIndex;

+    

+    if (startIndex == 0 && startIndex + count == _length)

+      return *this;

+    

+    CStringBase<T> result;

+    result.SetCapacity(count);

+    // MyStringNCopy(result._chars, _chars + startIndex, count);

+    for (int i = 0; i < count; i++)

+      result._chars[i] = _chars[startIndex + i];

+    result._chars[count] = 0;

+    result._length = count;

+    return result;

+  }

+  CStringBase Left(int count) const

+    { return Mid(0, count); }

+  CStringBase Right(int count) const

+  {

+    if (count > _length)

+      count = _length;

+    return Mid(_length - count, count);

+  }

+

+  void MakeUpper()

+    { MyStringUpper(_chars); }

+  void MakeLower()

+    { MyStringLower(_chars); }

+

+  int Compare(const CStringBase& s) const

+    { return MyStringCompare(_chars, s._chars); }

+

+  int Compare(const T *s) const

+    { return MyStringCompare(_chars, s); }

+

+  int CompareNoCase(const CStringBase& s) const

+    { return MyStringCompareNoCase(_chars, s._chars); }

+

+  int CompareNoCase(const T *s) const

+    { return MyStringCompareNoCase(_chars, s); }

+

+  /*

+  int Collate(const CStringBase& s) const

+    { return MyStringCollate(_chars, s._chars); }

+  int CollateNoCase(const CStringBase& s) const

+    { return MyStringCollateNoCase(_chars, s._chars); }

+  */

+

+  int Find(T c) const { return Find(c, 0); }

+  int Find(T c, int startIndex) const

+  {

+    const T *p = _chars + startIndex;

+    for (;;)

+    {

+      if (*p == c)

+        return (int)(p - _chars);

+      if (*p == 0)

+        return -1;

+      p = GetNextCharPointer(p);

+    }

+  }

+  int Find(const CStringBase &s) const { return Find(s, 0); }

+  int Find(const CStringBase &s, int startIndex) const

+  {

+    if (s.IsEmpty())

+      return startIndex;

+    for (; startIndex < _length; startIndex++)

+    {

+      int j;

+      for (j = 0; j < s._length && startIndex + j < _length; j++)

+        if (_chars[startIndex+j] != s._chars[j])

+          break;

+      if (j == s._length)

+        return startIndex;

+    }

+    return -1;

+  }

+  int ReverseFind(T c) const

+  {

+    if (_length == 0)

+      return -1;

+    const T *p = _chars + _length - 1;

+    for (;;)

+    {

+      if (*p == c)

+        return (int)(p - _chars);

+      if (p == _chars)

+        return -1;

+      p = GetPrevCharPointer(_chars, p);

+    }

+  }

+  int FindOneOf(const CStringBase &s) const

+  {

+    for (int i = 0; i < _length; i++)

+      if (s.Find(_chars[i]) >= 0)

+        return i;

+      return -1;

+  }

+

+  void TrimLeft(T c)

+  {

+    const T *p = _chars;

+    while (c == *p)

+      p = GetNextCharPointer(p);

+    Delete(0, p - _chars);

+  }

+  private:

+  CStringBase GetTrimDefaultCharSet()

+  {

+    CStringBase<T> charSet;

+    charSet += (T)' ';

+    charSet += (T)'\n';

+    charSet += (T)'\t';

+    return charSet;

+  }

+  public:

+

+  void TrimLeft()

+  {

+    TrimLeftWithCharSet(GetTrimDefaultCharSet());

+  }

+  void TrimRight()

+  {

+    TrimRightWithCharSet(GetTrimDefaultCharSet());

+  }

+  void TrimRight(T c)

+  {

+    const T *p = _chars;

+    const T *pLast = NULL;

+    while (*p != 0)

+    {

+      if (*p == c)

+      {

+        if (pLast == NULL)

+          pLast = p;

+      }

+      else

+        pLast = NULL;

+      p = GetNextCharPointer(p);

+    }

+    if (pLast != NULL)

+    {

+      int i = pLast - _chars;

+      Delete(i, _length - i);

+    }

+  }

+  void Trim()

+  {

+    TrimRight();

+    TrimLeft();

+  }

+

+  int Insert(int index, T c)

+  {

+    InsertSpace(index, 1);

+    _chars[index] = c;

+    _length++;

+    return _length;

+  }

+  int Insert(int index, const CStringBase &s)

+  {

+    CorrectIndex(index);

+    if (s.IsEmpty())

+      return _length;

+    int numInsertChars = s.Length();

+    InsertSpace(index, numInsertChars);

+    for (int i = 0; i < numInsertChars; i++)

+      _chars[index + i] = s[i];

+    _length += numInsertChars;

+    return _length;

+  }

+

+  // !!!!!!!!!!!!!!! test it if newChar = '\0'

+  int Replace(T oldChar, T newChar)

+  {

+    if (oldChar == newChar)

+      return 0;

+    int number  = 0;

+    int pos  = 0;

+    while (pos < Length())

+    {

+      pos = Find(oldChar, pos);

+      if (pos < 0)

+        break;

+      _chars[pos] = newChar;

+      pos++;

+      number++;

+    }

+    return number;

+  }

+  int Replace(const CStringBase &oldString, const CStringBase &newString)

+  {

+    if (oldString.IsEmpty())

+      return 0;

+    if (oldString == newString)

+      return 0;

+    int oldStringLength = oldString.Length();

+    int newStringLength = newString.Length();

+    int number  = 0;

+    int pos  = 0;

+    while (pos < _length)

+    {

+      pos = Find(oldString, pos);

+      if (pos < 0)

+        break;

+      Delete(pos, oldStringLength);

+      Insert(pos, newString);

+      pos += newStringLength;

+      number++;

+    }

+    return number;

+  }

+  int Delete(int index, int count = 1)

+  {

+    if (index + count > _length)

+      count = _length - index;

+    if (count > 0)

+    {

+      MoveItems(index, index + count);

+      _length -= count;

+    }

+    return _length;

+  }

+  void DeleteBack() { Delete(_length - 1); }

+};

+

+template <class T>

+CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2)

+{

+  CStringBase<T> result(s1);

+  result += s2;

+  return result;

+}

+

+template <class T>

+CStringBase<T> operator+(const CStringBase<T>& s, T c)

+{

+  CStringBase<T> result(s);

+  result += c;

+  return result;

+}

+

+template <class T>

+CStringBase<T> operator+(T c, const CStringBase<T>& s)

+{

+  CStringBase<T> result(c);

+  result += s;

+  return result;

+}

+

+template <class T>

+CStringBase<T> operator+(const CStringBase<T>& s, const T * chars)

+{

+  CStringBase<T> result(s);

+  result += chars;

+  return result;

+}

+

+template <class T>

+CStringBase<T> operator+(const T * chars, const CStringBase<T>& s)

+{

+  CStringBase<T> result(chars);

+  result += s;

+  return result;

+}

+

+template <class T>

+bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2)

+  { return (s1.Compare(s2) == 0); }

+

+template <class T>

+bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2)

+  { return (s1.Compare(s2) < 0); }

+

+template <class T>

+bool operator==(const T *s1, const CStringBase<T>& s2)

+  { return (s2.Compare(s1) == 0); }

+

+template <class T>

+bool operator==(const CStringBase<T>& s1, const T *s2)

+  { return (s1.Compare(s2) == 0); }

+

+template <class T>

+bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2)

+  { return (s1.Compare(s2) != 0); }

+

+template <class T>

+bool operator!=(const T *s1, const CStringBase<T>& s2)

+  { return (s2.Compare(s1) != 0); }

+

+template <class T>

+bool operator!=(const CStringBase<T>& s1, const T *s2)

+  { return (s1.Compare(s2) != 0); }

+

+typedef CStringBase<char> AString;

+typedef CStringBase<wchar_t> UString;

+

+typedef CObjectVector<AString> AStringVector;

+typedef CObjectVector<UString> UStringVector;

+

+#ifdef _UNICODE

+  typedef UString CSysString;

+#else

+  typedef AString CSysString;

+#endif

+

+typedef CObjectVector<CSysString> CSysStringVector;

+

+#endif

diff --git a/CPP/Common/MyUnknown.h b/CPP/Common/MyUnknown.h
new file mode 100755
index 0000000..7935124
--- /dev/null
+++ b/CPP/Common/MyUnknown.h
@@ -0,0 +1,13 @@
+// MyUnknown.h

+

+#ifndef __MY_UNKNOWN_H

+#define __MY_UNKNOWN_H

+

+#ifdef _WIN32

+#include <basetyps.h>

+#include <unknwn.h>

+#else

+#include "MyWindows.h"

+#endif

+  

+#endif

diff --git a/CPP/Common/MyVector.cpp b/CPP/Common/MyVector.cpp
new file mode 100755
index 0000000..054d0aa
--- /dev/null
+++ b/CPP/Common/MyVector.cpp
@@ -0,0 +1,87 @@
+// Common/MyVector.cpp

+

+#include "StdAfx.h"

+

+#include <string.h>

+

+#include "MyVector.h"

+

+CBaseRecordVector::~CBaseRecordVector() { ClearAndFree(); }

+

+void CBaseRecordVector::ClearAndFree()

+{

+  Clear();

+  delete []((unsigned char *)_items);

+  _capacity = 0;

+  _size = 0;

+  _items = 0;

+}

+

+void CBaseRecordVector::Clear() { DeleteFrom(0); }

+void CBaseRecordVector::DeleteBack() { Delete(_size - 1); }

+void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); }

+

+void CBaseRecordVector::ReserveOnePosition()

+{

+  if (_size != _capacity)

+    return;

+  unsigned delta = 1;

+  if (_capacity >= 64)

+    delta = (unsigned)_capacity / 4;

+  else if (_capacity >= 8)

+    delta = 8;

+  Reserve(_capacity + (int)delta);

+}

+

+void CBaseRecordVector::Reserve(int newCapacity)

+{

+  // if (newCapacity <= _capacity)

+  if (newCapacity == _capacity)

+    return;

+  if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1)))

+    throw 1052353;

+  size_t newSize = (size_t)(unsigned)newCapacity * _itemSize;

+  if (newSize / _itemSize != (size_t)(unsigned)newCapacity)

+    throw 1052354;

+  unsigned char *p = NULL;

+  if (newSize > 0)

+  {

+    p = new unsigned char[newSize];

+    if (p == 0)

+      throw 1052355;

+    int numRecordsToMove = (_size < newCapacity ? _size : newCapacity);

+    memcpy(p, _items, _itemSize * numRecordsToMove);

+  }

+  delete [](unsigned char *)_items;

+  _items = p;

+  _capacity = newCapacity;

+}

+

+void CBaseRecordVector::ReserveDown()

+{

+  Reserve(_size);

+}

+

+void CBaseRecordVector::MoveItems(int destIndex, int srcIndex)

+{

+  memmove(((unsigned char *)_items) + destIndex * _itemSize,

+    ((unsigned char  *)_items) + srcIndex * _itemSize,

+    _itemSize * (_size - srcIndex));

+}

+

+void CBaseRecordVector::InsertOneItem(int index)

+{

+  ReserveOnePosition();

+  MoveItems(index + 1, index);

+  _size++;

+}

+

+void CBaseRecordVector::Delete(int index, int num)

+{

+  TestIndexAndCorrectNum(index, num);

+  if (num > 0)

+  {

+    MoveItems(index, index + num);

+    _size -= num;

+  }

+}

diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h
new file mode 100755
index 0000000..24740dc
--- /dev/null
+++ b/CPP/Common/MyVector.h
@@ -0,0 +1,266 @@
+// Common/Vector.h

+

+#ifndef __COMMON_VECTOR_H

+#define __COMMON_VECTOR_H

+

+#include "Defs.h"

+

+class CBaseRecordVector

+{

+  void MoveItems(int destIndex, int srcIndex);

+protected:

+  int _capacity;

+  int _size;

+  void *_items;

+  size_t _itemSize;

+  

+  void ReserveOnePosition();

+  void InsertOneItem(int index);

+  void TestIndexAndCorrectNum(int index, int &num) const

+    { if (index + num > _size) num = _size - index; }

+public:

+  CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {}

+  virtual ~CBaseRecordVector();

+  void ClearAndFree();

+  int Size() const { return _size; }

+  bool IsEmpty() const { return (_size == 0); }

+  void Reserve(int newCapacity);

+  void ReserveDown();

+  virtual void Delete(int index, int num = 1);

+  void Clear();

+  void DeleteFrom(int index);

+  void DeleteBack();

+};

+

+template <class T>

+class CRecordVector: public CBaseRecordVector

+{

+public:

+  CRecordVector(): CBaseRecordVector(sizeof(T)){};

+  CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v; }

+  CRecordVector& operator=(const CRecordVector &v)

+  {

+    Clear();

+    return (*this += v);

+  }

+  CRecordVector& operator+=(const CRecordVector &v)

+  {

+    int size = v.Size();

+    Reserve(Size() + size);

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

+      Add(v[i]);

+    return *this;

+  }

+  int Add(T item)

+  {

+    ReserveOnePosition();

+    ((T *)_items)[_size] = item;

+    return _size++;

+  }

+  void Insert(int index, T item)

+  {

+    InsertOneItem(index);

+    ((T *)_items)[index] = item;

+  }

+  // T* GetPointer() const { return (T*)_items; }

+  // operator const T *() const { return _items; };

+  const T& operator[](int index) const { return ((T *)_items)[index]; }

+  T& operator[](int index) { return ((T *)_items)[index]; }

+  const T& Front() const { return operator[](0); }

+  T& Front() { return operator[](0); }

+  const T& Back() const { return operator[](_size - 1); }

+  T& Back() { return operator[](_size - 1); }

+

+  void Swap(int i, int j)

+  {

+    T temp = operator[](i);

+    operator[](i) = operator[](j);

+    operator[](j) = temp;

+  }

+

+  int FindInSorted(const T& item, int left, int right) const

+  {

+    while (left != right)

+    {

+      int mid = (left + right) / 2;

+      const T& midValue = (*this)[mid];

+      if (item == midValue)

+        return mid;

+      if (item < midValue)

+        right = mid;

+      else

+        left = mid + 1;

+    }

+    return -1;

+  }

+

+  int FindInSorted(const T& item) const

+  {

+    int left = 0, right = Size();

+    while (left != right)

+    {

+      int mid = (left + right) / 2;

+      const T& midValue = (*this)[mid];

+      if (item == midValue)

+        return mid;

+      if (item < midValue)

+        right = mid;

+      else

+        left = mid + 1;

+    }

+    return -1;

+  }

+

+  int AddToUniqueSorted(const T& item)

+  {

+    int left = 0, right = Size();

+    while (left != right)

+    {

+      int mid = (left + right) / 2;

+      const T& midValue = (*this)[mid];

+      if (item == midValue)

+        return mid;

+      if (item < midValue)

+        right = mid;

+      else

+        left = mid + 1;

+    }

+    Insert(right, item);

+    return right;

+  }

+

+  static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param)

+  {

+    T temp = p[k];

+    for (;;)

+    {

+      int s = (k << 1);

+      if (s > size)

+        break;

+      if (s < size && compare(p + s + 1, p + s, param) > 0)

+        s++;

+      if (compare(&temp, p + s, param) >= 0)

+        break;

+      p[k] = p[s];

+      k = s;

+    }

+    p[k] = temp;

+  }

+

+  void Sort(int (*compare)(const T*, const T*, void *), void *param)

+  {

+    int size = _size;

+    if (size <= 1)

+      return;

+    T* p = (&Front()) - 1;

+    {

+      int i = size / 2;

+      do

+        SortRefDown(p, i, size, compare, param);

+      while (--i != 0);

+    }

+    do

+    {

+      T temp = p[size];

+      p[size--] = p[1];

+      p[1] = temp;

+      SortRefDown(p, 1, size, compare, param);

+    }

+    while (size > 1);

+  }

+};

+

+typedef CRecordVector<int> CIntVector;

+typedef CRecordVector<unsigned int> CUIntVector;

+typedef CRecordVector<bool> CBoolVector;

+typedef CRecordVector<unsigned char> CByteVector;

+typedef CRecordVector<void *> CPointerVector;

+

+template <class T>

+class CObjectVector: public CPointerVector

+{

+public:

+  CObjectVector() {};

+  ~CObjectVector() { Clear(); };

+  CObjectVector(const CObjectVector &v): CPointerVector() { *this = v; }

+  CObjectVector& operator=(const CObjectVector &v)

+  {

+    Clear();

+    return (*this += v);

+  }

+  CObjectVector& operator+=(const CObjectVector &v)

+  {

+    int size = v.Size();

+    Reserve(Size() + size);

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

+      Add(v[i]);

+    return *this;

+  }

+  const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); }

+  T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); }

+  T& Front() { return operator[](0); }

+  const T& Front() const { return operator[](0); }

+  T& Back() { return operator[](_size - 1); }

+  const T& Back() const { return operator[](_size - 1); }

+  int Add(const T& item) { return CPointerVector::Add(new T(item)); }

+  void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); }

+  virtual void Delete(int index, int num = 1)

+  {

+    TestIndexAndCorrectNum(index, num);

+    for (int i = 0; i < num; i++)

+      delete (T *)(((void **)_items)[index + i]);

+    CPointerVector::Delete(index, num);

+  }

+  int Find(const T& item) const

+  {

+    for (int i = 0; i < Size(); i++)

+      if (item == (*this)[i])

+        return i;

+    return -1;

+  }

+  int FindInSorted(const T& item) const

+  {

+    int left = 0, right = Size();

+    while (left != right)

+    {

+      int mid = (left + right) / 2;

+      const T& midValue = (*this)[mid];

+      if (item == midValue)

+        return mid;

+      if (item < midValue)

+        right = mid;

+      else

+        left = mid + 1;

+    }

+    return -1;

+  }

+  int AddToSorted(const T& item)

+  {

+    int left = 0, right = Size();

+    while (left != right)

+    {

+      int mid = (left + right) / 2;

+      const T& midValue = (*this)[mid];

+      if (item == midValue)

+      {

+        right = mid + 1;

+        break;

+      }

+      if (item < midValue)

+        right = mid;

+      else

+        left = mid + 1;

+    }

+    Insert(right, item);

+    return right;

+  }

+

+  void Sort(int (*compare)(void *const *, void *const *, void *), void *param)

+    { CPointerVector::Sort(compare, param); }

+

+  static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */)

+    { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); }

+  void Sort() { CPointerVector::Sort(CompareObjectItems, 0); }

+};

+

+#endif

diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h
new file mode 100755
index 0000000..5cfded1
--- /dev/null
+++ b/CPP/Common/MyWindows.h
@@ -0,0 +1,204 @@
+// MyWindows.h

+

+#ifndef __MYWINDOWS_H

+#define __MYWINDOWS_H

+

+#ifdef _WIN32

+

+#include <windows.h>

+

+#else

+

+#include <stddef.h> // for wchar_t

+#include <string.h>

+

+#include "MyGuidDef.h"

+

+typedef char CHAR;

+typedef unsigned char UCHAR;

+

+#undef BYTE

+typedef unsigned char BYTE;

+

+typedef short SHORT;

+typedef unsigned short USHORT;

+

+#undef WORD

+typedef unsigned short WORD;

+typedef short VARIANT_BOOL;

+

+typedef int INT;

+typedef Int32 INT32;

+typedef unsigned int UINT;

+typedef UInt32 UINT32;

+typedef INT32 LONG;   // LONG, ULONG and DWORD must be 32-bit

+typedef UINT32 ULONG;

+

+#undef DWORD

+typedef UINT32 DWORD;

+

+typedef Int64 LONGLONG;

+typedef UInt64 ULONGLONG;

+

+typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER;

+typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER;

+

+typedef const CHAR *LPCSTR;

+typedef CHAR TCHAR;

+typedef const TCHAR *LPCTSTR;

+typedef wchar_t WCHAR;

+typedef WCHAR OLECHAR;

+typedef const WCHAR *LPCWSTR;

+typedef OLECHAR *BSTR;

+typedef const OLECHAR *LPCOLESTR;

+typedef OLECHAR *LPOLESTR;

+

+typedef struct _FILETIME

+{

+  DWORD dwLowDateTime;

+  DWORD dwHighDateTime;

+}FILETIME;

+

+#define HRESULT LONG

+#define FAILED(Status) ((HRESULT)(Status)<0)

+typedef ULONG PROPID;

+typedef LONG SCODE;

+

+#define S_OK    ((HRESULT)0x00000000L)

+#define S_FALSE ((HRESULT)0x00000001L)

+#define E_NOTIMPL ((HRESULT)0x80004001L)

+#define E_NOINTERFACE ((HRESULT)0x80004002L)

+#define E_ABORT ((HRESULT)0x80004004L)

+#define E_FAIL ((HRESULT)0x80004005L)

+#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L)

+#define E_OUTOFMEMORY ((HRESULT)0x8007000EL)

+#define E_INVALIDARG ((HRESULT)0x80070057L)

+

+#ifdef _MSC_VER

+#define STDMETHODCALLTYPE __stdcall

+#else

+#define STDMETHODCALLTYPE

+#endif

+

+#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f

+#define STDMETHOD(f) STDMETHOD_(HRESULT, f)

+#define STDMETHODIMP_(type) type STDMETHODCALLTYPE

+#define STDMETHODIMP STDMETHODIMP_(HRESULT)

+

+#define PURE = 0

+

+#define MIDL_INTERFACE(x) struct

+

+#ifdef __cplusplus

+

+DEFINE_GUID(IID_IUnknown,

+0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);

+struct IUnknown

+{

+  STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE;

+  STDMETHOD_(ULONG, AddRef)() PURE;

+  STDMETHOD_(ULONG, Release)() PURE;

+  #ifndef _WIN32

+  virtual ~IUnknown() {}

+  #endif

+};

+

+typedef IUnknown *LPUNKNOWN;

+

+#endif

+

+#define VARIANT_TRUE ((VARIANT_BOOL)-1)

+#define VARIANT_FALSE ((VARIANT_BOOL)0)

+

+enum VARENUM

+{

+  VT_EMPTY = 0,

+  VT_NULL = 1,

+  VT_I2 = 2,

+  VT_I4 = 3,

+  VT_R4 = 4,

+  VT_R8 = 5,

+  VT_CY = 6,

+  VT_DATE = 7,

+  VT_BSTR = 8,

+  VT_DISPATCH = 9,

+  VT_ERROR = 10,

+  VT_BOOL = 11,

+  VT_VARIANT = 12,

+  VT_UNKNOWN = 13,

+  VT_DECIMAL = 14,

+  VT_I1 = 16,

+  VT_UI1 = 17,

+  VT_UI2 = 18,

+  VT_UI4 = 19,

+  VT_I8 = 20,

+  VT_UI8 = 21,

+  VT_INT = 22,

+  VT_UINT = 23,

+  VT_VOID = 24,

+  VT_HRESULT = 25,

+  VT_FILETIME = 64

+};

+

+typedef unsigned short VARTYPE;

+typedef WORD PROPVAR_PAD1;

+typedef WORD PROPVAR_PAD2;

+typedef WORD PROPVAR_PAD3;

+

+#ifdef __cplusplus

+

+typedef struct tagPROPVARIANT

+{

+  VARTYPE vt;

+  PROPVAR_PAD1 wReserved1;

+  PROPVAR_PAD2 wReserved2;

+  PROPVAR_PAD3 wReserved3;

+  union

+  {

+    CHAR cVal;

+    UCHAR bVal;

+    SHORT iVal;

+    USHORT uiVal;

+    LONG lVal;

+    ULONG ulVal;

+    INT intVal;

+    UINT uintVal;

+    LARGE_INTEGER hVal;

+    ULARGE_INTEGER uhVal;

+    VARIANT_BOOL boolVal;

+    SCODE scode;

+    FILETIME filetime;

+    BSTR bstrVal;

+  };

+} PROPVARIANT;

+

+typedef PROPVARIANT tagVARIANT;

+typedef tagVARIANT VARIANT;

+typedef VARIANT VARIANTARG;

+

+MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop);

+MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src);

+

+#endif

+

+MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);

+MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz);

+MY_EXTERN_C void SysFreeString(BSTR bstr);

+MY_EXTERN_C UINT SysStringByteLen(BSTR bstr);

+MY_EXTERN_C UINT SysStringLen(BSTR bstr);

+

+MY_EXTERN_C DWORD GetLastError();

+MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2);

+

+#define CP_ACP    0

+#define CP_OEMCP  1

+

+typedef enum tagSTREAM_SEEK

+{

+  STREAM_SEEK_SET = 0,

+  STREAM_SEEK_CUR = 1,

+  STREAM_SEEK_END = 2

+} STREAM_SEEK;

+

+#endif

+#endif

diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp
new file mode 100755
index 0000000..611bbd8
--- /dev/null
+++ b/CPP/Common/NewHandler.cpp
@@ -0,0 +1,116 @@
+// NewHandler.cpp

+ 

+#include "StdAfx.h"

+

+#include <stdlib.h>

+

+#include "NewHandler.h"

+

+// #define DEBUG_MEMORY_LEAK

+

+#ifndef DEBUG_MEMORY_LEAK

+

+#ifdef _WIN32

+void *

+#ifdef _MSC_VER

+__cdecl

+#endif

+operator new(size_t size)

+{

+  // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);

+  void *p = ::malloc(size);

+  if (p == 0)

+    throw CNewException();

+  return p;

+}

+

+void

+#ifdef _MSC_VER

+__cdecl

+#endif

+operator delete(void *p) throw()

+{

+  /*

+  if (p == 0)

+    return;

+  ::HeapFree(::GetProcessHeap(), 0, p);

+  */

+  ::free(p);

+}

+#endif

+

+#else

+

+#pragma init_seg(lib)

+const int kDebugSize = 1000000;

+static void *a[kDebugSize];

+static int index = 0;

+

+static int numAllocs = 0;

+void * __cdecl operator new(size_t size)

+{

+  numAllocs++;

+  void *p = HeapAlloc(GetProcessHeap(), 0, size);

+  if (index == 40)

+  {

+    int t = 1;

+  }

+  if (index < kDebugSize)

+  {

+    a[index] = p;

+    index++;

+  }

+  if (p == 0)

+    throw CNewException();

+  printf("Alloc %6d, size = %8d\n", numAllocs, size);

+  return p;

+}

+

+class CC

+{

+public:

+  CC()

+  {

+    for (int i = 0; i < kDebugSize; i++)

+      a[i] = 0;

+  }

+  ~CC()

+  {

+    for (int i = 0; i < kDebugSize; i++)

+      if (a[i] != 0)

+        return;

+  }

+} g_CC;

+

+

+void __cdecl operator delete(void *p)

+{

+  if (p == 0)

+    return;

+  /*

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

+    if (a[i] == p)

+      a[i] = 0;

+  */

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

+  numAllocs--;

+  printf("Free %d\n", numAllocs);

+}

+

+#endif

+

+/*

+int MemErrorVC(size_t)

+{

+  throw CNewException();

+  // return 1;

+}

+CNewHandlerSetter::CNewHandlerSetter()

+{

+  // MemErrorOldVCFunction = _set_new_handler(MemErrorVC);

+}

+CNewHandlerSetter::~CNewHandlerSetter()

+{

+  // _set_new_handler(MemErrorOldVCFunction);

+}

+*/

diff --git a/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h
new file mode 100755
index 0000000..6f710cd
--- /dev/null
+++ b/CPP/Common/NewHandler.h
@@ -0,0 +1,16 @@
+// Common/NewHandler.h

+

+#ifndef __COMMON_NEWHANDLER_H

+#define __COMMON_NEWHANDLER_H

+

+class CNewException {};

+

+#ifdef _WIN32

+void

+#ifdef _MSC_VER

+__cdecl

+#endif

+operator delete(void *p) throw();

+#endif

+

+#endif

diff --git a/CPP/Common/StdAfx.h b/CPP/Common/StdAfx.h
new file mode 100755
index 0000000..9b43572
--- /dev/null
+++ b/CPP/Common/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+// #include "MyWindows.h"

+#include "NewHandler.h"

+

+#endif

diff --git a/CPP/Common/StdInStream.cpp b/CPP/Common/StdInStream.cpp
new file mode 100755
index 0000000..442191e
--- /dev/null
+++ b/CPP/Common/StdInStream.cpp
@@ -0,0 +1,107 @@
+// Common/StdInStream.cpp

+

+#include "StdAfx.h"

+

+#include <tchar.h>

+

+#include "StdInStream.h"

+#include "StringConvert.h"

+#include "UTFConvert.h"

+

+#ifdef _MSC_VER

+// "was declared deprecated" disabling

+#pragma warning(disable : 4996 )

+#endif

+

+static const char kIllegalChar = '\0';

+static const char kNewLineChar = '\n';

+

+static const char *kEOFMessage = "Unexpected end of input stream";

+static const char *kReadErrorMessage  ="Error reading input stream";

+static const char *kIllegalCharMessage = "Illegal character in input stream";

+

+static LPCTSTR kFileOpenMode = TEXT("r");

+

+extern int g_CodePage;

+

+CStdInStream g_StdIn(stdin);

+

+bool CStdInStream::Open(LPCTSTR fileName)

+{

+  Close();

+  _stream = _tfopen(fileName, kFileOpenMode);

+  _streamIsOpen = (_stream != 0);

+  return _streamIsOpen;

+}

+

+bool CStdInStream::Close()

+{

+  if (!_streamIsOpen)

+    return true;

+  _streamIsOpen = (fclose(_stream) != 0);

+  return !_streamIsOpen;

+}

+

+CStdInStream::~CStdInStream()

+{

+  Close();

+}

+

+AString CStdInStream::ScanStringUntilNewLine(bool allowEOF)

+{

+  AString s;

+  for (;;)

+  {

+    int intChar = GetChar();

+    if (intChar == EOF)

+    {

+      if (allowEOF)

+        break;

+      throw kEOFMessage;

+    }

+    char c = char(intChar);

+    if (c == kIllegalChar)

+      throw kIllegalCharMessage;

+    if (c == kNewLineChar)

+      break;

+    s += c;

+  }

+  return s;

+}

+

+UString CStdInStream::ScanUStringUntilNewLine()

+{

+  AString s = ScanStringUntilNewLine(true);

+  int codePage = g_CodePage;

+  if (codePage == -1)

+    codePage = CP_OEMCP;

+  UString dest;

+  if (codePage == CP_UTF8)

+    ConvertUTF8ToUnicode(s, dest);

+  else

+    dest = MultiByteToUnicodeString(s, (UINT)codePage);

+  return dest;

+}

+

+void CStdInStream::ReadToString(AString &resultString)

+{

+  resultString.Empty();

+  int c;

+  while ((c = GetChar()) != EOF)

+    resultString += char(c);

+}

+

+bool CStdInStream::Eof()

+{

+  return (feof(_stream) != 0);

+}

+

+int CStdInStream::GetChar()

+{

+  int c = fgetc(_stream); // getc() doesn't work in BeOS?

+  if (c == EOF && !Eof())

+    throw kReadErrorMessage;

+  return c;

+}

+

+

diff --git a/CPP/Common/StdInStream.h b/CPP/Common/StdInStream.h
new file mode 100755
index 0000000..67ef82b
--- /dev/null
+++ b/CPP/Common/StdInStream.h
@@ -0,0 +1,32 @@
+// Common/StdInStream.h

+

+#ifndef __COMMON_STDINSTREAM_H

+#define __COMMON_STDINSTREAM_H

+

+#include <stdio.h>

+

+#include "MyString.h"

+#include "Types.h"

+

+class CStdInStream

+{

+  bool _streamIsOpen;

+  FILE *_stream;

+public:

+  CStdInStream(): _streamIsOpen(false) {};

+  CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {};

+  ~CStdInStream();

+  bool Open(LPCTSTR fileName);

+  bool Close();

+

+  AString ScanStringUntilNewLine(bool allowEOF = false);

+  void ReadToString(AString &resultString);

+  UString ScanUStringUntilNewLine();

+

+  bool Eof();

+  int GetChar();

+};

+

+extern CStdInStream g_StdIn;

+

+#endif

diff --git a/CPP/Common/StdOutStream.cpp b/CPP/Common/StdOutStream.cpp
new file mode 100755
index 0000000..f7ec2a6
--- /dev/null
+++ b/CPP/Common/StdOutStream.cpp
@@ -0,0 +1,104 @@
+// Common/StdOutStream.cpp

+

+#include "StdAfx.h"

+

+#include <tchar.h>

+

+#include "IntToString.h"

+#include "StdOutStream.h"

+#include "StringConvert.h"

+#include "UTFConvert.h"

+

+#ifdef _MSC_VER

+// "was declared deprecated" disabling

+#pragma warning(disable : 4996 )

+#endif

+

+static const char kNewLineChar =  '\n';

+

+static const char *kFileOpenMode = "wt";

+

+extern int g_CodePage;

+

+CStdOutStream  g_StdOut(stdout);

+CStdOutStream  g_StdErr(stderr);

+

+bool CStdOutStream::Open(const char *fileName)

+{

+  Close();

+  _stream = fopen(fileName, kFileOpenMode);

+  _streamIsOpen = (_stream != 0);

+  return _streamIsOpen;

+}

+

+bool CStdOutStream::Close()

+{

+  if (!_streamIsOpen)

+    return true;

+  if (fclose(_stream) != 0)

+    return false;

+  _stream = 0;

+  _streamIsOpen = false;

+  return true;

+}

+

+bool CStdOutStream::Flush()

+{

+  return (fflush(_stream) == 0);

+}

+

+CStdOutStream::~CStdOutStream ()

+{

+  Close();

+}

+

+CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream  &))

+{

+  (*aFunction)(*this);

+  return *this;

+}

+

+CStdOutStream & endl(CStdOutStream & outStream)

+{

+  return outStream << kNewLineChar;

+}

+

+CStdOutStream & CStdOutStream::operator<<(const char *s)

+{

+  fputs(s, _stream);

+  return *this;

+}

+

+CStdOutStream & CStdOutStream::operator<<(const wchar_t *s)

+{

+  int codePage = g_CodePage;

+  if (codePage == -1)

+    codePage = CP_OEMCP;

+  AString dest;

+  if (codePage == CP_UTF8)

+    ConvertUnicodeToUTF8(s, dest);

+  else

+    dest = UnicodeStringToMultiByte(s, (UINT)codePage);

+  *this << (const char *)dest;

+  return *this;

+}

+

+CStdOutStream & CStdOutStream::operator<<(char c)

+{

+  fputc(c, _stream);

+  return *this;

+}

+

+CStdOutStream & CStdOutStream::operator<<(int number)

+{

+  char textString[32];

+  ConvertInt64ToString(number, textString);

+  return operator<<(textString);

+}

+

+CStdOutStream & CStdOutStream::operator<<(UInt64 number)

+{

+  char textString[32];

+  ConvertUInt64ToString(number, textString);

+  return operator<<(textString);

+}

diff --git a/CPP/Common/StdOutStream.h b/CPP/Common/StdOutStream.h
new file mode 100755
index 0000000..c2fcd9d
--- /dev/null
+++ b/CPP/Common/StdOutStream.h
@@ -0,0 +1,35 @@
+// Common/StdOutStream.h

+

+#ifndef __COMMON_STDOUTSTREAM_H

+#define __COMMON_STDOUTSTREAM_H

+

+#include <stdio.h>

+

+#include "Types.h"

+

+class CStdOutStream

+{

+  bool _streamIsOpen;

+  FILE *_stream;

+public:

+  CStdOutStream (): _streamIsOpen(false), _stream(0) {};

+  CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {};

+  ~CStdOutStream ();

+  operator FILE *() { return _stream; }

+  bool Open(const char *fileName);

+  bool Close();

+  bool Flush();

+  CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream  &));

+  CStdOutStream & operator<<(const char *string);

+  CStdOutStream & operator<<(const wchar_t *string);

+  CStdOutStream & operator<<(char c);

+  CStdOutStream & operator<<(int number);

+  CStdOutStream & operator<<(UInt64 number);

+};

+

+CStdOutStream & endl(CStdOutStream & outStream);

+

+extern CStdOutStream g_StdOut;

+extern CStdOutStream g_StdErr;

+

+#endif

diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp
new file mode 100755
index 0000000..7f9999c
--- /dev/null
+++ b/CPP/Common/StringConvert.cpp
@@ -0,0 +1,97 @@
+// Common/StringConvert.cpp

+

+#include "StdAfx.h"

+

+#include "StringConvert.h"

+

+#ifndef _WIN32

+#include <stdlib.h>

+#endif

+

+#ifdef _WIN32

+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)

+{

+  UString resultString;

+  if (!srcString.IsEmpty())

+  {

+    int numChars = MultiByteToWideChar(codePage, 0, srcString,

+      srcString.Length(), resultString.GetBuffer(srcString.Length()),

+      srcString.Length() + 1);

+    if (numChars == 0)

+      throw 282228;

+    resultString.ReleaseBuffer(numChars);

+  }

+  return resultString;

+}

+

+AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed)

+{

+  AString dest;

+  defaultCharWasUsed = false;

+  if (!s.IsEmpty())

+  {

+    int numRequiredBytes = s.Length() * 2;

+    BOOL defUsed;

+    int numChars = WideCharToMultiByte(codePage, 0, s, s.Length(),

+        dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1,

+        &defaultChar, &defUsed);

+    defaultCharWasUsed = (defUsed != FALSE);

+    if (numChars == 0)

+      throw 282229;

+    dest.ReleaseBuffer(numChars);

+  }

+  return dest;

+}

+

+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)

+{

+  bool defaultCharWasUsed;

+  return UnicodeStringToMultiByte(srcString, codePage, '_', defaultCharWasUsed);

+}

+

+#ifndef UNDER_CE

+AString SystemStringToOemString(const CSysString &srcString)

+{

+  AString result;

+  CharToOem(srcString, result.GetBuffer(srcString.Length() * 2));

+  result.ReleaseBuffer();

+  return result;

+}

+#endif

+

+#else

+

+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)

+{

+  UString resultString;

+  for (int i = 0; i < srcString.Length(); i++)

+    resultString += wchar_t(srcString[i]);

+  /*

+  if (!srcString.IsEmpty())

+  {

+    int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1);

+    if (numChars < 0) throw "Your environment does not support UNICODE";

+    resultString.ReleaseBuffer(numChars);

+  }

+  */

+  return resultString;

+}

+

+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)

+{

+  AString resultString;

+  for (int i = 0; i < srcString.Length(); i++)

+    resultString += char(srcString[i]);

+  /*

+  if (!srcString.IsEmpty())

+  {

+    int numRequiredBytes = srcString.Length() * 6 + 1;

+    int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes);

+    if (numChars < 0) throw "Your environment does not support UNICODE";

+    resultString.ReleaseBuffer(numChars);

+  }

+  */

+  return resultString;

+}

+

+#endif

diff --git a/CPP/Common/StringConvert.h b/CPP/Common/StringConvert.h
new file mode 100755
index 0000000..1c7a951
--- /dev/null
+++ b/CPP/Common/StringConvert.h
@@ -0,0 +1,73 @@
+// Common/StringConvert.h

+

+#ifndef __COMMON_STRING_CONVERT_H

+#define __COMMON_STRING_CONVERT_H

+

+#include "MyWindows.h"

+#include "MyString.h"

+#include "Types.h"

+

+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP);

+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed);

+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP);

+

+

+inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString)

+  { return unicodeString; }

+inline const UString& GetUnicodeString(const UString &unicodeString)

+  { return unicodeString; }

+inline UString GetUnicodeString(const AString &ansiString)

+  { return MultiByteToUnicodeString(ansiString); }

+inline UString GetUnicodeString(const AString &multiByteString, UINT codePage)

+  { return MultiByteToUnicodeString(multiByteString, codePage); }

+inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT)

+  { return unicodeString; }

+inline const UString& GetUnicodeString(const UString &unicodeString, UINT)

+  { return unicodeString; }

+

+inline const char* GetAnsiString(const char* ansiString)

+  { return ansiString; }

+inline const AString& GetAnsiString(const AString &ansiString)

+  { return ansiString; }

+inline AString GetAnsiString(const UString &unicodeString)

+  { return UnicodeStringToMultiByte(unicodeString); }

+

+inline const char* GetOemString(const char* oemString)

+  { return oemString; }

+inline const AString& GetOemString(const AString &oemString)

+  { return oemString; }

+inline AString GetOemString(const UString &unicodeString)

+  { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); }

+

+

+#ifdef _UNICODE

+  inline const wchar_t* GetSystemString(const wchar_t* unicodeString)

+    { return unicodeString;}

+  inline const UString& GetSystemString(const UString &unicodeString)

+    { return unicodeString;}

+  inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */)

+    { return unicodeString;}

+  inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */)

+    { return unicodeString;}

+  inline UString GetSystemString(const AString &multiByteString, UINT codePage)

+    { return MultiByteToUnicodeString(multiByteString, codePage);}

+  inline UString GetSystemString(const AString &multiByteString)

+    { return MultiByteToUnicodeString(multiByteString);}

+#else

+  inline const char* GetSystemString(const char *ansiString)

+    { return ansiString; }

+  inline const AString& GetSystemString(const AString &multiByteString, UINT)

+    { return multiByteString; }

+  inline const char * GetSystemString(const char *multiByteString, UINT)

+    { return multiByteString; }

+  inline AString GetSystemString(const UString &unicodeString)

+    { return UnicodeStringToMultiByte(unicodeString); }

+  inline AString GetSystemString(const UString &unicodeString, UINT codePage)

+    { return UnicodeStringToMultiByte(unicodeString, codePage); }

+#endif

+

+#ifndef UNDER_CE

+AString SystemStringToOemString(const CSysString &srcString);

+#endif

+

+#endif

diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp
new file mode 100755
index 0000000..77ce7c5
--- /dev/null
+++ b/CPP/Common/StringToInt.cpp
@@ -0,0 +1,90 @@
+// Common/StringToInt.cpp

+

+#include "StdAfx.h"

+

+#include "StringToInt.h"

+

+UInt64 ConvertStringToUInt64(const char *s, const char **end)

+{

+  UInt64 result = 0;

+  for (;;)

+  {

+    char c = *s;

+    if (c < '0' || c > '9')

+    {

+      if (end != NULL)

+        *end = s;

+      return result;

+    }

+    result *= 10;

+    result += (c - '0');

+    s++;

+  }

+}

+

+UInt64 ConvertOctStringToUInt64(const char *s, const char **end)

+{

+  UInt64 result = 0;

+  for (;;)

+  {

+    char c = *s;

+    if (c < '0' || c > '7')

+    {

+      if (end != NULL)

+        *end = s;

+      return result;

+    }

+    result <<= 3;

+    result += (c - '0');

+    s++;

+  }

+}

+

+UInt64 ConvertHexStringToUInt64(const char *s, const char **end)

+{

+  UInt64 result = 0;

+  for (;;)

+  {

+    char c = *s;

+    UInt32 v;

+    if (c >= '0' && c <= '9') v = (c - '0');

+    else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');

+    else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a');

+    else

+    {

+      if (end != NULL)

+        *end = s;

+      return result;

+    }

+    result <<= 4;

+    result |= v;

+    s++;

+  }

+}

+

+

+UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end)

+{

+  UInt64 result = 0;

+  for (;;)

+  {

+    wchar_t c = *s;

+    if (c < '0' || c > '9')

+    {

+      if (end != NULL)

+        *end = s;

+      return result;

+    }

+    result *= 10;

+    result += (c - '0');

+    s++;

+  }

+}

+

+

+Int64 ConvertStringToInt64(const char *s, const char **end)

+{

+  if (*s == '-')

+    return -(Int64)ConvertStringToUInt64(s + 1, end);

+  return ConvertStringToUInt64(s, end);

+}

diff --git a/CPP/Common/StringToInt.h b/CPP/Common/StringToInt.h
new file mode 100755
index 0000000..16a1a4f
--- /dev/null
+++ b/CPP/Common/StringToInt.h
@@ -0,0 +1,18 @@
+// Common/StringToInt.h

+

+#ifndef __COMMON_STRINGTOINT_H

+#define __COMMON_STRINGTOINT_H

+

+#include <string.h>

+#include "Types.h"

+

+UInt64 ConvertStringToUInt64(const char *s, const char **end);

+UInt64 ConvertOctStringToUInt64(const char *s, const char **end);

+UInt64 ConvertHexStringToUInt64(const char *s, const char **end);

+UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end);

+

+Int64 ConvertStringToInt64(const char *s, const char **end);

+

+#endif

+

+

diff --git a/CPP/Common/Types.h b/CPP/Common/Types.h
new file mode 100755
index 0000000..fd00237
--- /dev/null
+++ b/CPP/Common/Types.h
@@ -0,0 +1,11 @@
+// Common/Types.h

+

+#ifndef __COMMON_TYPES_H

+#define __COMMON_TYPES_H

+

+#include "../../C/Types.h"

+

+typedef int HRes;

+

+#endif

+

diff --git a/CPP/Common/UTFConvert.cpp b/CPP/Common/UTFConvert.cpp
new file mode 100755
index 0000000..d3935b1
--- /dev/null
+++ b/CPP/Common/UTFConvert.cpp
@@ -0,0 +1,145 @@
+// UTFConvert.cpp

+

+#include "StdAfx.h"

+

+#include "UTFConvert.h"

+#include "Types.h"

+

+static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };

+

+static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen)

+{

+  size_t destPos = 0, srcPos = 0;

+  for (;;)

+  {

+    Byte c;

+    int numAdds;

+    if (srcPos == srcLen)

+    {

+      *destLen = destPos;

+      return True;

+    }

+    c = (Byte)src[srcPos++];

+

+    if (c < 0x80)

+    {

+      if (dest)

+        dest[destPos] = (wchar_t)c;

+      destPos++;

+      continue;

+    }

+    if (c < 0xC0)

+      break;

+    for (numAdds = 1; numAdds < 5; numAdds++)

+      if (c < kUtf8Limits[numAdds])

+        break;

+    UInt32 value = (c - kUtf8Limits[numAdds - 1]);

+

+    do

+    {

+      Byte c2;

+      if (srcPos == srcLen)

+        break;

+      c2 = (Byte)src[srcPos++];

+      if (c2 < 0x80 || c2 >= 0xC0)

+        break;

+      value <<= 6;

+      value |= (c2 - 0x80);

+    }

+    while (--numAdds != 0);

+    

+    if (value < 0x10000)

+    {

+      if (dest)

+        dest[destPos] = (wchar_t)value;

+      destPos++;

+    }

+    else

+    {

+      value -= 0x10000;

+      if (value >= 0x100000)

+        break;

+      if (dest)

+      {

+        dest[destPos + 0] = (wchar_t)(0xD800 + (value >> 10));

+        dest[destPos + 1] = (wchar_t)(0xDC00 + (value & 0x3FF));

+      }

+      destPos += 2;

+    }

+  }

+  *destLen = destPos;

+  return False;

+}

+

+static Bool Utf16_To_Utf8(char *dest, size_t *destLen, const wchar_t *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;

+}

+

+bool ConvertUTF8ToUnicode(const AString &src, UString &dest)

+{

+  dest.Empty();

+  size_t destLen = 0;

+  Utf8_To_Utf16(NULL, &destLen, src, src.Length());

+  wchar_t *p = dest.GetBuffer((int)destLen);

+  Bool res = Utf8_To_Utf16(p, &destLen, src, src.Length());

+  p[destLen] = 0;

+  dest.ReleaseBuffer();

+  return res ? true : false;

+}

+

+bool ConvertUnicodeToUTF8(const UString &src, AString &dest)

+{

+  dest.Empty();

+  size_t destLen = 0;

+  Utf16_To_Utf8(NULL, &destLen, src, src.Length());

+  char *p = dest.GetBuffer((int)destLen);

+  Bool res = Utf16_To_Utf8(p, &destLen, src, src.Length());

+  p[destLen] = 0;

+  dest.ReleaseBuffer();

+  return res ? true : false;

+}

diff --git a/CPP/Common/UTFConvert.h b/CPP/Common/UTFConvert.h
new file mode 100755
index 0000000..d553101
--- /dev/null
+++ b/CPP/Common/UTFConvert.h
@@ -0,0 +1,11 @@
+// Common/UTFConvert.h

+

+#ifndef __COMMON_UTFCONVERT_H

+#define __COMMON_UTFCONVERT_H

+

+#include "MyString.h"

+

+bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString);

+bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString);

+

+#endif

diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp
new file mode 100755
index 0000000..024d7a5
--- /dev/null
+++ b/CPP/Common/Wildcard.cpp
@@ -0,0 +1,462 @@
+// Common/Wildcard.cpp

+

+#include "StdAfx.h"

+

+#include "../../C/Types.h"

+

+#include "Wildcard.h"

+

+bool g_CaseSensitive =

+  #ifdef _WIN32

+    false;

+  #else

+    true;

+  #endif

+

+static const wchar_t kAnyCharsChar = L'*';

+static const wchar_t kAnyCharChar = L'?';

+

+#ifdef _WIN32

+static const wchar_t kDirDelimiter1 = L'\\';

+#endif

+static const wchar_t kDirDelimiter2 = L'/';

+

+static const UString kWildCardCharSet = L"?*";

+

+static const UString kIllegalWildCardFileNameChars=

+  L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF"

+  L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"

+  L"\"/:<>\\|";

+

+

+static inline bool IsCharDirLimiter(wchar_t c)

+{

+  return (

+    #ifdef _WIN32

+    c == kDirDelimiter1 ||

+    #endif

+    c == kDirDelimiter2);

+}

+

+int CompareFileNames(const UString &s1, const UString &s2)

+{

+  if (g_CaseSensitive)

+    return s1.Compare(s2);

+  return s1.CompareNoCase(s2);

+}

+

+// -----------------------------------------

+// this function compares name with mask

+// ? - any char

+// * - any char or empty

+

+static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name)

+{

+  for (;;)

+  {

+    wchar_t m = *mask;

+    wchar_t c = *name;

+    if (m == 0)

+      return (c == 0);

+    if (m == kAnyCharsChar)

+    {

+      if (EnhancedMaskTest(mask + 1, name))

+        return true;

+      if (c == 0)

+        return false;

+    }

+    else

+    {

+      if (m == kAnyCharChar)

+      {

+        if (c == 0)

+          return false;

+      }

+      else if (m != c)

+        if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c))

+          return false;

+      mask++;

+    }

+    name++;

+  }

+}

+

+// --------------------------------------------------

+// Splits path to strings

+

+void SplitPathToParts(const UString &path, UStringVector &pathParts)

+{

+  pathParts.Clear();

+  UString name;

+  int len = path.Length();

+  if (len == 0)

+    return;

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

+  {

+    wchar_t c = path[i];

+    if (IsCharDirLimiter(c))

+    {

+      pathParts.Add(name);

+      name.Empty();

+    }

+    else

+      name += c;

+  }

+  pathParts.Add(name);

+}

+

+void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name)

+{

+  int i;

+  for (i = path.Length() - 1; i >= 0; i--)

+    if (IsCharDirLimiter(path[i]))

+      break;

+  dirPrefix = path.Left(i + 1);

+  name = path.Mid(i + 1);

+}

+

+UString ExtractDirPrefixFromPath(const UString &path)

+{

+  int i;

+  for (i = path.Length() - 1; i >= 0; i--)

+    if (IsCharDirLimiter(path[i]))

+      break;

+  return path.Left(i + 1);

+}

+

+UString ExtractFileNameFromPath(const UString &path)

+{

+  int i;

+  for (i = path.Length() - 1; i >= 0; i--)

+    if (IsCharDirLimiter(path[i]))

+      break;

+  return path.Mid(i + 1);

+}

+

+

+bool CompareWildCardWithName(const UString &mask, const UString &name)

+{

+  return EnhancedMaskTest(mask, name);

+}

+

+bool DoesNameContainWildCard(const UString &path)

+{

+  return (path.FindOneOf(kWildCardCharSet) >= 0);

+}

+

+

+// ----------------------------------------------------------'

+// NWildcard

+

+namespace NWildcard {

+

+

+/*

+M = MaskParts.Size();

+N = TestNameParts.Size();

+

+                           File                          Dir

+ForFile     req   M<=N  [N-M, N)                          -

+         nonreq   M=N   [0, M)                            -

+ 

+ForDir      req   M<N   [0, M) ... [N-M-1, N-1)  same as ForBoth-File

+         nonreq         [0, M)                   same as ForBoth-File

+

+ForBoth     req   m<=N  [0, M) ... [N-M, N)      same as ForBoth-File

+         nonreq         [0, M)                   same as ForBoth-File

+

+*/

+

+bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const

+{

+  if (!isFile && !ForDir)

+    return false;

+  int delta = (int)pathParts.Size() - (int)PathParts.Size();

+  if (delta < 0)

+    return false;

+  int start = 0;

+  int finish = 0;

+  if (isFile)

+  {

+    if (!ForDir && !Recursive && delta !=0)

+      return false;

+    if (!ForFile && delta == 0)

+      return false;

+    if (!ForDir && Recursive)

+      start = delta;

+  }

+  if (Recursive)

+  {

+    finish = delta;

+    if (isFile && !ForFile)

+      finish = delta - 1;

+  }

+  for (int d = start; d <= finish; d++)

+  {

+    int i;

+    for (i = 0; i < PathParts.Size(); i++)

+      if (!CompareWildCardWithName(PathParts[i], pathParts[i + d]))

+        break;

+    if (i == PathParts.Size())

+      return true;

+  }

+  return false;

+}

+

+int CCensorNode::FindSubNode(const UString &name) const

+{

+  for (int i = 0; i < SubNodes.Size(); i++)

+    if (CompareFileNames(SubNodes[i].Name, name) == 0)

+      return i;

+  return -1;

+}

+

+void CCensorNode::AddItemSimple(bool include, CItem &item)

+{

+  if (include)

+    IncludeItems.Add(item);

+  else

+    ExcludeItems.Add(item);

+}

+

+void CCensorNode::AddItem(bool include, CItem &item)

+{

+  if (item.PathParts.Size() <= 1)

+  {

+    AddItemSimple(include, item);

+    return;

+  }

+  const UString &front = item.PathParts.Front();

+  if (DoesNameContainWildCard(front))

+  {

+    AddItemSimple(include, item);

+    return;

+  }

+  int index = FindSubNode(front);

+  if (index < 0)

+    index = SubNodes.Add(CCensorNode(front, this));

+  item.PathParts.Delete(0);

+  SubNodes[index].AddItem(include, item);

+}

+

+void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir)

+{

+  CItem item;

+  SplitPathToParts(path, item.PathParts);

+  item.Recursive = recursive;

+  item.ForFile = forFile;

+  item.ForDir = forDir;

+  AddItem(include, item);

+}

+

+bool CCensorNode::NeedCheckSubDirs() const

+{

+  for (int i = 0; i < IncludeItems.Size(); i++)

+  {

+    const CItem &item = IncludeItems[i];

+    if (item.Recursive || item.PathParts.Size() > 1)

+      return true;

+  }

+  return false;

+}

+

+bool CCensorNode::AreThereIncludeItems() const

+{

+  if (IncludeItems.Size() > 0)

+    return true;

+  for (int i = 0; i < SubNodes.Size(); i++)

+    if (SubNodes[i].AreThereIncludeItems())

+      return true;

+  return false;

+}

+

+bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const

+{

+  const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;

+  for (int i = 0; i < items.Size(); i++)

+    if (items[i].CheckPath(pathParts, isFile))

+      return true;

+  return false;

+}

+

+bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const

+{

+  if (CheckPathCurrent(false, pathParts, isFile))

+  {

+    include = false;

+    return true;

+  }

+  include = true;

+  bool finded = CheckPathCurrent(true, pathParts, isFile);

+  if (pathParts.Size() == 1)

+    return finded;

+  int index = FindSubNode(pathParts.Front());

+  if (index >= 0)

+  {

+    UStringVector pathParts2 = pathParts;

+    pathParts2.Delete(0);

+    if (SubNodes[index].CheckPath(pathParts2, isFile, include))

+      return true;

+  }

+  return finded;

+}

+

+bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const

+{

+  UStringVector pathParts;

+  SplitPathToParts(path, pathParts);

+  return CheckPath(pathParts, isFile, include);

+}

+

+bool CCensorNode::CheckPath(const UString &path, bool isFile) const

+{

+  bool include;

+  if (CheckPath(path, isFile, include))

+    return include;

+  return false;

+}

+

+bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const

+{

+  if (CheckPathCurrent(include, pathParts, isFile))

+    return true;

+  if (Parent == 0)

+    return false;

+  pathParts.Insert(0, Name);

+  return Parent->CheckPathToRoot(include, pathParts, isFile);

+}

+

+/*

+bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const

+{

+  UStringVector pathParts;

+  SplitPathToParts(path, pathParts);

+  return CheckPathToRoot(include, pathParts, isFile);

+}

+*/

+

+void CCensorNode::AddItem2(bool include, const UString &path, bool recursive)

+{

+  if (path.IsEmpty())

+    return;

+  bool forFile = true;

+  bool forFolder = true;

+  UString path2 = path;

+  if (IsCharDirLimiter(path[path.Length() - 1]))

+  {

+    path2.Delete(path.Length() - 1);

+    forFile = false;

+  }

+  AddItem(include, path2, recursive, forFile, forFolder);

+}

+

+void CCensorNode::ExtendExclude(const CCensorNode &fromNodes)

+{

+  ExcludeItems += fromNodes.ExcludeItems;

+  for (int i = 0; i < fromNodes.SubNodes.Size(); i++)

+  {

+    const CCensorNode &node = fromNodes.SubNodes[i];

+    int subNodeIndex = FindSubNode(node.Name);

+    if (subNodeIndex < 0)

+      subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this));

+    SubNodes[subNodeIndex].ExtendExclude(node);

+  }

+}

+

+int CCensor::FindPrefix(const UString &prefix) const

+{

+  for (int i = 0; i < Pairs.Size(); i++)

+    if (CompareFileNames(Pairs[i].Prefix, prefix) == 0)

+      return i;

+  return -1;

+}

+

+void CCensor::AddItem(bool include, const UString &path, bool recursive)

+{

+  UStringVector pathParts;

+  if (path.IsEmpty())

+    throw "Empty file path";

+  SplitPathToParts(path, pathParts);

+  bool forFile = true;

+  if (pathParts.Back().IsEmpty())

+  {

+    forFile = false;

+    pathParts.DeleteBack();

+  }

+  const UString &front = pathParts.Front();

+  bool isAbs = false;

+  if (front.IsEmpty())

+    isAbs = true;

+  else if (front.Length() == 2 && front[1] == L':')

+    isAbs = true;

+  else

+  {

+    for (int i = 0; i < pathParts.Size(); i++)

+    {

+      const UString &part = pathParts[i];

+      if (part == L".." || part == L".")

+      {

+        isAbs = true;

+        break;

+      }

+    }

+  }

+  int numAbsParts = 0;

+  if (isAbs)

+    if (pathParts.Size() > 1)

+      numAbsParts = pathParts.Size() - 1;

+    else

+      numAbsParts = 1;

+  UString prefix;

+  for (int i = 0; i < numAbsParts; i++)

+  {

+    const UString &front = pathParts.Front();

+    if (DoesNameContainWildCard(front))

+      break;

+    prefix += front;

+    prefix += WCHAR_PATH_SEPARATOR;

+    pathParts.Delete(0);

+  }

+  int index = FindPrefix(prefix);

+  if (index < 0)

+    index = Pairs.Add(CPair(prefix));

+

+  CItem item;

+  item.PathParts = pathParts;

+  item.ForDir = true;

+  item.ForFile = forFile;

+  item.Recursive = recursive;

+  Pairs[index].Head.AddItem(include, item);

+}

+

+bool CCensor::CheckPath(const UString &path, bool isFile) const

+{

+  bool finded = false;

+  for (int i = 0; i < Pairs.Size(); i++)

+  {

+    bool include;

+    if (Pairs[i].Head.CheckPath(path, isFile, include))

+    {

+      if (!include)

+        return false;

+      finded = true;

+    }

+  }

+  return finded;

+}

+

+void CCensor::ExtendExclude()

+{

+  int i;

+  for (i = 0; i < Pairs.Size(); i++)

+    if (Pairs[i].Prefix.IsEmpty())

+      break;

+  if (i == Pairs.Size())

+    return;

+  int index = i;

+  for (i = 0; i < Pairs.Size(); i++)

+    if (index != i)

+      Pairs[i].Head.ExtendExclude(Pairs[index].Head);

+}

+

+}

diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h
new file mode 100755
index 0000000..e2a42c8
--- /dev/null
+++ b/CPP/Common/Wildcard.h
@@ -0,0 +1,80 @@
+// Common/Wildcard.h

+

+#ifndef __COMMON_WILDCARD_H

+#define __COMMON_WILDCARD_H

+

+#include "MyString.h"

+

+int CompareFileNames(const UString &s1, const UString &s2);

+

+void SplitPathToParts(const UString &path, UStringVector &pathParts);

+void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name);

+UString ExtractDirPrefixFromPath(const UString &path);

+UString ExtractFileNameFromPath(const UString &path);

+bool DoesNameContainWildCard(const UString &path);

+bool CompareWildCardWithName(const UString &mask, const UString &name);

+

+namespace NWildcard {

+

+struct CItem

+{

+  UStringVector PathParts;

+  bool Recursive;

+  bool ForFile;

+  bool ForDir;

+  bool CheckPath(const UStringVector &pathParts, bool isFile) const;

+};

+

+class CCensorNode

+{

+  CCensorNode *Parent;

+  bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const;

+  void AddItemSimple(bool include, CItem &item);

+  bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const;

+public:

+  CCensorNode(): Parent(0) { };

+  CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { };

+  UString Name;

+  CObjectVector<CCensorNode> SubNodes;

+  CObjectVector<CItem> IncludeItems;

+  CObjectVector<CItem> ExcludeItems;

+

+  int FindSubNode(const UString &path) const;

+

+  void AddItem(bool include, CItem &item);

+  void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir);

+  void AddItem2(bool include, const UString &path, bool recursive);

+

+  bool NeedCheckSubDirs() const;

+  bool AreThereIncludeItems() const;

+

+  bool CheckPath(const UString &path, bool isFile, bool &include) const;

+  bool CheckPath(const UString &path, bool isFile) const;

+

+  bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const;

+  // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const;

+  void ExtendExclude(const CCensorNode &fromNodes);

+};

+

+struct CPair

+{

+  UString Prefix;

+  CCensorNode Head;

+  CPair(const UString &prefix): Prefix(prefix) { };

+};

+

+class CCensor

+{

+  int FindPrefix(const UString &prefix) const;

+public:

+  CObjectVector<CPair> Pairs;

+  bool AllAreRelative() const

+    { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); }

+  void AddItem(bool include, const UString &path, bool recursive);

+  bool CheckPath(const UString &path, bool isFile) const;

+  void ExtendExclude();

+};

+

+}

+

+#endif

diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp
new file mode 100755
index 0000000..6aaedb0
--- /dev/null
+++ b/CPP/Windows/DLL.cpp
@@ -0,0 +1,110 @@
+// Windows/DLL.cpp

+

+#include "StdAfx.h"

+

+#ifndef _UNICODE

+#include "../Common/StringConvert.h"

+#endif

+

+#include "DLL.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NDLL {

+

+bool CLibrary::Free()

+{

+  if (_module == 0)

+    return true;

+  // MessageBox(0, TEXT(""), TEXT("Free"), 0);

+  // Sleep(5000);

+  if (!::FreeLibrary(_module))

+    return false;

+  _module = 0;

+  return true;

+}

+

+bool CLibrary::LoadOperations(HMODULE newModule)

+{

+  if (newModule == NULL)

+    return false;

+  if (!Free())

+    return false;

+  _module = newModule;

+  return true;

+}

+

+bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags)

+{

+  // MessageBox(0, fileName, TEXT("LoadEx"), 0);

+  return LoadOperations(::LoadLibraryEx(fileName, NULL, flags));

+}

+

+bool CLibrary::Load(LPCTSTR fileName)

+{

+  // MessageBox(0, fileName, TEXT("Load"), 0);

+  // Sleep(5000);

+  // OutputDebugString(fileName);

+  // OutputDebugString(TEXT("\n"));

+  return LoadOperations(::LoadLibrary(fileName));

+}

+

+#ifndef _UNICODE

+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }

+CSysString GetSysPath(LPCWSTR sysPath)

+  { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }

+

+bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags)

+{

+  if (g_IsNT)

+    return LoadOperations(::LoadLibraryExW(fileName, NULL, flags));

+  return LoadEx(GetSysPath(fileName), flags);

+}

+bool CLibrary::Load(LPCWSTR fileName)

+{

+  if (g_IsNT)

+    return LoadOperations(::LoadLibraryW(fileName));

+  return Load(GetSysPath(fileName));

+}

+#endif

+

+bool MyGetModuleFileName(HMODULE hModule, CSysString &result)

+{

+  result.Empty();

+  TCHAR fullPath[MAX_PATH + 2];

+  DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1);

+  if (size <= MAX_PATH && size != 0)

+  {

+    result = fullPath;

+    return true;

+  }

+  return false;

+}

+

+#ifndef _UNICODE

+bool MyGetModuleFileName(HMODULE hModule, UString &result)

+{

+  result.Empty();

+  if (g_IsNT)

+  {

+    wchar_t fullPath[MAX_PATH + 2];

+    DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1);

+    if (size <= MAX_PATH && size != 0)

+    {

+      result = fullPath;

+      return true;

+    }

+    return false;

+  }

+  CSysString resultSys;

+  if (!MyGetModuleFileName(hModule, resultSys))

+    return false;

+  result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage());

+  return true;

+}

+#endif

+

+}}

diff --git a/CPP/Windows/DLL.h b/CPP/Windows/DLL.h
new file mode 100755
index 0000000..7d02887
--- /dev/null
+++ b/CPP/Windows/DLL.h
@@ -0,0 +1,59 @@
+// Windows/DLL.h

+

+#ifndef __WINDOWS_DLL_H

+#define __WINDOWS_DLL_H

+

+#include "../Common/MyString.h"

+

+namespace NWindows {

+namespace NDLL {

+

+#ifdef UNDER_CE

+#define My_GetProcAddress(module, proceName) GetProcAddressA(module, proceName)

+#else

+#define My_GetProcAddress(module, proceName) ::GetProcAddress(module, proceName)

+#endif

+ 

+class CLibrary

+{

+  bool LoadOperations(HMODULE newModule);

+protected:

+  HMODULE _module;

+public:

+  CLibrary(): _module(NULL) {};

+  ~CLibrary() { Free(); }

+

+  operator HMODULE() const { return _module; }

+  HMODULE* operator&() { return &_module; }

+  bool IsLoaded() const { return (_module != NULL); };

+

+  void Attach(HMODULE m)

+  {

+    Free();

+    _module = m;

+  }

+  HMODULE Detach()

+  {

+    HMODULE m = _module;

+    _module = NULL;

+    return m;

+  }

+

+  bool Free();

+  bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE);

+  bool Load(LPCTSTR fileName);

+  #ifndef _UNICODE

+  bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE);

+  bool Load(LPCWSTR fileName);

+  #endif

+  FARPROC GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); }

+};

+

+bool MyGetModuleFileName(HMODULE hModule, CSysString &result);

+#ifndef _UNICODE

+bool MyGetModuleFileName(HMODULE hModule, UString &result);

+#endif

+

+}}

+

+#endif

diff --git a/CPP/Windows/Defs.h b/CPP/Windows/Defs.h
new file mode 100755
index 0000000..f3d692f
--- /dev/null
+++ b/CPP/Windows/Defs.h
@@ -0,0 +1,17 @@
+// Windows/Defs.h

+

+#ifndef __WINDOWS_DEFS_H

+#define __WINDOWS_DEFS_H

+

+#include "../Common/MyWindows.h"

+

+#ifdef _WIN32

+inline bool LRESULTToBool(LRESULT v) { return (v != FALSE); }

+inline bool BOOLToBool(BOOL v) { return (v != FALSE); }

+inline BOOL BoolToBOOL(bool v) { return (v ? TRUE: FALSE); }

+#endif

+

+inline VARIANT_BOOL BoolToVARIANT_BOOL(bool v) { return (v ? VARIANT_TRUE: VARIANT_FALSE); }

+inline bool VARIANT_BOOLToBool(VARIANT_BOOL v) { return (v != VARIANT_FALSE); }

+

+#endif

diff --git a/CPP/Windows/Error.cpp b/CPP/Windows/Error.cpp
new file mode 100755
index 0000000..fcba1e6
--- /dev/null
+++ b/CPP/Windows/Error.cpp
@@ -0,0 +1,50 @@
+// Windows/Error.h

+

+#include "StdAfx.h"

+

+#include "Windows/Error.h"

+#ifndef _UNICODE

+#include "Common/StringConvert.h"

+#endif

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NError {

+

+bool MyFormatMessage(DWORD messageID, CSysString &message)

+{

+  LPVOID msgBuf;

+  if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |

+      FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,

+      NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0)

+    return false;

+  message = (LPCTSTR)msgBuf;

+  ::LocalFree(msgBuf);

+  return true;

+}

+

+#ifndef _UNICODE

+bool MyFormatMessage(DWORD messageID, UString &message)

+{

+  if (g_IsNT)

+  {

+    LPVOID msgBuf;

+    if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |

+        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,

+        NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0)

+      return false;

+    message = (LPCWSTR)msgBuf;

+    ::LocalFree(msgBuf);

+    return true;

+  }

+  CSysString messageSys;

+  bool result = MyFormatMessage(messageID, messageSys);

+  message = GetUnicodeString(messageSys);

+  return result;

+}

+#endif

+

+}}

diff --git a/CPP/Windows/Error.h b/CPP/Windows/Error.h
new file mode 100755
index 0000000..d916e8e
--- /dev/null
+++ b/CPP/Windows/Error.h
@@ -0,0 +1,33 @@
+// Windows/Error.h

+

+#ifndef __WINDOWS_ERROR_H

+#define __WINDOWS_ERROR_H

+

+#include "Common/MyString.h"

+

+namespace NWindows {

+namespace NError {

+

+bool MyFormatMessage(DWORD messageID, CSysString &message);

+inline CSysString MyFormatMessage(DWORD messageID)

+{

+  CSysString message;

+  MyFormatMessage(messageID, message);

+  return message;

+}

+#ifdef _UNICODE

+inline UString MyFormatMessageW(DWORD messageID)

+  { return MyFormatMessage(messageID); }

+#else

+bool MyFormatMessage(DWORD messageID, UString &message);

+inline UString MyFormatMessageW(DWORD messageID)

+{

+  UString message;

+  MyFormatMessage(messageID, message);

+  return message;

+}

+#endif

+

+}}

+

+#endif

diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
new file mode 100755
index 0000000..daec1d3
--- /dev/null
+++ b/CPP/Windows/FileDir.cpp
@@ -0,0 +1,909 @@
+// Windows/FileDir.cpp

+

+#include "StdAfx.h"

+

+#ifndef _UNICODE

+#include "../Common/StringConvert.h"

+#endif

+

+#include "FileDir.h"

+#include "FileFind.h"

+#include "FileName.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NFile {

+

+#if defined(WIN_LONG_PATH) && defined(_UNICODE)

+#define WIN_LONG_PATH2

+#endif

+

+// SetCurrentDirectory doesn't support \\?\ prefix

+

+#ifdef WIN_LONG_PATH

+bool GetLongPathBase(LPCWSTR fileName, UString &res);

+bool GetLongPath(LPCWSTR fileName, UString &res);

+#endif

+

+namespace NDirectory {

+

+#ifndef _UNICODE

+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }

+static UString GetUnicodePath(const CSysString &sysPath)

+  { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); }

+static CSysString GetSysPath(LPCWSTR sysPath)

+  { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }

+#endif

+

+#ifndef UNDER_CE

+

+bool MyGetWindowsDirectory(CSysString &path)

+{

+  UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);

+  path.ReleaseBuffer();

+  return (needLength > 0 && needLength <= MAX_PATH);

+}

+

+bool MyGetSystemDirectory(CSysString &path)

+{

+  UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);

+  path.ReleaseBuffer();

+  return (needLength > 0 && needLength <= MAX_PATH);

+}

+

+#endif

+

+#ifndef _UNICODE

+bool MyGetWindowsDirectory(UString &path)

+{

+  if (g_IsNT)

+  {

+    UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);

+    path.ReleaseBuffer();

+    return (needLength > 0 && needLength <= MAX_PATH);

+  }

+  CSysString sysPath;

+  if (!MyGetWindowsDirectory(sysPath))

+    return false;

+  path = GetUnicodePath(sysPath);

+  return true;

+}

+

+bool MyGetSystemDirectory(UString &path)

+{

+  if (g_IsNT)

+  {

+    UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);

+    path.ReleaseBuffer();

+    return (needLength > 0 && needLength <= MAX_PATH);

+  }

+  CSysString sysPath;

+  if (!MyGetSystemDirectory(sysPath))

+    return false;

+  path = GetUnicodePath(sysPath);

+  return true;

+}

+#endif

+

+bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)

+{

+  #ifndef _UNICODE

+  if (!g_IsNT)

+  {

+    ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

+    return false;

+  }

+  #endif

+  HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE,

+      FILE_SHARE_READ | FILE_SHARE_WRITE,

+      NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

+  #ifdef WIN_LONG_PATH

+  if (hDir == INVALID_HANDLE_VALUE)

+  {

+    UString longPath;

+    if (GetLongPath(fileName, longPath))

+      hDir = ::CreateFileW(longPath, GENERIC_WRITE,

+        FILE_SHARE_READ | FILE_SHARE_WRITE,

+        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

+  }

+  #endif

+

+  bool res = false;

+  if (hDir != INVALID_HANDLE_VALUE)

+  {

+    res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime));

+    ::CloseHandle(hDir);

+  }

+  return res;

+}

+

+bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes)

+{

+  if (::SetFileAttributes(fileName, fileAttributes))

+    return true;

+  #ifdef WIN_LONG_PATH2

+  UString longPath;

+  if (GetLongPath(fileName, longPath))

+    return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));

+  #endif

+  return false;

+}

+

+bool MyRemoveDirectory(LPCTSTR pathName)

+{

+  if (::RemoveDirectory(pathName))

+    return true;

+  #ifdef WIN_LONG_PATH2

+  UString longPath;

+  if (GetLongPath(pathName, longPath))

+    return BOOLToBool(::RemoveDirectoryW(longPath));

+  #endif

+  return false;

+}

+

+#ifdef WIN_LONG_PATH

+bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2)

+{

+  if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2))

+    return false;

+  if (d1.IsEmpty() && d2.IsEmpty()) return false;

+  if (d1.IsEmpty()) d1 = s1;

+  if (d2.IsEmpty()) d2 = s2;

+  return true;

+}

+#endif

+

+bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName)

+{

+  if (::MoveFile(existFileName, newFileName))

+    return true;

+  #ifdef WIN_LONG_PATH2

+  UString d1, d2;

+  if (GetLongPaths(existFileName, newFileName, d1, d2))

+    return BOOLToBool(::MoveFileW(d1, d2));

+  #endif

+  return false;

+}

+

+#ifndef _UNICODE

+bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes)

+{

+  if (!g_IsNT)

+    return MySetFileAttributes(GetSysPath(fileName), fileAttributes);

+  if (::SetFileAttributesW(fileName, fileAttributes))

+    return true;

+  #ifdef WIN_LONG_PATH

+  UString longPath;

+  if (GetLongPath(fileName, longPath))

+    return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));

+  #endif

+  return false;

+}

+

+

+bool MyRemoveDirectory(LPCWSTR pathName)

+{

+  if (!g_IsNT)

+    return MyRemoveDirectory(GetSysPath(pathName));

+  if (::RemoveDirectoryW(pathName))

+    return true;

+  #ifdef WIN_LONG_PATH

+  UString longPath;

+  if (GetLongPath(pathName, longPath))

+    return BOOLToBool(::RemoveDirectoryW(longPath));

+  #endif

+  return false;

+}

+

+bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName)

+{

+  if (!g_IsNT)

+    return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName));

+  if (::MoveFileW(existFileName, newFileName))

+    return true;

+  #ifdef WIN_LONG_PATH

+  UString d1, d2;

+  if (GetLongPaths(existFileName, newFileName, d1, d2))

+    return BOOLToBool(::MoveFileW(d1, d2));

+  #endif

+  return false;

+}

+#endif

+

+bool MyCreateDirectory(LPCTSTR pathName)

+{

+  if (::CreateDirectory(pathName, NULL))

+    return true;

+  #ifdef WIN_LONG_PATH2

+  if (::GetLastError() != ERROR_ALREADY_EXISTS)

+  {

+    UString longPath;

+    if (GetLongPath(pathName, longPath))

+      return BOOLToBool(::CreateDirectoryW(longPath, NULL));

+  }

+  #endif

+  return false;

+}

+

+#ifndef _UNICODE

+bool MyCreateDirectory(LPCWSTR pathName)

+{

+  if (!g_IsNT)

+    return MyCreateDirectory(GetSysPath(pathName));

+  if (::CreateDirectoryW(pathName, NULL))

+    return true;

+  #ifdef WIN_LONG_PATH

+  if (::GetLastError() != ERROR_ALREADY_EXISTS)

+  {

+    UString longPath;

+    if (GetLongPath(pathName, longPath))

+      return BOOLToBool(::CreateDirectoryW(longPath, NULL));

+  }

+  #endif

+  return false;

+}

+#endif

+

+/*

+bool CreateComplexDirectory(LPCTSTR pathName)

+{

+  NName::CParsedPath path;

+  path.ParsePath(pathName);

+  CSysString fullPath = path.Prefix;

+  DWORD errorCode = ERROR_SUCCESS;

+  for (int i = 0; i < path.PathParts.Size(); i++)

+  {

+    const CSysString &string = path.PathParts[i];

+    if (string.IsEmpty())

+    {

+      if (i != path.PathParts.Size() - 1)

+        return false;

+      return true;

+    }

+    fullPath += path.PathParts[i];

+    if (!MyCreateDirectory(fullPath))

+    {

+      DWORD errorCode = GetLastError();

+      if (errorCode != ERROR_ALREADY_EXISTS)

+        return false;

+    }

+    fullPath += NName::kDirDelimiter;

+  }

+  return true;

+}

+*/

+

+bool CreateComplexDirectory(LPCTSTR _aPathName)

+{

+  CSysString pathName = _aPathName;

+  int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));

+  if (pos > 0 && pos == pathName.Length() - 1)

+  {

+    if (pathName.Length() == 3 && pathName[1] == ':')

+      return true; // Disk folder;

+    pathName.Delete(pos);

+  }

+  CSysString pathName2 = pathName;

+  pos = pathName.Length();

+  for (;;)

+  {

+    if (MyCreateDirectory(pathName))

+      break;

+    if (::GetLastError() == ERROR_ALREADY_EXISTS)

+    {

+      NFind::CFileInfo fileInfo;

+      if (!fileInfo.Find(pathName)) // For network folders

+        return true;

+      if (!fileInfo.IsDir())

+        return false;

+      break;

+    }

+    pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));

+    if (pos < 0 || pos == 0)

+      return false;

+    if (pathName[pos - 1] == ':')

+      return false;

+    pathName = pathName.Left(pos);

+  }

+  pathName = pathName2;

+  while (pos < pathName.Length())

+  {

+    pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1);

+    if (pos < 0)

+      pos = pathName.Length();

+    if (!MyCreateDirectory(pathName.Left(pos)))

+      return false;

+  }

+  return true;

+}

+

+#ifndef _UNICODE

+

+bool CreateComplexDirectory(LPCWSTR _aPathName)

+{

+  UString pathName = _aPathName;

+  int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);

+  if (pos > 0 && pos == pathName.Length() - 1)

+  {

+    if (pathName.Length() == 3 && pathName[1] == L':')

+      return true; // Disk folder;

+    pathName.Delete(pos);

+  }

+  UString pathName2 = pathName;

+  pos = pathName.Length();

+  for (;;)

+  {

+    if (MyCreateDirectory(pathName))

+      break;

+    if (::GetLastError() == ERROR_ALREADY_EXISTS)

+    {

+      NFind::CFileInfoW fileInfo;

+      if (!fileInfo.Find(pathName)) // For network folders

+        return true;

+      if (!fileInfo.IsDir())

+        return false;

+      break;

+    }

+    pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);

+    if (pos < 0 || pos == 0)

+      return false;

+    if (pathName[pos - 1] == L':')

+      return false;

+    pathName = pathName.Left(pos);

+  }

+  pathName = pathName2;

+  while (pos < pathName.Length())

+  {

+    pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1);

+    if (pos < 0)

+      pos = pathName.Length();

+    if (!MyCreateDirectory(pathName.Left(pos)))

+      return false;

+  }

+  return true;

+}

+

+#endif

+

+bool DeleteFileAlways(LPCTSTR name)

+{

+  if (!MySetFileAttributes(name, 0))

+    return false;

+  if (::DeleteFile(name))

+    return true;

+  #ifdef WIN_LONG_PATH2

+  UString longPath;

+  if (GetLongPath(name, longPath))

+    return BOOLToBool(::DeleteFileW(longPath));

+  #endif

+  return false;

+}

+

+#ifndef _UNICODE

+bool DeleteFileAlways(LPCWSTR name)

+{

+  if (!g_IsNT)

+    return DeleteFileAlways(GetSysPath(name));

+  if (!MySetFileAttributes(name, 0))

+    return false;

+  if (::DeleteFileW(name))

+    return true;

+  #ifdef WIN_LONG_PATH

+  UString longPath;

+  if (GetLongPath(name, longPath))

+    return BOOLToBool(::DeleteFileW(longPath));

+  #endif

+  return false;

+}

+#endif

+

+static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo)

+{

+  if (fileInfo.IsDir())

+    return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);

+  return DeleteFileAlways(pathPrefix + fileInfo.Name);

+}

+

+bool RemoveDirectoryWithSubItems(const CSysString &path)

+{

+  NFind::CFileInfo fileInfo;

+  CSysString pathPrefix = path + NName::kDirDelimiter;

+  {

+    NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard));

+    while (enumerator.Next(fileInfo))

+      if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))

+        return false;

+  }

+  if (!MySetFileAttributes(path, 0))

+    return false;

+  return MyRemoveDirectory(path);

+}

+

+#ifndef _UNICODE

+static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo)

+{

+  if (fileInfo.IsDir())

+    return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);

+  return DeleteFileAlways(pathPrefix + fileInfo.Name);

+}

+bool RemoveDirectoryWithSubItems(const UString &path)

+{

+  NFind::CFileInfoW fileInfo;

+  UString pathPrefix = path + UString(NName::kDirDelimiter);

+  {

+    NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard));

+    while (enumerator.Next(fileInfo))

+      if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))

+        return false;

+  }

+  if (!MySetFileAttributes(path, 0))

+    return false;

+  return MyRemoveDirectory(path);

+}

+#endif

+

+bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName)

+{

+  int index;

+  if (!MyGetFullPathName(fileName, resultName, index))

+    return false;

+  resultName = resultName.Left(index);

+  return true;

+}

+

+bool GetOnlyName(LPCTSTR fileName, CSysString &resultName)

+{

+  int index;

+  if (!MyGetFullPathName(fileName, resultName, index))

+    return false;

+  resultName = resultName.Mid(index);

+  return true;

+}

+

+#ifdef UNDER_CE

+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath)

+{

+  resultPath = fileName;

+  return true;

+}

+

+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex)

+{

+  resultPath = fileName;

+  // change it

+  fileNamePartStartIndex = resultPath.ReverseFind(WCHAR_PATH_SEPARATOR);

+  fileNamePartStartIndex++;

+  return true;

+}

+

+#else

+

+bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath)

+{

+  DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);

+  shortPath.ReleaseBuffer();

+  return (needLength > 0 && needLength < MAX_PATH);

+}

+

+#ifdef WIN_LONG_PATH

+

+static UString GetLastPart(LPCWSTR path)

+{

+  int i = (int)wcslen(path);

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

+  {

+    WCHAR c = path[i - 1];

+    if (c == WCHAR_PATH_SEPARATOR || c == '/')

+      break;

+  }

+  return path + i;

+}

+

+static void AddTrailingDots(LPCWSTR oldPath, UString &newPath)

+{

+  int len = (int)wcslen(oldPath);

+  int i;

+  for (i = len; i > 0 && oldPath[i - 1] == '.'; i--);

+  if (i == 0 || i == len)

+    return;

+  UString oldName = GetLastPart(oldPath);

+  UString newName = GetLastPart(newPath);

+  int nonDotsLen = oldName.Length() - (len - i);

+  if (nonDotsLen == 0 || newName.CompareNoCase(oldName.Left(nonDotsLen)) != 0)

+    return;

+  for (; i != len; i++)

+    newPath += '.';

+}

+

+#endif

+

+bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex)

+{

+  resultPath.Empty();

+  LPTSTR fileNamePointer = 0;

+  LPTSTR buffer = resultPath.GetBuffer(MAX_PATH);

+  DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer);

+  resultPath.ReleaseBuffer();

+  if (needLength == 0)

+    return false;

+  if (needLength >= MAX_PATH)

+  {

+    #ifdef WIN_LONG_PATH2

+    needLength++;

+    buffer = resultPath.GetBuffer(needLength + 1);

+    DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);

+    resultPath.ReleaseBuffer();

+    if (needLength2 == 0 || needLength2 > needLength)

+    #endif

+      return false;

+  }

+  if (fileNamePointer == 0)

+    fileNamePartStartIndex = lstrlen(fileName);

+  else

+    fileNamePartStartIndex = (int)(fileNamePointer - buffer);

+  #ifdef _UNICODE

+  #ifdef WIN_LONG_PATH

+  AddTrailingDots(fileName, resultPath);

+  #endif

+  #endif

+  return true;

+}

+

+#ifndef _UNICODE

+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex)

+{

+  resultPath.Empty();

+  if (g_IsNT)

+  {

+    LPWSTR fileNamePointer = 0;

+    LPWSTR buffer = resultPath.GetBuffer(MAX_PATH);

+    DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer);

+    resultPath.ReleaseBuffer();

+    if (needLength == 0)

+      return false;

+    if (needLength >= MAX_PATH)

+    {

+      #ifdef WIN_LONG_PATH

+      needLength++;

+      buffer = resultPath.GetBuffer(needLength + 1);

+      DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);

+      resultPath.ReleaseBuffer();

+      if (needLength2 == 0 || needLength2 > needLength)

+      #endif

+        return false;

+    }

+    if (fileNamePointer == 0)

+      fileNamePartStartIndex = MyStringLen(fileName);

+    else

+      fileNamePartStartIndex = (int)(fileNamePointer - buffer);

+    #ifdef WIN_LONG_PATH

+    AddTrailingDots(fileName, resultPath);

+    #endif

+  }

+  else

+  {

+    CSysString sysPath;

+    if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex))

+      return false;

+    UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex));

+    UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex));

+    fileNamePartStartIndex = resultPath1.Length();

+    resultPath = resultPath1 + resultPath2;

+  }

+  return true;

+}

+#endif

+

+

+bool MyGetFullPathName(LPCTSTR fileName, CSysString &path)

+{

+  int index;

+  return MyGetFullPathName(fileName, path, index);

+}

+

+#ifndef _UNICODE

+bool MyGetFullPathName(LPCWSTR fileName, UString &path)

+{

+  int index;

+  return MyGetFullPathName(fileName, path, index);

+}

+#endif

+

+#ifndef _UNICODE

+bool GetOnlyName(LPCWSTR fileName, UString &resultName)

+{

+  int index;

+  if (!MyGetFullPathName(fileName, resultName, index))

+    return false;

+  resultName = resultName.Mid(index);

+  return true;

+}

+#endif

+

+#ifndef _UNICODE

+bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName)

+{

+  int index;

+  if (!MyGetFullPathName(fileName, resultName, index))

+    return false;

+  resultName = resultName.Left(index);

+  return true;

+}

+#endif

+

+bool MyGetCurrentDirectory(CSysString &path)

+{

+  DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));

+  path.ReleaseBuffer();

+  return (needLength > 0 && needLength <= MAX_PATH);

+}

+

+#ifndef _UNICODE

+bool MySetCurrentDirectory(LPCWSTR path)

+{

+  if (g_IsNT)

+    return BOOLToBool(::SetCurrentDirectoryW(path));

+  return MySetCurrentDirectory(GetSysPath(path));

+}

+bool MyGetCurrentDirectory(UString &path)

+{

+  if (g_IsNT)

+  {

+    DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));

+    path.ReleaseBuffer();

+    return (needLength > 0 && needLength <= MAX_PATH);

+  }

+  CSysString sysPath;

+  if (!MyGetCurrentDirectory(sysPath))

+    return false;

+  path = GetUnicodePath(sysPath);

+  return true;

+}

+#endif

+

+bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension,

+  CSysString &resultPath, UINT32 &filePart)

+{

+  LPTSTR filePartPointer;

+  DWORD value = ::SearchPath(path, fileName, extension,

+    MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);

+  filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath);

+  resultPath.ReleaseBuffer();

+  return (value > 0 && value <= MAX_PATH);

+}

+#endif

+

+#ifndef _UNICODE

+bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension,

+  UString &resultPath, UINT32 &filePart)

+{

+  if (g_IsNT)

+  {

+    LPWSTR filePartPointer = 0;

+    DWORD value = ::SearchPathW(path, fileName, extension,

+        MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);

+    filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath);

+    resultPath.ReleaseBuffer();

+    return (value > 0 && value <= MAX_PATH);

+  }

+  

+  CSysString sysPath;

+  if (!MySearchPath(

+      path != 0 ? (LPCTSTR)GetSysPath(path): 0,

+      fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0,

+      extension != 0 ? (LPCTSTR)GetSysPath(extension): 0,

+      sysPath, filePart))

+    return false;

+  UString resultPath1 = GetUnicodePath(sysPath.Left(filePart));

+  UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart));

+  filePart = resultPath1.Length();

+  resultPath = resultPath1 + resultPath2;

+  return true;

+}

+#endif

+

+bool MyGetTempPath(CSysString &path)

+{

+  DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));

+  path.ReleaseBuffer();

+  return (needLength > 0 && needLength <= MAX_PATH);

+}

+

+#ifndef _UNICODE

+bool MyGetTempPath(UString &path)

+{

+  path.Empty();

+  if (g_IsNT)

+  {

+    DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));

+    path.ReleaseBuffer();

+    return (needLength > 0 && needLength <= MAX_PATH);

+  }

+  CSysString sysPath;

+  if (!MyGetTempPath(sysPath))

+    return false;

+  path = GetUnicodePath(sysPath);

+  return true;

+}

+#endif

+

+UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path)

+{

+  UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1));

+  path.ReleaseBuffer();

+  return number;

+}

+

+#ifndef _UNICODE

+UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path)

+{

+  if (g_IsNT)

+  {

+    UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH));

+    path.ReleaseBuffer();

+    return number;

+  }

+  CSysString sysPath;

+  UINT number = MyGetTempFileName(

+      dirPath ? (LPCTSTR)GetSysPath(dirPath): 0,

+      prefix ? (LPCTSTR)GetSysPath(prefix): 0,

+      sysPath);

+  path = GetUnicodePath(sysPath);

+  return number;

+}

+#endif

+

+UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath)

+{

+  Remove();

+  UINT number = MyGetTempFileName(dirPath, prefix, resultPath);

+  if (number != 0)

+  {

+    _fileName = resultPath;

+    _mustBeDeleted = true;

+  }

+  return number;

+}

+

+bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath)

+{

+  CSysString tempPath;

+  if (!MyGetTempPath(tempPath))

+    return false;

+  if (Create(tempPath, prefix, resultPath) != 0)

+    return true;

+  #ifdef UNDER_CE

+  return false;

+  #else

+  if (!MyGetWindowsDirectory(tempPath))

+    return false;

+  return (Create(tempPath, prefix, resultPath) != 0);

+  #endif

+}

+

+bool CTempFile::Remove()

+{

+  if (!_mustBeDeleted)

+    return true;

+  _mustBeDeleted = !DeleteFileAlways(_fileName);

+  return !_mustBeDeleted;

+}

+

+#ifndef _UNICODE

+

+UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath)

+{

+  Remove();

+  UINT number = MyGetTempFileName(dirPath, prefix, resultPath);

+  if (number != 0)

+  {

+    _fileName = resultPath;

+    _mustBeDeleted = true;

+  }

+  return number;

+}

+

+bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath)

+{

+  UString tempPath;

+  if (!MyGetTempPath(tempPath))

+    return false;

+  if (Create(tempPath, prefix, resultPath) != 0)

+    return true;

+  if (!MyGetWindowsDirectory(tempPath))

+    return false;

+  return (Create(tempPath, prefix, resultPath) != 0);

+}

+

+bool CTempFileW::Remove()

+{

+  if (!_mustBeDeleted)

+    return true;

+  _mustBeDeleted = !DeleteFileAlways(_fileName);

+  return !_mustBeDeleted;

+}

+

+#endif

+

+bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName)

+{

+  /*

+  CSysString prefix = tempPath + prefixChars;

+  CRandom random;

+  random.Init();

+  */

+  for (;;)

+  {

+    {

+      CTempFile tempFile;

+      if (!tempFile.Create(prefix, dirName))

+        return false;

+      if (!tempFile.Remove())

+        return false;

+    }

+    /*

+    UINT32 randomNumber = random.Generate();

+    TCHAR randomNumberString[32];

+    _stprintf(randomNumberString, _T("%04X"), randomNumber);

+    dirName = prefix + randomNumberString;

+    */

+    if (NFind::DoesFileOrDirExist(dirName))

+      continue;

+    if (MyCreateDirectory(dirName))

+      return true;

+    if (::GetLastError() != ERROR_ALREADY_EXISTS)

+      return false;

+  }

+}

+

+bool CTempDirectory::Create(LPCTSTR prefix)

+{

+  Remove();

+  return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir));

+}

+

+#ifndef _UNICODE

+

+bool CreateTempDirectory(LPCWSTR prefix, UString &dirName)

+{

+  /*

+  CSysString prefix = tempPath + prefixChars;

+  CRandom random;

+  random.Init();

+  */

+  for (;;)

+  {

+    {

+      CTempFileW tempFile;

+      if (!tempFile.Create(prefix, dirName))

+        return false;

+      if (!tempFile.Remove())

+        return false;

+    }

+    /*

+    UINT32 randomNumber = random.Generate();

+    TCHAR randomNumberString[32];

+    _stprintf(randomNumberString, _T("%04X"), randomNumber);

+    dirName = prefix + randomNumberString;

+    */

+    if (NFind::DoesFileOrDirExist(dirName))

+      continue;

+    if (MyCreateDirectory(dirName))

+      return true;

+    if (::GetLastError() != ERROR_ALREADY_EXISTS)

+      return false;

+  }

+}

+

+bool CTempDirectoryW::Create(LPCWSTR prefix)

+{

+  Remove();

+  return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir));

+}

+

+#endif

+

+}}}

diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h
new file mode 100755
index 0000000..2c15071
--- /dev/null
+++ b/CPP/Windows/FileDir.h
@@ -0,0 +1,177 @@
+// Windows/FileDir.h

+

+#ifndef __WINDOWS_FILEDIR_H

+#define __WINDOWS_FILEDIR_H

+

+#include "../Common/MyString.h"

+#include "Defs.h"

+

+namespace NWindows {

+namespace NFile {

+namespace NDirectory {

+

+#ifdef WIN_LONG_PATH

+bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2);

+#endif

+

+bool MyGetWindowsDirectory(CSysString &path);

+bool MyGetSystemDirectory(CSysString &path);

+#ifndef _UNICODE

+bool MyGetWindowsDirectory(UString &path);

+bool MyGetSystemDirectory(UString &path);

+#endif

+

+bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);

+

+bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes);

+bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName);

+bool MyRemoveDirectory(LPCTSTR pathName);

+bool MyCreateDirectory(LPCTSTR pathName);

+bool CreateComplexDirectory(LPCTSTR pathName);

+bool DeleteFileAlways(LPCTSTR name);

+bool RemoveDirectoryWithSubItems(const CSysString &path);

+

+#ifndef _UNICODE

+bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes);

+bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName);

+bool MyRemoveDirectory(LPCWSTR pathName);

+bool MyCreateDirectory(LPCWSTR pathName);

+bool CreateComplexDirectory(LPCWSTR pathName);

+bool DeleteFileAlways(LPCWSTR name);

+bool RemoveDirectoryWithSubItems(const UString &path);

+#endif

+

+bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName);

+bool GetOnlyName(LPCTSTR fileName, CSysString &resultName);

+#ifdef UNDER_CE

+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath);

+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex);

+#else

+bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath);

+

+bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex);

+bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath);

+#ifndef _UNICODE

+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath,

+    int &fileNamePartStartIndex);

+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath);

+bool GetOnlyName(LPCWSTR fileName, UString &resultName);

+bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName);

+#endif

+

+inline bool MySetCurrentDirectory(LPCTSTR path)

+  { return BOOLToBool(::SetCurrentDirectory(path)); }

+bool MyGetCurrentDirectory(CSysString &resultPath);

+#ifndef _UNICODE

+bool MySetCurrentDirectory(LPCWSTR path);

+bool MyGetCurrentDirectory(UString &resultPath);

+#endif

+

+bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart);

+#ifndef _UNICODE

+bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart);

+#endif

+

+inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath)

+{

+  UINT32 value;

+  return MySearchPath(path, fileName, extension, resultPath, value);

+}

+

+#ifndef _UNICODE

+inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath)

+{

+  UINT32 value;

+  return MySearchPath(path, fileName, extension, resultPath, value);

+}

+#endif

+

+#endif

+

+bool MyGetTempPath(CSysString &resultPath);

+#ifndef _UNICODE

+bool MyGetTempPath(UString &resultPath);

+#endif

+

+UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath);

+#ifndef _UNICODE

+UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath);

+#endif

+

+class CTempFile

+{

+  bool _mustBeDeleted;

+  CSysString _fileName;

+public:

+  CTempFile(): _mustBeDeleted(false) {}

+  ~CTempFile() { Remove(); }

+  void DisableDeleting() { _mustBeDeleted = false; }

+  UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath);

+  bool Create(LPCTSTR prefix, CSysString &resultPath);

+  bool Remove();

+};

+

+#ifdef _UNICODE

+typedef CTempFile CTempFileW;

+#else

+class CTempFileW

+{

+  bool _mustBeDeleted;

+  UString _fileName;

+public:

+  CTempFileW(): _mustBeDeleted(false) {}

+  ~CTempFileW() { Remove(); }

+  void DisableDeleting() { _mustBeDeleted = false; }

+  UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath);

+  bool Create(LPCWSTR prefix, UString &resultPath);

+  bool Remove();

+};

+#endif

+

+bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName);

+

+class CTempDirectory

+{

+  bool _mustBeDeleted;

+  CSysString _tempDir;

+public:

+  const CSysString &GetPath() const { return _tempDir; }

+  CTempDirectory(): _mustBeDeleted(false) {}

+  ~CTempDirectory() { Remove();  }

+  bool Create(LPCTSTR prefix) ;

+  bool Remove()

+  {

+    if (!_mustBeDeleted)

+      return true;

+    _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir);

+    return (!_mustBeDeleted);

+  }

+  void DisableDeleting() { _mustBeDeleted = false; }

+};

+

+#ifdef _UNICODE

+typedef CTempDirectory CTempDirectoryW;

+#else

+class CTempDirectoryW

+{

+  bool _mustBeDeleted;

+  UString _tempDir;

+public:

+  const UString &GetPath() const { return _tempDir; }

+  CTempDirectoryW(): _mustBeDeleted(false) {}

+  ~CTempDirectoryW() { Remove();  }

+  bool Create(LPCWSTR prefix) ;

+  bool Remove()

+  {

+    if (!_mustBeDeleted)

+      return true;

+    _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir);

+    return (!_mustBeDeleted);

+  }

+  void DisableDeleting() { _mustBeDeleted = false; }

+};

+#endif

+

+}}}

+

+#endif

diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp
new file mode 100755
index 0000000..99fb706
--- /dev/null
+++ b/CPP/Windows/FileFind.cpp
@@ -0,0 +1,462 @@
+// Windows/FileFind.cpp

+

+#include "StdAfx.h"

+

+#include "FileFind.h"

+#include "FileIO.h"

+#ifndef _UNICODE

+#include "../Common/StringConvert.h"

+#endif

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NFile {

+

+#ifdef SUPPORT_DEVICE_FILE

+bool IsDeviceName(LPCTSTR n);

+#ifndef _UNICODE

+bool IsDeviceName(LPCWSTR n);

+#endif

+#endif

+

+#if defined(WIN_LONG_PATH) && defined(_UNICODE)

+#define WIN_LONG_PATH2

+#endif

+

+bool GetLongPath(LPCWSTR fileName, UString &res);

+

+namespace NFind {

+

+static const TCHAR kDot = TEXT('.');

+

+bool CFileInfo::IsDots() const

+{

+  if (!IsDir() || Name.IsEmpty())

+    return false;

+  if (Name[0] != kDot)

+    return false;

+  return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);

+}

+

+#ifndef _UNICODE

+bool CFileInfoW::IsDots() const

+{

+  if (!IsDir() || Name.IsEmpty())

+    return false;

+  if (Name[0] != kDot)

+    return false;

+  return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);

+}

+#endif

+

+#define WIN_FD_TO_MY_FI(fi, fd) \

+  fi.Attrib = fd.dwFileAttributes; \

+  fi.CTime = fd.ftCreationTime; \

+  fi.ATime = fd.ftLastAccessTime; \

+  fi.MTime = fd.ftLastWriteTime; \

+  fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \

+  fi.IsDevice = false;

+

+  /*

+  #ifdef UNDER_CE

+  fi.ObjectID = fd.dwOID;

+  #else

+  fi.ReparseTag = fd.dwReserved0;

+  #endif

+  */

+

+static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi)

+{

+  WIN_FD_TO_MY_FI(fi, fd);

+  fi.Name = fd.cFileName;

+}

+

+#ifndef _UNICODE

+

+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }

+

+static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi)

+{

+  WIN_FD_TO_MY_FI(fi, fd);

+  fi.Name = fd.cFileName;

+}

+

+static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi)

+{

+  WIN_FD_TO_MY_FI(fi, fd);

+  fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage());

+}

+#endif

+  

+////////////////////////////////

+// CFindFile

+

+bool CFindFile::Close()

+{

+  if (_handle == INVALID_HANDLE_VALUE)

+    return true;

+  if (!::FindClose(_handle))

+    return false;

+  _handle = INVALID_HANDLE_VALUE;

+  return true;

+}

+

+          

+bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fi)

+{

+  if (!Close())

+    return false;

+  WIN32_FIND_DATA fd;

+  _handle = ::FindFirstFile(wildcard, &fd);

+  #ifdef WIN_LONG_PATH2

+  if (_handle == INVALID_HANDLE_VALUE)

+  {

+    UString longPath;

+    if (GetLongPath(wildcard, longPath))

+      _handle = ::FindFirstFileW(longPath, &fd);

+  }

+  #endif

+  if (_handle == INVALID_HANDLE_VALUE)

+    return false;

+  ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

+  return true;

+}

+

+#ifndef _UNICODE

+bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fi)

+{

+  if (!Close())

+    return false;

+  if (g_IsNT)

+  {

+    WIN32_FIND_DATAW fd;

+    _handle = ::FindFirstFileW(wildcard, &fd);

+    #ifdef WIN_LONG_PATH

+    if (_handle == INVALID_HANDLE_VALUE)

+    {

+      UString longPath;

+      if (GetLongPath(wildcard, longPath))

+        _handle = ::FindFirstFileW(longPath, &fd);

+    }

+    #endif

+    if (_handle != INVALID_HANDLE_VALUE)

+      ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

+  }

+  else

+  {

+    WIN32_FIND_DATAA fd;

+    _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard,

+        GetCurrentCodePage()), &fd);

+    if (_handle != INVALID_HANDLE_VALUE)

+      ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

+  }

+  return (_handle != INVALID_HANDLE_VALUE);

+}

+#endif

+

+bool CFindFile::FindNext(CFileInfo &fi)

+{

+  WIN32_FIND_DATA fd;

+  bool result = BOOLToBool(::FindNextFile(_handle, &fd));

+  if (result)

+    ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

+  return result;

+}

+

+#ifndef _UNICODE

+bool CFindFile::FindNext(CFileInfoW &fi)

+{

+  if (g_IsNT)

+  {

+    WIN32_FIND_DATAW fd;

+    if (!::FindNextFileW(_handle, &fd))

+      return false;

+    ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

+  }

+  else

+  {

+    WIN32_FIND_DATAA fd;

+    if (!::FindNextFileA(_handle, &fd))

+      return false;

+    ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi);

+  }

+  return true;

+}

+#endif

+

+#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;

+

+void CFileInfoBase::Clear()

+{

+  Size = 0;

+  MY_CLEAR_FILETIME(CTime);

+  MY_CLEAR_FILETIME(ATime);

+  MY_CLEAR_FILETIME(MTime);

+  Attrib = 0;

+}

+  

+bool CFileInfo::Find(LPCTSTR wildcard)

+{

+  #ifdef SUPPORT_DEVICE_FILE

+  if (IsDeviceName(wildcard))

+  {

+    Clear();

+    IsDevice = true;

+    NIO::CInFile inFile;

+    if (!inFile.Open(wildcard))

+      return false;

+    Name = wildcard + 4;

+    if (inFile.LengthDefined)

+      Size = inFile.Length;

+    return true;

+  }

+  #endif

+  CFindFile finder;

+  return finder.FindFirst(wildcard, *this);

+}

+

+

+#ifndef _UNICODE

+bool CFileInfoW::Find(LPCWSTR wildcard)

+{

+  #ifdef SUPPORT_DEVICE_FILE

+  if (IsDeviceName(wildcard))

+  {

+    Clear();

+    IsDevice = true;

+    NIO::CInFile inFile;

+    if (!inFile.Open(wildcard))

+      return false;

+    Name = wildcard + 4;

+    if (inFile.LengthDefined)

+      Size = inFile.Length;

+    return true;

+  }

+  #endif

+  CFindFile finder;

+  return finder.FindFirst(wildcard, *this);

+}

+#endif

+

+bool DoesFileExist(LPCTSTR name)

+{

+  CFileInfo fi;

+  return fi.Find(name) && !fi.IsDir();

+}

+

+bool DoesDirExist(LPCTSTR name)

+{

+  CFileInfo fi;

+  return fi.Find(name) && fi.IsDir();

+}

+

+bool DoesFileOrDirExist(LPCTSTR name)

+{

+  CFileInfo fi;

+  return fi.Find(name);

+}

+

+#ifndef _UNICODE

+bool DoesFileExist(LPCWSTR name)

+{

+  CFileInfoW fi;

+  return fi.Find(name) && !fi.IsDir();

+}

+

+bool DoesDirExist(LPCWSTR name)

+{

+  CFileInfoW fi;

+  return fi.Find(name) && fi.IsDir();

+}

+bool DoesFileOrDirExist(LPCWSTR name)

+{

+  CFileInfoW fi;

+  return fi.Find(name);

+}

+#endif

+

+/////////////////////////////////////

+// CEnumerator

+

+bool CEnumerator::NextAny(CFileInfo &fi)

+{

+  if (_findFile.IsHandleAllocated())

+    return _findFile.FindNext(fi);

+  else

+    return _findFile.FindFirst(_wildcard, fi);

+}

+

+bool CEnumerator::Next(CFileInfo &fi)

+{

+  for (;;)

+  {

+    if (!NextAny(fi))

+      return false;

+    if (!fi.IsDots())

+      return true;

+  }

+}

+

+bool CEnumerator::Next(CFileInfo &fi, bool &found)

+{

+  if (Next(fi))

+  {

+    found = true;

+    return true;

+  }

+  found = false;

+  return (::GetLastError() == ERROR_NO_MORE_FILES);

+}

+

+#ifndef _UNICODE

+bool CEnumeratorW::NextAny(CFileInfoW &fi)

+{

+  if (_findFile.IsHandleAllocated())

+    return _findFile.FindNext(fi);

+  else

+    return _findFile.FindFirst(_wildcard, fi);

+}

+

+bool CEnumeratorW::Next(CFileInfoW &fi)

+{

+  for (;;)

+  {

+    if (!NextAny(fi))

+      return false;

+    if (!fi.IsDots())

+      return true;

+  }

+}

+

+bool CEnumeratorW::Next(CFileInfoW &fi, bool &found)

+{

+  if (Next(fi))

+  {

+    found = true;

+    return true;

+  }

+  found = false;

+  return (::GetLastError() == ERROR_NO_MORE_FILES);

+}

+

+#endif

+

+////////////////////////////////

+// CFindChangeNotification

+// FindFirstChangeNotification can return 0. MSDN doesn't tell about it.

+

+bool CFindChangeNotification::Close()

+{

+  if (!IsHandleAllocated())

+    return true;

+  if (!::FindCloseChangeNotification(_handle))

+    return false;

+  _handle = INVALID_HANDLE_VALUE;

+  return true;

+}

+           

+HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter)

+{

+  _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter);

+  #ifdef WIN_LONG_PATH2

+  if (!IsHandleAllocated())

+  {

+    UString longPath;

+    if (GetLongPath(pathName, longPath))

+      _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);

+  }

+  #endif

+  return _handle;

+}

+

+#ifndef _UNICODE

+HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter)

+{

+  if (!g_IsNT)

+    return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter);

+  _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter);

+  #ifdef WIN_LONG_PATH

+  if (!IsHandleAllocated())

+  {

+    UString longPath;

+    if (GetLongPath(pathName, longPath))

+      _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);

+  }

+  #endif

+  return _handle;

+}

+#endif

+

+#ifndef UNDER_CE

+bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings)

+{

+  driveStrings.Clear();

+  UINT32 size = GetLogicalDriveStrings(0, NULL);

+  if (size == 0)

+    return false;

+  CSysString buffer;

+  UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size));

+  if (newSize == 0)

+    return false;

+  if (newSize > size)

+    return false;

+  CSysString string;

+  for (UINT32 i = 0; i < newSize; i++)

+  {

+    TCHAR c = buffer[i];

+    if (c == TEXT('\0'))

+    {

+      driveStrings.Add(string);

+      string.Empty();

+    }

+    else

+      string += c;

+  }

+  if (!string.IsEmpty())

+    return false;

+  return true;

+}

+

+#ifndef _UNICODE

+bool MyGetLogicalDriveStrings(UStringVector &driveStrings)

+{

+  driveStrings.Clear();

+  if (g_IsNT)

+  {

+    UINT32 size = GetLogicalDriveStringsW(0, NULL);

+    if (size == 0)

+      return false;

+    UString buffer;

+    UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size));

+    if (newSize == 0)

+      return false;

+    if (newSize > size)

+      return false;

+    UString string;

+    for (UINT32 i = 0; i < newSize; i++)

+    {

+      WCHAR c = buffer[i];

+      if (c == L'\0')

+      {

+        driveStrings.Add(string);

+        string.Empty();

+      }

+      else

+        string += c;

+    }

+    return string.IsEmpty();

+  }

+  CSysStringVector driveStringsA;

+  bool res = MyGetLogicalDriveStrings(driveStringsA);

+  for (int i = 0; i < driveStringsA.Size(); i++)

+    driveStrings.Add(GetUnicodeString(driveStringsA[i]));

+  return res;

+}

+#endif

+

+#endif

+

+}}}

diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h
new file mode 100755
index 0000000..5affd83
--- /dev/null
+++ b/CPP/Windows/FileFind.h
@@ -0,0 +1,161 @@
+// Windows/FileFind.h

+

+#ifndef __WINDOWS_FILEFIND_H

+#define __WINDOWS_FILEFIND_H

+

+#include "../Common/MyString.h"

+#include "../Common/Types.h"

+#include "Defs.h"

+#include "FileName.h"

+

+namespace NWindows {

+namespace NFile {

+namespace NFind {

+

+namespace NAttributes

+{

+  inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; }

+  inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; }

+  inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; }

+  inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; }

+  inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; }

+  inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; }

+  inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; }

+}

+

+class CFileInfoBase

+{

+  bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); }

+protected:

+  void Clear();

+public:

+  UInt64 Size;

+  FILETIME CTime;

+  FILETIME ATime;

+  FILETIME MTime;

+  DWORD Attrib;

+  bool IsDevice;

+

+  /*

+  #ifdef UNDER_CE

+  DWORD ObjectID;

+  #else

+  UINT32 ReparseTag;

+  #endif

+  */

+

+  bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); }

+  bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); }

+  bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); }

+  bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); }

+  bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); }

+  bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); }

+  bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); }

+  bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); }

+  bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); }

+  bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); }

+  bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); }

+  bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); }

+};

+

+struct CFileInfo: public CFileInfoBase

+{

+  CSysString Name;

+

+  bool IsDots() const;

+  bool Find(LPCTSTR wildcard);

+};

+

+#ifdef _UNICODE

+typedef CFileInfo CFileInfoW;

+#else

+struct CFileInfoW: public CFileInfoBase

+{

+  UString Name;

+

+  bool IsDots() const;

+  bool Find(LPCWSTR wildcard);

+};

+#endif

+

+class CFindFile

+{

+  friend class CEnumerator;

+  HANDLE _handle;

+public:

+  bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; }

+  CFindFile(): _handle(INVALID_HANDLE_VALUE) {}

+  ~CFindFile() {  Close(); }

+  bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo);

+  bool FindNext(CFileInfo &fileInfo);

+  #ifndef _UNICODE

+  bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo);

+  bool FindNext(CFileInfoW &fileInfo);

+  #endif

+  bool Close();

+};

+

+bool DoesFileExist(LPCTSTR name);

+bool DoesDirExist(LPCTSTR name);

+bool DoesFileOrDirExist(LPCTSTR name);

+#ifndef _UNICODE

+bool DoesFileExist(LPCWSTR name);

+bool DoesDirExist(LPCWSTR name);

+bool DoesFileOrDirExist(LPCWSTR name);

+#endif

+

+class CEnumerator

+{

+  CFindFile _findFile;

+  CSysString _wildcard;

+  bool NextAny(CFileInfo &fileInfo);

+public:

+  CEnumerator(): _wildcard(NName::kAnyStringWildcard) {}

+  CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {}

+  bool Next(CFileInfo &fileInfo);

+  bool Next(CFileInfo &fileInfo, bool &found);

+};

+

+#ifdef _UNICODE

+typedef CEnumerator CEnumeratorW;

+#else

+class CEnumeratorW

+{

+  CFindFile _findFile;

+  UString _wildcard;

+  bool NextAny(CFileInfoW &fileInfo);

+public:

+  CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {}

+  CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {}

+  bool Next(CFileInfoW &fileInfo);

+  bool Next(CFileInfoW &fileInfo, bool &found);

+};

+#endif

+

+class CFindChangeNotification

+{

+  HANDLE _handle;

+public:

+  operator HANDLE () { return _handle; }

+  bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; }

+  CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {}

+  ~CFindChangeNotification() { Close(); }

+  bool Close();

+  HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter);

+  #ifndef _UNICODE

+  HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter);

+  #endif

+  bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); }

+};

+

+#ifndef UNDER_CE

+bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings);

+#ifndef _UNICODE

+bool MyGetLogicalDriveStrings(UStringVector &driveStrings);

+#endif

+#endif

+

+}}}

+

+#endif

+

diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp
new file mode 100755
index 0000000..a1a1bcc
--- /dev/null
+++ b/CPP/Windows/FileIO.cpp
@@ -0,0 +1,434 @@
+// Windows/FileIO.cpp

+

+#include "StdAfx.h"

+

+#include "FileIO.h"

+

+#if defined(WIN_LONG_PATH) || defined(SUPPORT_DEVICE_FILE)

+#include "../Common/MyString.h"

+#endif

+#ifndef _UNICODE

+#include "../Common/StringConvert.h"

+#endif

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NFile {

+

+#ifdef SUPPORT_DEVICE_FILE

+bool IsDeviceName(LPCTSTR n)

+{

+  #ifdef UNDER_CE

+  int len = (int)MyStringLen(n);

+  if (len < 5 || len > 5 || memcmp(n, TEXT("DSK"), 3 * sizeof(TCHAR)) != 0)

+    return false;

+  if (n[4] != ':')

+    return false;

+  // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ));

+  #else

+  if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' ||  n[3] != '\\')

+    return false;

+  int len = (int)MyStringLen(n);

+  if (len == 6 && n[5] == ':')

+    return true;

+  if (len < 18 || len > 22 || memcmp(n + 4, TEXT("PhysicalDrive"), 13 * sizeof(TCHAR)) != 0)

+    return false;

+  for (int i = 17; i < len; i++)

+    if (n[i] < '0' || n[i] > '9')

+      return false;

+  #endif

+  return true;

+}

+

+#ifndef _UNICODE

+bool IsDeviceName(LPCWSTR n)

+{

+  if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' ||  n[3] != '\\')

+    return false;

+  int len = (int)wcslen(n);

+  if (len == 6 && n[5] == ':')

+    return true;

+  if (len < 18 || len > 22 || wcsncmp(n + 4, L"PhysicalDrive", 13) != 0)

+    return false;

+  for (int i = 17; i < len; i++)

+    if (n[i] < '0' || n[i] > '9')

+      return false;

+  return true;

+}

+#endif

+#endif

+

+#if defined(WIN_LONG_PATH) && defined(_UNICODE)

+#define WIN_LONG_PATH2

+#endif

+

+#ifdef WIN_LONG_PATH

+bool GetLongPathBase(LPCWSTR s, UString &res)

+{

+  res.Empty();

+  int len = MyStringLen(s);

+  wchar_t c = s[0];

+  if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.'))

+    return true;

+  UString curDir;

+  bool isAbs = false;

+  if (len > 3)

+    isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z'));

+

+  if (!isAbs)

+    {

+      DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1));

+      curDir.ReleaseBuffer();

+      if (needLength == 0 || needLength > MAX_PATH)

+        return false;

+      if (curDir[curDir.Length() - 1] != L'\\')

+        curDir += L'\\';

+    }

+  res = UString(L"\\\\?\\") + curDir + s;

+  return true;

+}

+

+bool GetLongPath(LPCWSTR path, UString &longPath)

+{

+  if (GetLongPathBase(path, longPath))

+    return !longPath.IsEmpty();

+  return false;

+}

+#endif

+

+namespace NIO {

+

+CFileBase::~CFileBase() { Close(); }

+

+bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess,

+    DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

+{

+  if (!Close())

+    return false;

+  _handle = ::CreateFile(fileName, desiredAccess, shareMode,

+      (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,

+      flagsAndAttributes, (HANDLE)NULL);

+  #ifdef WIN_LONG_PATH2

+  if (_handle == INVALID_HANDLE_VALUE)

+  {

+    UString longPath;

+    if (GetLongPath(fileName, longPath))

+      _handle = ::CreateFileW(longPath, desiredAccess, shareMode,

+        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,

+        flagsAndAttributes, (HANDLE)NULL);

+  }

+  #endif

+  #ifdef SUPPORT_DEVICE_FILE

+  IsDeviceFile = false;

+  #endif

+  return (_handle != INVALID_HANDLE_VALUE);

+}

+

+#ifndef _UNICODE

+bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess,

+    DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

+{

+  if (!g_IsNT)

+    return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP),

+      desiredAccess, shareMode, creationDisposition, flagsAndAttributes);

+  if (!Close())

+    return false;

+  _handle = ::CreateFileW(fileName, desiredAccess, shareMode,

+    (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,

+    flagsAndAttributes, (HANDLE)NULL);

+  #ifdef WIN_LONG_PATH

+  if (_handle == INVALID_HANDLE_VALUE)

+  {

+    UString longPath;

+    if (GetLongPath(fileName, longPath))

+      _handle = ::CreateFileW(longPath, desiredAccess, shareMode,

+        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,

+        flagsAndAttributes, (HANDLE)NULL);

+  }

+  #endif

+  #ifdef SUPPORT_DEVICE_FILE

+  IsDeviceFile = false;

+  #endif

+  return (_handle != INVALID_HANDLE_VALUE);

+}

+#endif

+

+bool CFileBase::Close()

+{

+  if (_handle == INVALID_HANDLE_VALUE)

+    return true;

+  if (!::CloseHandle(_handle))

+    return false;

+  _handle = INVALID_HANDLE_VALUE;

+  return true;

+}

+

+bool CFileBase::GetPosition(UInt64 &position) const

+{

+  return Seek(0, FILE_CURRENT, position);

+}

+

+bool CFileBase::GetLength(UInt64 &length) const

+{

+  #ifdef SUPPORT_DEVICE_FILE

+  if (IsDeviceFile && LengthDefined)

+  {

+    length = Length;

+    return true;

+  }

+  #endif

+

+  DWORD sizeHigh;

+  DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh);

+  if (sizeLow == 0xFFFFFFFF)

+    if (::GetLastError() != NO_ERROR)

+      return false;

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

+  return true;

+}

+

+bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const

+{

+  #ifdef SUPPORT_DEVICE_FILE

+  if (IsDeviceFile && LengthDefined && moveMethod == FILE_END)

+  {

+    distanceToMove += Length;

+    moveMethod = FILE_BEGIN;

+  }

+  #endif

+

+  LARGE_INTEGER value;

+  value.QuadPart = distanceToMove;

+  value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod);

+  if (value.LowPart == 0xFFFFFFFF)

+    if (::GetLastError() != NO_ERROR)

+      return false;

+  newPosition = value.QuadPart;

+  return true;

+}

+

+bool CFileBase::Seek(UInt64 position, UInt64 &newPosition)

+{

+  return Seek(position, FILE_BEGIN, newPosition);

+}

+

+bool CFileBase::SeekToBegin()

+{

+  UInt64 newPosition;

+  return Seek(0, newPosition);

+}

+

+bool CFileBase::SeekToEnd(UInt64 &newPosition)

+{

+  return Seek(0, FILE_END, newPosition);

+}

+

+bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const

+{

+  BY_HANDLE_FILE_INFORMATION winFileInfo;

+  if (!::GetFileInformationByHandle(_handle, &winFileInfo))

+    return false;

+  fileInfo.Attrib = winFileInfo.dwFileAttributes;

+  fileInfo.CTime = winFileInfo.ftCreationTime;

+  fileInfo.ATime = winFileInfo.ftLastAccessTime;

+  fileInfo.MTime = winFileInfo.ftLastWriteTime;

+  fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes;

+  fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) +  winFileInfo.nFileSizeLow;

+  fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks;

+  fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow;

+  return true;

+}

+

+/////////////////////////

+// CInFile

+

+#ifdef SUPPORT_DEVICE_FILE

+void CInFile::GetDeviceLength()

+{

+  if (_handle != INVALID_HANDLE_VALUE && IsDeviceFile)

+  {

+    #ifdef UNDER_CE

+    LengthDefined = true;

+    Length = 128 << 20;

+

+    #else

+    PARTITION_INFORMATION partInfo;

+    LengthDefined = true;

+    Length = 0;

+

+    if (GetPartitionInfo(&partInfo))

+      Length = partInfo.PartitionLength.QuadPart;

+    else

+    {

+      DISK_GEOMETRY geom;

+      if (!GetGeometry(&geom))

+        if (!GetCdRomGeometry(&geom))

+          LengthDefined = false;

+      if (LengthDefined)

+        Length = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;

+    }

+    // SeekToBegin();

+    #endif

+  }

+}

+

+// ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 &&

+

+#define MY_DEVICE_EXTRA_CODE \

+  IsDeviceFile = IsDeviceName(fileName); \

+  GetDeviceLength();

+#else

+#define MY_DEVICE_EXTRA_CODE

+#endif

+

+bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

+{

+  bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes);

+  MY_DEVICE_EXTRA_CODE

+  return res;

+}

+

+bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite)

+{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }

+

+bool CInFile::Open(LPCTSTR fileName)

+  { return OpenShared(fileName, false); }

+

+#ifndef _UNICODE

+bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

+{

+  bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes);

+  MY_DEVICE_EXTRA_CODE

+  return res;

+}

+

+bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite)

+{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }

+

+bool CInFile::Open(LPCWSTR fileName)

+  { return OpenShared(fileName, false); }

+#endif

+

+// 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"

+

+static UInt32 kChunkSizeMax = (1 << 22);

+

+bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize)

+{

+  DWORD processedLoc = 0;

+  bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL));

+  processedSize = (UInt32)processedLoc;

+  return res;

+}

+

+bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize)

+{

+  if (size > kChunkSizeMax)

+    size = kChunkSizeMax;

+  return Read1(data, size, processedSize);

+}

+

+bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize)

+{

+  processedSize = 0;

+  do

+  {

+    UInt32 processedLoc = 0;

+    bool res = ReadPart(data, size, processedLoc);

+    processedSize += processedLoc;

+    if (!res)

+      return false;

+    if (processedLoc == 0)

+      return true;

+    data = (void *)((unsigned char *)data + processedLoc);

+    size -= processedLoc;

+  }

+  while (size > 0);

+  return true;

+}

+

+/////////////////////////

+// COutFile

+

+bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

+  { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }

+

+static inline DWORD GetCreationDisposition(bool createAlways)

+  { return createAlways? CREATE_ALWAYS: CREATE_NEW; }

+

+bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition)

+  { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }

+

+bool COutFile::Create(LPCTSTR fileName, bool createAlways)

+  { return Open(fileName, GetCreationDisposition(createAlways)); }

+

+#ifndef _UNICODE

+

+bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)

+  { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }

+

+bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition)

+  { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }

+

+bool COutFile::Create(LPCWSTR fileName, bool createAlways)

+  { return Open(fileName, GetCreationDisposition(createAlways)); }

+

+#endif

+

+bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)

+  { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); }

+

+bool COutFile::SetMTime(const FILETIME *mTime) {  return SetTime(NULL, NULL, mTime); }

+

+bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize)

+{

+  if (size > kChunkSizeMax)

+    size = kChunkSizeMax;

+  DWORD processedLoc = 0;

+  bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL));

+  processedSize = (UInt32)processedLoc;

+  return res;

+}

+

+bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize)

+{

+  processedSize = 0;

+  do

+  {

+    UInt32 processedLoc = 0;

+    bool res = WritePart(data, size, processedLoc);

+    processedSize += processedLoc;

+    if (!res)

+      return false;

+    if (processedLoc == 0)

+      return true;

+    data = (const void *)((const unsigned char *)data + processedLoc);

+    size -= processedLoc;

+  }

+  while (size > 0);

+  return true;

+}

+

+bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); }

+

+bool COutFile::SetLength(UInt64 length)

+{

+  UInt64 newPosition;

+  if (!Seek(length, newPosition))

+    return false;

+  if (newPosition != length)

+    return false;

+  return SetEndOfFile();

+}

+

+}}}

diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h
new file mode 100755
index 0000000..6f14817
--- /dev/null
+++ b/CPP/Windows/FileIO.h
@@ -0,0 +1,136 @@
+// Windows/FileIO.h

+

+#ifndef __WINDOWS_FILEIO_H

+#define __WINDOWS_FILEIO_H

+

+#include "../Common/Types.h"

+

+#include "Defs.h"

+

+namespace NWindows {

+namespace NFile {

+namespace NIO {

+

+struct CByHandleFileInfo

+{

+  DWORD Attrib;

+  FILETIME CTime;

+  FILETIME ATime;

+  FILETIME MTime;

+  DWORD VolumeSerialNumber;

+  UInt64 Size;

+  DWORD NumberOfLinks;

+  UInt64 FileIndex;

+};

+

+class CFileBase

+{

+protected:

+  HANDLE _handle;

+  

+  bool Create(LPCTSTR fileName, DWORD desiredAccess,

+      DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

+  #ifndef _UNICODE

+  bool Create(LPCWSTR fileName, DWORD desiredAccess,

+      DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

+  #endif

+

+public:

+  #ifdef SUPPORT_DEVICE_FILE

+  bool IsDeviceFile;

+  bool LengthDefined;

+  UInt64 Length;

+  #endif

+

+  CFileBase(): _handle(INVALID_HANDLE_VALUE) {};

+  ~CFileBase();

+

+  bool Close();

+

+  bool GetPosition(UInt64 &position) const;

+  bool GetLength(UInt64 &length) const;

+

+  bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const;

+  bool Seek(UInt64 position, UInt64 &newPosition);

+  bool SeekToBegin();

+  bool SeekToEnd(UInt64 &newPosition);

+  

+  bool GetFileInformation(CByHandleFileInfo &fileInfo) const;

+};

+

+#define IOCTL_CDROM_BASE  FILE_DEVICE_CD_ROM

+#define IOCTL_CDROM_GET_DRIVE_GEOMETRY  CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)

+#define IOCTL_CDROM_MEDIA_REMOVAL  CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS)

+

+class CInFile: public CFileBase

+{

+  #ifdef SUPPORT_DEVICE_FILE

+  bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize,

+      LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped) const

+  {

+    return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize,

+        outBuffer, outSize, bytesReturned, overlapped));

+  }

+

+  bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer,

+      DWORD inSize, LPVOID outBuffer, DWORD outSize) const

+  {

+    DWORD ret;

+    return DeviceIoControl(controlCode, inBuffer, inSize, outBuffer, outSize, &ret, 0);

+  }

+

+  bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const

+    { return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize); }

+

+  #ifndef UNDER_CE

+  bool GetGeometry(DISK_GEOMETRY *res) const

+    { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }

+

+  bool GetCdRomGeometry(DISK_GEOMETRY *res) const

+    { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }

+  

+  bool GetPartitionInfo(PARTITION_INFORMATION *res)

+    { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); }

+  #endif

+

+  void GetDeviceLength();

+  #endif

+

+public:

+  bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

+  bool OpenShared(LPCTSTR fileName, bool shareForWrite);

+  bool Open(LPCTSTR fileName);

+  #ifndef _UNICODE

+  bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

+  bool OpenShared(LPCWSTR fileName, bool shareForWrite);

+  bool Open(LPCWSTR fileName);

+  #endif

+  bool Read1(void *data, UInt32 size, UInt32 &processedSize);

+  bool ReadPart(void *data, UInt32 size, UInt32 &processedSize);

+  bool Read(void *data, UInt32 size, UInt32 &processedSize);

+};

+

+class COutFile: public CFileBase

+{

+public:

+  bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

+  bool Open(LPCTSTR fileName, DWORD creationDisposition);

+  bool Create(LPCTSTR fileName, bool createAlways);

+

+  #ifndef _UNICODE

+  bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);

+  bool Open(LPCWSTR fileName, DWORD creationDisposition);

+  bool Create(LPCWSTR fileName, bool createAlways);

+  #endif

+

+  bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);

+  bool SetMTime(const FILETIME *mTime);

+  bool WritePart(const void *data, UInt32 size, UInt32 &processedSize);

+  bool Write(const void *data, UInt32 size, UInt32 &processedSize);

+  bool SetEndOfFile();

+  bool SetLength(UInt64 length);

+};

+

+}}}

+

+#endif

diff --git a/CPP/Windows/FileMapping.cpp b/CPP/Windows/FileMapping.cpp
new file mode 100755
index 0000000..857e70d
--- /dev/null
+++ b/CPP/Windows/FileMapping.cpp
@@ -0,0 +1,12 @@
+// Windows/FileMapping.cpp

+

+#include "StdAfx.h"

+

+#include "Windows/FileMapping.h"

+

+namespace NWindows {

+namespace NFile {

+namespace NMapping {

+

+

+}}}

diff --git a/CPP/Windows/FileMapping.h b/CPP/Windows/FileMapping.h
new file mode 100755
index 0000000..138a175
--- /dev/null
+++ b/CPP/Windows/FileMapping.h
@@ -0,0 +1,62 @@
+// Windows/FileMapping.h

+

+#ifndef __WINDOWS_FILEMAPPING_H

+#define __WINDOWS_FILEMAPPING_H

+

+#include "Common/Types.h"

+

+#include "Handle.h"

+

+namespace NWindows {

+

+class CFileMapping: public CHandle

+{

+public:

+  WRes Create(DWORD protect, UInt64 maxSize, LPCTSTR name)

+  {

+    _handle = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, protect, (DWORD)(maxSize >> 32), (DWORD)maxSize, name);

+    return ::GetLastError();

+  }

+

+  WRes Open(DWORD desiredAccess, LPCTSTR name)

+  {

+    #ifdef UNDER_CE

+    WRes res = Create(PAGE_READONLY, 0, name);

+    if (res == ERROR_ALREADY_EXISTS)

+      return 0;

+    Close();

+    if (res == 0)

+      res = ERROR_FILE_NOT_FOUND;

+    return res;

+    #else

+    _handle = ::OpenFileMapping(desiredAccess, FALSE, name);

+    if (_handle != 0)

+      return 0;

+    return ::GetLastError();

+    #endif

+  }

+

+  LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap)

+  {

+    return ::MapViewOfFile(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap);

+  }

+

+  #ifndef UNDER_CE

+  LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress)

+  {

+    return ::MapViewOfFileEx(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap, baseAddress);

+  }

+  #endif

+};

+

+class CFileUnmapper

+{

+  const void *_data;

+public:

+  CFileUnmapper(const void *data) : _data(data) {}

+  ~CFileUnmapper() { ::UnmapViewOfFile(_data); }

+};

+

+}

+

+#endif

diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp
new file mode 100755
index 0000000..4e55a53
--- /dev/null
+++ b/CPP/Windows/FileName.cpp
@@ -0,0 +1,50 @@
+// Windows/FileName.cpp

+

+#include "StdAfx.h"

+

+#include "Windows/FileName.h"

+#include "Common/Wildcard.h"

+

+namespace NWindows {

+namespace NFile {

+namespace NName {

+

+void NormalizeDirPathPrefix(CSysString &dirPath)

+{

+  if (dirPath.IsEmpty())

+    return;

+  if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1)

+    dirPath += kDirDelimiter;

+}

+

+#ifndef _UNICODE

+void NormalizeDirPathPrefix(UString &dirPath)

+{

+  if (dirPath.IsEmpty())

+    return;

+  if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1)

+    dirPath += wchar_t(kDirDelimiter);

+}

+#endif

+

+const wchar_t kExtensionDelimiter = L'.';

+

+void SplitNameToPureNameAndExtension(const UString &fullName,

+    UString &pureName, UString &extensionDelimiter, UString &extension)

+{

+  int index = fullName.ReverseFind(kExtensionDelimiter);

+  if (index < 0)

+  {

+    pureName = fullName;

+    extensionDelimiter.Empty();

+    extension.Empty();

+  }

+  else

+  {

+    pureName = fullName.Left(index);

+    extensionDelimiter = kExtensionDelimiter;

+    extension = fullName.Mid(index + 1);

+  }

+}

+

+}}}

diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h
new file mode 100755
index 0000000..b980236
--- /dev/null
+++ b/CPP/Windows/FileName.h
@@ -0,0 +1,27 @@
+// Windows/FileName.h

+

+#ifndef __WINDOWS_FILENAME_H

+#define __WINDOWS_FILENAME_H

+

+#include "../../C/Types.h"

+

+#include "../Common/MyString.h"

+

+namespace NWindows {

+namespace NFile {

+namespace NName {

+

+const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR;

+const TCHAR kAnyStringWildcard = '*';

+

+void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\'

+#ifndef _UNICODE

+void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\'

+#endif

+

+void SplitNameToPureNameAndExtension(const UString &fullName,

+    UString &pureName, UString &extensionDelimiter, UString &extension);

+

+}}}

+

+#endif

diff --git a/CPP/Windows/Handle.h b/CPP/Windows/Handle.h
new file mode 100755
index 0000000..755eeb8
--- /dev/null
+++ b/CPP/Windows/Handle.h
@@ -0,0 +1,37 @@
+// Windows/Handle.h

+

+#ifndef __WINDOWS_HANDLE_H

+#define __WINDOWS_HANDLE_H

+

+namespace NWindows {

+

+class CHandle

+{

+protected:

+  HANDLE _handle;

+public:

+  operator HANDLE() { return _handle; }

+  CHandle(): _handle(NULL) {}

+  ~CHandle() { Close(); }

+  bool IsCreated() const { return (_handle != NULL); }

+  bool Close()

+  {

+    if (_handle == NULL)

+      return true;

+    if (!::CloseHandle(_handle))

+      return false;

+    _handle = NULL;

+    return true;

+  }

+  void Attach(HANDLE handle) { _handle = handle; }

+  HANDLE Detach()

+  {

+    HANDLE handle = _handle;

+    _handle = NULL;

+    return handle;

+  }

+};

+

+}

+

+#endif

diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp
new file mode 100755
index 0000000..9b2ffb8
--- /dev/null
+++ b/CPP/Windows/MemoryLock.cpp
@@ -0,0 +1,82 @@
+// Common/MemoryLock.cpp

+

+#include "StdAfx.h"

+

+namespace NWindows {

+namespace NSecurity {

+

+#ifndef UNDER_CE

+

+#ifndef _UNICODE

+typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);

+typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID  lpLuid);

+typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges,

+    PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength);

+#endif

+

+#ifdef _UNICODE

+bool EnableLockMemoryPrivilege(

+#else

+static bool EnableLockMemoryPrivilege2(HMODULE hModule,

+#endif

+bool enable)

+{

+  #ifndef _UNICODE

+  if (hModule == NULL)

+    return false;

+  OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken");

+  LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" );

+  AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges");

+  if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL)

+    return false;

+  #endif

+

+  HANDLE token;

+  if (!

+    #ifdef _UNICODE

+    ::OpenProcessToken

+    #else

+    openProcessToken

+    #endif

+    (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))

+    return false;

+  TOKEN_PRIVILEGES tp;

+  bool res = false;

+  if (

+    #ifdef _UNICODE

+    ::LookupPrivilegeValue

+    #else

+    lookupPrivilegeValue

+    #endif

+    (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)))

+  {

+    tp.PrivilegeCount = 1;

+    tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0;

+    if (

+      #ifdef _UNICODE

+      ::AdjustTokenPrivileges

+      #else

+      adjustTokenPrivileges

+      #endif

+      (token, FALSE, &tp, 0, NULL, NULL))

+      res = (GetLastError() == ERROR_SUCCESS);

+  }

+  ::CloseHandle(token);

+  return res;

+}

+

+#ifndef _UNICODE

+bool EnableLockMemoryPrivilege(bool enable)

+{

+  HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll"));

+  if (hModule == NULL)

+    return false;

+  bool res = EnableLockMemoryPrivilege2(hModule, enable);

+  ::FreeLibrary(hModule);

+  return res;

+}

+#endif

+

+#endif

+

+}}

diff --git a/CPP/Windows/MemoryLock.h b/CPP/Windows/MemoryLock.h
new file mode 100755
index 0000000..f2e574b
--- /dev/null
+++ b/CPP/Windows/MemoryLock.h
@@ -0,0 +1,15 @@
+// Windows/MemoryLock.h

+

+#ifndef __WINDOWS_MEMORYLOCK_H

+#define __WINDOWS_MEMORYLOCK_H

+

+namespace NWindows {

+namespace NSecurity {

+

+#ifndef UNDER_CE

+bool EnableLockMemoryPrivilege(bool enable = true);

+#endif

+

+}}

+

+#endif

diff --git a/CPP/Windows/NtCheck.h b/CPP/Windows/NtCheck.h
new file mode 100755
index 0000000..b8fa99b
--- /dev/null
+++ b/CPP/Windows/NtCheck.h
@@ -0,0 +1,44 @@
+// Windows/NtCheck.h

+

+#ifndef __WINDOWS_NT_CHECK_H

+#define __WINDOWS_NT_CHECK_H

+

+#ifdef _WIN32

+

+#if !defined(_WIN64) && !defined(UNDER_CE)

+static inline bool IsItWindowsNT()

+{

+  OSVERSIONINFO vi;

+  vi.dwOSVersionInfoSize = sizeof(vi);

+  return (::GetVersionEx(&vi) && vi.dwPlatformId == VER_PLATFORM_WIN32_NT);

+}

+#endif

+

+#ifndef _UNICODE

+  #if defined(_WIN64) || defined(UNDER_CE)

+    bool g_IsNT = true;

+    #define SET_IS_NT

+  #else

+    bool g_IsNT = false;

+    #define SET_IS_NT g_IsNT = IsItWindowsNT();

+  #endif

+  #define NT_CHECK_ACTION

+  // #define NT_CHECK_ACTION { NT_CHECK_FAIL_ACTION }

+#else

+  #if !defined(_WIN64) && !defined(UNDER_CE)

+    #define NT_CHECK_ACTION if (!IsItWindowsNT()) { NT_CHECK_FAIL_ACTION }

+  #else

+    #define NT_CHECK_ACTION

+  #endif

+  #define SET_IS_NT

+#endif

+

+#define NT_CHECK  NT_CHECK_ACTION SET_IS_NT

+

+#else

+

+#define NT_CHECK

+

+#endif

+

+#endif

diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
new file mode 100755
index 0000000..bcd85a5
--- /dev/null
+++ b/CPP/Windows/PropVariant.cpp
@@ -0,0 +1,243 @@
+// Windows/PropVariant.cpp

+

+#include "StdAfx.h"

+

+#include "PropVariant.h"

+

+#include "../Common/Defs.h"

+

+namespace NWindows {

+namespace NCOM {

+

+CPropVariant::CPropVariant(const PROPVARIANT &varSrc)

+{

+  vt = VT_EMPTY;

+  InternalCopy(&varSrc);

+}

+

+CPropVariant::CPropVariant(const CPropVariant &varSrc)

+{

+  vt = VT_EMPTY;

+  InternalCopy(&varSrc);

+}

+

+CPropVariant::CPropVariant(BSTR bstrSrc)

+{

+  vt = VT_EMPTY;

+  *this = bstrSrc;

+}

+

+CPropVariant::CPropVariant(LPCOLESTR lpszSrc)

+{

+  vt = VT_EMPTY;

+  *this = lpszSrc;

+}

+

+CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)

+{

+  InternalCopy(&varSrc);

+  return *this;

+}

+CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)

+{

+  InternalCopy(&varSrc);

+  return *this;

+}

+

+CPropVariant& CPropVariant::operator=(BSTR bstrSrc)

+{

+  *this = (LPCOLESTR)bstrSrc;

+  return *this;

+}

+

+static const char *kMemException = "out of memory";

+

+CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)

+{

+  InternalClear();

+  vt = VT_BSTR;

+  wReserved1 = 0;

+  bstrVal = ::SysAllocString(lpszSrc);

+  if (bstrVal == NULL && lpszSrc != NULL)

+  {

+    throw kMemException;

+    // vt = VT_ERROR;

+    // scode = E_OUTOFMEMORY;

+  }

+  return *this;

+}

+

+

+CPropVariant& CPropVariant::operator=(const char *s)

+{

+  InternalClear();

+  vt = VT_BSTR;

+  wReserved1 = 0;

+  UINT len = (UINT)strlen(s);

+  bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR));

+  if (bstrVal == NULL)

+  {

+    throw kMemException;

+    // vt = VT_ERROR;

+    // scode = E_OUTOFMEMORY;

+  }

+  else

+  {

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

+      bstrVal[i] = s[i];

+  }

+  return *this;

+}

+

+CPropVariant& CPropVariant::operator=(bool bSrc)

+{

+  if (vt != VT_BOOL)

+  {

+    InternalClear();

+    vt = VT_BOOL;

+  }

+  boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;

+  return *this;

+}

+

+#define SET_PROP_FUNC(type, id, dest) \

+  CPropVariant& CPropVariant::operator=(type value) \

+  { if (vt != id) { InternalClear(); vt = id; } \

+    dest = value; return *this; }

+

+SET_PROP_FUNC(Byte, VT_UI1, bVal)

+SET_PROP_FUNC(Int16, VT_I2, iVal)

+SET_PROP_FUNC(Int32, VT_I4, lVal)

+SET_PROP_FUNC(UInt32, VT_UI4, ulVal)

+SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)

+SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)

+

+static HRESULT MyPropVariantClear(PROPVARIANT *prop)

+{

+  switch(prop->vt)

+  {

+    case VT_UI1:

+    case VT_I1:

+    case VT_I2:

+    case VT_UI2:

+    case VT_BOOL:

+    case VT_I4:

+    case VT_UI4:

+    case VT_R4:

+    case VT_INT:

+    case VT_UINT:

+    case VT_ERROR:

+    case VT_FILETIME:

+    case VT_UI8:

+    case VT_R8:

+    case VT_CY:

+    case VT_DATE:

+      prop->vt = VT_EMPTY;

+      prop->wReserved1 = 0;

+      return S_OK;

+  }

+  return ::VariantClear((VARIANTARG *)prop);

+}

+

+HRESULT CPropVariant::Clear()

+{

+  return MyPropVariantClear(this);

+}

+

+HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc)

+{

+  ::VariantClear((tagVARIANT *)this);

+  switch(pSrc->vt)

+  {

+    case VT_UI1:

+    case VT_I1:

+    case VT_I2:

+    case VT_UI2:

+    case VT_BOOL:

+    case VT_I4:

+    case VT_UI4:

+    case VT_R4:

+    case VT_INT:

+    case VT_UINT:

+    case VT_ERROR:

+    case VT_FILETIME:

+    case VT_UI8:

+    case VT_R8:

+    case VT_CY:

+    case VT_DATE:

+      memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));

+      return S_OK;

+  }

+  return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));

+}

+

+

+HRESULT CPropVariant::Attach(PROPVARIANT *pSrc)

+{

+  HRESULT hr = Clear();

+  if (FAILED(hr))

+    return hr;

+  memcpy(this, pSrc, sizeof(PROPVARIANT));

+  pSrc->vt = VT_EMPTY;

+  return S_OK;

+}

+

+HRESULT CPropVariant::Detach(PROPVARIANT *pDest)

+{

+  HRESULT hr = MyPropVariantClear(pDest);

+  if (FAILED(hr))

+    return hr;

+  memcpy(pDest, this, sizeof(PROPVARIANT));

+  vt = VT_EMPTY;

+  return S_OK;

+}

+

+HRESULT CPropVariant::InternalClear()

+{

+  HRESULT hr = Clear();

+  if (FAILED(hr))

+  {

+    vt = VT_ERROR;

+    scode = hr;

+  }

+  return hr;

+}

+

+void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)

+{

+  HRESULT hr = Copy(pSrc);

+  if (FAILED(hr))

+  {

+    if (hr == E_OUTOFMEMORY)

+      throw kMemException;

+    vt = VT_ERROR;

+    scode = hr;

+  }

+}

+

+int CPropVariant::Compare(const CPropVariant &a)

+{

+  if (vt != a.vt)

+    return MyCompare(vt, a.vt);

+  switch (vt)

+  {

+    case VT_EMPTY: return 0;

+    // case VT_I1: return MyCompare(cVal, a.cVal);

+    case VT_UI1: return MyCompare(bVal, a.bVal);

+    case VT_I2: return MyCompare(iVal, a.iVal);

+    case VT_UI2: return MyCompare(uiVal, a.uiVal);

+    case VT_I4: return MyCompare(lVal, a.lVal);

+    case VT_UI4: return MyCompare(ulVal, a.ulVal);

+    // case VT_UINT: return MyCompare(uintVal, a.uintVal);

+    case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);

+    case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);

+    case VT_BOOL: return -MyCompare(boolVal, a.boolVal);

+    case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime);

+    case VT_BSTR:

+      return 0; // Not implemented

+      // return MyCompare(aPropVarint.cVal);

+    default: return 0;

+  }

+}

+

+}}

diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h
new file mode 100755
index 0000000..1605eec
--- /dev/null
+++ b/CPP/Windows/PropVariant.h
@@ -0,0 +1,56 @@
+// Windows/PropVariant.h

+

+#ifndef __WINDOWS_PROPVARIANT_H

+#define __WINDOWS_PROPVARIANT_H

+

+#include "../Common/MyWindows.h"

+#include "../Common/Types.h"

+

+namespace NWindows {

+namespace NCOM {

+

+class CPropVariant : public tagPROPVARIANT

+{

+public:

+  CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; }

+  ~CPropVariant() { Clear(); }

+  CPropVariant(const PROPVARIANT &varSrc);

+  CPropVariant(const CPropVariant &varSrc);

+  CPropVariant(BSTR bstrSrc);

+  CPropVariant(LPCOLESTR lpszSrc);

+  CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); };

+  CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; }

+  CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; }

+  CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; }

+  CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; }

+  CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; }

+  CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; }

+

+  CPropVariant& operator=(const CPropVariant &varSrc);

+  CPropVariant& operator=(const PROPVARIANT &varSrc);

+  CPropVariant& operator=(BSTR bstrSrc);

+  CPropVariant& operator=(LPCOLESTR lpszSrc);

+  CPropVariant& operator=(const char *s);

+  CPropVariant& operator=(bool bSrc);

+  CPropVariant& operator=(Byte value);

+  CPropVariant& operator=(Int16 value);

+  CPropVariant& operator=(Int32 value);

+  CPropVariant& operator=(UInt32 value);

+  CPropVariant& operator=(Int64 value);

+  CPropVariant& operator=(UInt64 value);

+  CPropVariant& operator=(const FILETIME &value);

+

+  HRESULT Clear();

+  HRESULT Copy(const PROPVARIANT *pSrc);

+  HRESULT Attach(PROPVARIANT *pSrc);

+  HRESULT Detach(PROPVARIANT *pDest);

+

+  HRESULT InternalClear();

+  void InternalCopy(const PROPVARIANT *pSrc);

+

+  int Compare(const CPropVariant &a1);

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/PropVariantConversions.cpp b/CPP/Windows/PropVariantConversions.cpp
new file mode 100755
index 0000000..9d7c2a2
--- /dev/null
+++ b/CPP/Windows/PropVariantConversions.cpp
@@ -0,0 +1,105 @@
+// PropVariantConversions.cpp

+

+#include "StdAfx.h"

+

+#include "Common/IntToString.h"

+#include "Common/StringConvert.h"

+

+#include "Windows/Defs.h"

+

+#include "PropVariantConversions.h"

+

+static UString ConvertUInt64ToString(UInt64 value)

+{

+  wchar_t buffer[32];

+  ConvertUInt64ToString(value, buffer);

+  return buffer;

+}

+

+static UString ConvertInt64ToString(Int64 value)

+{

+  wchar_t buffer[32];

+  ConvertInt64ToString(value, buffer);

+  return buffer;

+}

+

+static char *UIntToStringSpec(char c, UInt32 value, char *s, int numPos)

+{

+  if (c != 0)

+    *s++ = c;

+  char temp[16];

+  int pos = 0;

+  do

+  {

+    temp[pos++] = (char)('0' + value % 10);

+    value /= 10;

+  }

+  while (value != 0);

+  int i;

+  for (i = 0; i < numPos - pos; i++)

+    *s++ = '0';

+  do

+    *s++ = temp[--pos];

+  while (pos > 0);

+  *s = '\0';

+  return s;

+}

+

+bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds)

+{

+  s[0] = '\0';

+  SYSTEMTIME st;

+  if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))

+    return false;

+  s = UIntToStringSpec(0, st.wYear, s, 4);

+  s = UIntToStringSpec('-', st.wMonth, s, 2);

+  s = UIntToStringSpec('-', st.wDay, s, 2);

+  if (includeTime)

+  {

+    s = UIntToStringSpec(' ', st.wHour, s, 2);

+    s = UIntToStringSpec(':', st.wMinute, s, 2);

+    if (includeSeconds)

+      UIntToStringSpec(':', st.wSecond, s, 2);

+  }

+  return true;

+}

+

+UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime, bool includeSeconds)

+{

+  char s[32];

+  ConvertFileTimeToString(ft, s, includeTime, includeSeconds);

+  return GetUnicodeString(s);

+}

+ 

+

+UString ConvertPropVariantToString(const PROPVARIANT &prop)

+{

+  switch (prop.vt)

+  {

+    case VT_EMPTY: return UString();

+    case VT_BSTR: return prop.bstrVal;

+    case VT_UI1: return ConvertUInt64ToString(prop.bVal);

+    case VT_UI2: return ConvertUInt64ToString(prop.uiVal);

+    case VT_UI4: return ConvertUInt64ToString(prop.ulVal);

+    case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart);

+    case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, true, true);

+    // case VT_I1: return ConvertInt64ToString(prop.cVal);

+    case VT_I2: return ConvertInt64ToString(prop.iVal);

+    case VT_I4: return ConvertInt64ToString(prop.lVal);

+    case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart);

+    case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-";

+    default: throw 150245;

+  }

+}

+

+UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop)

+{

+  switch (prop.vt)

+  {

+    case VT_UI1: return prop.bVal;

+    case VT_UI2: return prop.uiVal;

+    case VT_UI4: return prop.ulVal;

+    case VT_UI8: return (UInt64)prop.uhVal.QuadPart;

+    default: throw 151199;

+  }

+}

diff --git a/CPP/Windows/PropVariantConversions.h b/CPP/Windows/PropVariantConversions.h
new file mode 100755
index 0000000..74139a4
--- /dev/null
+++ b/CPP/Windows/PropVariantConversions.h
@@ -0,0 +1,14 @@
+// Windows/PropVariantConversions.h

+

+#ifndef __PROP_VARIANT_CONVERSIONS_H

+#define __PROP_VARIANT_CONVERSIONS_H

+

+#include "Common/MyString.h"

+#include "Common/Types.h"

+

+bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true);

+UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true);

+UString ConvertPropVariantToString(const PROPVARIANT &prop);

+UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop);

+

+#endif

diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp
new file mode 100755
index 0000000..3db00ea
--- /dev/null
+++ b/CPP/Windows/Registry.cpp
@@ -0,0 +1,369 @@
+// Windows/Registry.cpp

+

+#include "StdAfx.h"

+

+#ifndef _UNICODE

+#include "Common/StringConvert.h"

+#endif

+#include "Windows/Registry.h"

+

+#ifndef _UNICODE

+extern bool g_IsNT;

+#endif

+

+namespace NWindows {

+namespace NRegistry {

+

+#define MYASSERT(expr) // _ASSERTE(expr)

+

+LONG CKey::Create(HKEY parentKey, LPCTSTR keyName,

+    LPTSTR keyClass, DWORD options, REGSAM accessMask,

+    LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition)

+{

+  MYASSERT(parentKey != NULL);

+  DWORD dispositionReal;

+  HKEY key = NULL;

+  LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass,

+      options, accessMask, securityAttributes, &key, &dispositionReal);

+  if (disposition != NULL)

+    *disposition = dispositionReal;

+  if (res == ERROR_SUCCESS)

+  {

+    res = Close();

+    _object = key;

+  }

+  return res;

+}

+

+LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask)

+{

+  MYASSERT(parentKey != NULL);

+  HKEY key = NULL;

+  LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key);

+  if (res == ERROR_SUCCESS)

+  {

+    res = Close();

+    MYASSERT(res == ERROR_SUCCESS);

+    _object = key;

+  }

+  return res;

+}

+

+LONG CKey::Close()

+{

+  LONG res = ERROR_SUCCESS;

+  if (_object != NULL)

+  {

+    res = RegCloseKey(_object);

+    _object = NULL;

+  }

+  return res;

+}

+

+// win95, win98: deletes sunkey and all its subkeys

+// winNT to be deleted must not have subkeys

+LONG CKey::DeleteSubKey(LPCTSTR subKeyName)

+{

+  MYASSERT(_object != NULL);

+  return RegDeleteKey(_object, subKeyName);

+}

+

+LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName)

+{

+  CKey key;

+  LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE);

+  if (res != ERROR_SUCCESS)

+    return res;

+  FILETIME fileTime;

+  const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL

+  DWORD size = kBufferSize;

+  TCHAR buffer[kBufferSize];

+  while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS)

+  {

+    res = key.RecurseDeleteKey(buffer);

+    if (res != ERROR_SUCCESS)

+      return res;

+    size = kBufferSize;

+  }

+  key.Close();

+  return DeleteSubKey(subKeyName);

+}

+

+

+/////////////////////////

+// Value Functions

+

+static inline UInt32 BoolToUINT32(bool value) {  return (value ? 1: 0); }

+static inline bool UINT32ToBool(UInt32 value) {  return (value != 0); }

+

+

+LONG CKey::DeleteValue(LPCTSTR name)

+{

+  MYASSERT(_object != NULL);

+  return ::RegDeleteValue(_object, name);

+}

+

+#ifndef _UNICODE

+LONG CKey::DeleteValue(LPCWSTR name)

+{

+  MYASSERT(_object != NULL);

+  if (g_IsNT)

+    return ::RegDeleteValueW(_object, name);

+  return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name));

+}

+#endif

+

+LONG CKey::SetValue(LPCTSTR name, UInt32 value)

+{

+  MYASSERT(_object != NULL);

+  return RegSetValueEx(_object, name, NULL, REG_DWORD,

+      (BYTE * const)&value, sizeof(UInt32));

+}

+

+LONG CKey::SetValue(LPCTSTR name, bool value)

+{

+  return SetValue(name, BoolToUINT32(value));

+}

+

+LONG CKey::SetValue(LPCTSTR name, LPCTSTR value)

+{

+  MYASSERT(value != NULL);

+  MYASSERT(_object != NULL);

+  return RegSetValueEx(_object, name, NULL, REG_SZ,

+      (const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR));

+}

+

+/*

+LONG CKey::SetValue(LPCTSTR name, const CSysString &value)

+{

+  MYASSERT(value != NULL);

+  MYASSERT(_object != NULL);

+  return RegSetValueEx(_object, name, NULL, REG_SZ,

+      (const BYTE *)(const TCHAR *)value, (value.Length() + 1) * sizeof(TCHAR));

+}

+*/

+

+#ifndef _UNICODE

+

+LONG CKey::SetValue(LPCWSTR name, LPCWSTR value)

+{

+  MYASSERT(value != NULL);

+  MYASSERT(_object != NULL);

+  if (g_IsNT)

+    return RegSetValueExW(_object, name, NULL, REG_SZ,

+      (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t)));

+  return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name),

+    value == 0 ? 0 : (LPCSTR)GetSystemString(value));

+}

+

+#endif

+

+

+LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size)

+{

+  MYASSERT(value != NULL);

+  MYASSERT(_object != NULL);

+  return RegSetValueEx(_object, name, NULL, REG_BINARY,

+      (const BYTE *)value, size);

+}

+

+LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value)

+{

+  MYASSERT(value != NULL);

+  CKey key;

+  LONG res = key.Create(parentKey, keyName);

+  if (res == ERROR_SUCCESS)

+    res = key.SetValue(valueName, value);

+  return res;

+}

+

+LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value)

+{

+  MYASSERT(value != NULL);

+  CKey key;

+  LONG res = key.Create(_object, keyName);

+  if (res == ERROR_SUCCESS)

+    res = key.SetValue(valueName, value);

+  return res;

+}

+

+LONG CKey::QueryValue(LPCTSTR name, UInt32 &value)

+{

+  DWORD type = NULL;

+  DWORD count = sizeof(DWORD);

+  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type,

+    (LPBYTE)&value, &count);

+  MYASSERT((res!=ERROR_SUCCESS) || (type == REG_DWORD));

+  MYASSERT((res!=ERROR_SUCCESS) || (count == sizeof(UInt32)));

+  return res;

+}

+

+LONG CKey::QueryValue(LPCTSTR name, bool &value)

+{

+  UInt32 uintValue = BoolToUINT32(value);

+  LONG res = QueryValue(name, uintValue);

+  value = UINT32ToBool(uintValue);

+  return res;

+}

+

+LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value)

+{

+  UInt32 newVal;

+  LONG res = QueryValue(name, newVal);

+  if (res == ERROR_SUCCESS)

+    value = newVal;

+  return res;

+}

+

+LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value)

+{

+  bool newVal;

+  LONG res = QueryValue(name, newVal);

+  if (res == ERROR_SUCCESS)

+    value = newVal;

+  return res;

+}

+

+LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count)

+{

+  MYASSERT(count != NULL);

+  DWORD type = NULL;

+  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);

+  MYASSERT((res!=ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));

+  return res;

+}

+

+LONG CKey::QueryValue(LPCTSTR name, CSysString &value)

+{

+  value.Empty();

+  DWORD type = NULL;

+  UInt32 currentSize = 0;

+  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&currentSize);

+  if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)

+    return res;

+  res = QueryValue(name, value.GetBuffer(currentSize), currentSize);

+  value.ReleaseBuffer();

+  return res;

+}

+

+#ifndef _UNICODE

+LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count)

+{

+  MYASSERT(count != NULL);

+  DWORD type = NULL;

+  LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);

+  MYASSERT((res!=ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));

+  return res;

+}

+LONG CKey::QueryValue(LPCWSTR name, UString &value)

+{

+  value.Empty();

+  DWORD type = NULL;

+  UInt32 currentSize = 0;

+

+  LONG res;

+  if (g_IsNT)

+  {

+    res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&currentSize);

+    if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)

+      return res;

+    res = QueryValue(name, value.GetBuffer(currentSize), currentSize);

+    value.ReleaseBuffer();

+  }

+  else

+  {

+    AString vTemp;

+    res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp);

+    value = GetUnicodeString(vTemp);

+  }

+  return res;

+}

+#endif

+

+LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count)

+{

+  DWORD type = NULL;

+  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);

+  MYASSERT((res!=ERROR_SUCCESS) || (type == REG_BINARY));

+  return res;

+}

+

+

+LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize)

+{

+  DWORD type = NULL;

+  dataSize = 0;

+  LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize);

+  if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)

+    return res;

+  value.SetCapacity(dataSize);

+  return QueryValue(name, (BYTE *)value, dataSize);

+}

+

+LONG CKey::EnumKeys(CSysStringVector &keyNames)

+{

+  keyNames.Clear();

+  CSysString keyName;

+  for (UInt32 index = 0; ; index++)

+  {

+    const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL

+    FILETIME lastWriteTime;

+    UInt32 nameSize = kBufferSize;

+    LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuffer(kBufferSize),

+        (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime);

+    keyName.ReleaseBuffer();

+    if (result == ERROR_NO_MORE_ITEMS)

+      break;

+    if (result != ERROR_SUCCESS)

+      return result;

+    keyNames.Add(keyName);

+  }

+  return ERROR_SUCCESS;

+}

+

+LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings)

+{

+  UInt32 numChars = 0;

+  int i;

+  for (i = 0; i < strings.Size(); i++)

+    numChars += strings[i].Length() + 1;

+  CBuffer<wchar_t> buffer;

+  buffer.SetCapacity(numChars);

+  int pos = 0;

+  for (i = 0; i < strings.Size(); i++)

+  {

+    const UString &s = strings[i];

+    MyStringCopy((wchar_t *)buffer + pos, (const wchar_t *)s);

+    pos += s.Length() + 1;

+  }

+  return SetValue(valueName, buffer, numChars * sizeof(wchar_t));

+}

+

+LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)

+{

+  strings.Clear();

+  CByteBuffer buffer;

+  UInt32 dataSize;

+  LONG res = QueryValue(valueName, buffer, dataSize);

+  if (res != ERROR_SUCCESS)

+    return res;

+  if (dataSize % sizeof(wchar_t) != 0)

+    return E_FAIL;

+  const wchar_t *data = (const wchar_t *)(const Byte  *)buffer;

+  int numChars = dataSize / sizeof(wchar_t);

+  UString s;

+  for (int i = 0; i < numChars; i++)

+  {

+    wchar_t c = data[i];

+    if (c == 0)

+    {

+      strings.Add(s);

+      s.Empty();

+    }

+    else

+      s += c;

+  }

+  return res;

+}

+

+}}

diff --git a/CPP/Windows/Registry.h b/CPP/Windows/Registry.h
new file mode 100755
index 0000000..8f4ede3
--- /dev/null
+++ b/CPP/Windows/Registry.h
@@ -0,0 +1,85 @@
+// Windows/Registry.h

+

+#ifndef __WINDOWS_REGISTRY_H

+#define __WINDOWS_REGISTRY_H

+

+#include "Common/Buffer.h"

+#include "Common/MyString.h"

+#include "Common/Types.h"

+

+namespace NWindows {

+namespace NRegistry {

+

+LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value);

+

+class CKey

+{

+  HKEY _object;

+public:

+  CKey(): _object(NULL) {}

+  ~CKey() { Close(); }

+

+  operator HKEY() const { return _object; }

+  void Attach(HKEY key) { _object = key; }

+  HKEY Detach()

+  {

+    HKEY key = _object;

+    _object = NULL;

+    return key;

+  }

+

+  LONG Create(HKEY parentKey, LPCTSTR keyName,

+      LPTSTR keyClass = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE,

+      REGSAM accessMask = KEY_ALL_ACCESS,

+      LPSECURITY_ATTRIBUTES securityAttributes = NULL,

+      LPDWORD disposition = NULL);

+  LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS);

+

+  LONG Close();

+

+  LONG DeleteSubKey(LPCTSTR subKeyName);

+  LONG RecurseDeleteKey(LPCTSTR subKeyName);

+

+  LONG DeleteValue(LPCTSTR name);

+  #ifndef _UNICODE

+  LONG DeleteValue(LPCWSTR name);

+  #endif

+

+  LONG SetValue(LPCTSTR valueName, UInt32 value);

+  LONG SetValue(LPCTSTR valueName, bool value);

+  LONG SetValue(LPCTSTR valueName, LPCTSTR value);

+  // LONG SetValue(LPCTSTR valueName, const CSysString &value);

+  #ifndef _UNICODE

+  LONG SetValue(LPCWSTR name, LPCWSTR value);

+  // LONG SetValue(LPCWSTR name, const UString &value);

+  #endif

+

+  LONG SetValue(LPCTSTR name, const void *value, UInt32 size);

+

+  LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings);

+  LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings);

+

+  LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value);

+

+  LONG QueryValue(LPCTSTR name, UInt32 &value);

+  LONG QueryValue(LPCTSTR name, bool &value);

+  LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize);

+  LONG QueryValue(LPCTSTR name, CSysString &value);

+

+  LONG GetValue_IfOk(LPCTSTR name, UInt32 &value);

+  LONG GetValue_IfOk(LPCTSTR name, bool &value);

+

+  #ifndef _UNICODE

+  LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize);

+  LONG QueryValue(LPCWSTR name, UString &value);

+  #endif

+

+  LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize);

+  LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize);

+

+  LONG EnumKeys(CSysStringVector &keyNames);

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/StdAfx.h b/CPP/Windows/StdAfx.h
new file mode 100755
index 0000000..5308d63
--- /dev/null
+++ b/CPP/Windows/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h

+

+#ifndef __STDAFX_H

+#define __STDAFX_H

+

+#include "../Common/MyWindows.h"

+#include "../Common/NewHandler.h"

+

+#endif

diff --git a/CPP/Windows/Synchronization.cpp b/CPP/Windows/Synchronization.cpp
new file mode 100755
index 0000000..01f1ad9
--- /dev/null
+++ b/CPP/Windows/Synchronization.cpp
@@ -0,0 +1,10 @@
+// Windows/Synchronization.cpp

+

+#include "StdAfx.h"

+

+#include "Synchronization.h"

+

+namespace NWindows {

+namespace NSynchronization {

+

+}}

diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h
new file mode 100755
index 0000000..786da00
--- /dev/null
+++ b/CPP/Windows/Synchronization.h
@@ -0,0 +1,164 @@
+// Windows/Synchronization.h

+

+#ifndef __WINDOWS_SYNCHRONIZATION_H

+#define __WINDOWS_SYNCHRONIZATION_H

+

+#include "../../C/Threads.h"

+

+#include "Defs.h"

+

+#ifdef _WIN32

+#include "Handle.h"

+#endif

+

+namespace NWindows {

+namespace NSynchronization {

+

+class CBaseEvent

+{

+protected:

+  ::CEvent _object;

+public:

+  bool IsCreated() { return Event_IsCreated(&_object) != 0; }

+  operator HANDLE() { return _object; }

+  CBaseEvent() { Event_Construct(&_object); }

+  ~CBaseEvent() { Close(); }

+  WRes Close() { return Event_Close(&_object); }

+  #ifdef _WIN32

+  WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL)

+  {

+    _object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name);

+    if (name == NULL && _object != 0)

+      return 0;

+    return ::GetLastError();

+  }

+  WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)

+  {

+    _object = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name);

+    if (_object != 0)

+      return 0;

+    return ::GetLastError();

+  }

+  #endif

+

+  WRes Set() { return Event_Set(&_object); }

+  // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); }

+  WRes Reset() { return Event_Reset(&_object); }

+  WRes Lock() { return Event_Wait(&_object); }

+};

+

+class CManualResetEvent: public CBaseEvent

+{

+public:

+  WRes Create(bool initiallyOwn = false)

+  {

+    return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0);

+  }

+  WRes CreateIfNotCreated()

+  {

+    if (IsCreated())

+      return 0;

+    return ManualResetEvent_CreateNotSignaled(&_object);

+  }

+  #ifdef _WIN32

+  WRes CreateWithName(bool initiallyOwn, LPCTSTR name)

+  {

+    return CBaseEvent::Create(true, initiallyOwn, name);

+  }

+  #endif

+};

+

+class CAutoResetEvent: public CBaseEvent

+{

+public:

+  WRes Create()

+  {

+    return AutoResetEvent_CreateNotSignaled(&_object);

+  }

+  WRes CreateIfNotCreated()

+  {

+    if (IsCreated())

+      return 0;

+    return AutoResetEvent_CreateNotSignaled(&_object);

+  }

+};

+

+#ifdef _WIN32

+class CObject: public CHandle

+{

+public:

+  WRes Lock(DWORD timeoutInterval = INFINITE)

+    { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); }

+};

+class CMutex: public CObject

+{

+public:

+  WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL)

+  {

+    _handle = ::CreateMutex(sa, BoolToBOOL(initiallyOwn), name);

+    if (name == NULL && _handle != 0)

+      return 0;

+    return ::GetLastError();

+  }

+  #ifndef UNDER_CE

+  WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)

+  {

+    _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name);

+    if (_handle != 0)

+      return 0;

+    return ::GetLastError();

+  }

+  #endif

+  WRes Release()

+  {

+    return ::ReleaseMutex(_handle) ? 0 : ::GetLastError();

+  }

+};

+class CMutexLock

+{

+  CMutex *_object;

+public:

+  CMutexLock(CMutex &object): _object(&object) { _object->Lock(); }

+  ~CMutexLock() { _object->Release(); }

+};

+#endif

+

+class CSemaphore

+{

+  ::CSemaphore _object;

+public:

+  CSemaphore() { Semaphore_Construct(&_object); }

+  ~CSemaphore() { Close(); }

+  WRes Close() {  return Semaphore_Close(&_object); }

+  operator HANDLE() { return _object; }

+  WRes Create(UInt32 initiallyCount, UInt32 maxCount)

+  {

+    return Semaphore_Create(&_object, initiallyCount, maxCount);

+  }

+  WRes Release() { return Semaphore_Release1(&_object); }

+  WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); }

+  WRes Lock() { return Semaphore_Wait(&_object); }

+};

+

+class CCriticalSection

+{

+  ::CCriticalSection _object;

+public:

+  CCriticalSection() { CriticalSection_Init(&_object); }

+  ~CCriticalSection() { CriticalSection_Delete(&_object); }

+  void Enter() { CriticalSection_Enter(&_object); }

+  void Leave() { CriticalSection_Leave(&_object); }

+};

+

+class CCriticalSectionLock

+{

+  CCriticalSection *_object;

+  void Unlock()  { _object->Leave(); }

+public:

+  CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); }

+  ~CCriticalSectionLock() { Unlock(); }

+};

+

+}}

+

+#endif

diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
new file mode 100755
index 0000000..545ea0e
--- /dev/null
+++ b/CPP/Windows/System.cpp
@@ -0,0 +1,72 @@
+// Windows/System.cpp

+

+#include "StdAfx.h"

+

+#include "../Common/Defs.h"

+

+#include "System.h"

+

+namespace NWindows {

+namespace NSystem {

+

+UInt32 GetNumberOfProcessors()

+{

+  SYSTEM_INFO systemInfo;

+  GetSystemInfo(&systemInfo);

+  return (UInt32)systemInfo.dwNumberOfProcessors;

+}

+

+#ifndef UNDER_CE

+

+#if !defined(_WIN64) && defined(__GNUC__)

+

+typedef struct _MY_MEMORYSTATUSEX {

+  DWORD dwLength;

+  DWORD dwMemoryLoad;

+  DWORDLONG ullTotalPhys;

+  DWORDLONG ullAvailPhys;

+  DWORDLONG ullTotalPageFile;

+  DWORDLONG ullAvailPageFile;

+  DWORDLONG ullTotalVirtual;

+  DWORDLONG ullAvailVirtual;

+  DWORDLONG ullAvailExtendedVirtual;

+} MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX;

+

+#else

+

+#define MY_MEMORYSTATUSEX MEMORYSTATUSEX

+#define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX

+

+#endif

+

+typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer);

+

+#endif

+

+UInt64 GetRamSize()

+{

+  #ifndef UNDER_CE

+  MY_MEMORYSTATUSEX stat;

+  stat.dwLength = sizeof(stat);

+  #endif

+  #ifdef _WIN64

+  if (!::GlobalMemoryStatusEx(&stat))

+    return 0;

+  return MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);

+  #else

+  #ifndef UNDER_CE

+  GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP)

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

+  if (globalMemoryStatusEx != 0 && globalMemoryStatusEx(&stat))

+    return MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);

+  #endif

+  {

+    MEMORYSTATUS stat;

+    stat.dwLength = sizeof(stat);

+    ::GlobalMemoryStatus(&stat);

+    return MyMin(stat.dwTotalVirtual, stat.dwTotalPhys);

+  }

+  #endif

+}

+

+}}

diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h
new file mode 100755
index 0000000..49a4fe7
--- /dev/null
+++ b/CPP/Windows/System.h
@@ -0,0 +1,16 @@
+// Windows/System.h

+

+#ifndef __WINDOWS_SYSTEM_H

+#define __WINDOWS_SYSTEM_H

+

+#include "../Common/Types.h"

+

+namespace NWindows {

+namespace NSystem {

+

+UInt32 GetNumberOfProcessors();

+UInt64 GetRamSize();

+

+}}

+

+#endif

diff --git a/CPP/Windows/Thread.h b/CPP/Windows/Thread.h
new file mode 100755
index 0000000..1b5863c
--- /dev/null
+++ b/CPP/Windows/Thread.h
@@ -0,0 +1,38 @@
+// Windows/Thread.h

+

+#ifndef __WINDOWS_THREAD_H

+#define __WINDOWS_THREAD_H

+

+#include "../../C/Threads.h"

+

+#include "Defs.h"

+

+namespace NWindows {

+

+class CThread

+{

+  ::CThread thread;

+public:

+  CThread() { Thread_Construct(&thread); }

+  ~CThread() { Close(); }

+  bool IsCreated() { return Thread_WasCreated(&thread) != 0; }

+  WRes Close()  { return Thread_Close(&thread); }

+  WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter)

+    { return Thread_Create(&thread, startAddress, parameter); }

+  WRes Wait() { return Thread_Wait(&thread); }

+  

+  #ifdef _WIN32

+  operator HANDLE() { return thread; }

+  void Attach(HANDLE handle) { thread = handle; }

+  HANDLE Detach() { HANDLE h = thread; thread = NULL; return h; }

+  DWORD Resume() { return ::ResumeThread(thread); }

+  DWORD Suspend() { return ::SuspendThread(thread); }

+  bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread, exitCode)); }

+  int GetPriority() { return ::GetThreadPriority(thread); }

+  bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread, priority)); }

+  #endif

+};

+

+}

+

+#endif

diff --git a/CPP/Windows/Time.cpp b/CPP/Windows/Time.cpp
new file mode 100755
index 0000000..0504cdf
--- /dev/null
+++ b/CPP/Windows/Time.cpp
@@ -0,0 +1,170 @@
+// Windows/Time.cpp

+

+#include "StdAfx.h"

+

+#include "Windows/Defs.h"

+

+#include "Time.h"

+

+namespace NWindows {

+namespace NTime {

+

+static const UInt32 kNumTimeQuantumsInSecond = 10000000;

+static const UInt32 kFileTimeStartYear = 1601;

+static const UInt32 kDosTimeStartYear = 1980;

+static const UInt32 kUnixTimeStartYear = 1970;

+static const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) *

+    60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));

+

+bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft)

+{

+  #if defined(_WIN32) && !defined(UNDER_CE)

+  return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft));

+  #else

+  ft.dwLowDateTime = 0;

+  ft.dwHighDateTime = 0;

+  UInt64 res;

+  if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F,

+      (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res))

+    return false;

+  res *= kNumTimeQuantumsInSecond;

+  ft.dwLowDateTime = (UInt32)res;

+  ft.dwHighDateTime = (UInt32)(res >> 32);

+  return true;

+  #endif

+}

+

+static const UInt32 kHighDosTime = 0xFF9FBF7D;

+static const UInt32 kLowDosTime = 0x210000;

+

+#define PERIOD_4 (4 * 365 + 1)

+#define PERIOD_100 (PERIOD_4 * 25 - 1)

+#define PERIOD_400 (PERIOD_100 * 4 + 1)

+

+bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime)

+{

+  #if defined(_WIN32) && !defined(UNDER_CE)

+

+  WORD datePart, timePart;

+  if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart))

+  {

+    dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime;

+    return false;

+  }

+  dosTime = (((UInt32)datePart) << 16) + timePart;

+

+  #else

+

+  unsigned year, mon, day, hour, min, sec;

+  UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32);

+  Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

+  unsigned temp;

+  UInt32 v;

+  v64 += (kNumTimeQuantumsInSecond * 2 - 1);

+  v64 /= kNumTimeQuantumsInSecond;

+  sec = (unsigned)(v64 % 60);

+  v64 /= 60;

+  min = (unsigned)(v64 % 60);

+  v64 /= 60;

+  hour = (unsigned)(v64 % 24);

+  v64 /= 24;

+

+  v = (UInt32)v64;

+

+  year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400);

+  v %= PERIOD_400;

+

+  temp = (unsigned)(v / PERIOD_100);

+  if (temp == 4)

+    temp = 3;

+  year += temp * 100;

+  v -= temp * PERIOD_100;

+

+  temp = v / PERIOD_4;

+  if (temp == 25)

+    temp = 24;

+  year += temp * 4;

+  v -= temp * PERIOD_4;

+

+  temp = v / 365;

+  if (temp == 4)

+    temp = 3;

+  year += temp;

+  v -= temp * 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;

+

+  dosTime = kLowDosTime;

+  if (year < kDosTimeStartYear)

+    return false;

+  year -= kDosTimeStartYear;

+  dosTime = kHighDosTime;

+  if (year >= 128)

+    return false;

+  dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1);

+  #endif

+  return true;

+}

+

+void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft)

+{

+  UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond;

+  ft.dwLowDateTime = (DWORD)v;

+  ft.dwHighDateTime = (DWORD)(v >> 32);

+}

+

+bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime)

+{

+  UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;

+  if (winTime < kUnixTimeStartValue)

+  {

+    unixTime = 0;

+    return false;

+  }

+  winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond;

+  if (winTime > 0xFFFFFFFF)

+  {

+    unixTime = 0xFFFFFFFF;

+    return false;

+  }

+  unixTime = (UInt32)winTime;

+  return true;

+}

+

+bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,

+  unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds)

+{

+  resSeconds = 0;

+  if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 ||

+      day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59)

+    return false;

+  UInt32 numYears = year - kFileTimeStartYear;

+  UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400;

+  Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

+  if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))

+    ms[1] = 29;

+  month--;

+  for (unsigned i = 0; i < month; i++)

+    numDays += ms[i];

+  numDays += day - 1;

+  resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec;

+  return true;

+}

+

+void GetCurUtcFileTime(FILETIME &ft)

+{

+  SYSTEMTIME st;

+  GetSystemTime(&st);

+  SystemTimeToFileTime(&st, &ft);

+}

+

+}}

diff --git a/CPP/Windows/Time.h b/CPP/Windows/Time.h
new file mode 100755
index 0000000..7ecb204
--- /dev/null
+++ b/CPP/Windows/Time.h
@@ -0,0 +1,21 @@
+// Windows/Time.h

+

+#ifndef __WINDOWS_TIME_H

+#define __WINDOWS_TIME_H

+

+#include "Common/Types.h"

+

+namespace NWindows {

+namespace NTime {

+

+bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime);

+bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime);

+void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime);

+bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime);

+bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,

+  unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds);

+void GetCurUtcFileTime(FILETIME &ft);

+

+}}

+

+#endif

diff --git a/CS/7zip/Common/CRC.cs b/CS/7zip/Common/CRC.cs
new file mode 100755
index 0000000..62bb847
--- /dev/null
+++ b/CS/7zip/Common/CRC.cs
@@ -0,0 +1,55 @@
+// Common/CRC.cs

+

+namespace SevenZip

+{

+	class CRC

+	{

+		public static readonly uint[] Table;

+

+		static CRC()

+		{

+			Table = new uint[256];

+			const uint kPoly = 0xEDB88320;

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

+			{

+				uint r = i;

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

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

+						r = (r >> 1) ^ kPoly;

+					else

+						r >>= 1;

+				Table[i] = r;

+			}

+		}

+

+		uint _value = 0xFFFFFFFF;

+

+		public void Init() { _value = 0xFFFFFFFF; }

+

+		public void UpdateByte(byte b)

+		{

+			_value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8);

+		}

+

+		public void Update(byte[] data, uint offset, uint size)

+		{

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

+				_value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8);

+		}

+

+		public uint GetDigest() { return _value ^ 0xFFFFFFFF; }

+

+		static uint CalculateDigest(byte[] data, uint offset, uint size)

+		{

+			CRC crc = new CRC();

+			// crc.Init();

+			crc.Update(data, offset, size);

+			return crc.GetDigest();

+		}

+

+		static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)

+		{

+			return (CalculateDigest(data, offset, size) == digest);

+		}

+	}

+}

diff --git a/CS/7zip/Common/CommandLineParser.cs b/CS/7zip/Common/CommandLineParser.cs
new file mode 100755
index 0000000..b46f6f2
--- /dev/null
+++ b/CS/7zip/Common/CommandLineParser.cs
@@ -0,0 +1,274 @@
+// CommandLineParser.cs

+

+using System;

+using System.Collections;

+

+namespace SevenZip.CommandLineParser

+{

+	public enum SwitchType

+	{

+		Simple,

+		PostMinus,

+		LimitedPostString,

+		UnLimitedPostString,

+		PostChar

+	}

+

+	public class SwitchForm

+	{

+		public string IDString;

+		public SwitchType Type;

+		public bool Multi;

+		public int MinLen;

+		public int MaxLen;

+		public string PostCharSet;

+

+		public SwitchForm(string idString, SwitchType type, bool multi,

+			int minLen, int maxLen, string postCharSet)

+		{

+			IDString = idString;

+			Type = type;

+			Multi = multi;

+			MinLen = minLen;

+			MaxLen = maxLen;

+			PostCharSet = postCharSet;

+		}

+		public SwitchForm(string idString, SwitchType type, bool multi, int minLen):

+			this(idString, type, multi, minLen, 0, "")

+		{

+		}

+		public SwitchForm(string idString, SwitchType type, bool multi):

+			this(idString, type, multi, 0)

+		{

+		}

+	}

+

+	public class SwitchResult

+	{

+		public bool ThereIs;

+		public bool WithMinus;

+		public ArrayList PostStrings = new ArrayList();

+		public int PostCharIndex;

+		public SwitchResult()

+		{

+			ThereIs = false;

+		}

+	}

+

+	public class Parser

+	{

+		public ArrayList NonSwitchStrings = new ArrayList();

+		SwitchResult[] _switches;

+

+		public Parser(int numSwitches)

+		{

+			_switches = new SwitchResult[numSwitches];

+			for (int i = 0; i < numSwitches; i++)

+				_switches[i] = new SwitchResult();

+		}

+

+		bool ParseString(string srcString, SwitchForm[] switchForms)

+		{

+			int len = srcString.Length;

+			if (len == 0)

+				return false;

+			int pos = 0;

+			if (!IsItSwitchChar(srcString[pos]))

+				return false;

+			while (pos < len)

+			{

+				if (IsItSwitchChar(srcString[pos]))

+					pos++;

+				const int kNoLen = -1;

+				int matchedSwitchIndex = 0;

+				int maxLen = kNoLen;

+				for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)

+				{

+					int switchLen = switchForms[switchIndex].IDString.Length;

+					if (switchLen <= maxLen || pos + switchLen > len)

+						continue;

+					if (String.Compare(switchForms[switchIndex].IDString, 0,

+							srcString, pos, switchLen, true) == 0)

+					{

+						matchedSwitchIndex = switchIndex;

+						maxLen = switchLen;

+					}

+				}

+				if (maxLen == kNoLen)

+					throw new Exception("maxLen == kNoLen");

+				SwitchResult matchedSwitch = _switches[matchedSwitchIndex];

+				SwitchForm switchForm = switchForms[matchedSwitchIndex];

+				if ((!switchForm.Multi) && matchedSwitch.ThereIs)

+					throw new Exception("switch must be single");

+				matchedSwitch.ThereIs = true;

+				pos += maxLen;

+				int tailSize = len - pos;

+				SwitchType type = switchForm.Type;

+				switch (type)

+				{

+					case SwitchType.PostMinus:

+						{

+							if (tailSize == 0)

+								matchedSwitch.WithMinus = false;

+							else

+							{

+								matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus);

+								if (matchedSwitch.WithMinus)

+									pos++;

+							}

+							break;

+						}

+					case SwitchType.PostChar:

+						{

+							if (tailSize < switchForm.MinLen)

+								throw new Exception("switch is not full");

+							string charSet = switchForm.PostCharSet;

+							const int kEmptyCharValue = -1;

+							if (tailSize == 0)

+								matchedSwitch.PostCharIndex = kEmptyCharValue;

+							else

+							{

+								int index = charSet.IndexOf(srcString[pos]);

+								if (index < 0)

+									matchedSwitch.PostCharIndex = kEmptyCharValue;

+								else

+								{

+									matchedSwitch.PostCharIndex = index;

+									pos++;

+								}

+							}

+							break;

+						}

+					case SwitchType.LimitedPostString:

+					case SwitchType.UnLimitedPostString:

+						{

+							int minLen = switchForm.MinLen;

+							if (tailSize < minLen)

+								throw new Exception("switch is not full");

+							if (type == SwitchType.UnLimitedPostString)

+							{

+								matchedSwitch.PostStrings.Add(srcString.Substring(pos));

+								return true;

+							}

+							String stringSwitch = srcString.Substring(pos, minLen);

+							pos += minLen;

+							for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)

+							{

+								char c = srcString[pos];

+								if (IsItSwitchChar(c))

+									break;

+								stringSwitch += c;

+							}

+							matchedSwitch.PostStrings.Add(stringSwitch);

+							break;

+						}

+				}

+			}

+			return true;

+

+		}

+

+		public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)

+		{

+			int numCommandStrings = commandStrings.Length;

+			bool stopSwitch = false;

+			for (int i = 0; i < numCommandStrings; i++)

+			{

+				string s = commandStrings[i];

+				if (stopSwitch)

+					NonSwitchStrings.Add(s);

+				else

+					if (s == kStopSwitchParsing)

+					stopSwitch = true;

+				else

+					if (!ParseString(s, switchForms))

+					NonSwitchStrings.Add(s);

+			}

+		}

+

+		public SwitchResult this[int index] { get { return _switches[index]; } }

+

+		public static int ParseCommand(CommandForm[] commandForms, string commandString,

+			out string postString)

+		{

+			for (int i = 0; i < commandForms.Length; i++)

+			{

+				string id = commandForms[i].IDString;

+				if (commandForms[i].PostStringMode)

+				{

+					if (commandString.IndexOf(id) == 0)

+					{

+						postString = commandString.Substring(id.Length);

+						return i;

+					}

+				}

+				else

+					if (commandString == id)

+				{

+					postString = "";

+					return i;

+				}

+			}

+			postString = "";

+			return -1;

+		}

+

+		static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,

+			string commandString, ArrayList indices)

+		{

+			indices.Clear();

+			int numUsedChars = 0;

+			for (int i = 0; i < numForms; i++)

+			{

+				CommandSubCharsSet charsSet = forms[i];

+				int currentIndex = -1;

+				int len = charsSet.Chars.Length;

+				for (int j = 0; j < len; j++)

+				{

+					char c = charsSet.Chars[j];

+					int newIndex = commandString.IndexOf(c);

+					if (newIndex >= 0)

+					{

+						if (currentIndex >= 0)

+							return false;

+						if (commandString.IndexOf(c, newIndex + 1) >= 0)

+							return false;

+						currentIndex = j;

+						numUsedChars++;

+					}

+				}

+				if (currentIndex == -1 && !charsSet.EmptyAllowed)

+					return false;

+				indices.Add(currentIndex);

+			}

+			return (numUsedChars == commandString.Length);

+		}

+		const char kSwitchID1 = '-';

+		const char kSwitchID2 = '/';

+

+		const char kSwitchMinus = '-';

+		const string kStopSwitchParsing = "--";

+

+		static bool IsItSwitchChar(char c)

+		{

+			return (c == kSwitchID1 || c == kSwitchID2);

+		}

+	}

+

+	public class CommandForm

+	{

+		public string IDString = "";

+		public bool PostStringMode = false;

+		public CommandForm(string idString, bool postStringMode)

+		{

+			IDString = idString;

+			PostStringMode = postStringMode;

+		}

+	}

+

+	class CommandSubCharsSet

+	{

+		public string Chars = "";

+		public bool EmptyAllowed = false;

+	}

+}

diff --git a/CS/7zip/Common/InBuffer.cs b/CS/7zip/Common/InBuffer.cs
new file mode 100755
index 0000000..9c47c73
--- /dev/null
+++ b/CS/7zip/Common/InBuffer.cs
@@ -0,0 +1,72 @@
+// InBuffer.cs

+

+namespace SevenZip.Buffer

+{

+	public class InBuffer

+	{

+		byte[] m_Buffer;

+		uint m_Pos;

+		uint m_Limit;

+		uint m_BufferSize;

+		System.IO.Stream m_Stream;

+		bool m_StreamWasExhausted;

+		ulong m_ProcessedSize;

+

+		public InBuffer(uint bufferSize)

+		{

+			m_Buffer = new byte[bufferSize];

+			m_BufferSize = bufferSize;

+		}

+

+		public void Init(System.IO.Stream stream)

+		{

+			m_Stream = stream;

+			m_ProcessedSize = 0;

+			m_Limit = 0;

+			m_Pos = 0;

+			m_StreamWasExhausted = false;

+		}

+

+		public bool ReadBlock()

+		{

+			if (m_StreamWasExhausted)

+				return false;

+			m_ProcessedSize += m_Pos;

+			int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);

+			m_Pos = 0;

+			m_Limit = (uint)aNumProcessedBytes;

+			m_StreamWasExhausted = (aNumProcessedBytes == 0);

+			return (!m_StreamWasExhausted);

+		}

+

+

+		public void ReleaseStream()

+		{

+			// m_Stream.Close(); 

+			m_Stream = null;

+		}

+

+		public bool ReadByte(byte b) // check it

+		{

+			if (m_Pos >= m_Limit)

+				if (!ReadBlock())

+					return false;

+			b = m_Buffer[m_Pos++];

+			return true;

+		}

+

+		public byte ReadByte()

+		{

+			// return (byte)m_Stream.ReadByte();

+			if (m_Pos >= m_Limit)

+				if (!ReadBlock())

+					return 0xFF;

+			return m_Buffer[m_Pos++];

+		}

+

+		public ulong GetProcessedSize()

+		{

+			return m_ProcessedSize + m_Pos;

+		}

+	}

+}

diff --git a/CS/7zip/Common/OutBuffer.cs b/CS/7zip/Common/OutBuffer.cs
new file mode 100755
index 0000000..c205aa6
--- /dev/null
+++ b/CS/7zip/Common/OutBuffer.cs
@@ -0,0 +1,47 @@
+// OutBuffer.cs

+

+namespace SevenZip.Buffer

+{

+	public class OutBuffer

+	{

+		byte[] m_Buffer;

+		uint m_Pos;

+		uint m_BufferSize;

+		System.IO.Stream m_Stream;

+		ulong m_ProcessedSize;

+

+		public OutBuffer(uint bufferSize)

+		{

+			m_Buffer = new byte[bufferSize];

+			m_BufferSize = bufferSize;

+		}

+

+		public void SetStream(System.IO.Stream stream) { m_Stream = stream; }

+		public void FlushStream() { m_Stream.Flush(); }

+		public void CloseStream() { m_Stream.Close(); }

+		public void ReleaseStream() { m_Stream = null; }

+

+		public void Init()

+		{

+			m_ProcessedSize = 0;

+			m_Pos = 0;

+		}

+

+		public void WriteByte(byte b)

+		{

+			m_Buffer[m_Pos++] = b;

+			if (m_Pos >= m_BufferSize)

+				FlushData();

+		}

+

+		public void FlushData()

+		{

+			if (m_Pos == 0)

+				return;

+			m_Stream.Write(m_Buffer, 0, (int)m_Pos);

+			m_Pos = 0;

+		}

+

+		public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; }

+	}

+}

diff --git a/CS/7zip/Compress/LZ/IMatchFinder.cs b/CS/7zip/Compress/LZ/IMatchFinder.cs
new file mode 100755
index 0000000..30fab86
--- /dev/null
+++ b/CS/7zip/Compress/LZ/IMatchFinder.cs
@@ -0,0 +1,24 @@
+// IMatchFinder.cs

+

+using System;

+

+namespace SevenZip.Compression.LZ

+{

+	interface IInWindowStream

+	{

+		void SetStream(System.IO.Stream inStream);

+		void Init();

+		void ReleaseStream();

+		Byte GetIndexByte(Int32 index);

+		UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);

+		UInt32 GetNumAvailableBytes();

+	}

+

+	interface IMatchFinder : IInWindowStream

+	{

+		void Create(UInt32 historySize, UInt32 keepAddBufferBefore,

+				UInt32 matchMaxLen, UInt32 keepAddBufferAfter);

+		UInt32 GetMatches(UInt32[] distances);

+		void Skip(UInt32 num);

+	}

+}

diff --git a/CS/7zip/Compress/LZ/LzBinTree.cs b/CS/7zip/Compress/LZ/LzBinTree.cs
new file mode 100755
index 0000000..7a9ca20
--- /dev/null
+++ b/CS/7zip/Compress/LZ/LzBinTree.cs
@@ -0,0 +1,367 @@
+// LzBinTree.cs

+

+using System;

+

+namespace SevenZip.Compression.LZ

+{

+	public class BinTree : InWindow, IMatchFinder

+	{

+		UInt32 _cyclicBufferPos;

+		UInt32 _cyclicBufferSize = 0;

+		UInt32 _matchMaxLen;

+

+		UInt32[] _son;

+		UInt32[] _hash;

+

+		UInt32 _cutValue = 0xFF;

+		UInt32 _hashMask;

+		UInt32 _hashSizeSum = 0;

+

+		bool HASH_ARRAY = true;

+

+		const UInt32 kHash2Size = 1 << 10;

+		const UInt32 kHash3Size = 1 << 16;

+		const UInt32 kBT2HashSize = 1 << 16;

+		const UInt32 kStartMaxLen = 1;

+		const UInt32 kHash3Offset = kHash2Size;

+		const UInt32 kEmptyHashValue = 0;

+		const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;

+	

+		UInt32 kNumHashDirectBytes = 0;

+		UInt32 kMinMatchCheck = 4;

+		UInt32 kFixHashSize = kHash2Size + kHash3Size;

+		

+		public void SetType(int numHashBytes)

+		{

+			HASH_ARRAY = (numHashBytes > 2);

+			if (HASH_ARRAY)

+			{

+				kNumHashDirectBytes = 0;

+				kMinMatchCheck = 4;

+				kFixHashSize = kHash2Size + kHash3Size;

+			}

+			else

+			{

+				kNumHashDirectBytes = 2;

+				kMinMatchCheck = 2 + 1;

+				kFixHashSize = 0;

+			}

+		}

+

+		public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }

+		public new void ReleaseStream() { base.ReleaseStream(); }

+		

+		public new void Init()

+		{

+			base.Init();

+			for (UInt32 i = 0; i < _hashSizeSum; i++)

+				_hash[i] = kEmptyHashValue;

+			_cyclicBufferPos = 0;

+			ReduceOffsets(-1);

+		}

+

+		public new void MovePos()

+		{

+			if (++_cyclicBufferPos >= _cyclicBufferSize)

+				_cyclicBufferPos = 0;

+			base.MovePos();

+			if (_pos == kMaxValForNormalize)

+				Normalize();

+		}

+

+		public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }

+

+		public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)

+		{ return base.GetMatchLen(index, distance, limit); }

+

+		public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }

+

+		public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,

+				UInt32 matchMaxLen, UInt32 keepAddBufferAfter)

+		{

+			if (historySize > kMaxValForNormalize - 256)

+				throw new Exception();

+			_cutValue = 16 + (matchMaxLen >> 1);

+				

+			UInt32 windowReservSize = (historySize + keepAddBufferBefore +

+					matchMaxLen + keepAddBufferAfter) / 2 + 256;

+

+			base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);

+

+			_matchMaxLen = matchMaxLen;

+

+			UInt32 cyclicBufferSize = historySize + 1;

+			if (_cyclicBufferSize != cyclicBufferSize)

+				_son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];

+

+			UInt32 hs = kBT2HashSize;

+

+			if (HASH_ARRAY)

+			{

+				hs = historySize - 1;

+				hs |= (hs >> 1);

+				hs |= (hs >> 2);

+				hs |= (hs >> 4);

+				hs |= (hs >> 8);

+				hs >>= 1;

+				hs |= 0xFFFF;

+				if (hs > (1 << 24))

+					hs >>= 1;

+				_hashMask = hs;

+				hs++;

+				hs += kFixHashSize;

+			}

+			if (hs != _hashSizeSum)

+				_hash = new UInt32[_hashSizeSum = hs];

+		}

+

+		public UInt32 GetMatches(UInt32[] distances)

+		{

+			UInt32 lenLimit;

+			if (_pos + _matchMaxLen <= _streamPos)

+				lenLimit = _matchMaxLen;

+			else

+			{

+				lenLimit = _streamPos - _pos;

+				if (lenLimit < kMinMatchCheck)

+				{

+					MovePos();

+					return 0;

+				}

+			}

+

+			UInt32 offset = 0;

+			UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;

+			UInt32 cur = _bufferOffset + _pos;

+			UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;

+			UInt32 hashValue, hash2Value = 0, hash3Value = 0;

+

+			if (HASH_ARRAY)

+			{

+				UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];

+				hash2Value = temp & (kHash2Size - 1);

+				temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);

+				hash3Value = temp & (kHash3Size - 1);

+				hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;

+			}

+			else

+				hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);

+

+			UInt32 curMatch = _hash[kFixHashSize + hashValue];

+			if (HASH_ARRAY)

+			{

+				UInt32 curMatch2 = _hash[hash2Value];

+				UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];

+				_hash[hash2Value] = _pos;

+				_hash[kHash3Offset + hash3Value] = _pos;

+				if (curMatch2 > matchMinPos)

+					if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])

+					{

+						distances[offset++] = maxLen = 2;

+						distances[offset++] = _pos - curMatch2 - 1;

+					}

+				if (curMatch3 > matchMinPos)

+					if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])

+					{

+						if (curMatch3 == curMatch2)

+							offset -= 2;

+						distances[offset++] = maxLen = 3;

+						distances[offset++] = _pos - curMatch3 - 1;

+						curMatch2 = curMatch3;

+					}

+				if (offset != 0 && curMatch2 == curMatch)

+				{

+					offset -= 2;

+					maxLen = kStartMaxLen;

+				}

+			}

+

+			_hash[kFixHashSize + hashValue] = _pos;

+

+			UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;

+			UInt32 ptr1 = (_cyclicBufferPos << 1);

+

+			UInt32 len0, len1;

+			len0 = len1 = kNumHashDirectBytes;

+			

+			if (kNumHashDirectBytes != 0)

+			{

+				if (curMatch > matchMinPos)

+				{

+					if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=

+							_bufferBase[cur + kNumHashDirectBytes])

+					{

+						distances[offset++] = maxLen = kNumHashDirectBytes;

+						distances[offset++] = _pos - curMatch - 1;

+					}

+				}

+			}

+			

+			UInt32 count = _cutValue;

+			

+			while(true)

+			{

+				if(curMatch <= matchMinPos || count-- == 0)

+				{

+					_son[ptr0] = _son[ptr1] = kEmptyHashValue;

+					break;

+				}

+				UInt32 delta = _pos - curMatch;

+				UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?

+							(_cyclicBufferPos - delta) :

+							(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;

+

+				UInt32 pby1 = _bufferOffset + curMatch;

+				UInt32 len = Math.Min(len0, len1);

+				if (_bufferBase[pby1 + len] == _bufferBase[cur + len])

+				{

+					while(++len != lenLimit)

+						if (_bufferBase[pby1 + len] != _bufferBase[cur + len])

+							break;

+					if (maxLen < len)

+					{

+						distances[offset++] = maxLen = len;

+						distances[offset++] = delta - 1;

+						if (len == lenLimit)

+						{

+							_son[ptr1] = _son[cyclicPos];

+							_son[ptr0] = _son[cyclicPos + 1];

+							break;

+						}

+					}

+				}

+				if (_bufferBase[pby1 + len] < _bufferBase[cur + len])

+				{

+					_son[ptr1] = curMatch;

+					ptr1 = cyclicPos + 1;

+					curMatch = _son[ptr1];

+					len1 = len;

+				}

+				else

+				{

+					_son[ptr0] = curMatch;

+					ptr0 = cyclicPos;

+					curMatch = _son[ptr0];

+					len0 = len;

+				}

+			}

+			MovePos();

+			return offset;

+		}

+

+		public void Skip(UInt32 num)

+		{

+			do

+			{

+				UInt32 lenLimit;

+				if (_pos + _matchMaxLen <= _streamPos)

+					lenLimit = _matchMaxLen;

+				else

+				{

+					lenLimit = _streamPos - _pos;

+					if (lenLimit < kMinMatchCheck)

+					{

+						MovePos();

+						continue;

+					}

+				}

+

+				UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;

+				UInt32 cur = _bufferOffset + _pos;

+

+				UInt32 hashValue;

+

+				if (HASH_ARRAY)

+				{

+					UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];

+					UInt32 hash2Value = temp & (kHash2Size - 1);

+					_hash[hash2Value] = _pos;

+					temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);

+					UInt32 hash3Value = temp & (kHash3Size - 1);

+					_hash[kHash3Offset + hash3Value] = _pos;

+					hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;

+				}

+				else

+					hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);

+

+				UInt32 curMatch = _hash[kFixHashSize + hashValue];

+				_hash[kFixHashSize + hashValue] = _pos;

+

+				UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;

+				UInt32 ptr1 = (_cyclicBufferPos << 1);

+

+				UInt32 len0, len1;

+				len0 = len1 = kNumHashDirectBytes;

+

+				UInt32 count = _cutValue;

+				while (true)

+				{

+					if (curMatch <= matchMinPos || count-- == 0)

+					{

+						_son[ptr0] = _son[ptr1] = kEmptyHashValue;

+						break;

+					}

+

+					UInt32 delta = _pos - curMatch;

+					UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?

+								(_cyclicBufferPos - delta) :

+								(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;

+

+					UInt32 pby1 = _bufferOffset + curMatch;

+					UInt32 len = Math.Min(len0, len1);

+					if (_bufferBase[pby1 + len] == _bufferBase[cur + len])

+					{

+						while (++len != lenLimit)

+							if (_bufferBase[pby1 + len] != _bufferBase[cur + len])

+								break;

+						if (len == lenLimit)

+						{

+							_son[ptr1] = _son[cyclicPos];

+							_son[ptr0] = _son[cyclicPos + 1];

+							break;

+						}

+					}

+					if (_bufferBase[pby1 + len] < _bufferBase[cur + len])

+					{

+						_son[ptr1] = curMatch;

+						ptr1 = cyclicPos + 1;

+						curMatch = _son[ptr1];

+						len1 = len;

+					}

+					else

+					{

+						_son[ptr0] = curMatch;

+						ptr0 = cyclicPos;

+						curMatch = _son[ptr0];

+						len0 = len;

+					}

+				}

+				MovePos();

+			}

+			while (--num != 0);

+		}

+

+		void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)

+		{

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

+			{

+				UInt32 value = items[i];

+				if (value <= subValue)

+					value = kEmptyHashValue;

+				else

+					value -= subValue;

+				items[i] = value;

+			}

+		}

+

+		void Normalize()

+		{

+			UInt32 subValue = _pos - _cyclicBufferSize;

+			NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);

+			NormalizeLinks(_hash, _hashSizeSum, subValue);

+			ReduceOffsets((Int32)subValue);

+		}

+

+		public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }

+	}

+}

diff --git a/CS/7zip/Compress/LZ/LzInWindow.cs b/CS/7zip/Compress/LZ/LzInWindow.cs
new file mode 100755
index 0000000..f1974ce
--- /dev/null
+++ b/CS/7zip/Compress/LZ/LzInWindow.cs
@@ -0,0 +1,132 @@
+// LzInWindow.cs

+

+using System;

+

+namespace SevenZip.Compression.LZ

+{

+	public class InWindow

+	{

+		public Byte[] _bufferBase = null; // pointer to buffer with data

+		System.IO.Stream _stream;

+		UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done

+		bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream

+

+		UInt32 _pointerToLastSafePosition;

+

+		public UInt32 _bufferOffset;

+

+		public UInt32 _blockSize; // Size of Allocated memory block

+		public UInt32 _pos; // offset (from _buffer) of curent byte

+		UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos

+		UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos

+		public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream

+

+		public void MoveBlock()

+		{

+			UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore;

+			// we need one additional byte, since MovePos moves on 1 byte.

+			if (offset > 0)

+				offset--;

+			

+			UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset;

+

+			// check negative offset ????

+			for (UInt32 i = 0; i < numBytes; i++)

+				_bufferBase[i] = _bufferBase[offset + i];

+			_bufferOffset -= offset;

+		}

+

+		public virtual void ReadBlock()

+		{

+			if (_streamEndWasReached)

+				return;

+			while (true)

+			{

+				int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos);

+				if (size == 0)

+					return;

+				int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);

+				if (numReadBytes == 0)

+				{

+					_posLimit = _streamPos;

+					UInt32 pointerToPostion = _bufferOffset + _posLimit;

+					if (pointerToPostion > _pointerToLastSafePosition)

+						_posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset);

+

+					_streamEndWasReached = true;

+					return;

+				}

+				_streamPos += (UInt32)numReadBytes;

+				if (_streamPos >= _pos + _keepSizeAfter)

+					_posLimit = _streamPos - _keepSizeAfter;

+			}

+		}

+

+		void Free() { _bufferBase = null; }

+

+		public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)

+		{

+			_keepSizeBefore = keepSizeBefore;

+			_keepSizeAfter = keepSizeAfter;

+			UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;

+			if (_bufferBase == null || _blockSize != blockSize)

+			{

+				Free();

+				_blockSize = blockSize;

+				_bufferBase = new Byte[_blockSize];

+			}

+			_pointerToLastSafePosition = _blockSize - keepSizeAfter;

+		}

+

+		public void SetStream(System.IO.Stream stream) { _stream = stream; }

+		public void ReleaseStream() { _stream = null; }

+

+		public void Init()

+		{

+			_bufferOffset = 0;

+			_pos = 0;

+			_streamPos = 0;

+			_streamEndWasReached = false;

+			ReadBlock();

+		}

+

+		public void MovePos()

+		{

+			_pos++;

+			if (_pos > _posLimit)

+			{

+				UInt32 pointerToPostion = _bufferOffset + _pos;

+				if (pointerToPostion > _pointerToLastSafePosition)

+					MoveBlock();

+				ReadBlock();

+			}

+		}

+

+		public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }

+

+		// index + limit have not to exceed _keepSizeAfter;

+		public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)

+		{

+			if (_streamEndWasReached)

+				if ((_pos + index) + limit > _streamPos)

+					limit = _streamPos - (UInt32)(_pos + index);

+			distance++;

+			// Byte *pby = _buffer + (size_t)_pos + index;

+			UInt32 pby = _bufferOffset + _pos + (UInt32)index;

+

+			UInt32 i;

+			for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);

+			return i;

+		}

+

+		public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }

+

+		public void ReduceOffsets(Int32 subValue)

+		{

+			_bufferOffset += (UInt32)subValue;

+			_posLimit -= (UInt32)subValue;

+			_pos -= (UInt32)subValue;

+			_streamPos -= (UInt32)subValue;

+		}

+	}

+}

diff --git a/CS/7zip/Compress/LZ/LzOutWindow.cs b/CS/7zip/Compress/LZ/LzOutWindow.cs
new file mode 100755
index 0000000..84914f0
--- /dev/null
+++ b/CS/7zip/Compress/LZ/LzOutWindow.cs
@@ -0,0 +1,110 @@
+// LzOutWindow.cs

+

+namespace SevenZip.Compression.LZ

+{

+	public class OutWindow

+	{

+		byte[] _buffer = null;

+		uint _pos;

+		uint _windowSize = 0;

+		uint _streamPos;

+		System.IO.Stream _stream;

+

+		public uint TrainSize = 0;

+

+		public void Create(uint windowSize)

+		{

+			if (_windowSize != windowSize)

+			{

+				// System.GC.Collect();

+				_buffer = new byte[windowSize];

+			}

+			_windowSize = windowSize;

+			_pos = 0;

+			_streamPos = 0;

+		}

+

+		public void Init(System.IO.Stream stream, bool solid)

+		{

+			ReleaseStream();

+			_stream = stream;

+			if (!solid)

+			{

+				_streamPos = 0;

+				_pos = 0;

+				TrainSize = 0;

+			}

+		}

+	

+		public bool Train(System.IO.Stream stream)

+		{

+			long len = stream.Length;

+			uint size = (len < _windowSize) ? (uint)len : _windowSize;

+			TrainSize = size;

+			stream.Position = len - size;

+			_streamPos = _pos = 0;

+			while (size > 0)

+			{

+				uint curSize = _windowSize - _pos;

+				if (size < curSize)

+					curSize = size;

+				int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);

+				if (numReadBytes == 0)

+					return false;

+				size -= (uint)numReadBytes;

+				_pos += (uint)numReadBytes;

+				_streamPos += (uint)numReadBytes;

+				if (_pos == _windowSize)

+					_streamPos = _pos = 0;

+			}

+			return true;

+		}

+

+		public void ReleaseStream()

+		{

+			Flush();

+			_stream = null;

+		}

+

+		public void Flush()

+		{

+			uint size = _pos - _streamPos;

+			if (size == 0)

+				return;

+			_stream.Write(_buffer, (int)_streamPos, (int)size);

+			if (_pos >= _windowSize)

+				_pos = 0;

+			_streamPos = _pos;

+		}

+

+		public void CopyBlock(uint distance, uint len)

+		{

+			uint pos = _pos - distance - 1;

+			if (pos >= _windowSize)

+				pos += _windowSize;

+			for (; len > 0; len--)

+			{

+				if (pos >= _windowSize)

+					pos = 0;

+				_buffer[_pos++] = _buffer[pos++];

+				if (_pos >= _windowSize)

+					Flush();

+			}

+		}

+

+		public void PutByte(byte b)

+		{

+			_buffer[_pos++] = b;

+			if (_pos >= _windowSize)

+				Flush();

+		}

+

+		public byte GetByte(uint distance)

+		{

+			uint pos = _pos - distance - 1;

+			if (pos >= _windowSize)

+				pos += _windowSize;

+			return _buffer[pos];

+		}

+	}

+}

diff --git a/CS/7zip/Compress/LZMA/LzmaBase.cs b/CS/7zip/Compress/LZMA/LzmaBase.cs
new file mode 100755
index 0000000..8447a2a
--- /dev/null
+++ b/CS/7zip/Compress/LZMA/LzmaBase.cs
@@ -0,0 +1,76 @@
+// LzmaBase.cs

+

+namespace SevenZip.Compression.LZMA

+{

+	internal abstract class Base

+	{

+		public const uint kNumRepDistances = 4;

+		public const uint kNumStates = 12;

+

+		// static byte []kLiteralNextStates  = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};

+		// static byte []kMatchNextStates    = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};

+		// static byte []kRepNextStates      = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};

+		// static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};

+

+		public struct State

+		{

+			public uint Index;

+			public void Init() { Index = 0; }

+			public void UpdateChar()

+			{

+				if (Index < 4) Index = 0;

+				else if (Index < 10) Index -= 3;

+				else Index -= 6;

+			}

+			public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }

+			public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }

+			public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }

+			public bool IsCharState() { return Index < 7; }

+		}

+

+		public const int kNumPosSlotBits = 6;

+		public const int kDicLogSizeMin = 0;

+		// public const int kDicLogSizeMax = 30;

+		// public const uint kDistTableSizeMax = kDicLogSizeMax * 2;

+

+		public const int kNumLenToPosStatesBits = 2; // it's for speed optimization

+		public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;

+

+		public const uint kMatchMinLen = 2;

+

+		public static uint GetLenToPosState(uint len)

+		{

+			len -= kMatchMinLen;

+			if (len < kNumLenToPosStates)

+				return len;

+			return (uint)(kNumLenToPosStates - 1);

+		}

+

+		public const int kNumAlignBits = 4;

+		public const uint kAlignTableSize = 1 << kNumAlignBits;

+		public const uint kAlignMask = (kAlignTableSize - 1);

+

+		public const uint kStartPosModelIndex = 4;

+		public const uint kEndPosModelIndex = 14;

+		public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;

+

+		public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);

+

+		public const uint kNumLitPosStatesBitsEncodingMax = 4;

+		public const uint kNumLitContextBitsMax = 8;

+

+		public const int kNumPosStatesBitsMax = 4;

+		public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax);

+		public const int kNumPosStatesBitsEncodingMax = 4;

+		public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);

+

+		public const int kNumLowLenBits = 3;

+		public const int kNumMidLenBits = 3;

+		public const int kNumHighLenBits = 8;

+		public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;

+		public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;

+		public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +

+				(1 << kNumHighLenBits);

+		public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;

+	}

+}

diff --git a/CS/7zip/Compress/LZMA/LzmaDecoder.cs b/CS/7zip/Compress/LZMA/LzmaDecoder.cs
new file mode 100755
index 0000000..00bfe63
--- /dev/null
+++ b/CS/7zip/Compress/LZMA/LzmaDecoder.cs
@@ -0,0 +1,398 @@
+// LzmaDecoder.cs

+

+using System;

+

+namespace SevenZip.Compression.LZMA

+{

+	using RangeCoder;

+

+	public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream

+	{

+		class LenDecoder

+		{

+			BitDecoder m_Choice = new BitDecoder();

+			BitDecoder m_Choice2 = new BitDecoder();

+			BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];

+			BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];

+			BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);

+			uint m_NumPosStates = 0;

+

+			public void Create(uint numPosStates)

+			{

+				for (uint posState = m_NumPosStates; posState < numPosStates; posState++)

+				{

+					m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);

+					m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);

+				}

+				m_NumPosStates = numPosStates;

+			}

+

+			public void Init()

+			{

+				m_Choice.Init();

+				for (uint posState = 0; posState < m_NumPosStates; posState++)

+				{

+					m_LowCoder[posState].Init();

+					m_MidCoder[posState].Init();

+				}

+				m_Choice2.Init();

+				m_HighCoder.Init();

+			}

+

+			public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)

+			{

+				if (m_Choice.Decode(rangeDecoder) == 0)

+					return m_LowCoder[posState].Decode(rangeDecoder);

+				else

+				{

+					uint symbol = Base.kNumLowLenSymbols;

+					if (m_Choice2.Decode(rangeDecoder) == 0)

+						symbol += m_MidCoder[posState].Decode(rangeDecoder);

+					else

+					{

+						symbol += Base.kNumMidLenSymbols;

+						symbol += m_HighCoder.Decode(rangeDecoder);

+					}

+					return symbol;

+				}

+			}

+		}

+

+		class LiteralDecoder

+		{

+			struct Decoder2

+			{

+				BitDecoder[] m_Decoders;

+				public void Create() { m_Decoders = new BitDecoder[0x300]; }

+				public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); }

+

+				public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)

+				{

+					uint symbol = 1;

+					do

+						symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);

+					while (symbol < 0x100);

+					return (byte)symbol;

+				}

+

+				public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)

+				{

+					uint symbol = 1;

+					do

+					{

+						uint matchBit = (uint)(matchByte >> 7) & 1;

+						matchByte <<= 1;

+						uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);

+						symbol = (symbol << 1) | bit;

+						if (matchBit != bit)

+						{

+							while (symbol < 0x100)

+								symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);

+							break;

+						}

+					}

+					while (symbol < 0x100);

+					return (byte)symbol;

+				}

+			}

+

+			Decoder2[] m_Coders;

+			int m_NumPrevBits;

+			int m_NumPosBits;

+			uint m_PosMask;

+

+			public void Create(int numPosBits, int numPrevBits)

+			{

+				if (m_Coders != null && m_NumPrevBits == numPrevBits &&

+					m_NumPosBits == numPosBits)

+					return;

+				m_NumPosBits = numPosBits;

+				m_PosMask = ((uint)1 << numPosBits) - 1;

+				m_NumPrevBits = numPrevBits;

+				uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);

+				m_Coders = new Decoder2[numStates];

+				for (uint i = 0; i < numStates; i++)

+					m_Coders[i].Create();

+			}

+

+			public void Init()

+			{

+				uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);

+				for (uint i = 0; i < numStates; i++)

+					m_Coders[i].Init();

+			}

+

+			uint GetState(uint pos, byte prevByte)

+			{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }

+

+			public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)

+			{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }

+

+			public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)

+			{ return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }

+		};

+

+		LZ.OutWindow m_OutWindow = new LZ.OutWindow();

+		RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder();

+

+		BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];

+		BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];

+		BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];

+		BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];

+		BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];

+		BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];

+

+		BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];

+		BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];

+

+		BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);

+

+		LenDecoder m_LenDecoder = new LenDecoder();

+		LenDecoder m_RepLenDecoder = new LenDecoder();

+

+		LiteralDecoder m_LiteralDecoder = new LiteralDecoder();

+

+		uint m_DictionarySize;

+		uint m_DictionarySizeCheck;

+

+		uint m_PosStateMask;

+

+		public Decoder()

+		{

+			m_DictionarySize = 0xFFFFFFFF;

+			for (int i = 0; i < Base.kNumLenToPosStates; i++)

+				m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);

+		}

+

+		void SetDictionarySize(uint dictionarySize)

+		{

+			if (m_DictionarySize != dictionarySize)

+			{

+				m_DictionarySize = dictionarySize;

+				m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);

+				uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12));

+				m_OutWindow.Create(blockSize);

+			}

+		}

+

+		void SetLiteralProperties(int lp, int lc)

+		{

+			if (lp > 8)

+				throw new InvalidParamException();

+			if (lc > 8)

+				throw new InvalidParamException();

+			m_LiteralDecoder.Create(lp, lc);

+		}

+

+		void SetPosBitsProperties(int pb)

+		{

+			if (pb > Base.kNumPosStatesBitsMax)

+				throw new InvalidParamException();

+			uint numPosStates = (uint)1 << pb;

+			m_LenDecoder.Create(numPosStates);

+			m_RepLenDecoder.Create(numPosStates);

+			m_PosStateMask = numPosStates - 1;

+		}

+

+		bool _solid = false;

+		void Init(System.IO.Stream inStream, System.IO.Stream outStream)

+		{

+			m_RangeDecoder.Init(inStream);

+			m_OutWindow.Init(outStream, _solid);

+

+			uint i;

+			for (i = 0; i < Base.kNumStates; i++)

+			{

+				for (uint j = 0; j <= m_PosStateMask; j++)

+				{

+					uint index = (i << Base.kNumPosStatesBitsMax) + j;

+					m_IsMatchDecoders[index].Init();

+					m_IsRep0LongDecoders[index].Init();

+				}

+				m_IsRepDecoders[i].Init();

+				m_IsRepG0Decoders[i].Init();

+				m_IsRepG1Decoders[i].Init();

+				m_IsRepG2Decoders[i].Init();

+			}

+

+			m_LiteralDecoder.Init();

+			for (i = 0; i < Base.kNumLenToPosStates; i++)

+				m_PosSlotDecoder[i].Init();

+			// m_PosSpecDecoder.Init();

+			for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)

+				m_PosDecoders[i].Init();

+

+			m_LenDecoder.Init();

+			m_RepLenDecoder.Init();

+			m_PosAlignDecoder.Init();

+		}

+

+		public void Code(System.IO.Stream inStream, System.IO.Stream outStream,

+			Int64 inSize, Int64 outSize, ICodeProgress progress)

+		{

+			Init(inStream, outStream);

+

+			Base.State state = new Base.State();

+			state.Init();

+			uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;

+

+			UInt64 nowPos64 = 0;

+			UInt64 outSize64 = (UInt64)outSize;

+			if (nowPos64 < outSize64)

+			{

+				if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)

+					throw new DataErrorException();

+				state.UpdateChar();

+				byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);

+				m_OutWindow.PutByte(b);

+				nowPos64++;

+			}

+			while (nowPos64 < outSize64)

+			{

+				// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);

+					// while(nowPos64 < next)

+				{

+					uint posState = (uint)nowPos64 & m_PosStateMask;

+					if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)

+					{

+						byte b;

+						byte prevByte = m_OutWindow.GetByte(0);

+						if (!state.IsCharState())

+							b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,

+								(uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0));

+						else

+							b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);

+						m_OutWindow.PutByte(b);

+						state.UpdateChar();

+						nowPos64++;

+					}

+					else

+					{

+						uint len;

+						if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)

+						{

+							if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)

+							{

+								if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)

+								{

+									state.UpdateShortRep();

+									m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));

+									nowPos64++;

+									continue;

+								}

+							}

+							else

+							{

+								UInt32 distance;

+								if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)

+								{

+									distance = rep1;

+								}

+								else

+								{

+									if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)

+										distance = rep2;

+									else

+									{

+										distance = rep3;

+										rep3 = rep2;

+									}

+									rep2 = rep1;

+								}

+								rep1 = rep0;

+								rep0 = distance;

+							}

+							len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;

+							state.UpdateRep();

+						}

+						else

+						{

+							rep3 = rep2;

+							rep2 = rep1;

+							rep1 = rep0;

+							len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);

+							state.UpdateMatch();

+							uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);

+							if (posSlot >= Base.kStartPosModelIndex)

+							{

+								int numDirectBits = (int)((posSlot >> 1) - 1);

+								rep0 = ((2 | (posSlot & 1)) << numDirectBits);

+								if (posSlot < Base.kEndPosModelIndex)

+									rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,

+											rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);

+								else

+								{

+									rep0 += (m_RangeDecoder.DecodeDirectBits(

+										numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);

+									rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);

+								}

+							}

+							else

+								rep0 = posSlot;

+						}

+						if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)

+						{

+							if (rep0 == 0xFFFFFFFF)

+								break;

+							throw new DataErrorException();

+						}

+						m_OutWindow.CopyBlock(rep0, len);

+						nowPos64 += len;

+					}

+				}

+			}

+			m_OutWindow.Flush();

+			m_OutWindow.ReleaseStream();

+			m_RangeDecoder.ReleaseStream();

+		}

+

+		public void SetDecoderProperties(byte[] properties)

+		{

+			if (properties.Length < 5)

+				throw new InvalidParamException();

+			int lc = properties[0] % 9;

+			int remainder = properties[0] / 9;

+			int lp = remainder % 5;

+			int pb = remainder / 5;

+			if (pb > Base.kNumPosStatesBitsMax)

+				throw new InvalidParamException();

+			UInt32 dictionarySize = 0;

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

+				dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);

+			SetDictionarySize(dictionarySize);

+			SetLiteralProperties(lp, lc);

+			SetPosBitsProperties(pb);

+		}

+

+		public bool Train(System.IO.Stream stream)

+		{

+			_solid = true;

+			return m_OutWindow.Train(stream);

+		}

+

+		/*

+		public override bool CanRead { get { return true; }}

+		public override bool CanWrite { get { return true; }}

+		public override bool CanSeek { get { return true; }}

+		public override long Length { get { return 0; }}

+		public override long Position

+		{

+			get { return 0;	}

+			set { }

+		}

+		public override void Flush() { }

+		public override int Read(byte[] buffer, int offset, int count) 

+		{

+			return 0;

+		}

+		public override void Write(byte[] buffer, int offset, int count)

+		{

+		}

+		public override long Seek(long offset, System.IO.SeekOrigin origin)

+		{

+			return 0;

+		}

+		public override void SetLength(long value) {}

+		*/

+	}

+}

diff --git a/CS/7zip/Compress/LZMA/LzmaEncoder.cs b/CS/7zip/Compress/LZMA/LzmaEncoder.cs
new file mode 100755
index 0000000..6dc2708
--- /dev/null
+++ b/CS/7zip/Compress/LZMA/LzmaEncoder.cs
@@ -0,0 +1,1480 @@
+// LzmaEncoder.cs

+

+using System;

+

+namespace SevenZip.Compression.LZMA

+{

+	using RangeCoder;

+

+	public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties

+	{

+		enum EMatchFinderType

+		{

+			BT2,

+			BT4,

+		};

+

+		const UInt32 kIfinityPrice = 0xFFFFFFF;

+

+		static Byte[] g_FastPos = new Byte[1 << 11];

+

+		static Encoder()

+		{

+			const Byte kFastSlots = 22;

+			int c = 2;

+			g_FastPos[0] = 0;

+			g_FastPos[1] = 1;

+			for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)

+			{

+				UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1));

+				for (UInt32 j = 0; j < k; j++, c++)

+					g_FastPos[c] = slotFast;

+			}

+		}

+

+		static UInt32 GetPosSlot(UInt32 pos)

+		{

+			if (pos < (1 << 11))

+				return g_FastPos[pos];

+			if (pos < (1 << 21))

+				return (UInt32)(g_FastPos[pos >> 10] + 20);

+			return (UInt32)(g_FastPos[pos >> 20] + 40);

+		}

+

+		static UInt32 GetPosSlot2(UInt32 pos)

+		{

+			if (pos < (1 << 17))

+				return (UInt32)(g_FastPos[pos >> 6] + 12);

+			if (pos < (1 << 27))

+				return (UInt32)(g_FastPos[pos >> 16] + 32);

+			return (UInt32)(g_FastPos[pos >> 26] + 52);

+		}

+

+		Base.State _state = new Base.State();

+		Byte _previousByte;

+		UInt32[] _repDistances = new UInt32[Base.kNumRepDistances];

+

+		void BaseInit()

+		{

+			_state.Init();

+			_previousByte = 0;

+			for (UInt32 i = 0; i < Base.kNumRepDistances; i++)

+				_repDistances[i] = 0;

+		}

+

+		const int kDefaultDictionaryLogSize = 22;

+		const UInt32 kNumFastBytesDefault = 0x20;

+

+		class LiteralEncoder

+		{

+			public struct Encoder2

+			{

+				BitEncoder[] m_Encoders;

+

+				public void Create() { m_Encoders = new BitEncoder[0x300]; }

+

+				public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); }

+

+				public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol)

+				{

+					uint context = 1;

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

+					{

+						uint bit = (uint)((symbol >> i) & 1);

+						m_Encoders[context].Encode(rangeEncoder, bit);

+						context = (context << 1) | bit;

+					}

+				}

+

+				public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)

+				{

+					uint context = 1;

+					bool same = true;

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

+					{

+						uint bit = (uint)((symbol >> i) & 1);

+						uint state = context;

+						if (same)

+						{

+							uint matchBit = (uint)((matchByte >> i) & 1);

+							state += ((1 + matchBit) << 8);

+							same = (matchBit == bit);

+						}

+						m_Encoders[state].Encode(rangeEncoder, bit);

+						context = (context << 1) | bit;

+					}

+				}

+

+				public uint GetPrice(bool matchMode, byte matchByte, byte symbol)

+				{

+					uint price = 0;

+					uint context = 1;

+					int i = 7;

+					if (matchMode)

+					{

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

+						{

+							uint matchBit = (uint)(matchByte >> i) & 1;

+							uint bit = (uint)(symbol >> i) & 1;

+							price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit);

+							context = (context << 1) | bit;

+							if (matchBit != bit)

+							{

+								i--;

+								break;

+							}

+						}

+					}

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

+					{

+						uint bit = (uint)(symbol >> i) & 1;

+						price += m_Encoders[context].GetPrice(bit);

+						context = (context << 1) | bit;

+					}

+					return price;

+				}

+			}

+

+			Encoder2[] m_Coders;

+			int m_NumPrevBits;

+			int m_NumPosBits;

+			uint m_PosMask;

+

+			public void Create(int numPosBits, int numPrevBits)

+			{

+				if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)

+					return;

+				m_NumPosBits = numPosBits;

+				m_PosMask = ((uint)1 << numPosBits) - 1;

+				m_NumPrevBits = numPrevBits;

+				uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);

+				m_Coders = new Encoder2[numStates];

+				for (uint i = 0; i < numStates; i++)

+					m_Coders[i].Create();

+			}

+

+			public void Init()

+			{

+				uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);

+				for (uint i = 0; i < numStates; i++)

+					m_Coders[i].Init();

+			}

+

+			public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte)

+			{ return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; }

+		}

+

+		class LenEncoder

+		{

+			RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder();

+			RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder();

+			RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax];

+			RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax];

+			RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits);

+

+			public LenEncoder()

+			{

+				for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)

+				{

+					_lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits);

+					_midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits);

+				}

+			}

+

+			public void Init(UInt32 numPosStates)

+			{

+				_choice.Init();

+				_choice2.Init();

+				for (UInt32 posState = 0; posState < numPosStates; posState++)

+				{

+					_lowCoder[posState].Init();

+					_midCoder[posState].Init();

+				}

+				_highCoder.Init();

+			}

+

+			public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)

+			{

+				if (symbol < Base.kNumLowLenSymbols)

+				{

+					_choice.Encode(rangeEncoder, 0);

+					_lowCoder[posState].Encode(rangeEncoder, symbol);

+				}

+				else

+				{

+					symbol -= Base.kNumLowLenSymbols;

+					_choice.Encode(rangeEncoder, 1);

+					if (symbol < Base.kNumMidLenSymbols)

+					{

+						_choice2.Encode(rangeEncoder, 0);

+						_midCoder[posState].Encode(rangeEncoder, symbol);

+					}

+					else

+					{

+						_choice2.Encode(rangeEncoder, 1);

+						_highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);

+					}

+				}

+			}

+

+			public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st)

+			{

+				UInt32 a0 = _choice.GetPrice0();

+				UInt32 a1 = _choice.GetPrice1();

+				UInt32 b0 = a1 + _choice2.GetPrice0();

+				UInt32 b1 = a1 + _choice2.GetPrice1();

+				UInt32 i = 0;

+				for (i = 0; i < Base.kNumLowLenSymbols; i++)

+				{

+					if (i >= numSymbols)

+						return;

+					prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);

+				}

+				for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++)

+				{

+					if (i >= numSymbols)

+						return;

+					prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols);

+				}

+				for (; i < numSymbols; i++)

+					prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);

+			}

+		};

+

+		const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;

+

+		class LenPriceTableEncoder : LenEncoder

+		{

+			UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax];

+			UInt32 _tableSize;

+			UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax];

+

+			public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }

+

+			public UInt32 GetPrice(UInt32 symbol, UInt32 posState)

+			{

+				return _prices[posState * Base.kNumLenSymbols + symbol];

+			}

+

+			void UpdateTable(UInt32 posState)

+			{

+				SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);

+				_counters[posState] = _tableSize;

+			}

+

+			public void UpdateTables(UInt32 numPosStates)

+			{

+				for (UInt32 posState = 0; posState < numPosStates; posState++)

+					UpdateTable(posState);

+			}

+

+			public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)

+			{

+				base.Encode(rangeEncoder, symbol, posState);

+				if (--_counters[posState] == 0)

+					UpdateTable(posState);

+			}

+		}

+

+		const UInt32 kNumOpts = 1 << 12;

+		class Optimal

+		{

+			public Base.State State;

+

+			public bool Prev1IsChar;

+			public bool Prev2;

+

+			public UInt32 PosPrev2;

+			public UInt32 BackPrev2;

+

+			public UInt32 Price;

+			public UInt32 PosPrev;

+			public UInt32 BackPrev;

+

+			public UInt32 Backs0;

+			public UInt32 Backs1;

+			public UInt32 Backs2;

+			public UInt32 Backs3;

+

+			public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; }

+			public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }

+			public bool IsShortRep() { return (BackPrev == 0); }

+		};

+		Optimal[] _optimum = new Optimal[kNumOpts];

+		LZ.IMatchFinder _matchFinder = null;

+		RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder();

+

+		RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];

+		RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates];

+		RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates];

+		RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates];

+		RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates];

+		RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];

+

+		RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates];

+		

+		RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex];

+		RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits);

+

+		LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();

+		LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();

+

+		LiteralEncoder _literalEncoder = new LiteralEncoder();

+

+		UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2];

+		

+		UInt32 _numFastBytes = kNumFastBytesDefault;

+		UInt32 _longestMatchLength;

+		UInt32 _numDistancePairs;

+

+		UInt32 _additionalOffset;

+

+		UInt32 _optimumEndIndex;

+		UInt32 _optimumCurrentIndex;

+

+		bool _longestMatchWasFound;

+

+		UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)];

+		UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits];

+		UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize];

+		UInt32 _alignPriceCount;

+

+		UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2);

+

+		int _posStateBits = 2;

+		UInt32 _posStateMask = (4 - 1);

+		int _numLiteralPosStateBits = 0;

+		int _numLiteralContextBits = 3;

+

+		UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize);

+		UInt32 _dictionarySizePrev = 0xFFFFFFFF;

+		UInt32 _numFastBytesPrev = 0xFFFFFFFF;

+

+		Int64 nowPos64;

+		bool _finished;

+		System.IO.Stream _inStream;

+

+		EMatchFinderType _matchFinderType = EMatchFinderType.BT4;

+		bool _writeEndMark = false;

+		

+		bool _needReleaseMFStream;

+

+		void Create()

+		{

+			if (_matchFinder == null)

+			{

+				LZ.BinTree bt = new LZ.BinTree();

+				int numHashBytes = 4;

+				if (_matchFinderType == EMatchFinderType.BT2)

+					numHashBytes = 2;

+				bt.SetType(numHashBytes);

+				_matchFinder = bt;

+			}

+			_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);

+

+			if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)

+				return;

+			_matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);

+			_dictionarySizePrev = _dictionarySize;

+			_numFastBytesPrev = _numFastBytes;

+		}

+

+		public Encoder()

+		{

+			for (int i = 0; i < kNumOpts; i++)

+				_optimum[i] = new Optimal();

+			for (int i = 0; i < Base.kNumLenToPosStates; i++)

+				_posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits);

+		}

+

+		void SetWriteEndMarkerMode(bool writeEndMarker)

+		{

+			_writeEndMark = writeEndMarker;

+		}

+

+		void Init()

+		{

+			BaseInit();

+			_rangeEncoder.Init();

+

+			uint i;

+			for (i = 0; i < Base.kNumStates; i++)

+			{

+				for (uint j = 0; j <= _posStateMask; j++)

+				{

+					uint complexState = (i << Base.kNumPosStatesBitsMax) + j;

+					_isMatch[complexState].Init();

+					_isRep0Long[complexState].Init();

+				}

+				_isRep[i].Init();

+				_isRepG0[i].Init();

+				_isRepG1[i].Init();

+				_isRepG2[i].Init();

+			}

+			_literalEncoder.Init();

+			for (i = 0; i < Base.kNumLenToPosStates; i++)

+				_posSlotEncoder[i].Init();

+			for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)

+				_posEncoders[i].Init();

+

+			_lenEncoder.Init((UInt32)1 << _posStateBits);

+			_repMatchLenEncoder.Init((UInt32)1 << _posStateBits);

+

+			_posAlignEncoder.Init();

+

+			_longestMatchWasFound = false;

+			_optimumEndIndex = 0;

+			_optimumCurrentIndex = 0;

+			_additionalOffset = 0;

+		}

+

+		void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs)

+		{

+			lenRes = 0;

+			numDistancePairs = _matchFinder.GetMatches(_matchDistances);

+			if (numDistancePairs > 0)

+			{

+				lenRes = _matchDistances[numDistancePairs - 2];

+				if (lenRes == _numFastBytes)

+					lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1],

+						Base.kMatchMaxLen - lenRes);

+			}

+			_additionalOffset++;

+		}

+

+

+		void MovePos(UInt32 num)

+		{

+			if (num > 0)

+			{

+				_matchFinder.Skip(num);

+				_additionalOffset += num;

+			}

+		}

+

+		UInt32 GetRepLen1Price(Base.State state, UInt32 posState)

+		{

+			return _isRepG0[state.Index].GetPrice0() +

+					_isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0();

+		}

+

+		UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState)

+		{

+			UInt32 price;

+			if (repIndex == 0)

+			{

+				price = _isRepG0[state.Index].GetPrice0();

+				price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();

+			}

+			else

+			{

+				price = _isRepG0[state.Index].GetPrice1();

+				if (repIndex == 1)

+					price += _isRepG1[state.Index].GetPrice0();

+				else

+				{

+					price += _isRepG1[state.Index].GetPrice1();

+					price += _isRepG2[state.Index].GetPrice(repIndex - 2);

+				}

+			}

+			return price;

+		}

+

+		UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState)

+		{

+			UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);

+			return price + GetPureRepPrice(repIndex, state, posState);

+		}

+	

+		UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState)

+		{

+			UInt32 price;

+			UInt32 lenToPosState = Base.GetLenToPosState(len);

+			if (pos < Base.kNumFullDistances)

+				price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos];

+			else

+				price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] +

+					_alignPrices[pos & Base.kAlignMask];

+			return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);

+		}

+

+		UInt32 Backward(out UInt32 backRes, UInt32 cur)

+		{

+			_optimumEndIndex = cur;

+			UInt32 posMem = _optimum[cur].PosPrev;

+			UInt32 backMem = _optimum[cur].BackPrev;

+			do

+			{

+				if (_optimum[cur].Prev1IsChar)

+				{

+					_optimum[posMem].MakeAsChar();

+					_optimum[posMem].PosPrev = posMem - 1;

+					if (_optimum[cur].Prev2)

+					{

+						_optimum[posMem - 1].Prev1IsChar = false;

+						_optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;

+						_optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;

+					}

+				}

+				UInt32 posPrev = posMem;

+				UInt32 backCur = backMem;

+

+				backMem = _optimum[posPrev].BackPrev;

+				posMem = _optimum[posPrev].PosPrev;

+

+				_optimum[posPrev].BackPrev = backCur;

+				_optimum[posPrev].PosPrev = cur;

+				cur = posPrev;

+			}

+			while (cur > 0);

+			backRes = _optimum[0].BackPrev;

+			_optimumCurrentIndex = _optimum[0].PosPrev;

+			return _optimumCurrentIndex;

+		}

+

+		UInt32[] reps = new UInt32[Base.kNumRepDistances];

+		UInt32[] repLens = new UInt32[Base.kNumRepDistances];

+

+

+		UInt32 GetOptimum(UInt32 position, out UInt32 backRes)

+		{

+			if (_optimumEndIndex != _optimumCurrentIndex)

+			{

+				UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;

+				backRes = _optimum[_optimumCurrentIndex].BackPrev;

+				_optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;

+				return lenRes;

+			}

+			_optimumCurrentIndex = _optimumEndIndex = 0;

+

+			UInt32 lenMain, numDistancePairs;

+			if (!_longestMatchWasFound)

+			{

+				ReadMatchDistances(out lenMain, out numDistancePairs);

+			}

+			else

+			{

+				lenMain = _longestMatchLength;

+				numDistancePairs = _numDistancePairs;

+				_longestMatchWasFound = false;

+			}

+

+			UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;

+			if (numAvailableBytes < 2)

+			{

+				backRes = 0xFFFFFFFF;

+				return 1;

+			}

+			if (numAvailableBytes > Base.kMatchMaxLen)

+				numAvailableBytes = Base.kMatchMaxLen;

+

+			UInt32 repMaxIndex = 0;

+			UInt32 i;			

+			for (i = 0; i < Base.kNumRepDistances; i++)

+			{

+				reps[i] = _repDistances[i];

+				repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);

+				if (repLens[i] > repLens[repMaxIndex])

+					repMaxIndex = i;

+			}

+			if (repLens[repMaxIndex] >= _numFastBytes)

+			{

+				backRes = repMaxIndex;

+				UInt32 lenRes = repLens[repMaxIndex];

+				MovePos(lenRes - 1);

+				return lenRes;

+			}

+

+			if (lenMain >= _numFastBytes)

+			{

+				backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;

+				MovePos(lenMain - 1);

+				return lenMain;

+			}

+			

+			Byte currentByte = _matchFinder.GetIndexByte(0 - 1);

+			Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1));

+

+			if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)

+			{

+				backRes = (UInt32)0xFFFFFFFF;

+				return 1;

+			}

+

+			_optimum[0].State = _state;

+

+			UInt32 posState = (position & _posStateMask);

+

+			_optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +

+					_literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte);

+			_optimum[1].MakeAsChar();

+

+			UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();

+			UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();

+

+			if (matchByte == currentByte)

+			{

+				UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);

+				if (shortRepPrice < _optimum[1].Price)

+				{

+					_optimum[1].Price = shortRepPrice;

+					_optimum[1].MakeAsShortRep();

+				}

+			}

+

+			UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);

+

+			if(lenEnd < 2)

+			{

+				backRes = _optimum[1].BackPrev;

+				return 1;

+			}

+			

+			_optimum[1].PosPrev = 0;

+

+			_optimum[0].Backs0 = reps[0];

+			_optimum[0].Backs1 = reps[1];

+			_optimum[0].Backs2 = reps[2];

+			_optimum[0].Backs3 = reps[3];

+

+			UInt32 len = lenEnd;

+			do

+				_optimum[len--].Price = kIfinityPrice;

+			while (len >= 2);

+

+			for (i = 0; i < Base.kNumRepDistances; i++)

+			{

+				UInt32 repLen = repLens[i];

+				if (repLen < 2)

+					continue;

+				UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);

+				do

+				{

+					UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);

+					Optimal optimum = _optimum[repLen];

+					if (curAndLenPrice < optimum.Price)

+					{

+						optimum.Price = curAndLenPrice;

+						optimum.PosPrev = 0;

+						optimum.BackPrev = i;

+						optimum.Prev1IsChar = false;

+					}

+				}

+				while (--repLen >= 2);

+			}

+

+			UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();

+			

+			len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);

+			if (len <= lenMain)

+			{

+				UInt32 offs = 0;

+				while (len > _matchDistances[offs])

+					offs += 2;

+				for (; ; len++)

+				{

+					UInt32 distance = _matchDistances[offs + 1];

+					UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);

+					Optimal optimum = _optimum[len];

+					if (curAndLenPrice < optimum.Price)

+					{

+						optimum.Price = curAndLenPrice;

+						optimum.PosPrev = 0;

+						optimum.BackPrev = distance + Base.kNumRepDistances;

+						optimum.Prev1IsChar = false;

+					}

+					if (len == _matchDistances[offs])

+					{

+						offs += 2;

+						if (offs == numDistancePairs)

+							break;

+					}

+				}

+			}

+

+			UInt32 cur = 0;

+

+			while (true)

+			{

+				cur++;

+				if (cur == lenEnd)

+					return Backward(out backRes, cur);

+				UInt32 newLen;

+				ReadMatchDistances(out newLen, out numDistancePairs);

+				if (newLen >= _numFastBytes)

+				{

+					_numDistancePairs = numDistancePairs;

+					_longestMatchLength = newLen;

+					_longestMatchWasFound = true;

+					return Backward(out backRes, cur);

+				}

+				position++;

+				UInt32 posPrev = _optimum[cur].PosPrev;

+				Base.State state;

+				if (_optimum[cur].Prev1IsChar)

+				{

+					posPrev--;

+					if (_optimum[cur].Prev2)

+					{

+						state = _optimum[_optimum[cur].PosPrev2].State;

+						if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)

+							state.UpdateRep();

+						else

+							state.UpdateMatch();

+					}

+					else

+						state = _optimum[posPrev].State;

+					state.UpdateChar();

+				}

+				else

+					state = _optimum[posPrev].State;

+				if (posPrev == cur - 1)

+				{

+					if (_optimum[cur].IsShortRep())

+						state.UpdateShortRep();

+					else

+						state.UpdateChar();

+				}

+				else

+				{

+					UInt32 pos;

+					if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)

+					{

+						posPrev = _optimum[cur].PosPrev2;

+						pos = _optimum[cur].BackPrev2;

+						state.UpdateRep();

+					}

+					else

+					{

+						pos = _optimum[cur].BackPrev;

+						if (pos < Base.kNumRepDistances)

+							state.UpdateRep();

+						else

+							state.UpdateMatch();

+					}

+					Optimal opt = _optimum[posPrev];

+					if (pos < Base.kNumRepDistances)

+					{

+						if (pos == 0)

+						{

+							reps[0] = opt.Backs0;

+							reps[1] = opt.Backs1;

+							reps[2] = opt.Backs2;

+							reps[3] = opt.Backs3;

+						}

+						else if (pos == 1)

+						{

+							reps[0] = opt.Backs1;

+							reps[1] = opt.Backs0;

+							reps[2] = opt.Backs2;

+							reps[3] = opt.Backs3;

+						}

+						else if (pos == 2)

+						{

+							reps[0] = opt.Backs2;

+							reps[1] = opt.Backs0;

+							reps[2] = opt.Backs1;

+							reps[3] = opt.Backs3;

+						}

+						else

+						{

+							reps[0] = opt.Backs3;

+							reps[1] = opt.Backs0;

+							reps[2] = opt.Backs1;

+							reps[3] = opt.Backs2;

+						}

+					}

+					else

+					{

+						reps[0] = (pos - Base.kNumRepDistances);

+						reps[1] = opt.Backs0;

+						reps[2] = opt.Backs1;

+						reps[3] = opt.Backs2;

+					}

+				}

+				_optimum[cur].State = state;

+				_optimum[cur].Backs0 = reps[0];

+				_optimum[cur].Backs1 = reps[1];

+				_optimum[cur].Backs2 = reps[2];

+				_optimum[cur].Backs3 = reps[3];

+				UInt32 curPrice = _optimum[cur].Price;

+

+				currentByte = _matchFinder.GetIndexByte(0 - 1);

+				matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1));

+

+				posState = (position & _posStateMask);

+

+				UInt32 curAnd1Price = curPrice +

+					_isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +

+					_literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).

+					GetPrice(!state.IsCharState(), matchByte, currentByte);

+

+				Optimal nextOptimum = _optimum[cur + 1];

+

+				bool nextIsChar = false;

+				if (curAnd1Price < nextOptimum.Price)

+				{

+					nextOptimum.Price = curAnd1Price;

+					nextOptimum.PosPrev = cur;

+					nextOptimum.MakeAsChar();

+					nextIsChar = true;

+				}

+

+				matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();

+				repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();

+

+				if (matchByte == currentByte &&

+					!(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))

+				{

+					UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);

+					if (shortRepPrice <= nextOptimum.Price)

+					{

+						nextOptimum.Price = shortRepPrice;

+						nextOptimum.PosPrev = cur;

+						nextOptimum.MakeAsShortRep();

+						nextIsChar = true;

+					}

+				}

+

+				UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;

+				numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull);

+				numAvailableBytes = numAvailableBytesFull;

+

+				if (numAvailableBytes < 2)

+					continue;

+				if (numAvailableBytes > _numFastBytes)

+					numAvailableBytes = _numFastBytes;

+				if (!nextIsChar && matchByte != currentByte)

+				{

+					// try Literal + rep0

+					UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes);

+					UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);

+					if (lenTest2 >= 2)

+					{

+						Base.State state2 = state;

+						state2.UpdateChar();

+						UInt32 posStateNext = (position + 1) & _posStateMask;

+						UInt32 nextRepMatchPrice = curAnd1Price +

+							_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() +

+							_isRep[state2.Index].GetPrice1();

+						{

+							UInt32 offset = cur + 1 + lenTest2;

+							while (lenEnd < offset)

+								_optimum[++lenEnd].Price = kIfinityPrice;

+							UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(

+								0, lenTest2, state2, posStateNext);

+							Optimal optimum = _optimum[offset];

+							if (curAndLenPrice < optimum.Price)

+							{

+								optimum.Price = curAndLenPrice;

+								optimum.PosPrev = cur + 1;

+								optimum.BackPrev = 0;

+								optimum.Prev1IsChar = true;

+								optimum.Prev2 = false;

+							}

+						}

+					}

+				}

+

+				UInt32 startLen = 2; // speed optimization 

+

+				for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)

+				{

+					UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);

+					if (lenTest < 2)

+						continue;

+					UInt32 lenTestTemp = lenTest;

+					do

+					{

+						while (lenEnd < cur + lenTest)

+							_optimum[++lenEnd].Price = kIfinityPrice;

+						UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);

+						Optimal optimum = _optimum[cur + lenTest];

+						if (curAndLenPrice < optimum.Price)

+						{

+							optimum.Price = curAndLenPrice;

+							optimum.PosPrev = cur;

+							optimum.BackPrev = repIndex;

+							optimum.Prev1IsChar = false;

+						}

+					}

+					while(--lenTest >= 2);

+					lenTest = lenTestTemp;

+

+					if (repIndex == 0)

+						startLen = lenTest + 1;

+

+					// if (_maxMode)

+					if (lenTest < numAvailableBytesFull)

+					{

+						UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);

+						UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t);

+						if (lenTest2 >= 2)

+						{

+							Base.State state2 = state;

+							state2.UpdateRep();

+							UInt32 posStateNext = (position + lenTest) & _posStateMask;

+							UInt32 curAndLenCharPrice = 

+									repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + 

+									_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +

+									_literalEncoder.GetSubCoder(position + lenTest, 

+									_matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true,

+									_matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), 

+									_matchFinder.GetIndexByte((Int32)lenTest - 1));

+							state2.UpdateChar();

+							posStateNext = (position + lenTest + 1) & _posStateMask;

+							UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();

+							UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();

+							

+							// for(; lenTest2 >= 2; lenTest2--)

+							{

+								UInt32 offset = lenTest + 1 + lenTest2;

+								while(lenEnd < cur + offset)

+									_optimum[++lenEnd].Price = kIfinityPrice;

+								UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);

+								Optimal optimum = _optimum[cur + offset];

+								if (curAndLenPrice < optimum.Price) 

+								{

+									optimum.Price = curAndLenPrice;

+									optimum.PosPrev = cur + lenTest + 1;

+									optimum.BackPrev = 0;

+									optimum.Prev1IsChar = true;

+									optimum.Prev2 = true;

+									optimum.PosPrev2 = cur;

+									optimum.BackPrev2 = repIndex;

+								}

+							}

+						}

+					}

+				}

+

+				if (newLen > numAvailableBytes)

+				{

+					newLen = numAvailableBytes;

+					for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ;

+					_matchDistances[numDistancePairs] = newLen;

+					numDistancePairs += 2;

+				}

+				if (newLen >= startLen)

+				{

+					normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();

+					while (lenEnd < cur + newLen)

+						_optimum[++lenEnd].Price = kIfinityPrice;

+

+					UInt32 offs = 0;

+					while (startLen > _matchDistances[offs])

+						offs += 2;

+

+					for (UInt32 lenTest = startLen; ; lenTest++)

+					{

+						UInt32 curBack = _matchDistances[offs + 1];

+						UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);

+						Optimal optimum = _optimum[cur + lenTest];

+						if (curAndLenPrice < optimum.Price)

+						{

+							optimum.Price = curAndLenPrice;

+							optimum.PosPrev = cur;

+							optimum.BackPrev = curBack + Base.kNumRepDistances;

+							optimum.Prev1IsChar = false;

+						}

+

+						if (lenTest == _matchDistances[offs])

+						{

+							if (lenTest < numAvailableBytesFull)

+							{

+								UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);

+								UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t);

+								if (lenTest2 >= 2)

+								{

+									Base.State state2 = state;

+									state2.UpdateMatch();

+									UInt32 posStateNext = (position + lenTest) & _posStateMask;

+									UInt32 curAndLenCharPrice = curAndLenPrice +

+										_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +

+										_literalEncoder.GetSubCoder(position + lenTest,

+										_matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).

+										GetPrice(true,

+										_matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1),

+										_matchFinder.GetIndexByte((Int32)lenTest - 1));

+									state2.UpdateChar();

+									posStateNext = (position + lenTest + 1) & _posStateMask;

+									UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();

+									UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();

+

+									UInt32 offset = lenTest + 1 + lenTest2;

+									while (lenEnd < cur + offset)

+										_optimum[++lenEnd].Price = kIfinityPrice;

+									curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);

+									optimum = _optimum[cur + offset];

+									if (curAndLenPrice < optimum.Price)

+									{

+										optimum.Price = curAndLenPrice;

+										optimum.PosPrev = cur + lenTest + 1;

+										optimum.BackPrev = 0;

+										optimum.Prev1IsChar = true;

+										optimum.Prev2 = true;

+										optimum.PosPrev2 = cur;

+										optimum.BackPrev2 = curBack + Base.kNumRepDistances;

+									}

+								}

+							}

+							offs += 2;

+							if (offs == numDistancePairs)

+								break;

+						}

+					}

+				}

+			}

+		}

+

+		bool ChangePair(UInt32 smallDist, UInt32 bigDist)

+		{

+			const int kDif = 7;

+			return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif));

+		}

+

+		void WriteEndMarker(UInt32 posState)

+		{

+			if (!_writeEndMark)

+				return;

+

+			_isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1);

+			_isRep[_state.Index].Encode(_rangeEncoder, 0);

+			_state.UpdateMatch();

+			UInt32 len = Base.kMatchMinLen;

+			_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);

+			UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1;

+			UInt32 lenToPosState = Base.GetLenToPosState(len);

+			_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);

+			int footerBits = 30;

+			UInt32 posReduced = (((UInt32)1) << footerBits) - 1;

+			_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);

+			_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);

+		}

+

+		void Flush(UInt32 nowPos)

+		{

+			ReleaseMFStream();

+			WriteEndMarker(nowPos & _posStateMask);

+			_rangeEncoder.FlushData();

+			_rangeEncoder.FlushStream();

+		}

+

+		public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished)

+		{

+			inSize = 0;

+			outSize = 0;

+			finished = true;

+

+			if (_inStream != null)

+			{

+				_matchFinder.SetStream(_inStream);

+				_matchFinder.Init();

+				_needReleaseMFStream = true;

+				_inStream = null;

+				if (_trainSize > 0)

+					_matchFinder.Skip(_trainSize);

+			}

+

+			if (_finished)

+				return;

+			_finished = true;

+

+

+			Int64 progressPosValuePrev = nowPos64;

+			if (nowPos64 == 0)

+			{

+				if (_matchFinder.GetNumAvailableBytes() == 0)

+				{

+					Flush((UInt32)nowPos64);

+					return;

+				}

+				UInt32 len, numDistancePairs; // it's not used

+				ReadMatchDistances(out len, out numDistancePairs);

+				UInt32 posState = (UInt32)(nowPos64) & _posStateMask;

+				_isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0);

+				_state.UpdateChar();

+				Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));

+				_literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte);

+				_previousByte = curByte;

+				_additionalOffset--;

+				nowPos64++;

+			}

+			if (_matchFinder.GetNumAvailableBytes() == 0)

+			{

+				Flush((UInt32)nowPos64);

+				return;

+			}

+			while (true)

+			{

+				UInt32 pos;

+				UInt32 len = GetOptimum((UInt32)nowPos64, out pos);

+				

+				UInt32 posState = ((UInt32)nowPos64) & _posStateMask;

+				UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState;

+				if (len == 1 && pos == 0xFFFFFFFF)

+				{

+					_isMatch[complexState].Encode(_rangeEncoder, 0);

+					Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));

+					LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte);

+					if (!_state.IsCharState())

+					{

+						Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset));

+						subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);

+					}

+					else

+						subCoder.Encode(_rangeEncoder, curByte);

+					_previousByte = curByte;

+					_state.UpdateChar();

+				}

+				else

+				{

+					_isMatch[complexState].Encode(_rangeEncoder, 1);

+					if (pos < Base.kNumRepDistances)

+					{

+						_isRep[_state.Index].Encode(_rangeEncoder, 1);

+						if (pos == 0)

+						{

+							_isRepG0[_state.Index].Encode(_rangeEncoder, 0);

+							if (len == 1)

+								_isRep0Long[complexState].Encode(_rangeEncoder, 0);

+							else

+								_isRep0Long[complexState].Encode(_rangeEncoder, 1);

+						}

+						else

+						{

+							_isRepG0[_state.Index].Encode(_rangeEncoder, 1);

+							if (pos == 1)

+								_isRepG1[_state.Index].Encode(_rangeEncoder, 0);

+							else

+							{

+								_isRepG1[_state.Index].Encode(_rangeEncoder, 1);

+								_isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2);

+							}

+						}

+						if (len == 1)

+							_state.UpdateShortRep();

+						else

+						{

+							_repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);

+							_state.UpdateRep();

+						}

+						UInt32 distance = _repDistances[pos];

+						if (pos != 0)

+						{

+							for (UInt32 i = pos; i >= 1; i--)

+								_repDistances[i] = _repDistances[i - 1];

+							_repDistances[0] = distance;

+						}

+					}

+					else

+					{

+						_isRep[_state.Index].Encode(_rangeEncoder, 0);

+						_state.UpdateMatch();

+						_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);

+						pos -= Base.kNumRepDistances;

+						UInt32 posSlot = GetPosSlot(pos);

+						UInt32 lenToPosState = Base.GetLenToPosState(len);

+						_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);

+

+						if (posSlot >= Base.kStartPosModelIndex)

+						{

+							int footerBits = (int)((posSlot >> 1) - 1);

+							UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);

+							UInt32 posReduced = pos - baseVal;

+

+							if (posSlot < Base.kEndPosModelIndex)

+								RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders,

+										baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);

+							else

+							{

+								_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);

+								_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);

+								_alignPriceCount++;

+							}

+						}

+						UInt32 distance = pos;

+						for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--)

+							_repDistances[i] = _repDistances[i - 1];

+						_repDistances[0] = distance;

+						_matchPriceCount++;

+					}

+					_previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset));

+				}

+				_additionalOffset -= len;

+				nowPos64 += len;

+				if (_additionalOffset == 0)

+				{

+					// if (!_fastMode)

+					if (_matchPriceCount >= (1 << 7))

+						FillDistancesPrices();

+					if (_alignPriceCount >= Base.kAlignTableSize)

+						FillAlignPrices();

+					inSize = nowPos64;

+					outSize = _rangeEncoder.GetProcessedSizeAdd();

+					if (_matchFinder.GetNumAvailableBytes() == 0)

+					{

+						Flush((UInt32)nowPos64);

+						return;

+					}

+

+					if (nowPos64 - progressPosValuePrev >= (1 << 12))

+					{

+						_finished = false;

+						finished = false;

+						return;

+					}

+				}

+			}

+		}

+

+		void ReleaseMFStream()

+		{

+			if (_matchFinder != null && _needReleaseMFStream)

+			{

+				_matchFinder.ReleaseStream();

+				_needReleaseMFStream = false;

+			}

+		}

+

+		void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); }

+		void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); }

+

+		void ReleaseStreams()

+		{

+			ReleaseMFStream();

+			ReleaseOutStream();

+		}

+

+		void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream,

+				Int64 inSize, Int64 outSize)

+		{

+			_inStream = inStream;

+			_finished = false;

+			Create();

+			SetOutStream(outStream);

+			Init();

+

+			// if (!_fastMode)

+			{

+				FillDistancesPrices();

+				FillAlignPrices();

+			}

+

+			_lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);

+			_lenEncoder.UpdateTables((UInt32)1 << _posStateBits);

+			_repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);

+			_repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits);

+

+			nowPos64 = 0;

+		}

+

+

+		public void Code(System.IO.Stream inStream, System.IO.Stream outStream,

+			Int64 inSize, Int64 outSize, ICodeProgress progress)

+		{

+			_needReleaseMFStream = false;

+			try

+			{

+				SetStreams(inStream, outStream, inSize, outSize);

+				while (true)

+				{

+					Int64 processedInSize;

+					Int64 processedOutSize;

+					bool finished;

+					CodeOneBlock(out processedInSize, out processedOutSize, out finished);

+					if (finished)

+						return;

+					if (progress != null)

+					{

+						progress.SetProgress(processedInSize, processedOutSize);

+					}

+				}

+			}

+			finally

+			{

+				ReleaseStreams();

+			}

+		}

+

+		const int kPropSize = 5;

+		Byte[] properties = new Byte[kPropSize];

+

+		public void WriteCoderProperties(System.IO.Stream outStream)

+		{

+			properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);

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

+				properties[1 + i] = (Byte)((_dictionarySize >> (8 * i)) & 0xFF);

+			outStream.Write(properties, 0, kPropSize);

+		}

+		

+		UInt32[] tempPrices = new UInt32[Base.kNumFullDistances];

+		UInt32 _matchPriceCount;

+

+		void FillDistancesPrices()

+		{

+			for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)

+			{ 

+				UInt32 posSlot = GetPosSlot(i);

+				int footerBits = (int)((posSlot >> 1) - 1);

+				UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);

+				tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, 

+					baseVal - posSlot - 1, footerBits, i - baseVal);

+			}

+

+			for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)

+			{

+				UInt32 posSlot;

+				RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];

+			

+				UInt32 st = (lenToPosState << Base.kNumPosSlotBits);

+				for (posSlot = 0; posSlot < _distTableSize; posSlot++)

+					_posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);

+				for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)

+					_posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits);

+

+				UInt32 st2 = lenToPosState * Base.kNumFullDistances;

+				UInt32 i;

+				for (i = 0; i < Base.kStartPosModelIndex; i++)

+					_distancesPrices[st2 + i] = _posSlotPrices[st + i];

+				for (; i < Base.kNumFullDistances; i++)

+					_distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i];

+			}

+			_matchPriceCount = 0;

+		}

+

+		void FillAlignPrices()

+		{

+			for (UInt32 i = 0; i < Base.kAlignTableSize; i++)

+				_alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);

+			_alignPriceCount = 0;

+		}

+

+

+		static string[] kMatchFinderIDs = 

+		{

+			"BT2",

+			"BT4",

+		};

+

+		static int FindMatchFinder(string s)

+		{

+			for (int m = 0; m < kMatchFinderIDs.Length; m++)

+				if (s == kMatchFinderIDs[m])

+					return m;

+			return -1;

+		}

+	

+		public void SetCoderProperties(CoderPropID[] propIDs, object[] properties)

+		{

+			for (UInt32 i = 0; i < properties.Length; i++)

+			{

+				object prop = properties[i];

+				switch (propIDs[i])

+				{

+					case CoderPropID.NumFastBytes:

+					{

+						if (!(prop is Int32))

+							throw new InvalidParamException();

+						Int32 numFastBytes = (Int32)prop;

+						if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)

+							throw new InvalidParamException();

+						_numFastBytes = (UInt32)numFastBytes;

+						break;

+					}

+					case CoderPropID.Algorithm:

+					{

+						/*

+						if (!(prop is Int32))

+							throw new InvalidParamException();

+						Int32 maximize = (Int32)prop;

+						_fastMode = (maximize == 0);

+						_maxMode = (maximize >= 2);

+						*/

+						break;

+					}

+					case CoderPropID.MatchFinder:

+					{

+						if (!(prop is String))

+							throw new InvalidParamException();

+						EMatchFinderType matchFinderIndexPrev = _matchFinderType;

+						int m = FindMatchFinder(((string)prop).ToUpper());

+						if (m < 0)

+							throw new InvalidParamException();

+						_matchFinderType = (EMatchFinderType)m;

+						if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)

+							{

+							_dictionarySizePrev = 0xFFFFFFFF;

+							_matchFinder = null;

+							}

+						break;

+					}

+					case CoderPropID.DictionarySize:

+					{

+						const int kDicLogSizeMaxCompress = 30;

+						if (!(prop is Int32))

+							throw new InvalidParamException(); ;

+						Int32 dictionarySize = (Int32)prop;

+						if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) ||

+							dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress))

+							throw new InvalidParamException();

+						_dictionarySize = (UInt32)dictionarySize;

+						int dicLogSize;

+						for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)

+							if (dictionarySize <= ((UInt32)(1) << dicLogSize))

+								break;

+						_distTableSize = (UInt32)dicLogSize * 2;

+						break;

+					}

+					case CoderPropID.PosStateBits:

+					{

+						if (!(prop is Int32))

+							throw new InvalidParamException();

+						Int32 v = (Int32)prop;

+						if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax)

+							throw new InvalidParamException();

+						_posStateBits = (int)v;

+						_posStateMask = (((UInt32)1) << (int)_posStateBits) - 1;

+						break;

+					}

+					case CoderPropID.LitPosBits:

+					{

+						if (!(prop is Int32))

+							throw new InvalidParamException();

+						Int32 v = (Int32)prop;

+						if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax)

+							throw new InvalidParamException();

+						_numLiteralPosStateBits = (int)v;

+						break;

+					}

+					case CoderPropID.LitContextBits:

+					{

+						if (!(prop is Int32))

+							throw new InvalidParamException();

+						Int32 v = (Int32)prop;

+						if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax)

+							throw new InvalidParamException(); ;

+						_numLiteralContextBits = (int)v;

+						break;

+					}

+					case CoderPropID.EndMarker:

+					{

+						if (!(prop is Boolean))

+							throw new InvalidParamException();

+						SetWriteEndMarkerMode((Boolean)prop);

+						break;

+					}

+					default:

+						throw new InvalidParamException();

+				}

+			}

+		}

+

+		uint _trainSize = 0;

+		public void SetTrainSize(uint trainSize)

+		{

+			_trainSize = trainSize;

+		}

+		

+	}

+}

diff --git a/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs b/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs
new file mode 100755
index 0000000..8aa4462
--- /dev/null
+++ b/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs
@@ -0,0 +1,364 @@
+using System;

+using System.IO;

+namespace SevenZip

+{

+	using CommandLineParser;

+	

+	public class CDoubleStream: Stream

+	{

+		public System.IO.Stream s1;

+		public System.IO.Stream s2;

+		public int fileIndex;

+		public long skipSize;

+		

+		public override bool CanRead { get { return true; }}

+		public override bool CanWrite { get { return false; }}

+		public override bool CanSeek { get { return false; }}

+		public override long Length { get { return s1.Length + s2.Length - skipSize; } }

+		public override long Position

+		{

+			get { return 0;	}

+			set { }

+		}

+		public override void Flush() { }

+		public override int Read(byte[] buffer, int offset, int count) 

+		{

+			int numTotal = 0;

+			while (count > 0)

+			{

+				if (fileIndex == 0)

+				{

+					int num = s1.Read(buffer, offset, count);

+					offset += num;

+					count -= num;

+					numTotal += num;

+					if (num == 0)

+						fileIndex++;

+				}

+				if (fileIndex == 1)

+				{

+					numTotal += s2.Read(buffer, offset, count);

+					return numTotal;

+				}

+			}

+			return numTotal;

+		}

+		public override void Write(byte[] buffer, int offset, int count)

+		{

+			throw (new Exception("can't Write"));

+		}

+		public override long Seek(long offset, System.IO.SeekOrigin origin)

+		{

+			throw (new Exception("can't Seek"));

+		}

+		public override void SetLength(long value)

+		{

+			throw (new Exception("can't SetLength"));

+		}

+	}

+	

+	class LzmaAlone

+	{

+		enum Key

+		{

+			Help1 = 0,

+			Help2,

+			Mode,

+			Dictionary,

+			FastBytes,

+			LitContext,

+			LitPos,

+			PosBits,

+			MatchFinder,

+			EOS,

+			StdIn,

+			StdOut,

+			Train

+		};

+

+		static void PrintHelp()

+		{

+			System.Console.WriteLine("\nUsage:  LZMA <e|d> [<switches>...] inputFile outputFile\n" +

+				"  e: encode file\n" +

+				"  d: decode file\n" +

+				"  b: Benchmark\n" +

+				"<Switches>\n" +

+				// "  -a{N}:  set compression mode - [0, 1], default: 1 (max)\n" +

+				"  -d{N}:  set dictionary - [0, 29], default: 23 (8MB)\n" +

+				"  -fb{N}: set number of fast bytes - [5, 273], default: 128\n" +

+				"  -lc{N}: set number of literal context bits - [0, 8], default: 3\n" +

+				"  -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" +

+				"  -pb{N}: set number of pos bits - [0, 4], default: 2\n" +

+				"  -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" +

+				"  -eos:   write End Of Stream marker\n"

+				// + "  -si:    read data from stdin\n"

+				// + "  -so:    write data to stdout\n"

+				);

+		}

+

+		static bool GetNumber(string s, out Int32 v)

+		{

+			v = 0;

+			for (int i = 0; i < s.Length; i++)

+			{

+				char c = s[i];

+				if (c < '0' || c > '9')

+					return false;

+				v *= 10;

+				v += (Int32)(c - '0');

+			}

+			return true;

+		}

+

+		static int IncorrectCommand()

+		{

+			throw (new Exception("Command line error"));

+			// System.Console.WriteLine("\nCommand line error\n");

+			// return 1;

+		}

+		static int Main2(string[] args)

+		{

+			System.Console.WriteLine("\nLZMA# 4.61  2008-11-23\n");

+

+			if (args.Length == 0)

+			{

+				PrintHelp();

+				return 0;

+			}

+

+			SwitchForm[] kSwitchForms = new SwitchForm[13];

+			int sw = 0;

+			kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false);

+			kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false);

+			kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1);

+			kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1);

+			kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1);

+			kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1);

+			kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1);

+			kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1);

+			kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1);

+			kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false);

+			kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false);

+			kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false);

+			kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1);

+

+

+			Parser parser = new Parser(sw);

+			try

+			{

+				parser.ParseStrings(kSwitchForms, args);

+			}

+			catch

+			{

+				return IncorrectCommand();

+			}

+

+			if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs)

+			{

+				PrintHelp();

+				return 0;

+			}

+

+			System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings;

+

+			int paramIndex = 0;

+			if (paramIndex >= nonSwitchStrings.Count)

+				return IncorrectCommand();

+			string command = (string)nonSwitchStrings[paramIndex++];

+			command = command.ToLower();

+

+			bool dictionaryIsDefined = false;

+			Int32 dictionary = 1 << 21;

+			if (parser[(int)Key.Dictionary].ThereIs)

+			{

+				Int32 dicLog;

+				if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog))

+					IncorrectCommand();

+				dictionary = (Int32)1 << dicLog;

+				dictionaryIsDefined = true;

+			}

+			string mf = "bt4";

+			if (parser[(int)Key.MatchFinder].ThereIs)

+				mf = (string)parser[(int)Key.MatchFinder].PostStrings[0];

+			mf = mf.ToLower();

+

+			if (command == "b")

+			{

+				const Int32 kNumDefaultItereations = 10;

+				Int32 numIterations = kNumDefaultItereations;

+				if (paramIndex < nonSwitchStrings.Count)

+					if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations))

+						numIterations = kNumDefaultItereations;

+				return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary);

+			}

+

+			string train = "";

+			if (parser[(int)Key.Train].ThereIs)

+				train = (string)parser[(int)Key.Train].PostStrings[0];

+

+			bool encodeMode = false;

+			if (command == "e")

+				encodeMode = true;

+			else if (command == "d")

+				encodeMode = false;

+			else

+				IncorrectCommand();

+

+			bool stdInMode = parser[(int)Key.StdIn].ThereIs;

+			bool stdOutMode = parser[(int)Key.StdOut].ThereIs;

+

+			Stream inStream = null;

+			if (stdInMode)

+			{

+				throw (new Exception("Not implemeted"));

+			}

+			else

+			{

+				if (paramIndex >= nonSwitchStrings.Count)

+					IncorrectCommand();

+				string inputName = (string)nonSwitchStrings[paramIndex++];

+				inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read);

+			}

+

+			FileStream outStream = null;

+			if (stdOutMode)

+			{

+				throw (new Exception("Not implemeted"));

+			}

+			else

+			{

+				if (paramIndex >= nonSwitchStrings.Count)

+					IncorrectCommand();

+				string outputName = (string)nonSwitchStrings[paramIndex++];

+				outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write);

+			}

+

+			FileStream trainStream = null;

+			if (train.Length != 0)

+				trainStream = new FileStream(train, FileMode.Open, FileAccess.Read);

+

+			if (encodeMode)

+			{

+				if (!dictionaryIsDefined)

+					dictionary = 1 << 23;

+

+				Int32 posStateBits = 2;

+				Int32 litContextBits = 3; // for normal files

+				// UInt32 litContextBits = 0; // for 32-bit data

+				Int32 litPosBits = 0;

+				// UInt32 litPosBits = 2; // for 32-bit data

+				Int32 algorithm = 2;

+				Int32 numFastBytes = 128;

+

+				bool eos = parser[(int)Key.EOS].ThereIs || stdInMode;

+

+				if (parser[(int)Key.Mode].ThereIs)

+					if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm))

+						IncorrectCommand();

+

+				if (parser[(int)Key.FastBytes].ThereIs)

+					if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes))

+						IncorrectCommand();

+				if (parser[(int)Key.LitContext].ThereIs)

+					if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits))

+						IncorrectCommand();

+				if (parser[(int)Key.LitPos].ThereIs)

+					if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits))

+						IncorrectCommand();

+				if (parser[(int)Key.PosBits].ThereIs)

+					if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits))

+						IncorrectCommand();

+

+				CoderPropID[] propIDs = 

+				{

+					CoderPropID.DictionarySize,

+					CoderPropID.PosStateBits,

+					CoderPropID.LitContextBits,

+					CoderPropID.LitPosBits,

+					CoderPropID.Algorithm,

+					CoderPropID.NumFastBytes,

+					CoderPropID.MatchFinder,

+					CoderPropID.EndMarker

+				};

+				object[] properties = 

+				{

+					(Int32)(dictionary),

+					(Int32)(posStateBits),

+					(Int32)(litContextBits),

+					(Int32)(litPosBits),

+					(Int32)(algorithm),

+					(Int32)(numFastBytes),

+					mf,

+					eos

+				};

+

+				Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder();

+				encoder.SetCoderProperties(propIDs, properties);

+				encoder.WriteCoderProperties(outStream);

+				Int64 fileSize;

+				if (eos || stdInMode)

+					fileSize = -1;

+				else

+					fileSize = inStream.Length;

+				for (int i = 0; i < 8; i++)

+					outStream.WriteByte((Byte)(fileSize >> (8 * i)));

+				if (trainStream != null)

+				{

+					CDoubleStream doubleStream = new CDoubleStream();

+					doubleStream.s1 = trainStream;

+					doubleStream.s2 = inStream;

+					doubleStream.fileIndex = 0;

+					inStream = doubleStream;

+					long trainFileSize = trainStream.Length;

+					doubleStream.skipSize = 0;

+					if (trainFileSize > dictionary)

+						doubleStream.skipSize = trainFileSize - dictionary;

+					trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin);

+					encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize));

+				}

+				encoder.Code(inStream, outStream, -1, -1, null);

+			}

+			else if (command == "d")

+			{

+				byte[] properties = new byte[5];

+				if (inStream.Read(properties, 0, 5) != 5)

+					throw (new Exception("input .lzma is too short"));

+				Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder();

+				decoder.SetDecoderProperties(properties);

+				if (trainStream != null)

+				{

+					if (!decoder.Train(trainStream))

+						throw (new Exception("can't train"));

+				}

+				long outSize = 0;

+				for (int i = 0; i < 8; i++)

+				{

+					int v = inStream.ReadByte();

+					if (v < 0)

+						throw (new Exception("Can't Read 1"));

+					outSize |= ((long)(byte)v) << (8 * i);

+				}

+				long compressedSize = inStream.Length - inStream.Position;

+				decoder.Code(inStream, outStream, compressedSize, outSize, null);

+			}

+			else

+				throw (new Exception("Command Error"));

+			return 0;

+		}

+

+		[STAThread]

+		static int Main(string[] args)

+		{

+			try

+			{

+				return Main2(args);

+			}

+			catch (Exception e)

+			{

+				Console.WriteLine("{0} Caught exception #1.", e);

+				// throw e;

+				return 1;

+			}

+		}

+	}

+}

diff --git a/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj b/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj
new file mode 100755
index 0000000..ceb7073
--- /dev/null
+++ b/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj
@@ -0,0 +1,90 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <PropertyGroup>

+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>

+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>

+    <ProductVersion>8.0.50727</ProductVersion>

+    <SchemaVersion>2.0</SchemaVersion>

+    <ProjectGuid>{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}</ProjectGuid>

+    <OutputType>Exe</OutputType>

+    <RootNamespace>LzmaAlone</RootNamespace>

+    <AssemblyName>Lzma#</AssemblyName>

+    <WarningLevel>4</WarningLevel>

+  </PropertyGroup>

+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

+    <DebugSymbols>true</DebugSymbols>

+    <DebugType>full</DebugType>

+    <Optimize>false</Optimize>

+    <OutputPath>.\bin\Debug\</OutputPath>

+    <DefineConstants>DEBUG;TRACE</DefineConstants>

+  </PropertyGroup>

+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

+    <DebugSymbols>false</DebugSymbols>

+    <Optimize>true</Optimize>

+    <OutputPath>.\bin\Release\</OutputPath>

+    <DefineConstants>TRACE</DefineConstants>

+    <PlatformTarget>AnyCPU</PlatformTarget>

+  </PropertyGroup>

+  <ItemGroup>

+    <Reference Include="System" />

+    <Reference Include="System.Data" />

+    <Reference Include="System.Xml" />

+  </ItemGroup>

+  <ItemGroup>

+    <Compile Include="..\..\Common\CommandLineParser.cs">

+      <Link>Common\CommandLineParser.cs</Link>

+    </Compile>

+    <Compile Include="..\..\Common\CRC.cs">

+      <Link>Common\CRC.cs</Link>

+    </Compile>

+    <Compile Include="..\..\ICoder.cs">

+      <Link>ICoder.cs</Link>

+    </Compile>

+    <Compile Include="..\LZ\IMatchFinder.cs">

+      <Link>LZ\IMatchFinder.cs</Link>

+    </Compile>

+    <Compile Include="..\LZ\LzBinTree.cs">

+      <Link>LZ\LzBinTree.cs</Link>

+    </Compile>

+    <Compile Include="..\LZ\LzInWindow.cs">

+      <Link>LZ\LzInWindow.cs</Link>

+    </Compile>

+    <Compile Include="..\LZ\LzOutWindow.cs">

+      <Link>LZ\LzOutWindow.cs</Link>

+    </Compile>

+    <Compile Include="..\LZMA\LzmaBase.cs">

+      <Link>LZMA\LzmaBase.cs</Link>

+    </Compile>

+    <Compile Include="..\LZMA\LzmaDecoder.cs">

+      <Link>LZMA\LzmaDecoder.cs</Link>

+    </Compile>

+    <Compile Include="..\LZMA\LzmaEncoder.cs">

+      <Link>LZMA\LzmaEncoder.cs</Link>

+    </Compile>

+    <Compile Include="..\RangeCoder\RangeCoder.cs">

+      <Link>RangeCoder\RangeCoder.cs</Link>

+    </Compile>

+    <Compile Include="..\RangeCoder\RangeCoderBit.cs">

+      <Link>RangeCoder\RangeCoderBit.cs</Link>

+    </Compile>

+    <Compile Include="..\RangeCoder\RangeCoderBitTree.cs">

+      <Link>RangeCoder\RangeCoderBitTree.cs</Link>

+    </Compile>

+    <Compile Include="LzmaAlone.cs">

+      <SubType>Code</SubType>

+    </Compile>

+    <Compile Include="LzmaBench.cs">

+      <SubType>Code</SubType>

+    </Compile>

+    <Compile Include="Properties\AssemblyInfo.cs" />

+    <Compile Include="Properties\Settings.cs">

+      <AutoGen>True</AutoGen>

+      <DependentUpon>Settings.settings</DependentUpon>

+    </Compile>

+    <None Include="Properties\Settings.settings">

+      <Generator>SettingsSingleFileGenerator</Generator>

+      <LastGenOutput>Settings.cs</LastGenOutput>

+    </None>

+    <AppDesigner Include="Properties\" />

+  </ItemGroup>

+  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />

+</Project>
\ No newline at end of file
diff --git a/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln b/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln
new file mode 100755
index 0000000..a96ee3e
--- /dev/null
+++ b/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln
@@ -0,0 +1,20 @@
+

+Microsoft Visual Studio Solution File, Format Version 9.00

+# Visual C# Express 2005

+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}"

+EndProject

+Global

+	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+		Debug|Any CPU = Debug|Any CPU

+		Release|Any CPU = Release|Any CPU

+	EndGlobalSection

+	GlobalSection(ProjectConfigurationPlatforms) = postSolution

+		{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

+		{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU

+		{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU

+		{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU

+	EndGlobalSection

+	GlobalSection(SolutionProperties) = preSolution

+		HideSolutionNode = FALSE

+	EndGlobalSection

+EndGlobal

diff --git a/CS/7zip/Compress/LzmaAlone/LzmaBench.cs b/CS/7zip/Compress/LzmaAlone/LzmaBench.cs
new file mode 100755
index 0000000..6a1ffe2
--- /dev/null
+++ b/CS/7zip/Compress/LzmaAlone/LzmaBench.cs
@@ -0,0 +1,340 @@
+// LzmaBench.cs

+

+using System;

+using System.IO;

+

+namespace SevenZip

+{

+	/// <summary>

+	/// LZMA Benchmark

+	/// </summary>

+	internal abstract class LzmaBench

+	{

+		const UInt32 kAdditionalSize = (6 << 20);

+		const UInt32 kCompressedAdditionalSize = (1 << 10);

+		const UInt32 kMaxLzmaPropSize = 10;

+

+		class CRandomGenerator

+		{

+			UInt32 A1;

+			UInt32 A2;

+			public CRandomGenerator() { Init(); }

+			public void Init() { A1 = 362436069; A2 = 521288629; }

+			public UInt32 GetRnd()

+			{

+				return

+					((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^

+					((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)));

+			}

+		};

+

+		class CBitRandomGenerator

+		{

+			CRandomGenerator RG = new CRandomGenerator();

+			UInt32 Value;

+			int NumBits;

+			public void Init()

+			{

+				Value = 0;

+				NumBits = 0;

+			}

+			public UInt32 GetRnd(int numBits)

+			{

+				UInt32 result;

+				if (NumBits > numBits)

+				{

+					result = Value & (((UInt32)1 << numBits) - 1);

+					Value >>= numBits;

+					NumBits -= numBits;

+					return result;

+				}

+				numBits -= NumBits;

+				result = (Value << numBits);

+				Value = RG.GetRnd();

+				result |= Value & (((UInt32)1 << numBits) - 1);

+				Value >>= numBits;

+				NumBits = 32 - numBits;

+				return result;

+			}

+		};

+

+		class CBenchRandomGenerator

+		{

+			CBitRandomGenerator RG = new CBitRandomGenerator();

+			UInt32 Pos;

+			UInt32 Rep0;

+			

+			public UInt32 BufferSize;

+			public Byte[] Buffer = null;

+

+			public CBenchRandomGenerator() { }

+

+			public void Set(UInt32 bufferSize)

+			{

+				Buffer = new Byte[bufferSize];

+				Pos = 0;

+				BufferSize = bufferSize;

+			}

+			UInt32 GetRndBit() { return RG.GetRnd(1); }

+			UInt32 GetLogRandBits(int numBits)

+			{

+				UInt32 len = RG.GetRnd(numBits);

+				return RG.GetRnd((int)len);

+			}

+			UInt32 GetOffset()

+			{

+				if (GetRndBit() == 0)

+					return GetLogRandBits(4);

+				return (GetLogRandBits(4) << 10) | RG.GetRnd(10);

+			}

+			UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); }

+			UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); }

+			public void Generate()

+			{

+				RG.Init();

+				Rep0 = 1;

+				while (Pos < BufferSize)

+				{

+					if (GetRndBit() == 0 || Pos < 1)

+						Buffer[Pos++] = (Byte)RG.GetRnd(8);

+					else

+					{

+						UInt32 len;

+						if (RG.GetRnd(3) == 0)

+							len = 1 + GetLen1();

+						else

+						{

+							do

+								Rep0 = GetOffset();

+							while (Rep0 >= Pos);

+							Rep0++;

+							len = 2 + GetLen2();

+						}

+						for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++)

+							Buffer[Pos] = Buffer[Pos - Rep0];

+					}

+				}

+			}

+		};

+

+		class CrcOutStream : System.IO.Stream

+		{

+			public CRC CRC = new CRC();

+			public void Init() { CRC.Init(); }

+			public UInt32 GetDigest() { return CRC.GetDigest(); }

+

+			public override bool CanRead { get { return false; } }

+			public override bool CanSeek { get { return false; } }

+			public override bool CanWrite { get { return true; } }

+			public override Int64 Length { get { return 0; } }

+			public override Int64 Position { get { return 0; } set { } }

+			public override void Flush() { }

+			public override long Seek(long offset, SeekOrigin origin) { return 0; }

+			public override void SetLength(long value) { }

+			public override int Read(byte[] buffer, int offset, int count) { return 0; }

+

+			public override void WriteByte(byte b)

+			{

+				CRC.UpdateByte(b);

+			}

+			public override void Write(byte[] buffer, int offset, int count)

+			{

+				CRC.Update(buffer, (uint)offset, (uint)count);

+			}

+		};

+

+		class CProgressInfo : ICodeProgress

+		{

+			public Int64 ApprovedStart;

+			public Int64 InSize;

+			public System.DateTime Time;

+			public void Init() { InSize = 0; }

+			public void SetProgress(Int64 inSize, Int64 outSize)

+			{

+				if (inSize >= ApprovedStart && InSize == 0)

+				{

+					Time = DateTime.UtcNow;

+					InSize = inSize;

+				}

+			}

+		}

+		const int kSubBits = 8;

+

+		static UInt32 GetLogSize(UInt32 size)

+		{

+			for (int i = kSubBits; i < 32; i++)

+				for (UInt32 j = 0; j < (1 << kSubBits); j++)

+					if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))

+						return (UInt32)(i << kSubBits) + j;

+			return (32 << kSubBits);

+		}

+

+		static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime)

+		{

+			UInt64 freq = TimeSpan.TicksPerSecond;

+			UInt64 elTime = elapsedTime;

+			while (freq > 1000000)

+			{

+				freq >>= 1;

+				elTime >>= 1;

+			}

+			if (elTime == 0)

+				elTime = 1;

+			return value * freq / elTime;

+		}

+

+		static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size)

+		{

+			UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits);

+			UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits));

+			UInt64 numCommands = (UInt64)(size) * numCommandsForOne;

+			return MyMultDiv64(numCommands, elapsedTime);

+		}

+

+		static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize)

+		{

+			UInt64 numCommands = inSize * 220 + outSize * 20;

+			return MyMultDiv64(numCommands, elapsedTime);

+		}

+

+		static UInt64 GetTotalRating(

+			UInt32 dictionarySize,

+			UInt64 elapsedTimeEn, UInt64 sizeEn,

+			UInt64 elapsedTimeDe,

+			UInt64 inSizeDe, UInt64 outSizeDe)

+		{

+			return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) +

+				GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2;

+		}

+

+		static void PrintValue(UInt64 v)

+		{

+			string s = v.ToString();

+			for (int i = 0; i + s.Length < 6; i++)

+				System.Console.Write(" ");

+			System.Console.Write(s);

+		}

+

+		static void PrintRating(UInt64 rating)

+		{

+			PrintValue(rating / 1000000);

+			System.Console.Write(" MIPS");

+		}

+

+		static void PrintResults(

+			UInt32 dictionarySize,

+			UInt64 elapsedTime,

+			UInt64 size,

+			bool decompressMode, UInt64 secondSize)

+		{

+			UInt64 speed = MyMultDiv64(size, elapsedTime);

+			PrintValue(speed / 1024);

+			System.Console.Write(" KB/s  ");

+			UInt64 rating;

+			if (decompressMode)

+				rating = GetDecompressRating(elapsedTime, size, secondSize);

+			else

+				rating = GetCompressRating(dictionarySize, elapsedTime, size);

+			PrintRating(rating);

+		}

+

+		static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize)

+		{

+			if (numIterations <= 0)

+				return 0;

+			if (dictionarySize < (1 << 18))

+			{

+				System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)");

+				return 1;

+			}

+			System.Console.Write("\n       Compressing                Decompressing\n\n");

+

+			Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder();

+			Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder();

+

+

+			CoderPropID[] propIDs = 

+			{ 

+				CoderPropID.DictionarySize,

+			};

+			object[] properties = 

+			{

+				(Int32)(dictionarySize),

+			};

+

+			UInt32 kBufferSize = dictionarySize + kAdditionalSize;

+			UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;

+

+			encoder.SetCoderProperties(propIDs, properties);

+			System.IO.MemoryStream propStream = new System.IO.MemoryStream();

+			encoder.WriteCoderProperties(propStream);

+			byte[] propArray = propStream.ToArray();

+

+			CBenchRandomGenerator rg = new CBenchRandomGenerator();

+

+			rg.Set(kBufferSize);

+			rg.Generate();

+			CRC crc = new CRC();

+			crc.Init();

+			crc.Update(rg.Buffer, 0, rg.BufferSize);

+

+			CProgressInfo progressInfo = new CProgressInfo();

+			progressInfo.ApprovedStart = dictionarySize;

+

+			UInt64 totalBenchSize = 0;

+			UInt64 totalEncodeTime = 0;

+			UInt64 totalDecodeTime = 0;

+			UInt64 totalCompressedSize = 0;

+

+			MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize);

+			MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize);

+			CrcOutStream crcOutStream = new CrcOutStream();

+			for (Int32 i = 0; i < numIterations; i++)

+			{

+				progressInfo.Init();

+				inStream.Seek(0, SeekOrigin.Begin);

+				compressedStream.Seek(0, SeekOrigin.Begin);

+				encoder.Code(inStream, compressedStream, -1, -1, progressInfo);

+				TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time;

+				UInt64 encodeTime = (UInt64)sp2.Ticks;

+

+				long compressedSize = compressedStream.Position;

+				if (progressInfo.InSize == 0)

+					throw (new Exception("Internal ERROR 1282"));

+

+				UInt64 decodeTime = 0;

+				for (int j = 0; j < 2; j++)

+				{

+					compressedStream.Seek(0, SeekOrigin.Begin);

+					crcOutStream.Init();

+

+					decoder.SetDecoderProperties(propArray);

+					UInt64 outSize = kBufferSize;

+					System.DateTime startTime = DateTime.UtcNow;

+					decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null);

+					TimeSpan sp = (DateTime.UtcNow - startTime);

+					decodeTime = (ulong)sp.Ticks;

+					if (crcOutStream.GetDigest() != crc.GetDigest())

+						throw (new Exception("CRC Error"));

+				}

+				UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize;

+				PrintResults(dictionarySize, encodeTime, benchSize, false, 0);

+				System.Console.Write("     ");

+				PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize);

+				System.Console.WriteLine();

+

+				totalBenchSize += benchSize;

+				totalEncodeTime += encodeTime;

+				totalDecodeTime += decodeTime;

+				totalCompressedSize += (ulong)compressedSize;

+			}

+			System.Console.WriteLine("---------------------------------------------------");

+			PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0);

+			System.Console.Write("     ");

+			PrintResults(dictionarySize, totalDecodeTime,

+					kBufferSize * (UInt64)numIterations, true, totalCompressedSize);

+			System.Console.WriteLine("    Average");

+			return 0;

+		}

+	}

+}

diff --git a/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs b/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..a394aee
--- /dev/null
+++ b/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+#region Using directives

+

+using System.Reflection;

+using System.Runtime.CompilerServices;

+

+#endregion

+

+// General Information about an assembly is controlled through the following 

+// set of attributes. Change these attribute values to modify the information

+// associated with an assembly.

+[assembly: AssemblyTitle("LZMA#")]

+[assembly: AssemblyDescription("")]

+[assembly: AssemblyConfiguration("")]

+[assembly: AssemblyCompany("Igor Pavlov")]

+[assembly: AssemblyProduct("LZMA# SDK")]

+[assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")]

+[assembly: AssemblyTrademark("")]

+[assembly: AssemblyCulture("")]

+

+// Version information for an assembly consists of the following four values:

+//

+//      Major Version

+//      Minor Version 

+//      Build Number

+//      Revision

+//

+// You can specify all the values or you can default the Revision and Build Numbers 

+// by using the '*' as shown below:

+[assembly: AssemblyVersion("4.12.*")]

diff --git a/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs b/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs
new file mode 100755
index 0000000..efe4ee9
--- /dev/null
+++ b/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs
@@ -0,0 +1,70 @@
+//------------------------------------------------------------------------------

+// <autogenerated>

+//     This code was generated by a tool.

+//     Runtime Version:2.0.40607.42

+//

+//     Changes to this file may cause incorrect behavior and will be lost if

+//     the code is regenerated.

+// </autogenerated>

+//------------------------------------------------------------------------------

+

+namespace LzmaAlone.Properties

+{

+	using System;

+	using System.IO;

+	using System.Resources;

+

+	/// <summary>

+	///    A strongly-typed resource class, for looking up localized strings, etc.

+	/// </summary>

+	// This class was auto-generated by the Strongly Typed Resource Builder

+	// class via a tool like ResGen or Visual Studio.NET.

+	// To add or remove a member, edit your .ResX file then rerun ResGen

+	// with the /str option, or rebuild your VS project.

+	class Resources

+	{

+

+		private static System.Resources.ResourceManager _resMgr;

+

+		private static System.Globalization.CultureInfo _resCulture;

+

+		/*FamANDAssem*/

+		internal Resources()

+		{

+		}

+

+		/// <summary>

+		///    Returns the cached ResourceManager instance used by this class.

+		/// </summary>

+		[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]

+		public static System.Resources.ResourceManager ResourceManager

+		{

+			get

+			{

+				if ((_resMgr == null))

+				{

+					System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly);

+					_resMgr = temp;

+				}

+				return _resMgr;

+			}

+		}

+

+		/// <summary>

+		///    Overrides the current thread's CurrentUICulture property for all

+		///    resource lookups using this strongly typed resource class.

+		/// </summary>

+		[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]

+		public static System.Globalization.CultureInfo Culture

+		{

+			get

+			{

+				return _resCulture;

+			}

+			set

+			{

+				_resCulture = value;

+			}

+		}

+	}

+}

diff --git a/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs b/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs
new file mode 100755
index 0000000..1281fd2
--- /dev/null
+++ b/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs
@@ -0,0 +1,42 @@
+//------------------------------------------------------------------------------

+// <autogenerated>

+//     This code was generated by a tool.

+//     Runtime Version:2.0.40607.42

+//

+//     Changes to this file may cause incorrect behavior and will be lost if

+//     the code is regenerated.

+// </autogenerated>

+//------------------------------------------------------------------------------

+

+namespace LzmaAlone.Properties

+{

+	public partial class Settings : System.Configuration.ApplicationSettingsBase

+	{

+		private static Settings m_Value;

+

+		private static object m_SyncObject = new object();

+

+		public static Settings Value

+		{

+			get

+			{

+				if ((Settings.m_Value == null))

+				{

+					System.Threading.Monitor.Enter(Settings.m_SyncObject);

+					if ((Settings.m_Value == null))

+					{

+						try

+						{

+							Settings.m_Value = new Settings();

+						}

+						finally

+						{

+							System.Threading.Monitor.Exit(Settings.m_SyncObject);

+						}

+					}

+				}

+				return Settings.m_Value;

+			}

+		}

+	}

+}

diff --git a/CS/7zip/Compress/RangeCoder/RangeCoder.cs b/CS/7zip/Compress/RangeCoder/RangeCoder.cs
new file mode 100755
index 0000000..4ced247
--- /dev/null
+++ b/CS/7zip/Compress/RangeCoder/RangeCoder.cs
@@ -0,0 +1,234 @@
+using System;

+

+namespace SevenZip.Compression.RangeCoder

+{

+	class Encoder

+	{

+		public const uint kTopValue = (1 << 24);

+

+		System.IO.Stream Stream;

+

+		public UInt64 Low;

+		public uint Range;

+		uint _cacheSize;

+		byte _cache;

+

+		long StartPosition;

+

+		public void SetStream(System.IO.Stream stream)

+		{

+			Stream = stream;

+		}

+

+		public void ReleaseStream()

+		{

+			Stream = null;

+		}

+

+		public void Init()

+		{

+			StartPosition = Stream.Position;

+

+			Low = 0;

+			Range = 0xFFFFFFFF;

+			_cacheSize = 1;

+			_cache = 0;

+		}

+

+		public void FlushData()

+		{

+			for (int i = 0; i < 5; i++)

+				ShiftLow();

+		}

+

+		public void FlushStream()

+		{

+			Stream.Flush();

+		}

+

+		public void CloseStream()

+		{

+			Stream.Close();

+		}

+

+		public void Encode(uint start, uint size, uint total)

+		{

+			Low += start * (Range /= total);

+			Range *= size;

+			while (Range < kTopValue)

+			{

+				Range <<= 8;

+				ShiftLow();

+			}

+		}

+

+		public void ShiftLow()

+		{

+			if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)

+			{

+				byte temp = _cache;

+				do

+				{

+					Stream.WriteByte((byte)(temp + (Low >> 32)));

+					temp = 0xFF;

+				}

+				while (--_cacheSize != 0);

+				_cache = (byte)(((uint)Low) >> 24);

+			}

+			_cacheSize++;

+			Low = ((uint)Low) << 8;

+		}

+

+		public void EncodeDirectBits(uint v, int numTotalBits)

+		{

+			for (int i = numTotalBits - 1; i >= 0; i--)

+			{

+				Range >>= 1;

+				if (((v >> i) & 1) == 1)

+					Low += Range;

+				if (Range < kTopValue)

+				{

+					Range <<= 8;

+					ShiftLow();

+				}

+			}

+		}

+

+		public void EncodeBit(uint size0, int numTotalBits, uint symbol)

+		{

+			uint newBound = (Range >> numTotalBits) * size0;

+			if (symbol == 0)

+				Range = newBound;

+			else

+			{

+				Low += newBound;

+				Range -= newBound;

+			}

+			while (Range < kTopValue)

+			{

+				Range <<= 8;

+				ShiftLow();

+			}

+		}

+

+		public long GetProcessedSizeAdd()

+		{

+			return _cacheSize +

+				Stream.Position - StartPosition + 4;

+			// (long)Stream.GetProcessedSize();

+		}

+	}

+

+	class Decoder

+	{

+		public const uint kTopValue = (1 << 24);

+		public uint Range;

+		public uint Code;

+		// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);

+		public System.IO.Stream Stream;

+

+		public void Init(System.IO.Stream stream)

+		{

+			// Stream.Init(stream);

+			Stream = stream;

+

+			Code = 0;

+			Range = 0xFFFFFFFF;

+			for (int i = 0; i < 5; i++)

+				Code = (Code << 8) | (byte)Stream.ReadByte();

+		}

+

+		public void ReleaseStream()

+		{

+			// Stream.ReleaseStream();

+			Stream = null;

+		}

+

+		public void CloseStream()

+		{

+			Stream.Close();

+		}

+

+		public void Normalize()

+		{

+			while (Range < kTopValue)

+			{

+				Code = (Code << 8) | (byte)Stream.ReadByte();

+				Range <<= 8;

+			}

+		}

+

+		public void Normalize2()

+		{

+			if (Range < kTopValue)

+			{

+				Code = (Code << 8) | (byte)Stream.ReadByte();

+				Range <<= 8;

+			}

+		}

+

+		public uint GetThreshold(uint total)

+		{

+			return Code / (Range /= total);

+		}

+

+		public void Decode(uint start, uint size, uint total)

+		{

+			Code -= start * Range;

+			Range *= size;

+			Normalize();

+		}

+

+		public uint DecodeDirectBits(int numTotalBits)

+		{

+			uint range = Range;

+			uint code = Code;

+			uint result = 0;

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

+			{

+				range >>= 1;

+				/*

+				result <<= 1;

+				if (code >= range)

+				{

+					code -= range;

+					result |= 1;

+				}

+				*/

+				uint t = (code - range) >> 31;

+				code -= range & (t - 1);

+				result = (result << 1) | (1 - t);

+

+				if (range < kTopValue)

+				{

+					code = (code << 8) | (byte)Stream.ReadByte();

+					range <<= 8;

+				}

+			}

+			Range = range;

+			Code = code;

+			return result;

+		}

+

+		public uint DecodeBit(uint size0, int numTotalBits)

+		{

+			uint newBound = (Range >> numTotalBits) * size0;

+			uint symbol;

+			if (Code < newBound)

+			{

+				symbol = 0;

+				Range = newBound;

+			}

+			else

+			{

+				symbol = 1;

+				Code -= newBound;

+				Range -= newBound;

+			}

+			Normalize();

+			return symbol;

+		}

+

+		// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }

+	}

+}

diff --git a/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs b/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs
new file mode 100755
index 0000000..000a5a0
--- /dev/null
+++ b/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs
@@ -0,0 +1,117 @@
+using System;

+

+namespace SevenZip.Compression.RangeCoder

+{

+	struct BitEncoder

+	{

+		public const int kNumBitModelTotalBits = 11;

+		public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);

+		const int kNumMoveBits = 5;

+		const int kNumMoveReducingBits = 2;

+		public const int kNumBitPriceShiftBits = 6;

+

+		uint Prob;

+

+		public void Init() { Prob = kBitModelTotal >> 1; }

+

+		public void UpdateModel(uint symbol)

+		{

+			if (symbol == 0)

+				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;

+			else

+				Prob -= (Prob) >> kNumMoveBits;

+		}

+

+		public void Encode(Encoder encoder, uint symbol)

+		{

+			// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);

+			// UpdateModel(symbol);

+			uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;

+			if (symbol == 0)

+			{

+				encoder.Range = newBound;

+				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;

+			}

+			else

+			{

+				encoder.Low += newBound;

+				encoder.Range -= newBound;

+				Prob -= (Prob) >> kNumMoveBits;

+			}

+			if (encoder.Range < Encoder.kTopValue)

+			{

+				encoder.Range <<= 8;

+				encoder.ShiftLow();

+			}

+		}

+

+		private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];

+

+		static BitEncoder()

+		{

+			const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);

+			for (int i = kNumBits - 1; i >= 0; i--)

+			{

+				UInt32 start = (UInt32)1 << (kNumBits - i - 1);

+				UInt32 end = (UInt32)1 << (kNumBits - i);

+				for (UInt32 j = start; j < end; j++)

+					ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +

+						(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));

+			}

+		}

+

+		public uint GetPrice(uint symbol)

+		{

+			return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];

+		}

+	  public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }

+		public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }

+	}

+

+	struct BitDecoder

+	{

+		public const int kNumBitModelTotalBits = 11;

+		public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);

+		const int kNumMoveBits = 5;

+

+		uint Prob;

+

+		public void UpdateModel(int numMoveBits, uint symbol)

+		{

+			if (symbol == 0)

+				Prob += (kBitModelTotal - Prob) >> numMoveBits;

+			else

+				Prob -= (Prob) >> numMoveBits;

+		}

+

+		public void Init() { Prob = kBitModelTotal >> 1; }

+

+		public uint Decode(RangeCoder.Decoder rangeDecoder)

+		{

+			uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob;

+			if (rangeDecoder.Code < newBound)

+			{

+				rangeDecoder.Range = newBound;

+				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;

+				if (rangeDecoder.Range < Decoder.kTopValue)

+				{

+					rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();

+					rangeDecoder.Range <<= 8;

+				}

+				return 0;

+			}

+			else

+			{

+				rangeDecoder.Range -= newBound;

+				rangeDecoder.Code -= newBound;

+				Prob -= (Prob) >> kNumMoveBits;

+				if (rangeDecoder.Range < Decoder.kTopValue)

+				{

+					rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();

+					rangeDecoder.Range <<= 8;

+				}

+				return 1;

+			}

+		}

+	}

+}

diff --git a/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs b/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs
new file mode 100755
index 0000000..3309c14
--- /dev/null
+++ b/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs
@@ -0,0 +1,157 @@
+using System;

+

+namespace SevenZip.Compression.RangeCoder

+{

+	struct BitTreeEncoder

+	{

+		BitEncoder[] Models;

+		int NumBitLevels;

+

+		public BitTreeEncoder(int numBitLevels)

+		{

+			NumBitLevels = numBitLevels;

+			Models = new BitEncoder[1 << numBitLevels];

+		}

+

+		public void Init()

+		{

+			for (uint i = 1; i < (1 << NumBitLevels); i++)

+				Models[i].Init();

+		}

+

+		public void Encode(Encoder rangeEncoder, UInt32 symbol)

+		{

+			UInt32 m = 1;

+			for (int bitIndex = NumBitLevels; bitIndex > 0; )

+			{

+				bitIndex--;

+				UInt32 bit = (symbol >> bitIndex) & 1;

+				Models[m].Encode(rangeEncoder, bit);

+				m = (m << 1) | bit;

+			}

+		}

+

+		public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)

+		{

+			UInt32 m = 1;

+			for (UInt32 i = 0; i < NumBitLevels; i++)

+			{

+				UInt32 bit = symbol & 1;

+				Models[m].Encode(rangeEncoder, bit);

+				m = (m << 1) | bit;

+				symbol >>= 1;

+			}

+		}

+

+		public UInt32 GetPrice(UInt32 symbol)

+		{

+			UInt32 price = 0;

+			UInt32 m = 1;

+			for (int bitIndex = NumBitLevels; bitIndex > 0; )

+			{

+				bitIndex--;

+				UInt32 bit = (symbol >> bitIndex) & 1;

+				price += Models[m].GetPrice(bit);

+				m = (m << 1) + bit;

+			}

+			return price;

+		}

+

+		public UInt32 ReverseGetPrice(UInt32 symbol)

+		{

+			UInt32 price = 0;

+			UInt32 m = 1;

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

+			{

+				UInt32 bit = symbol & 1;

+				symbol >>= 1;

+				price += Models[m].GetPrice(bit);

+				m = (m << 1) | bit;

+			}

+			return price;

+		}

+

+		public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,

+			int NumBitLevels, UInt32 symbol)

+		{

+			UInt32 price = 0;

+			UInt32 m = 1;

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

+			{

+				UInt32 bit = symbol & 1;

+				symbol >>= 1;

+				price += Models[startIndex + m].GetPrice(bit);

+				m = (m << 1) | bit;

+			}

+			return price;

+		}

+

+		public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,

+			Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)

+		{

+			UInt32 m = 1;

+			for (int i = 0; i < NumBitLevels; i++)

+			{

+				UInt32 bit = symbol & 1;

+				Models[startIndex + m].Encode(rangeEncoder, bit);

+				m = (m << 1) | bit;

+				symbol >>= 1;

+			}

+		}

+	}

+

+	struct BitTreeDecoder

+	{

+		BitDecoder[] Models;

+		int NumBitLevels;

+

+		public BitTreeDecoder(int numBitLevels)

+		{

+			NumBitLevels = numBitLevels;

+			Models = new BitDecoder[1 << numBitLevels];

+		}

+

+		public void Init()

+		{

+			for (uint i = 1; i < (1 << NumBitLevels); i++)

+				Models[i].Init();

+		}

+

+		public uint Decode(RangeCoder.Decoder rangeDecoder)

+		{

+			uint m = 1;

+			for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)

+				m = (m << 1) + Models[m].Decode(rangeDecoder);

+			return m - ((uint)1 << NumBitLevels);

+		}

+

+		public uint ReverseDecode(RangeCoder.Decoder rangeDecoder)

+		{

+			uint m = 1;

+			uint symbol = 0;

+			for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)

+			{

+				uint bit = Models[m].Decode(rangeDecoder);

+				m <<= 1;

+				m += bit;

+				symbol |= (bit << bitIndex);

+			}

+			return symbol;

+		}

+

+		public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,

+			RangeCoder.Decoder rangeDecoder, int NumBitLevels)

+		{

+			uint m = 1;

+			uint symbol = 0;

+			for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)

+			{

+				uint bit = Models[startIndex + m].Decode(rangeDecoder);

+				m <<= 1;

+				m += bit;

+				symbol |= (bit << bitIndex);

+			}

+			return symbol;

+		}

+	}

+}

diff --git a/CS/7zip/ICoder.cs b/CS/7zip/ICoder.cs
new file mode 100755
index 0000000..875cb27
--- /dev/null
+++ b/CS/7zip/ICoder.cs
@@ -0,0 +1,157 @@
+// ICoder.h

+

+using System;

+

+namespace SevenZip

+{

+	/// <summary>

+	/// The exception that is thrown when an error in input stream occurs during decoding.

+	/// </summary>

+	class DataErrorException : ApplicationException

+	{

+		public DataErrorException(): base("Data Error") { }

+	}

+

+	/// <summary>

+	/// The exception that is thrown when the value of an argument is outside the allowable range.

+	/// </summary>

+	class InvalidParamException : ApplicationException

+	{

+		public InvalidParamException(): base("Invalid Parameter") { }

+	}

+

+	public interface ICodeProgress

+	{

+		/// <summary>

+		/// Callback progress.

+		/// </summary>

+		/// <param name="inSize">

+		/// input size. -1 if unknown.

+		/// </param>

+		/// <param name="outSize">

+		/// output size. -1 if unknown.

+		/// </param>

+		void SetProgress(Int64 inSize, Int64 outSize);

+	};

+

+	public interface ICoder

+	{

+		/// <summary>

+		/// Codes streams.

+		/// </summary>

+		/// <param name="inStream">

+		/// input Stream.

+		/// </param>

+		/// <param name="outStream">

+		/// output Stream.

+		/// </param>

+		/// <param name="inSize">

+		/// input Size. -1 if unknown.

+		/// </param>

+		/// <param name="outSize">

+		/// output Size. -1 if unknown.

+		/// </param>

+		/// <param name="progress">

+		/// callback progress reference.

+		/// </param>

+		/// <exception cref="SevenZip.DataErrorException">

+		/// if input stream is not valid

+		/// </exception>

+		void Code(System.IO.Stream inStream, System.IO.Stream outStream,

+			Int64 inSize, Int64 outSize, ICodeProgress progress);

+	};

+

+	/*

+	public interface ICoder2

+	{

+		 void Code(ISequentialInStream []inStreams,

+				const UInt64 []inSizes, 

+				ISequentialOutStream []outStreams, 

+				UInt64 []outSizes,

+				ICodeProgress progress);

+	};

+  */

+

+	/// <summary>

+	/// Provides the fields that represent properties idenitifiers for compressing.

+	/// </summary>

+	public enum CoderPropID

+	{

+		/// <summary>

+		/// Specifies default property.

+		/// </summary>

+		DefaultProp = 0,

+		/// <summary>

+		/// Specifies size of dictionary.

+		/// </summary>

+		DictionarySize,

+		/// <summary>

+		/// Specifies size of memory for PPM*.

+		/// </summary>

+		UsedMemorySize,

+		/// <summary>

+		/// Specifies order for PPM methods.

+		/// </summary>

+		Order,

+		/// <summary>

+		/// Specifies Block Size.

+		/// </summary>

+		BlockSize,

+		/// <summary>

+		/// Specifies number of postion state bits for LZMA (0 <= x <= 4).

+		/// </summary>

+		PosStateBits,

+		/// <summary>

+		/// Specifies number of literal context bits for LZMA (0 <= x <= 8).

+		/// </summary>

+		LitContextBits,

+		/// <summary>

+		/// Specifies number of literal position bits for LZMA (0 <= x <= 4).

+		/// </summary>

+		LitPosBits,

+		/// <summary>

+		/// Specifies number of fast bytes for LZ*.

+		/// </summary>

+		NumFastBytes,

+		/// <summary>

+		/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".

+		/// </summary>

+		MatchFinder,

+		/// <summary>

+		/// Specifies the number of match finder cyckes.

+		/// </summary>

+		MatchFinderCycles,

+		/// <summary>

+		/// Specifies number of passes.

+		/// </summary>

+		NumPasses,

+		/// <summary>

+		/// Specifies number of algorithm.

+		/// </summary>

+		Algorithm,

+		/// <summary>

+		/// Specifies the number of threads.

+		/// </summary>

+		NumThreads,

+		/// <summary>

+		/// Specifies mode with end marker.

+		/// </summary>

+		EndMarker

+	};

+

+

+	public interface ISetCoderProperties

+	{

+		void SetCoderProperties(CoderPropID[] propIDs, object[] properties);

+	};

+

+	public interface IWriteCoderProperties

+	{

+		void WriteCoderProperties(System.IO.Stream outStream);

+	}

+

+	public interface ISetDecoderProperties

+	{

+		void SetDecoderProperties(byte[] properties);

+	}

+}

diff --git a/Java/SevenZip/CRC.java b/Java/SevenZip/CRC.java
new file mode 100755
index 0000000..f2f791f
--- /dev/null
+++ b/Java/SevenZip/CRC.java
@@ -0,0 +1,52 @@
+// SevenZip/CRC.java

+

+package SevenZip;

+

+public class CRC

+{

+	static public int[] Table = new int[256];

+	

+	static

+	{

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

+		{

+			int r = i;

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

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

+					r = (r >>> 1) ^ 0xEDB88320;

+				else

+					r >>>= 1;

+			Table[i] = r;

+		}

+	}

+	

+	int _value = -1;

+	

+	public void Init()

+	{

+		_value = -1;

+	}

+	

+	public void Update(byte[] data, int offset, int size)

+	{

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

+			_value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8);

+	}

+	

+	public void Update(byte[] data)

+	{

+		int size = data.length;

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

+			_value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8);

+	}

+	

+	public void UpdateByte(int b)

+	{

+		_value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8);

+	}

+	

+	public int GetDigest()

+	{

+		return _value ^ (-1);

+	}

+}

diff --git a/Java/SevenZip/Compression/LZ/BinTree.java b/Java/SevenZip/Compression/LZ/BinTree.java
new file mode 100755
index 0000000..63d58c0
--- /dev/null
+++ b/Java/SevenZip/Compression/LZ/BinTree.java
@@ -0,0 +1,382 @@
+// LZ.BinTree

+

+package SevenZip.Compression.LZ;

+import java.io.IOException;

+

+

+public class BinTree extends InWindow

+{

+	int _cyclicBufferPos;

+	int _cyclicBufferSize = 0;

+	int _matchMaxLen;

+	

+	int[] _son;

+	int[] _hash;

+	

+	int _cutValue = 0xFF;

+	int _hashMask;

+	int _hashSizeSum = 0;

+	

+	boolean HASH_ARRAY = true;

+

+	static final int kHash2Size = 1 << 10;

+	static final int kHash3Size = 1 << 16;

+	static final int kBT2HashSize = 1 << 16;

+	static final int kStartMaxLen = 1;

+	static final int kHash3Offset = kHash2Size;

+	static final int kEmptyHashValue = 0;

+	static final int kMaxValForNormalize = (1 << 30) - 1;

+	

+	int kNumHashDirectBytes = 0;

+	int kMinMatchCheck = 4;

+	int kFixHashSize = kHash2Size + kHash3Size;

+

+	public void SetType(int numHashBytes)

+	{

+		HASH_ARRAY = (numHashBytes > 2);

+		if (HASH_ARRAY)

+		{

+			kNumHashDirectBytes = 0;

+			kMinMatchCheck = 4;

+			kFixHashSize = kHash2Size + kHash3Size;

+		}

+		else

+		{

+			kNumHashDirectBytes = 2;

+			kMinMatchCheck = 2 + 1;

+			kFixHashSize = 0;

+		}

+	}

+	

+

+	

+

+	public void Init() throws IOException

+	{

+		super.Init();

+		for (int i = 0; i < _hashSizeSum; i++)

+			_hash[i] = kEmptyHashValue;

+		_cyclicBufferPos = 0;

+		ReduceOffsets(-1);

+	}

+	

+	public void MovePos() throws IOException

+	{

+		if (++_cyclicBufferPos >= _cyclicBufferSize)

+			_cyclicBufferPos = 0;

+		super.MovePos();

+		if (_pos == kMaxValForNormalize)

+			Normalize();

+	}

+	

+

+	

+	

+	

+	

+	

+	

+	public boolean Create(int historySize, int keepAddBufferBefore,

+			int matchMaxLen, int keepAddBufferAfter)

+	{

+		if (historySize > kMaxValForNormalize - 256)

+			return false;

+		_cutValue = 16 + (matchMaxLen >> 1);

+

+		int windowReservSize = (historySize + keepAddBufferBefore +

+				matchMaxLen + keepAddBufferAfter) / 2 + 256;

+		

+		super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);

+		

+		_matchMaxLen = matchMaxLen;

+

+		int cyclicBufferSize = historySize + 1;

+		if (_cyclicBufferSize != cyclicBufferSize)

+			_son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2];

+

+		int hs = kBT2HashSize;

+

+		if (HASH_ARRAY)

+		{

+			hs = historySize - 1;

+			hs |= (hs >> 1);

+			hs |= (hs >> 2);

+			hs |= (hs >> 4);

+			hs |= (hs >> 8);

+			hs >>= 1;

+			hs |= 0xFFFF;

+			if (hs > (1 << 24))

+				hs >>= 1;

+			_hashMask = hs;

+			hs++;

+			hs += kFixHashSize;

+		}

+		if (hs != _hashSizeSum)

+			_hash = new int [_hashSizeSum = hs];

+		return true;

+	}

+	public int GetMatches(int[] distances) throws IOException

+	{

+		int lenLimit;

+		if (_pos + _matchMaxLen <= _streamPos)

+			lenLimit = _matchMaxLen;

+		else

+		{

+			lenLimit = _streamPos - _pos;

+			if (lenLimit < kMinMatchCheck)

+			{

+				MovePos();

+				return 0;

+			}

+		}

+

+		int offset = 0;

+		int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;

+		int cur = _bufferOffset + _pos;

+		int maxLen = kStartMaxLen; // to avoid items for len < hashSize;

+		int hashValue, hash2Value = 0, hash3Value = 0;

+		

+		if (HASH_ARRAY)

+		{

+			int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF);

+			hash2Value = temp & (kHash2Size - 1);

+			temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8);

+			hash3Value = temp & (kHash3Size - 1);

+			hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask;

+		}

+		else

+			hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8));

+

+		int curMatch = _hash[kFixHashSize + hashValue];

+		if (HASH_ARRAY)

+		{

+			int curMatch2 = _hash[hash2Value];

+			int curMatch3 = _hash[kHash3Offset + hash3Value];

+			_hash[hash2Value] = _pos;

+			_hash[kHash3Offset + hash3Value] = _pos;

+			if (curMatch2 > matchMinPos)

+				if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])

+				{

+					distances[offset++] = maxLen = 2;

+					distances[offset++] = _pos - curMatch2 - 1;

+				}

+			if (curMatch3 > matchMinPos)

+				if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])

+				{

+					if (curMatch3 == curMatch2)

+						offset -= 2;

+					distances[offset++] = maxLen = 3;

+					distances[offset++] = _pos - curMatch3 - 1;

+					curMatch2 = curMatch3;

+				}

+			if (offset != 0 && curMatch2 == curMatch)

+			{

+				offset -= 2;

+				maxLen = kStartMaxLen;

+			}

+		}

+

+		_hash[kFixHashSize + hashValue] = _pos;

+

+		int ptr0 = (_cyclicBufferPos << 1) + 1;

+		int ptr1 = (_cyclicBufferPos << 1);

+

+		int len0, len1;

+		len0 = len1 = kNumHashDirectBytes;

+

+		if (kNumHashDirectBytes != 0)

+		{

+			if (curMatch > matchMinPos)

+			{

+				if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=

+						_bufferBase[cur + kNumHashDirectBytes])

+				{

+					distances[offset++] = maxLen = kNumHashDirectBytes;

+					distances[offset++] = _pos - curMatch - 1;

+				}

+			}

+		}

+

+		int count = _cutValue;

+

+		while (true)

+		{

+			if (curMatch <= matchMinPos || count-- == 0)

+			{

+				_son[ptr0] = _son[ptr1] = kEmptyHashValue;

+				break;

+			}

+			int delta = _pos - curMatch;

+			int cyclicPos = ((delta <= _cyclicBufferPos) ?

+				(_cyclicBufferPos - delta) :

+				(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;

+

+			int pby1 = _bufferOffset + curMatch;

+			int len = Math.min(len0, len1);

+			if (_bufferBase[pby1 + len] == _bufferBase[cur + len])

+			{

+				while(++len != lenLimit)

+					if (_bufferBase[pby1 + len] != _bufferBase[cur + len])

+						break;

+				if (maxLen < len)

+				{

+					distances[offset++] = maxLen = len;

+					distances[offset++] = delta - 1;

+					if (len == lenLimit)

+					{

+						_son[ptr1] = _son[cyclicPos];

+						_son[ptr0] = _son[cyclicPos + 1];

+						break;

+					}

+				}

+			}

+			if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF))

+			{

+				_son[ptr1] = curMatch;

+				ptr1 = cyclicPos + 1;

+				curMatch = _son[ptr1];

+				len1 = len;

+			}

+			else

+			{

+				_son[ptr0] = curMatch;

+				ptr0 = cyclicPos;

+				curMatch = _son[ptr0];

+				len0 = len;

+			}

+		}

+		MovePos();

+		return offset;

+	}

+

+	public void Skip(int num) throws IOException

+	{

+		do

+		{

+			int lenLimit;

+			if (_pos + _matchMaxLen <= _streamPos)

+			lenLimit = _matchMaxLen;

+			else

+			{

+				lenLimit = _streamPos - _pos;

+				if (lenLimit < kMinMatchCheck)

+				{

+					MovePos();

+					continue;

+				}

+			}

+

+			int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;

+			int cur = _bufferOffset + _pos;

+			

+			int hashValue;

+

+			if (HASH_ARRAY)

+			{

+				int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF);

+				int hash2Value = temp & (kHash2Size - 1);

+				_hash[hash2Value] = _pos;

+				temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8);

+				int hash3Value = temp & (kHash3Size - 1);

+				_hash[kHash3Offset + hash3Value] = _pos;

+				hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask;

+			}

+			else

+				hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8));

+

+			int curMatch = _hash[kFixHashSize + hashValue];

+			_hash[kFixHashSize + hashValue] = _pos;

+

+			int ptr0 = (_cyclicBufferPos << 1) + 1;

+			int ptr1 = (_cyclicBufferPos << 1);

+

+			int len0, len1;

+			len0 = len1 = kNumHashDirectBytes;

+

+			int count = _cutValue;

+			while (true)

+			{

+				if (curMatch <= matchMinPos || count-- == 0)

+				{

+					_son[ptr0] = _son[ptr1] = kEmptyHashValue;

+					break;

+				}

+

+				int delta = _pos - curMatch;

+				int cyclicPos = ((delta <= _cyclicBufferPos) ?

+					(_cyclicBufferPos - delta) :

+					(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;

+

+				int pby1 = _bufferOffset + curMatch;

+				int len = Math.min(len0, len1);

+				if (_bufferBase[pby1 + len] == _bufferBase[cur + len])

+				{

+					while (++len != lenLimit)

+						if (_bufferBase[pby1 + len] != _bufferBase[cur + len])

+							break;

+					if (len == lenLimit)

+					{

+						_son[ptr1] = _son[cyclicPos];

+						_son[ptr0] = _son[cyclicPos + 1];

+						break;

+					}

+				}

+				if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF))

+				{

+					_son[ptr1] = curMatch;

+					ptr1 = cyclicPos + 1;

+					curMatch = _son[ptr1];

+					len1 = len;

+				}

+				else

+				{

+					_son[ptr0] = curMatch;

+					ptr0 = cyclicPos;

+					curMatch = _son[ptr0];

+					len0 = len;

+				}

+			}

+			MovePos();

+		}

+		while (--num != 0);

+	}

+	

+	void NormalizeLinks(int[] items, int numItems, int subValue)

+	{

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

+		{

+			int value = items[i];

+			if (value <= subValue)

+				value = kEmptyHashValue;

+			else

+				value -= subValue;

+			items[i] = value;

+		}

+	}

+	

+	void Normalize()

+	{

+		int subValue = _pos - _cyclicBufferSize;

+		NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);

+		NormalizeLinks(_hash, _hashSizeSum, subValue);

+		ReduceOffsets(subValue);

+	}

+	

+	public void SetCutValue(int cutValue) { _cutValue = cutValue; }

+

+	private static final int[] CrcTable = new int[256];

+

+	static

+	{

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

+		{

+			int r = i;

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

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

+					r = (r >>> 1) ^ 0xEDB88320;

+				else

+					r >>>= 1;

+			CrcTable[i] = r;

+		}

+	}

+}

diff --git a/Java/SevenZip/Compression/LZ/InWindow.java b/Java/SevenZip/Compression/LZ/InWindow.java
new file mode 100755
index 0000000..5f3f0b4
--- /dev/null
+++ b/Java/SevenZip/Compression/LZ/InWindow.java
@@ -0,0 +1,131 @@
+// LZ.InWindow

+

+package SevenZip.Compression.LZ;

+

+import java.io.IOException;

+

+public class InWindow

+{

+	public byte[] _bufferBase; // pointer to buffer with data

+	java.io.InputStream _stream;

+	int _posLimit;  // offset (from _buffer) of first byte when new block reading must be done

+	boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream

+	

+	int _pointerToLastSafePosition;

+	

+	public int _bufferOffset;

+	

+	public int _blockSize;  // Size of Allocated memory block

+	public int _pos;             // offset (from _buffer) of curent byte

+	int _keepSizeBefore;  // how many BYTEs must be kept in buffer before _pos

+	int _keepSizeAfter;   // how many BYTEs must be kept buffer after _pos

+	public int _streamPos;   // offset (from _buffer) of first not read byte from Stream

+	

+	public void MoveBlock()

+	{

+		int offset = _bufferOffset + _pos - _keepSizeBefore;

+		// we need one additional byte, since MovePos moves on 1 byte.

+		if (offset > 0)

+			offset--;

+

+		int numBytes = _bufferOffset + _streamPos - offset;

+		

+		// check negative offset ????

+		for (int i = 0; i < numBytes; i++)

+			_bufferBase[i] = _bufferBase[offset + i];

+		_bufferOffset -= offset;

+	}

+	

+	public void ReadBlock() throws IOException

+	{

+		if (_streamEndWasReached)

+			return;

+		while (true)

+		{

+			int size = (0 - _bufferOffset) + _blockSize - _streamPos;

+			if (size == 0)

+				return;

+			int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size);

+			if (numReadBytes == -1)

+			{

+				_posLimit = _streamPos;

+				int pointerToPostion = _bufferOffset + _posLimit;

+				if (pointerToPostion > _pointerToLastSafePosition)

+					_posLimit = _pointerToLastSafePosition - _bufferOffset;

+				

+				_streamEndWasReached = true;

+				return;

+			}

+			_streamPos += numReadBytes;

+			if (_streamPos >= _pos + _keepSizeAfter)

+				_posLimit = _streamPos - _keepSizeAfter;

+		}

+	}

+	

+	void Free() { _bufferBase = null; }

+	

+	public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv)

+	{

+		_keepSizeBefore = keepSizeBefore;

+		_keepSizeAfter = keepSizeAfter;

+		int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;

+		if (_bufferBase == null || _blockSize != blockSize)

+		{

+			Free();

+			_blockSize = blockSize;

+			_bufferBase = new byte[_blockSize];

+		}

+		_pointerToLastSafePosition = _blockSize - keepSizeAfter;

+	}

+	

+	public void SetStream(java.io.InputStream stream) { _stream = stream; 	}

+	public void ReleaseStream() { _stream = null; }

+

+	public void Init() throws IOException

+	{

+		_bufferOffset = 0;

+		_pos = 0;

+		_streamPos = 0;

+		_streamEndWasReached = false;

+		ReadBlock();

+	}

+	

+	public void MovePos() throws IOException

+	{

+		_pos++;

+		if (_pos > _posLimit)

+		{

+			int pointerToPostion = _bufferOffset + _pos;

+			if (pointerToPostion > _pointerToLastSafePosition)

+				MoveBlock();

+			ReadBlock();

+		}

+	}

+	

+	public byte GetIndexByte(int index)	{ return _bufferBase[_bufferOffset + _pos + index]; }

+	

+	// index + limit have not to exceed _keepSizeAfter;

+	public int GetMatchLen(int index, int distance, int limit)

+	{

+		if (_streamEndWasReached)

+			if ((_pos + index) + limit > _streamPos)

+				limit = _streamPos - (_pos + index);

+		distance++;

+		// Byte *pby = _buffer + (size_t)_pos + index;

+		int pby = _bufferOffset + _pos + index;

+		

+		int i;

+		for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);

+		return i;

+	}

+	

+	public int GetNumAvailableBytes()	{ return _streamPos - _pos; }

+	

+	public void ReduceOffsets(int subValue)

+	{

+		_bufferOffset += subValue;

+		_posLimit -= subValue;

+		_pos -= subValue;

+		_streamPos -= subValue;

+	}

+}

diff --git a/Java/SevenZip/Compression/LZ/OutWindow.java b/Java/SevenZip/Compression/LZ/OutWindow.java
new file mode 100755
index 0000000..620cb41
--- /dev/null
+++ b/Java/SevenZip/Compression/LZ/OutWindow.java
@@ -0,0 +1,85 @@
+// LZ.OutWindow

+

+package SevenZip.Compression.LZ;

+

+import java.io.IOException;

+

+public class OutWindow

+{

+	byte[] _buffer;

+	int _pos;

+	int _windowSize = 0;

+	int _streamPos;

+	java.io.OutputStream _stream;

+	

+	public void Create(int windowSize)

+	{

+		if (_buffer == null || _windowSize != windowSize)

+			_buffer = new byte[windowSize];

+		_windowSize = windowSize;

+		_pos = 0;

+		_streamPos = 0;

+	}

+	

+	public void SetStream(java.io.OutputStream stream) throws IOException

+	{

+		ReleaseStream();

+		_stream = stream;

+	}

+	

+	public void ReleaseStream() throws IOException

+	{

+		Flush();

+		_stream = null;

+	}

+	

+	public void Init(boolean solid)

+	{

+		if (!solid)

+		{

+			_streamPos = 0;

+			_pos = 0;

+		}

+	}

+	

+	public void Flush() throws IOException

+	{

+		int size = _pos - _streamPos;

+		if (size == 0)

+			return;

+		_stream.write(_buffer, _streamPos, size);

+		if (_pos >= _windowSize)

+			_pos = 0;

+		_streamPos = _pos;

+	}

+	

+	public void CopyBlock(int distance, int len) throws IOException

+	{

+		int pos = _pos - distance - 1;

+		if (pos < 0)

+			pos += _windowSize;

+		for (; len != 0; len--)

+		{

+			if (pos >= _windowSize)

+				pos = 0;

+			_buffer[_pos++] = _buffer[pos++];

+			if (_pos >= _windowSize)

+				Flush();

+		}

+	}

+	

+	public void PutByte(byte b) throws IOException

+	{

+		_buffer[_pos++] = b;

+		if (_pos >= _windowSize)

+			Flush();

+	}

+	

+	public byte GetByte(int distance)

+	{

+		int pos = _pos - distance - 1;

+		if (pos < 0)

+			pos += _windowSize;

+		return _buffer[pos];

+	}

+}

diff --git a/Java/SevenZip/Compression/LZMA/Base.java b/Java/SevenZip/Compression/LZMA/Base.java
new file mode 100755
index 0000000..18deed9
--- /dev/null
+++ b/Java/SevenZip/Compression/LZMA/Base.java
@@ -0,0 +1,88 @@
+// Base.java

+

+package SevenZip.Compression.LZMA;

+

+public class Base

+{

+	public static final int kNumRepDistances = 4;

+	public static final int kNumStates = 12;

+	

+	public static final int StateInit()

+	{

+		return 0;

+	}

+	

+	public static final int StateUpdateChar(int index)

+	{

+		if (index < 4) 

+			return 0;

+		if (index < 10) 

+			return index - 3;

+		return index - 6;

+	}

+	

+	public static final int StateUpdateMatch(int index)

+	{

+		return (index < 7 ? 7 : 10); 

+	}

+

+	public static final int StateUpdateRep(int index)

+	{ 

+		return (index < 7 ? 8 : 11); 

+	}

+	

+	public static final int StateUpdateShortRep(int index)

+	{ 

+		return (index < 7 ? 9 : 11); 

+	}

+

+	public static final boolean StateIsCharState(int index)

+	{ 

+		return index < 7; 

+	}

+	

+	public static final int kNumPosSlotBits = 6;

+	public static final int kDicLogSizeMin = 0;

+	// public static final int kDicLogSizeMax = 28;

+	// public static final int kDistTableSizeMax = kDicLogSizeMax * 2;

+	

+	public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization

+	public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits;

+	

+	public static final int kMatchMinLen = 2;

+	

+	public static final int GetLenToPosState(int len)

+	{

+		len -= kMatchMinLen;

+		if (len < kNumLenToPosStates)

+			return len;

+		return (int)(kNumLenToPosStates - 1);

+	}

+	

+	public static final int kNumAlignBits = 4;

+	public static final int kAlignTableSize = 1 << kNumAlignBits;

+	public static final int kAlignMask = (kAlignTableSize - 1);

+	

+	public static final int kStartPosModelIndex = 4;

+	public static final int kEndPosModelIndex = 14;

+	public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;

+	

+	public static final  int kNumFullDistances = 1 << (kEndPosModelIndex / 2);

+	

+	public static final  int kNumLitPosStatesBitsEncodingMax = 4;

+	public static final  int kNumLitContextBitsMax = 8;

+	

+	public static final  int kNumPosStatesBitsMax = 4;

+	public static final  int kNumPosStatesMax = (1 << kNumPosStatesBitsMax);

+	public static final  int kNumPosStatesBitsEncodingMax = 4;

+	public static final  int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);

+	

+	public static final  int kNumLowLenBits = 3;

+	public static final  int kNumMidLenBits = 3;

+	public static final  int kNumHighLenBits = 8;

+	public static final  int kNumLowLenSymbols = 1 << kNumLowLenBits;

+	public static final  int kNumMidLenSymbols = 1 << kNumMidLenBits;

+	public static final  int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +

+			(1 << kNumHighLenBits);

+	public static final  int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;

+}

diff --git a/Java/SevenZip/Compression/LZMA/Decoder.java b/Java/SevenZip/Compression/LZMA/Decoder.java
new file mode 100755
index 0000000..4ebd571
--- /dev/null
+++ b/Java/SevenZip/Compression/LZMA/Decoder.java
@@ -0,0 +1,329 @@
+package SevenZip.Compression.LZMA;

+

+import SevenZip.Compression.RangeCoder.BitTreeDecoder;

+import SevenZip.Compression.LZMA.Base;

+import SevenZip.Compression.LZ.OutWindow;

+import java.io.IOException;

+

+public class Decoder

+{

+	class LenDecoder

+	{

+		short[] m_Choice = new short[2];

+		BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];

+		BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];

+		BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);

+		int m_NumPosStates = 0;

+		

+		public void Create(int numPosStates)

+		{

+			for (; m_NumPosStates < numPosStates; m_NumPosStates++)

+			{

+				m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits);

+				m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits);

+			}

+		}

+		

+		public void Init()

+		{

+			SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice);

+			for (int posState = 0; posState < m_NumPosStates; posState++)

+			{

+				m_LowCoder[posState].Init();

+				m_MidCoder[posState].Init();

+			}

+			m_HighCoder.Init();

+		}

+		

+		public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException

+		{

+			if (rangeDecoder.DecodeBit(m_Choice, 0) == 0)

+				return m_LowCoder[posState].Decode(rangeDecoder);

+			int symbol = Base.kNumLowLenSymbols;

+			if (rangeDecoder.DecodeBit(m_Choice, 1) == 0)

+				symbol += m_MidCoder[posState].Decode(rangeDecoder);

+			else

+				symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder);

+			return symbol;

+		}

+	}

+	

+	class LiteralDecoder

+	{

+		class Decoder2

+		{

+			short[] m_Decoders = new short[0x300];

+			

+			public void Init()

+			{

+				SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders);

+			}

+			

+			public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException

+			{

+				int symbol = 1;

+				do

+					symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol);

+				while (symbol < 0x100);

+				return (byte)symbol;

+			}

+			

+			public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException

+			{

+				int symbol = 1;

+				do

+				{

+					int matchBit = (matchByte >> 7) & 1;

+					matchByte <<= 1;

+					int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol);

+					symbol = (symbol << 1) | bit;

+					if (matchBit != bit)

+					{

+						while (symbol < 0x100)

+							symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol);

+						break;

+					}

+				}

+				while (symbol < 0x100);

+				return (byte)symbol;

+			}

+		}

+		

+		Decoder2[] m_Coders;

+		int m_NumPrevBits;

+		int m_NumPosBits;

+		int m_PosMask;

+		

+		public void Create(int numPosBits, int numPrevBits)

+		{

+			if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)

+				return;

+			m_NumPosBits = numPosBits;

+			m_PosMask = (1 << numPosBits) - 1;

+			m_NumPrevBits = numPrevBits;

+			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);

+			m_Coders = new Decoder2[numStates];

+			for (int i = 0; i < numStates; i++)

+				m_Coders[i] = new Decoder2();

+		}

+		

+		public void Init()

+		{

+			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);

+			for (int i = 0; i < numStates; i++)

+				m_Coders[i].Init();

+		}

+		

+		Decoder2 GetDecoder(int pos, byte prevByte)

+		{

+			return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))];

+		}

+	}

+	

+	OutWindow m_OutWindow = new OutWindow();

+	SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder();

+	

+	short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];

+	short[] m_IsRepDecoders = new short[Base.kNumStates];

+	short[] m_IsRepG0Decoders = new short[Base.kNumStates];

+	short[] m_IsRepG1Decoders = new short[Base.kNumStates];

+	short[] m_IsRepG2Decoders = new short[Base.kNumStates];

+	short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];

+	

+	BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];

+	short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex];

+	

+	BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);

+	

+	LenDecoder m_LenDecoder = new LenDecoder();

+	LenDecoder m_RepLenDecoder = new LenDecoder();

+	

+	LiteralDecoder m_LiteralDecoder = new LiteralDecoder();

+	

+	int m_DictionarySize = -1;

+	int m_DictionarySizeCheck =  -1;

+	

+	int m_PosStateMask;

+	

+	public Decoder()

+	{

+		for (int i = 0; i < Base.kNumLenToPosStates; i++)

+			m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);

+	}

+	

+	boolean SetDictionarySize(int dictionarySize)

+	{

+		if (dictionarySize < 0)

+			return false;

+		if (m_DictionarySize != dictionarySize)

+		{

+			m_DictionarySize = dictionarySize;

+			m_DictionarySizeCheck = Math.max(m_DictionarySize, 1);

+			m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12)));

+		}

+		return true;

+	}

+	

+	boolean SetLcLpPb(int lc, int lp, int pb)

+	{

+		if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax)

+			return false;

+		m_LiteralDecoder.Create(lp, lc);

+		int numPosStates = 1 << pb;

+		m_LenDecoder.Create(numPosStates);

+		m_RepLenDecoder.Create(numPosStates);

+		m_PosStateMask = numPosStates - 1;

+		return true;

+	}

+	

+	void Init() throws IOException

+	{

+		m_OutWindow.Init(false);

+		

+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders);

+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders);

+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders);

+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders);

+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders);

+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders);

+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders);

+		

+		m_LiteralDecoder.Init();

+		int i;

+		for (i = 0; i < Base.kNumLenToPosStates; i++)

+			m_PosSlotDecoder[i].Init();

+		m_LenDecoder.Init();

+		m_RepLenDecoder.Init();

+		m_PosAlignDecoder.Init();

+		m_RangeDecoder.Init();

+	}

+	

+	public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream,

+			long outSize) throws IOException

+	{

+		m_RangeDecoder.SetStream(inStream);

+		m_OutWindow.SetStream(outStream);

+		Init();

+		

+		int state = Base.StateInit();

+		int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;

+		

+		long nowPos64 = 0;

+		byte prevByte = 0;

+		while (outSize < 0 || nowPos64 < outSize)

+		{

+			int posState = (int)nowPos64 & m_PosStateMask;

+			if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0)

+			{

+				LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte);

+				if (!Base.StateIsCharState(state))

+					prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0));

+				else

+					prevByte = decoder2.DecodeNormal(m_RangeDecoder);

+				m_OutWindow.PutByte(prevByte);

+				state = Base.StateUpdateChar(state);

+				nowPos64++;

+			}

+			else

+			{

+				int len;

+				if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1)

+				{

+					len = 0;

+					if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0)

+					{

+						if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0)

+						{

+							state = Base.StateUpdateShortRep(state);

+							len = 1;

+						}

+					}

+					else

+					{

+						int distance;

+						if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0)

+							distance = rep1;

+						else

+						{

+							if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0)

+								distance = rep2;

+							else

+							{

+								distance = rep3;

+								rep3 = rep2;

+							}

+							rep2 = rep1;

+						}

+						rep1 = rep0;

+						rep0 = distance;

+					}

+					if (len == 0)

+					{

+						len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;

+						state = Base.StateUpdateRep(state);

+					}

+				}

+				else

+				{

+					rep3 = rep2;

+					rep2 = rep1;

+					rep1 = rep0;

+					len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);

+					state = Base.StateUpdateMatch(state);

+					int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);

+					if (posSlot >= Base.kStartPosModelIndex)

+					{

+						int numDirectBits = (posSlot >> 1) - 1;

+						rep0 = ((2 | (posSlot & 1)) << numDirectBits);

+						if (posSlot < Base.kEndPosModelIndex)

+							rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,

+									rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);

+						else

+						{

+							rep0 += (m_RangeDecoder.DecodeDirectBits(

+									numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);

+							rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);

+							if (rep0 < 0)

+							{

+								if (rep0 == -1)

+									break;

+								return false;

+							}

+						}

+					}

+					else

+						rep0 = posSlot;

+				}

+				if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck)

+				{

+					// m_OutWindow.Flush();

+					return false;

+				}

+				m_OutWindow.CopyBlock(rep0, len);

+				nowPos64 += len;

+				prevByte = m_OutWindow.GetByte(0);

+			}

+		}

+		m_OutWindow.Flush();

+		m_OutWindow.ReleaseStream();

+		m_RangeDecoder.ReleaseStream();

+		return true;

+	}

+	

+	public boolean SetDecoderProperties(byte[] properties)

+	{

+		if (properties.length < 5)

+			return false;

+		int val = properties[0] & 0xFF;

+		int lc = val % 9;

+		int remainder = val / 9;

+		int lp = remainder % 5;

+		int pb = remainder / 5;

+		int dictionarySize = 0;

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

+			dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8);

+		if (!SetLcLpPb(lc, lp, pb))

+			return false;

+		return SetDictionarySize(dictionarySize);

+	}

+}

diff --git a/Java/SevenZip/Compression/LZMA/Encoder.java b/Java/SevenZip/Compression/LZMA/Encoder.java
new file mode 100755
index 0000000..771fb21
--- /dev/null
+++ b/Java/SevenZip/Compression/LZMA/Encoder.java
@@ -0,0 +1,1416 @@
+package SevenZip.Compression.LZMA;

+

+import SevenZip.Compression.RangeCoder.BitTreeEncoder;

+import SevenZip.Compression.LZMA.Base;

+import SevenZip.Compression.LZ.BinTree;

+import SevenZip.ICodeProgress;

+import java.io.IOException;

+

+public class Encoder

+{

+	public static final int EMatchFinderTypeBT2 = 0;

+	public static final int EMatchFinderTypeBT4 = 1;

+

+

+

+

+	static final int kIfinityPrice = 0xFFFFFFF;

+

+	static byte[] g_FastPos = new byte[1 << 11];

+

+	static

+	{

+		int kFastSlots = 22;

+		int c = 2;

+		g_FastPos[0] = 0;

+		g_FastPos[1] = 1;

+		for (int slotFast = 2; slotFast < kFastSlots; slotFast++)

+		{

+			int k = (1 << ((slotFast >> 1) - 1));

+			for (int j = 0; j < k; j++, c++)

+				g_FastPos[c] = (byte)slotFast;

+		}

+	}

+

+	static int GetPosSlot(int pos)

+	{

+		if (pos < (1 << 11))

+			return g_FastPos[pos];

+		if (pos < (1 << 21))

+			return (g_FastPos[pos >> 10] + 20);

+		return (g_FastPos[pos >> 20] + 40);

+	}

+

+	static int GetPosSlot2(int pos)

+	{

+		if (pos < (1 << 17))

+			return (g_FastPos[pos >> 6] + 12);

+		if (pos < (1 << 27))

+			return (g_FastPos[pos >> 16] + 32);

+		return (g_FastPos[pos >> 26] + 52);

+	}

+

+	int _state = Base.StateInit();

+	byte _previousByte;

+	int[] _repDistances = new int[Base.kNumRepDistances];

+

+	void BaseInit()

+	{

+		_state = Base.StateInit();

+		_previousByte = 0;

+		for (int i = 0; i < Base.kNumRepDistances; i++)

+			_repDistances[i] = 0;

+	}

+

+	static final int kDefaultDictionaryLogSize = 22;

+	static final int kNumFastBytesDefault = 0x20;

+

+	class LiteralEncoder

+	{

+		class Encoder2

+		{

+			short[] m_Encoders = new short[0x300];

+

+			public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); }

+

+

+

+			public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException

+			{

+				int context = 1;

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

+				{

+					int bit = ((symbol >> i) & 1);

+					rangeEncoder.Encode(m_Encoders, context, bit);

+					context = (context << 1) | bit;

+				}

+			}

+

+			public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException

+			{

+				int context = 1;

+				boolean same = true;

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

+				{

+					int bit = ((symbol >> i) & 1);

+					int state = context;

+					if (same)

+					{

+						int matchBit = ((matchByte >> i) & 1);

+						state += ((1 + matchBit) << 8);

+						same = (matchBit == bit);

+					}

+					rangeEncoder.Encode(m_Encoders, state, bit);

+					context = (context << 1) | bit;

+				}

+			}

+

+			public int GetPrice(boolean matchMode, byte matchByte, byte symbol)

+			{

+				int price = 0;

+				int context = 1;

+				int i = 7;

+				if (matchMode)

+				{

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

+					{

+						int matchBit = (matchByte >> i) & 1;

+						int bit = (symbol >> i) & 1;

+						price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit);

+						context = (context << 1) | bit;

+						if (matchBit != bit)

+						{

+							i--;

+							break;

+						}

+					}

+				}

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

+				{

+					int bit = (symbol >> i) & 1;

+					price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit);

+					context = (context << 1) | bit;

+				}

+				return price;

+			}

+		}

+

+		Encoder2[] m_Coders;

+		int m_NumPrevBits;

+		int m_NumPosBits;

+		int m_PosMask;

+

+		public void Create(int numPosBits, int numPrevBits)

+		{

+			if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)

+				return;

+			m_NumPosBits = numPosBits;

+			m_PosMask = (1 << numPosBits) - 1;

+			m_NumPrevBits = numPrevBits;

+			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);

+			m_Coders = new Encoder2[numStates];

+			for (int i = 0; i < numStates; i++)

+				m_Coders[i] = new Encoder2();

+		}

+

+		public void Init()

+		{

+			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);

+			for (int i = 0; i < numStates; i++)

+				m_Coders[i].Init();

+		}

+

+		public Encoder2 GetSubCoder(int pos, byte prevByte)

+		{ return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; }

+	}

+

+	class LenEncoder

+	{

+		short[] _choice = new short[2];

+		BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];

+		BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];

+		BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits);

+

+

+		public LenEncoder()

+		{

+			for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)

+			{

+				_lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits);

+				_midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits);

+			}

+		}

+

+		public void Init(int numPosStates)

+		{

+			SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice);

+

+			for (int posState = 0; posState < numPosStates; posState++)

+			{

+				_lowCoder[posState].Init();

+				_midCoder[posState].Init();

+			}

+			_highCoder.Init();

+		}

+

+		public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException

+		{

+			if (symbol < Base.kNumLowLenSymbols)

+			{

+				rangeEncoder.Encode(_choice, 0, 0);

+				_lowCoder[posState].Encode(rangeEncoder, symbol);

+			}

+			else

+			{

+				symbol -= Base.kNumLowLenSymbols;

+				rangeEncoder.Encode(_choice, 0, 1);

+				if (symbol < Base.kNumMidLenSymbols)

+				{

+					rangeEncoder.Encode(_choice, 1, 0);

+					_midCoder[posState].Encode(rangeEncoder, symbol);

+				}

+				else

+				{

+					rangeEncoder.Encode(_choice, 1, 1);

+					_highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);

+				}

+			}

+		}

+

+		public void SetPrices(int posState, int numSymbols, int[] prices, int st)

+		{

+			int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]);

+			int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]);

+			int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]);

+			int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]);

+			int i = 0;

+			for (i = 0; i < Base.kNumLowLenSymbols; i++)

+			{

+				if (i >= numSymbols)

+					return;

+				prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);

+			}

+			for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++)

+			{

+				if (i >= numSymbols)

+					return;

+				prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols);

+			}

+			for (; i < numSymbols; i++)

+				prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);

+		}

+	};

+

+	public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;

+

+	class LenPriceTableEncoder extends LenEncoder

+	{

+		int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax];

+		int _tableSize;

+		int[] _counters = new int[Base.kNumPosStatesEncodingMax];

+

+		public void SetTableSize(int tableSize) { _tableSize = tableSize; }

+

+		public int GetPrice(int symbol, int posState)

+		{

+			return _prices[posState * Base.kNumLenSymbols + symbol];

+		}

+

+		void UpdateTable(int posState)

+		{

+			SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);

+			_counters[posState] = _tableSize;

+		}

+

+		public void UpdateTables(int numPosStates)

+		{

+			for (int posState = 0; posState < numPosStates; posState++)

+				UpdateTable(posState);

+		}

+

+		public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException

+		{

+			super.Encode(rangeEncoder, symbol, posState);

+			if (--_counters[posState] == 0)

+				UpdateTable(posState);

+		}

+	}

+

+	static final int kNumOpts = 1 << 12;

+	class Optimal

+	{

+		public int State;

+

+		public boolean Prev1IsChar;

+		public boolean Prev2;

+

+		public int PosPrev2;

+		public int BackPrev2;

+

+		public int Price;

+		public int PosPrev;

+		public int BackPrev;

+

+		public int Backs0;

+		public int Backs1;

+		public int Backs2;

+		public int Backs3;

+

+		public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; }

+		public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }

+		public boolean IsShortRep() { return (BackPrev == 0); }

+	};

+	Optimal[] _optimum = new Optimal[kNumOpts];

+	SevenZip.Compression.LZ.BinTree _matchFinder = null;

+	SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder();

+

+	short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax];

+	short[] _isRep = new short[Base.kNumStates];

+	short[] _isRepG0 = new short[Base.kNumStates];

+	short[] _isRepG1 = new short[Base.kNumStates];

+	short[] _isRepG2 = new short[Base.kNumStates];

+	short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax];

+

+	BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits

+

+	short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex];

+	BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits);

+

+	LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();

+	LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();

+

+	LiteralEncoder _literalEncoder = new LiteralEncoder();

+

+	int[] _matchDistances = new int[Base.kMatchMaxLen*2+2];

+

+	int _numFastBytes = kNumFastBytesDefault;

+	int _longestMatchLength;

+	int _numDistancePairs;

+

+	int _additionalOffset;

+

+	int _optimumEndIndex;

+	int _optimumCurrentIndex;

+

+	boolean _longestMatchWasFound;

+

+	int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPosStatesBits)];

+	int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToPosStatesBits];

+	int[] _alignPrices = new int[Base.kAlignTableSize];

+	int _alignPriceCount;

+

+	int _distTableSize = (kDefaultDictionaryLogSize * 2);

+

+	int _posStateBits = 2;

+	int _posStateMask = (4 - 1);

+	int _numLiteralPosStateBits = 0;

+	int _numLiteralContextBits = 3;

+

+	int _dictionarySize = (1 << kDefaultDictionaryLogSize);

+	int _dictionarySizePrev = -1;

+	int _numFastBytesPrev = -1;

+

+	long nowPos64;

+	boolean _finished;

+	java.io.InputStream _inStream;

+

+	int _matchFinderType = EMatchFinderTypeBT4;

+	boolean _writeEndMark = false;

+

+	boolean _needReleaseMFStream = false;

+

+	void Create()

+	{

+		if (_matchFinder == null)

+		{

+			SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree();

+			int numHashBytes = 4;

+			if (_matchFinderType == EMatchFinderTypeBT2)

+				numHashBytes = 2;

+			bt.SetType(numHashBytes);

+			_matchFinder = bt;

+		}

+		_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);

+

+		if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)

+			return;

+		_matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);

+		_dictionarySizePrev = _dictionarySize;

+		_numFastBytesPrev = _numFastBytes;

+	}

+

+	public Encoder()

+	{

+		for (int i = 0; i < kNumOpts; i++)

+			_optimum[i] = new Optimal();

+		for (int i = 0; i < Base.kNumLenToPosStates; i++)

+			_posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits);

+	}

+

+	void SetWriteEndMarkerMode(boolean writeEndMarker)

+	{

+		_writeEndMark = writeEndMarker;

+	}

+

+	void Init()

+	{

+		BaseInit();

+		_rangeEncoder.Init();

+

+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch);

+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long);

+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep);

+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0);

+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1);

+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2);

+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders);

+

+

+

+

+

+

+

+		_literalEncoder.Init();

+		for (int i = 0; i < Base.kNumLenToPosStates; i++)

+			_posSlotEncoder[i].Init();

+

+

+

+		_lenEncoder.Init(1 << _posStateBits);

+		_repMatchLenEncoder.Init(1 << _posStateBits);

+

+		_posAlignEncoder.Init();

+

+		_longestMatchWasFound = false;

+		_optimumEndIndex = 0;

+		_optimumCurrentIndex = 0;

+		_additionalOffset = 0;

+	}

+

+	int ReadMatchDistances() throws java.io.IOException

+	{

+		int lenRes = 0;

+		_numDistancePairs = _matchFinder.GetMatches(_matchDistances);

+		if (_numDistancePairs > 0)

+		{

+			lenRes = _matchDistances[_numDistancePairs - 2];

+			if (lenRes == _numFastBytes)

+				lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1],

+					Base.kMatchMaxLen - lenRes);

+		}

+		_additionalOffset++;

+		return lenRes;

+	}

+

+	void MovePos(int num) throws java.io.IOException

+	{

+		if (num > 0)

+		{

+			_matchFinder.Skip(num);

+			_additionalOffset += num;

+		}

+	}

+

+	int GetRepLen1Price(int state, int posState)

+	{

+		return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) +

+				SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]);

+	}

+

+	int GetPureRepPrice(int repIndex, int state, int posState)

+	{

+		int price;

+		if (repIndex == 0)

+		{

+			price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]);

+			price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]);

+		}

+		else

+		{

+			price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]);

+			if (repIndex == 1)

+				price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]);

+			else

+			{

+				price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]);

+				price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2);

+			}

+		}

+		return price;

+	}

+

+	int GetRepPrice(int repIndex, int len, int state, int posState)

+	{

+		int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);

+		return price + GetPureRepPrice(repIndex, state, posState);

+	}

+

+	int GetPosLenPrice(int pos, int len, int posState)

+	{

+		int price;

+		int lenToPosState = Base.GetLenToPosState(len);

+		if (pos < Base.kNumFullDistances)

+			price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos];

+		else

+			price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] +

+				_alignPrices[pos & Base.kAlignMask];

+		return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);

+	}

+

+	int Backward(int cur)

+	{

+		_optimumEndIndex = cur;

+		int posMem = _optimum[cur].PosPrev;

+		int backMem = _optimum[cur].BackPrev;

+		do

+		{

+			if (_optimum[cur].Prev1IsChar)

+			{

+				_optimum[posMem].MakeAsChar();

+				_optimum[posMem].PosPrev = posMem - 1;

+				if (_optimum[cur].Prev2)

+				{

+					_optimum[posMem - 1].Prev1IsChar = false;

+					_optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;

+					_optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;

+				}

+			}

+			int posPrev = posMem;

+			int backCur = backMem;

+

+			backMem = _optimum[posPrev].BackPrev;

+			posMem = _optimum[posPrev].PosPrev;

+

+			_optimum[posPrev].BackPrev = backCur;

+			_optimum[posPrev].PosPrev = cur;

+			cur = posPrev;

+		}

+		while (cur > 0);

+		backRes = _optimum[0].BackPrev;

+		_optimumCurrentIndex = _optimum[0].PosPrev;

+		return _optimumCurrentIndex;

+	}

+

+	int[] reps = new int[Base.kNumRepDistances];

+	int[] repLens = new int[Base.kNumRepDistances];

+	int backRes;

+

+	int GetOptimum(int position) throws IOException

+	{

+		if (_optimumEndIndex != _optimumCurrentIndex)

+		{

+			int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;

+			backRes = _optimum[_optimumCurrentIndex].BackPrev;

+			_optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;

+			return lenRes;

+		}

+		_optimumCurrentIndex = _optimumEndIndex = 0;

+

+		int lenMain, numDistancePairs;

+		if (!_longestMatchWasFound)

+		{

+			lenMain = ReadMatchDistances();

+		}

+		else

+		{

+			lenMain = _longestMatchLength;

+			_longestMatchWasFound = false;

+		}

+		numDistancePairs = _numDistancePairs;

+

+		int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;

+		if (numAvailableBytes < 2)

+		{

+			backRes = -1;

+			return 1;

+		}

+		if (numAvailableBytes > Base.kMatchMaxLen)

+			numAvailableBytes = Base.kMatchMaxLen;

+

+		int repMaxIndex = 0;

+		int i;

+		for (i = 0; i < Base.kNumRepDistances; i++)

+		{

+			reps[i] = _repDistances[i];

+			repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);

+			if (repLens[i] > repLens[repMaxIndex])

+				repMaxIndex = i;

+		}

+		if (repLens[repMaxIndex] >= _numFastBytes)

+		{

+			backRes = repMaxIndex;

+			int lenRes = repLens[repMaxIndex];

+			MovePos(lenRes - 1);

+			return lenRes;

+		}

+

+		if (lenMain >= _numFastBytes)

+		{

+			backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;

+			MovePos(lenMain - 1);

+			return lenMain;

+		}

+

+		byte currentByte = _matchFinder.GetIndexByte(0 - 1);

+		byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1);

+

+		if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)

+		{

+			backRes = -1;

+			return 1;

+		}

+

+		_optimum[0].State = _state;

+

+		int posState = (position & _posStateMask);

+

+		_optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) +

+				_literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte);

+		_optimum[1].MakeAsChar();

+

+		int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]);

+		int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]);

+

+		if (matchByte == currentByte)

+		{

+			int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);

+			if (shortRepPrice < _optimum[1].Price)

+			{

+				_optimum[1].Price = shortRepPrice;

+				_optimum[1].MakeAsShortRep();

+			}

+		}

+

+		int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);

+

+		if (lenEnd < 2)

+		{

+			backRes = _optimum[1].BackPrev;

+			return 1;

+		}

+

+		_optimum[1].PosPrev = 0;

+

+		_optimum[0].Backs0 = reps[0];

+		_optimum[0].Backs1 = reps[1];

+		_optimum[0].Backs2 = reps[2];

+		_optimum[0].Backs3 = reps[3];

+

+		int len = lenEnd;

+		do

+			_optimum[len--].Price = kIfinityPrice;

+		while (len >= 2);

+

+		for (i = 0; i < Base.kNumRepDistances; i++)

+		{

+			int repLen = repLens[i];

+			if (repLen < 2)

+				continue;

+			int price = repMatchPrice + GetPureRepPrice(i, _state, posState);

+			do

+			{

+				int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);

+				Optimal optimum = _optimum[repLen];

+				if (curAndLenPrice < optimum.Price)

+				{

+					optimum.Price = curAndLenPrice;

+					optimum.PosPrev = 0;

+					optimum.BackPrev = i;

+					optimum.Prev1IsChar = false;

+				}

+			}

+			while (--repLen >= 2);

+		}

+

+		int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]);

+

+		len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);

+		if (len <= lenMain)

+		{

+			int offs = 0;

+			while (len > _matchDistances[offs])

+				offs += 2;

+			for (; ; len++)

+			{

+				int distance = _matchDistances[offs + 1];

+				int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);

+				Optimal optimum = _optimum[len];

+				if (curAndLenPrice < optimum.Price)

+				{

+					optimum.Price = curAndLenPrice;

+					optimum.PosPrev = 0;

+					optimum.BackPrev = distance + Base.kNumRepDistances;

+					optimum.Prev1IsChar = false;

+				}

+				if (len == _matchDistances[offs])

+				{

+					offs += 2;

+					if (offs == numDistancePairs)

+						break;

+				}

+			}

+		}

+

+		int cur = 0;

+

+		while (true)

+		{

+			cur++;

+			if (cur == lenEnd)

+				return Backward(cur);

+			int newLen = ReadMatchDistances();

+			numDistancePairs = _numDistancePairs;

+			if (newLen >= _numFastBytes)

+			{

+

+				_longestMatchLength = newLen;

+				_longestMatchWasFound = true;

+				return Backward(cur);

+			}

+			position++;

+			int posPrev = _optimum[cur].PosPrev;

+			int state;

+			if (_optimum[cur].Prev1IsChar)

+			{

+				posPrev--;

+				if (_optimum[cur].Prev2)

+				{

+					state = _optimum[_optimum[cur].PosPrev2].State;

+					if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)

+						state = Base.StateUpdateRep(state);

+					else

+						state = Base.StateUpdateMatch(state);

+				}

+				else

+					state = _optimum[posPrev].State;

+				state = Base.StateUpdateChar(state);

+			}

+			else

+				state = _optimum[posPrev].State;

+			if (posPrev == cur - 1)

+			{

+				if (_optimum[cur].IsShortRep())

+					state = Base.StateUpdateShortRep(state);

+				else

+					state = Base.StateUpdateChar(state);

+			}

+			else

+			{

+				int pos;

+				if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)

+				{

+					posPrev = _optimum[cur].PosPrev2;

+					pos = _optimum[cur].BackPrev2;

+					state = Base.StateUpdateRep(state);

+				}

+				else

+				{

+					pos = _optimum[cur].BackPrev;

+					if (pos < Base.kNumRepDistances)

+						state = Base.StateUpdateRep(state);

+					else

+						state = Base.StateUpdateMatch(state);

+				}

+				Optimal opt = _optimum[posPrev];

+				if (pos < Base.kNumRepDistances)

+				{

+					if (pos == 0)

+					{

+						reps[0] = opt.Backs0;

+						reps[1] = opt.Backs1;

+						reps[2] = opt.Backs2;

+						reps[3] = opt.Backs3;

+					}

+					else if (pos == 1)

+					{

+						reps[0] = opt.Backs1;

+						reps[1] = opt.Backs0;

+						reps[2] = opt.Backs2;

+						reps[3] = opt.Backs3;

+					}

+					else if (pos == 2)

+					{

+						reps[0] = opt.Backs2;

+						reps[1] = opt.Backs0;

+						reps[2] = opt.Backs1;

+						reps[3] = opt.Backs3;

+					}

+					else

+					{

+						reps[0] = opt.Backs3;

+						reps[1] = opt.Backs0;

+						reps[2] = opt.Backs1;

+						reps[3] = opt.Backs2;

+					}

+				}

+				else

+				{

+					reps[0] = (pos - Base.kNumRepDistances);

+					reps[1] = opt.Backs0;

+					reps[2] = opt.Backs1;

+					reps[3] = opt.Backs2;

+				}

+			}

+			_optimum[cur].State = state;

+			_optimum[cur].Backs0 = reps[0];

+			_optimum[cur].Backs1 = reps[1];

+			_optimum[cur].Backs2 = reps[2];

+			_optimum[cur].Backs3 = reps[3];

+			int curPrice = _optimum[cur].Price;

+

+			currentByte = _matchFinder.GetIndexByte(0 - 1);

+			matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1);

+

+			posState = (position & _posStateMask);

+

+			int curAnd1Price = curPrice +

+				SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) +

+				_literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).

+				GetPrice(!Base.StateIsCharState(state), matchByte, currentByte);

+

+			Optimal nextOptimum = _optimum[cur + 1];

+

+			boolean nextIsChar = false;

+			if (curAnd1Price < nextOptimum.Price)

+			{

+				nextOptimum.Price = curAnd1Price;

+				nextOptimum.PosPrev = cur;

+				nextOptimum.MakeAsChar();

+				nextIsChar = true;

+			}

+

+			matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]);

+			repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]);

+

+			if (matchByte == currentByte &&

+				!(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))

+			{

+				int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);

+				if (shortRepPrice <= nextOptimum.Price)

+				{

+					nextOptimum.Price = shortRepPrice;

+					nextOptimum.PosPrev = cur;

+					nextOptimum.MakeAsShortRep();

+					nextIsChar = true;

+				}

+			}

+

+			int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;

+			numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull);

+			numAvailableBytes = numAvailableBytesFull;

+

+			if (numAvailableBytes < 2)

+				continue;

+			if (numAvailableBytes > _numFastBytes)

+				numAvailableBytes = _numFastBytes;

+			if (!nextIsChar && matchByte != currentByte)

+			{

+				// try Literal + rep0

+				int t = Math.min(numAvailableBytesFull - 1, _numFastBytes);

+				int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);

+				if (lenTest2 >= 2)

+				{

+					int state2 = Base.StateUpdateChar(state);

+

+					int posStateNext = (position + 1) & _posStateMask;

+					int nextRepMatchPrice = curAnd1Price +

+						SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) +

+						SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]);

+					{

+						int offset = cur + 1 + lenTest2;

+						while (lenEnd < offset)

+							_optimum[++lenEnd].Price = kIfinityPrice;

+						int curAndLenPrice = nextRepMatchPrice + GetRepPrice(

+								0, lenTest2, state2, posStateNext);

+						Optimal optimum = _optimum[offset];

+						if (curAndLenPrice < optimum.Price)

+						{

+							optimum.Price = curAndLenPrice;

+							optimum.PosPrev = cur + 1;

+							optimum.BackPrev = 0;

+							optimum.Prev1IsChar = true;

+							optimum.Prev2 = false;

+						}

+					}

+				}

+			}

+

+			int startLen = 2; // speed optimization 

+

+			for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)

+			{

+				int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);

+				if (lenTest < 2)

+					continue;

+				int lenTestTemp = lenTest;

+				do

+				{

+					while (lenEnd < cur + lenTest)

+						_optimum[++lenEnd].Price = kIfinityPrice;

+					int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);

+					Optimal optimum = _optimum[cur + lenTest];

+					if (curAndLenPrice < optimum.Price)

+					{

+						optimum.Price = curAndLenPrice;

+						optimum.PosPrev = cur;

+						optimum.BackPrev = repIndex;

+						optimum.Prev1IsChar = false;

+					}

+				}

+				while (--lenTest >= 2);

+				lenTest = lenTestTemp;

+

+				if (repIndex == 0)

+					startLen = lenTest + 1;

+

+				// if (_maxMode)

+				if (lenTest < numAvailableBytesFull)

+				{

+					int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);

+					int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t);

+					if (lenTest2 >= 2)

+					{

+						int state2 = Base.StateUpdateRep(state);

+

+						int posStateNext = (position + lenTest) & _posStateMask;

+						int curAndLenCharPrice =

+								repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +

+								SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) +

+								_literalEncoder.GetSubCoder(position + lenTest,

+								_matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true,

+								_matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)),

+								_matchFinder.GetIndexByte(lenTest - 1));

+						state2 = Base.StateUpdateChar(state2);

+						posStateNext = (position + lenTest + 1) & _posStateMask;

+						int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]);

+						int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]);

+

+						// for(; lenTest2 >= 2; lenTest2--)

+						{

+							int offset = lenTest + 1 + lenTest2;

+							while (lenEnd < cur + offset)

+								_optimum[++lenEnd].Price = kIfinityPrice;

+							int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);

+							Optimal optimum = _optimum[cur + offset];

+							if (curAndLenPrice < optimum.Price)

+							{

+								optimum.Price = curAndLenPrice;

+								optimum.PosPrev = cur + lenTest + 1;

+								optimum.BackPrev = 0;

+								optimum.Prev1IsChar = true;

+								optimum.Prev2 = true;

+								optimum.PosPrev2 = cur;

+								optimum.BackPrev2 = repIndex;

+							}

+						}

+					}

+				}

+			}

+

+			if (newLen > numAvailableBytes)

+			{

+				newLen = numAvailableBytes;

+				for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ;

+				_matchDistances[numDistancePairs] = newLen;

+				numDistancePairs += 2;

+			}

+			if (newLen >= startLen)

+			{

+				normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]);

+				while (lenEnd < cur + newLen)

+					_optimum[++lenEnd].Price = kIfinityPrice;

+

+				int offs = 0;

+				while (startLen > _matchDistances[offs])

+					offs += 2;

+

+				for (int lenTest = startLen; ; lenTest++)

+				{

+					int curBack = _matchDistances[offs + 1];

+					int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);

+					Optimal optimum = _optimum[cur + lenTest];

+					if (curAndLenPrice < optimum.Price)

+					{

+						optimum.Price = curAndLenPrice;

+						optimum.PosPrev = cur;

+						optimum.BackPrev = curBack + Base.kNumRepDistances;

+						optimum.Prev1IsChar = false;

+					}

+

+					if (lenTest == _matchDistances[offs])

+					{

+						if (lenTest < numAvailableBytesFull)

+						{

+							int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);

+							int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t);

+							if (lenTest2 >= 2)

+							{

+								int state2 = Base.StateUpdateMatch(state);

+

+								int posStateNext = (position + lenTest) & _posStateMask;

+								int curAndLenCharPrice = curAndLenPrice +

+									SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) +

+									_literalEncoder.GetSubCoder(position + lenTest,

+									_matchFinder.GetIndexByte(lenTest - 1 - 1)).

+									GetPrice(true,

+									_matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1),

+									_matchFinder.GetIndexByte(lenTest - 1));

+								state2 = Base.StateUpdateChar(state2);

+								posStateNext = (position + lenTest + 1) & _posStateMask;

+								int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]);

+								int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]);

+

+								int offset = lenTest + 1 + lenTest2;

+								while (lenEnd < cur + offset)

+									_optimum[++lenEnd].Price = kIfinityPrice;

+								curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);

+								optimum = _optimum[cur + offset];

+								if (curAndLenPrice < optimum.Price)

+								{

+									optimum.Price = curAndLenPrice;

+									optimum.PosPrev = cur + lenTest + 1;

+									optimum.BackPrev = 0;

+									optimum.Prev1IsChar = true;

+									optimum.Prev2 = true;

+									optimum.PosPrev2 = cur;

+									optimum.BackPrev2 = curBack + Base.kNumRepDistances;

+								}

+							}

+						}

+						offs += 2;

+						if (offs == numDistancePairs)

+							break;

+					}

+				}

+			}

+		}

+	}

+

+	boolean ChangePair(int smallDist, int bigDist)

+	{

+		int kDif = 7;

+		return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif));

+	}

+

+	void WriteEndMarker(int posState) throws IOException

+	{

+		if (!_writeEndMark)

+			return;

+

+		_rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1);

+		_rangeEncoder.Encode(_isRep, _state, 0);

+		_state = Base.StateUpdateMatch(_state);

+		int len = Base.kMatchMinLen;

+		_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);

+		int posSlot = (1 << Base.kNumPosSlotBits) - 1;

+		int lenToPosState = Base.GetLenToPosState(len);

+		_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);

+		int footerBits = 30;

+		int posReduced = (1 << footerBits) - 1;

+		_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);

+		_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);

+	}

+

+	void Flush(int nowPos) throws IOException

+	{

+		ReleaseMFStream();

+		WriteEndMarker(nowPos & _posStateMask);

+		_rangeEncoder.FlushData();

+		_rangeEncoder.FlushStream();

+	}

+

+	public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException

+	{

+		inSize[0] = 0;

+		outSize[0] = 0;

+		finished[0] = true;

+

+		if (_inStream != null)

+		{

+			_matchFinder.SetStream(_inStream);

+			_matchFinder.Init();

+			_needReleaseMFStream = true;

+			_inStream = null;

+		}

+

+		if (_finished)

+			return;

+		_finished = true;

+

+

+		long progressPosValuePrev = nowPos64;

+		if (nowPos64 == 0)

+		{

+			if (_matchFinder.GetNumAvailableBytes() == 0)

+			{

+				Flush((int)nowPos64);

+				return;

+			}

+

+			ReadMatchDistances();

+			int posState = (int)(nowPos64) & _posStateMask;

+			_rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0);

+			_state = Base.StateUpdateChar(_state);

+			byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset);

+			_literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte);

+			_previousByte = curByte;

+			_additionalOffset--;

+			nowPos64++;

+		}

+		if (_matchFinder.GetNumAvailableBytes() == 0)

+		{

+			Flush((int)nowPos64);

+			return;

+		}

+		while (true)

+		{

+

+			int len = GetOptimum((int)nowPos64);

+			int pos = backRes;

+			int posState = ((int)nowPos64) & _posStateMask;

+			int complexState = (_state << Base.kNumPosStatesBitsMax) + posState;

+			if (len == 1 && pos == -1)

+			{

+				_rangeEncoder.Encode(_isMatch, complexState, 0);

+				byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset));

+				LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte);

+				if (!Base.StateIsCharState(_state))

+				{

+					byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset));

+					subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);

+				}

+				else

+					subCoder.Encode(_rangeEncoder, curByte);

+				_previousByte = curByte;

+				_state = Base.StateUpdateChar(_state);

+			}

+			else

+			{

+				_rangeEncoder.Encode(_isMatch, complexState, 1);

+				if (pos < Base.kNumRepDistances)

+				{

+					_rangeEncoder.Encode(_isRep, _state, 1);

+					if (pos == 0)

+					{

+						_rangeEncoder.Encode(_isRepG0, _state, 0);

+						if (len == 1)

+							_rangeEncoder.Encode(_isRep0Long, complexState, 0);

+						else

+							_rangeEncoder.Encode(_isRep0Long, complexState, 1);

+					}

+					else

+					{

+						_rangeEncoder.Encode(_isRepG0, _state, 1);

+						if (pos == 1)

+							_rangeEncoder.Encode(_isRepG1, _state, 0);

+						else

+						{

+							_rangeEncoder.Encode(_isRepG1, _state, 1);

+							_rangeEncoder.Encode(_isRepG2, _state, pos - 2);

+						}

+					}

+					if (len == 1)

+						_state = Base.StateUpdateShortRep(_state);

+					else

+					{

+						_repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);

+						_state = Base.StateUpdateRep(_state);

+					}

+					int distance = _repDistances[pos];

+					if (pos != 0)

+					{

+						for (int i = pos; i >= 1; i--)

+							_repDistances[i] = _repDistances[i - 1];

+						_repDistances[0] = distance;

+					}

+				}

+				else

+				{

+					_rangeEncoder.Encode(_isRep, _state, 0);

+					_state = Base.StateUpdateMatch(_state);

+					_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);

+					pos -= Base.kNumRepDistances;

+					int posSlot = GetPosSlot(pos);

+					int lenToPosState = Base.GetLenToPosState(len);

+					_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);

+

+					if (posSlot >= Base.kStartPosModelIndex)

+					{

+						int footerBits = (int)((posSlot >> 1) - 1);

+						int baseVal = ((2 | (posSlot & 1)) << footerBits);

+						int posReduced = pos - baseVal;

+

+						if (posSlot < Base.kEndPosModelIndex)

+							BitTreeEncoder.ReverseEncode(_posEncoders,

+									baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);

+						else

+						{

+							_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);

+							_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);

+							_alignPriceCount++;

+						}

+					}

+					int distance = pos;

+					for (int i = Base.kNumRepDistances - 1; i >= 1; i--)

+						_repDistances[i] = _repDistances[i - 1];

+					_repDistances[0] = distance;

+					_matchPriceCount++;

+				}

+				_previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset);

+			}

+			_additionalOffset -= len;

+			nowPos64 += len;

+			if (_additionalOffset == 0)

+			{

+				// if (!_fastMode)

+				if (_matchPriceCount >= (1 << 7))

+					FillDistancesPrices();

+				if (_alignPriceCount >= Base.kAlignTableSize)

+					FillAlignPrices();

+				inSize[0] = nowPos64;

+				outSize[0] = _rangeEncoder.GetProcessedSizeAdd();

+				if (_matchFinder.GetNumAvailableBytes() == 0)

+				{

+					Flush((int)nowPos64);

+					return;

+				}

+

+				if (nowPos64 - progressPosValuePrev >= (1 << 12))

+				{

+					_finished = false;

+					finished[0] = false;

+					return;

+				}

+			}

+		}

+	}

+

+	void ReleaseMFStream()

+	{

+		if (_matchFinder != null && _needReleaseMFStream)

+		{

+			_matchFinder.ReleaseStream();

+			_needReleaseMFStream = false;

+		}

+	}

+

+	void SetOutStream(java.io.OutputStream outStream)

+	{ _rangeEncoder.SetStream(outStream); }

+	void ReleaseOutStream()

+	{ _rangeEncoder.ReleaseStream(); }

+

+	void ReleaseStreams()

+	{

+		ReleaseMFStream();

+		ReleaseOutStream();

+	}

+

+	void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream,

+			long inSize, long outSize)

+	{

+		_inStream = inStream;

+		_finished = false;

+		Create();

+		SetOutStream(outStream);

+		Init();

+

+		// if (!_fastMode)

+		{

+			FillDistancesPrices();

+			FillAlignPrices();

+		}

+

+		_lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);

+		_lenEncoder.UpdateTables(1 << _posStateBits);

+		_repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);

+		_repMatchLenEncoder.UpdateTables(1 << _posStateBits);

+

+		nowPos64 = 0;

+	}

+

+	long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1];

+	public void Code(java.io.InputStream inStream, java.io.OutputStream outStream,

+			long inSize, long outSize, ICodeProgress progress) throws IOException

+	{

+		_needReleaseMFStream = false;

+		try

+		{

+			SetStreams(inStream, outStream, inSize, outSize);

+			while (true)

+			{

+

+

+

+				CodeOneBlock(processedInSize, processedOutSize, finished);

+				if (finished[0])

+					return;

+				if (progress != null)

+				{

+					progress.SetProgress(processedInSize[0], processedOutSize[0]);

+				}

+			}

+		}

+		finally

+		{

+			ReleaseStreams();

+		}

+	}

+

+	public static final int kPropSize = 5;

+	byte[] properties = new byte[kPropSize];

+

+	public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException

+	{

+		properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);

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

+			properties[1 + i] = (byte)(_dictionarySize >> (8 * i));

+		outStream.write(properties, 0, kPropSize);

+	}

+

+	int[] tempPrices = new int[Base.kNumFullDistances];

+	int _matchPriceCount;

+

+	void FillDistancesPrices()

+	{

+		for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)

+		{

+			int posSlot = GetPosSlot(i);

+			int footerBits = (int)((posSlot >> 1) - 1);

+			int baseVal = ((2 | (posSlot & 1)) << footerBits);

+			tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders,

+				baseVal - posSlot - 1, footerBits, i - baseVal);

+		}

+

+		for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)

+		{

+			int posSlot;

+			BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];

+

+			int st = (lenToPosState << Base.kNumPosSlotBits);

+			for (posSlot = 0; posSlot < _distTableSize; posSlot++)

+				_posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);

+			for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)

+				_posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits);

+

+			int st2 = lenToPosState * Base.kNumFullDistances;

+			int i;

+			for (i = 0; i < Base.kStartPosModelIndex; i++)

+				_distancesPrices[st2 + i] = _posSlotPrices[st + i];

+			for (; i < Base.kNumFullDistances; i++)

+				_distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i];

+		}

+		_matchPriceCount = 0;

+	}

+

+	void FillAlignPrices()

+	{

+		for (int i = 0; i < Base.kAlignTableSize; i++)

+			_alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);

+		_alignPriceCount = 0;

+	}

+

+

+	public boolean SetAlgorithm(int algorithm)

+	{

+		/*

+		_fastMode = (algorithm == 0);

+		_maxMode = (algorithm >= 2);

+		*/

+		return true;

+	}

+

+	public boolean SetDictionarySize(int dictionarySize)

+	{

+		int kDicLogSizeMaxCompress = 29;

+		if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress))

+			return false;

+		_dictionarySize = dictionarySize;

+		int dicLogSize;

+		for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ;

+		_distTableSize = dicLogSize * 2;

+		return true;

+	}

+

+	public boolean SetNumFastBytes(int numFastBytes)

+	{

+		if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)

+			return false;

+		_numFastBytes = numFastBytes;

+		return true;

+	}

+

+	public boolean SetMatchFinder(int matchFinderIndex)

+	{

+		if (matchFinderIndex < 0 || matchFinderIndex > 2)

+			return false;

+		int matchFinderIndexPrev = _matchFinderType;

+		_matchFinderType = matchFinderIndex;

+		if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)

+		{

+			_dictionarySizePrev = -1;

+			_matchFinder = null;

+		}

+		return true;

+	}

+

+	public boolean SetLcLpPb(int lc, int lp, int pb)

+	{

+		if (

+				lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax ||

+				lc < 0 || lc > Base.kNumLitContextBitsMax ||

+				pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax)

+			return false;

+		_numLiteralPosStateBits = lp;

+		_numLiteralContextBits = lc;

+		_posStateBits = pb;

+		_posStateMask = ((1) << _posStateBits) - 1;

+		return true;

+	}

+

+	public void SetEndMarkerMode(boolean endMarkerMode)

+	{

+		_writeEndMark = endMarkerMode;

+	}

+}

+

diff --git a/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java b/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java
new file mode 100755
index 0000000..6864c69
--- /dev/null
+++ b/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java
@@ -0,0 +1,55 @@
+package SevenZip.Compression.RangeCoder;

+

+public class BitTreeDecoder

+{

+	short[] Models;

+	int NumBitLevels;

+	

+	public BitTreeDecoder(int numBitLevels)

+	{

+		NumBitLevels = numBitLevels;

+		Models = new short[1 << numBitLevels];

+	}

+	

+	public void Init()

+	{

+		Decoder.InitBitModels(Models);

+	}

+	

+	public int Decode(Decoder rangeDecoder) throws java.io.IOException

+	{

+		int m = 1;

+		for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--)

+			m = (m << 1) + rangeDecoder.DecodeBit(Models, m);

+		return m - (1 << NumBitLevels);

+	}

+	

+	public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException

+	{

+		int m = 1;

+		int symbol = 0;

+		for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)

+		{

+			int bit = rangeDecoder.DecodeBit(Models, m);

+			m <<= 1;

+			m += bit;

+			symbol |= (bit << bitIndex);

+		}

+		return symbol;

+	}

+	

+	public static int ReverseDecode(short[] Models, int startIndex,

+			Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException

+	{

+		int m = 1;

+		int symbol = 0;

+		for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)

+		{

+			int bit = rangeDecoder.DecodeBit(Models, startIndex + m);

+			m <<= 1;

+			m += bit;

+			symbol |= (bit << bitIndex);

+		}

+		return symbol;

+	}

+}

diff --git a/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java b/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java
new file mode 100755
index 0000000..b4c0a07
--- /dev/null
+++ b/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java
@@ -0,0 +1,99 @@
+package SevenZip.Compression.RangeCoder;

+import java.io.IOException;

+

+public class BitTreeEncoder

+{

+	short[] Models;

+	int NumBitLevels;

+	

+	public BitTreeEncoder(int numBitLevels)

+	{

+		NumBitLevels = numBitLevels;

+		Models = new short[1 << numBitLevels];

+	}

+	

+	public void Init()

+	{

+		Decoder.InitBitModels(Models);

+	}

+	

+	public void Encode(Encoder rangeEncoder, int symbol) throws IOException

+	{

+		int m = 1;

+		for (int bitIndex = NumBitLevels; bitIndex != 0; )

+		{

+			bitIndex--;

+			int bit = (symbol >>> bitIndex) & 1;

+			rangeEncoder.Encode(Models, m, bit);

+			m = (m << 1) | bit;

+		}

+	}

+	

+	public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException

+	{

+		int m = 1;

+		for (int  i = 0; i < NumBitLevels; i++)

+		{

+			int bit = symbol & 1;

+			rangeEncoder.Encode(Models, m, bit);

+			m = (m << 1) | bit;

+			symbol >>= 1;

+		}

+	}

+	

+	public int GetPrice(int symbol)

+	{

+		int price = 0;

+		int m = 1;

+		for (int bitIndex = NumBitLevels; bitIndex != 0; )

+		{

+			bitIndex--;

+			int bit = (symbol >>> bitIndex) & 1;

+			price += Encoder.GetPrice(Models[m], bit);

+			m = (m << 1) + bit;

+		}

+		return price;

+	}

+	

+	public int ReverseGetPrice(int symbol)

+	{

+		int price = 0;

+		int m = 1;

+		for (int i = NumBitLevels; i != 0; i--)

+		{

+			int bit = symbol & 1;

+			symbol >>>= 1;

+			price += Encoder.GetPrice(Models[m], bit);

+			m = (m << 1) | bit;

+		}

+		return price;

+	}

+	

+	public static int ReverseGetPrice(short[] Models, int startIndex,

+			int NumBitLevels, int symbol)

+	{

+		int price = 0;

+		int m = 1;

+		for (int i = NumBitLevels; i != 0; i--)

+		{

+			int bit = symbol & 1;

+			symbol >>>= 1;

+			price += Encoder.GetPrice(Models[startIndex + m], bit);

+			m = (m << 1) | bit;

+		}

+		return price;

+	}

+	

+	public static void ReverseEncode(short[] Models, int startIndex,

+			Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException

+	{

+		int m = 1;

+		for (int i = 0; i < NumBitLevels; i++)

+		{

+			int bit = symbol & 1;

+			rangeEncoder.Encode(Models, startIndex + m, bit);

+			m = (m << 1) | bit;

+			symbol >>= 1;

+		}

+	}

+}

diff --git a/Java/SevenZip/Compression/RangeCoder/Decoder.java b/Java/SevenZip/Compression/RangeCoder/Decoder.java
new file mode 100755
index 0000000..7453383
--- /dev/null
+++ b/Java/SevenZip/Compression/RangeCoder/Decoder.java
@@ -0,0 +1,88 @@
+package SevenZip.Compression.RangeCoder;

+import java.io.IOException;

+

+public class Decoder

+{

+	static final int kTopMask = ~((1 << 24) - 1);

+	

+	static final int kNumBitModelTotalBits = 11;

+	static final int kBitModelTotal = (1 << kNumBitModelTotalBits);

+	static final int kNumMoveBits = 5;

+	

+	int Range;

+	int Code;

+

+	java.io.InputStream Stream;

+	

+	public final void SetStream(java.io.InputStream stream)

+	{ 

+		Stream = stream; 

+	}

+	

+	public final void ReleaseStream()

+	{ 

+		Stream = null; 

+	}

+	

+	public final void Init() throws IOException

+	{

+		Code = 0;

+		Range = -1;

+		for (int i = 0; i < 5; i++)

+			Code = (Code << 8) | Stream.read();

+	}

+	

+	public final int DecodeDirectBits(int numTotalBits) throws IOException

+	{

+		int result = 0;

+		for (int i = numTotalBits; i != 0; i--)

+		{

+			Range >>>= 1;

+			int t = ((Code - Range) >>> 31);

+			Code -= Range & (t - 1);

+			result = (result << 1) | (1 - t);

+			

+			if ((Range & kTopMask) == 0)

+			{

+				Code = (Code << 8) | Stream.read();

+				Range <<= 8;

+			}

+		}

+		return result;

+	}

+	

+	public int DecodeBit(short []probs, int index) throws IOException

+	{

+		int prob = probs[index];

+		int newBound = (Range >>> kNumBitModelTotalBits) * prob;

+		if ((Code ^ 0x80000000) < (newBound ^ 0x80000000))

+		{

+			Range = newBound;

+			probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits));

+			if ((Range & kTopMask) == 0)

+			{

+				Code = (Code << 8) | Stream.read();

+				Range <<= 8;

+			}

+			return 0;

+		}

+		else

+		{

+			Range -= newBound;

+			Code -= newBound;

+			probs[index] = (short)(prob - ((prob) >>> kNumMoveBits));

+			if ((Range & kTopMask) == 0)

+			{

+				Code = (Code << 8) | Stream.read();

+				Range <<= 8;

+			}

+			return 1;

+		}

+	}

+	

+	public static void InitBitModels(short []probs)

+	{

+		for (int i = 0; i < probs.length; i++)

+			probs[i] = (kBitModelTotal >>> 1);

+	}

+}

diff --git a/Java/SevenZip/Compression/RangeCoder/Encoder.java b/Java/SevenZip/Compression/RangeCoder/Encoder.java
new file mode 100755
index 0000000..2273e92
--- /dev/null
+++ b/Java/SevenZip/Compression/RangeCoder/Encoder.java
@@ -0,0 +1,151 @@
+package SevenZip.Compression.RangeCoder;

+import java.io.IOException;

+

+public class Encoder

+{

+	static final int kTopMask = ~((1 << 24) - 1);

+	

+	static final int kNumBitModelTotalBits = 11;

+	static final int kBitModelTotal = (1 << kNumBitModelTotalBits);

+	static final int kNumMoveBits = 5;

+	

+	java.io.OutputStream Stream;

+

+	long Low;

+	int Range;

+	int _cacheSize;

+	int _cache;

+	

+	long _position;

+	

+	public void SetStream(java.io.OutputStream stream)

+	{

+		Stream = stream;

+	}

+	

+	public void ReleaseStream()

+	{

+		Stream = null;

+	}

+	

+	public void Init()

+	{

+		_position = 0;

+		Low = 0;

+		Range = -1;

+		_cacheSize = 1;

+		_cache = 0;

+	}

+	

+	public void FlushData() throws IOException

+	{

+		for (int i = 0; i < 5; i++)

+			ShiftLow();

+	}

+	

+	public void FlushStream() throws IOException

+	{

+		Stream.flush();

+	}

+	

+	public void ShiftLow() throws IOException

+	{

+		int LowHi = (int)(Low >>> 32);

+		if (LowHi != 0 || Low < 0xFF000000L)

+		{

+			_position += _cacheSize;

+			int temp = _cache;

+			do

+			{

+				Stream.write(temp + LowHi);

+				temp = 0xFF;

+			}

+			while(--_cacheSize != 0);

+			_cache = (((int)Low) >>> 24);

+		}

+		_cacheSize++;

+		Low = (Low & 0xFFFFFF) << 8;

+	}

+	

+	public void EncodeDirectBits(int v, int numTotalBits) throws IOException

+	{

+		for (int i = numTotalBits - 1; i >= 0; i--)

+		{

+			Range >>>= 1;

+			if (((v >>> i) & 1) == 1)

+				Low += Range;

+			if ((Range & Encoder.kTopMask) == 0)

+			{

+				Range <<= 8;

+				ShiftLow();

+			}

+		}

+	}

+	

+	

+	public long GetProcessedSizeAdd()

+	{

+		return _cacheSize + _position + 4;

+	}

+	

+	

+	

+	static final int kNumMoveReducingBits = 2;

+	public static final int kNumBitPriceShiftBits = 6;

+	

+	public static void InitBitModels(short []probs)

+	{

+		for (int i = 0; i < probs.length; i++)

+			probs[i] = (kBitModelTotal >>> 1);

+	}

+	

+	public void Encode(short []probs, int index, int symbol) throws IOException

+	{

+		int prob = probs[index];

+		int newBound = (Range >>> kNumBitModelTotalBits) * prob;

+		if (symbol == 0)

+		{

+			Range = newBound;

+			probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits));

+		}

+		else

+		{

+			Low += (newBound & 0xFFFFFFFFL);

+			Range -= newBound;

+			probs[index] = (short)(prob - ((prob) >>> kNumMoveBits));

+		}

+		if ((Range & kTopMask) == 0)

+		{

+			Range <<= 8;

+			ShiftLow();

+		}

+	}

+	

+	private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits];

+	

+	static

+	{

+		int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);

+		for (int i = kNumBits - 1; i >= 0; i--)

+		{

+			int start = 1 << (kNumBits - i - 1);

+			int end = 1 << (kNumBits - i);

+			for (int j = start; j < end; j++)

+				ProbPrices[j] = (i << kNumBitPriceShiftBits) +

+						(((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1));

+		}

+	}

+	

+	static public int GetPrice(int Prob, int symbol)

+	{

+		return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits];

+	}

+	static public int GetPrice0(int Prob)

+	{ 

+		return ProbPrices[Prob >>> kNumMoveReducingBits]; 

+	}

+	static public int GetPrice1(int Prob)

+	{ 

+		return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; 

+	}

+}

diff --git a/Java/SevenZip/ICodeProgress.java b/Java/SevenZip/ICodeProgress.java
new file mode 100755
index 0000000..290bd2d
--- /dev/null
+++ b/Java/SevenZip/ICodeProgress.java
@@ -0,0 +1,6 @@
+package SevenZip;

+

+public interface ICodeProgress

+{

+	public void SetProgress(long inSize, long outSize);

+}

diff --git a/Java/SevenZip/LzmaAlone.java b/Java/SevenZip/LzmaAlone.java
new file mode 100755
index 0000000..de39a22
--- /dev/null
+++ b/Java/SevenZip/LzmaAlone.java
@@ -0,0 +1,253 @@
+package SevenZip;

+

+public class LzmaAlone

+{

+	static public class CommandLine

+	{

+		public static final int kEncode = 0;

+		public static final int kDecode = 1;

+		public static final int kBenchmak = 2;

+		

+		public int Command = -1;

+		public int NumBenchmarkPasses = 10;

+		

+		public int DictionarySize = 1 << 23;

+		public boolean DictionarySizeIsDefined = false;

+		

+		public int Lc = 3;

+		public int Lp = 0;

+		public int Pb = 2;

+		

+		public int Fb = 128;

+		public boolean FbIsDefined = false;

+		

+		public boolean Eos = false;

+		

+		public int Algorithm = 2;

+		public int MatchFinder = 1;

+		

+		public String InFile;

+		public String OutFile;

+		

+		boolean ParseSwitch(String s)

+		{

+			if (s.startsWith("d"))

+			{

+				DictionarySize = 1 << Integer.parseInt(s.substring(1));

+				DictionarySizeIsDefined = true;

+			}

+			else if (s.startsWith("fb"))

+			{

+				Fb = Integer.parseInt(s.substring(2));

+				FbIsDefined = true;

+			}

+			else if (s.startsWith("a"))

+				Algorithm = Integer.parseInt(s.substring(1));

+			else if (s.startsWith("lc"))

+				Lc = Integer.parseInt(s.substring(2));

+			else if (s.startsWith("lp"))

+				Lp = Integer.parseInt(s.substring(2));

+			else if (s.startsWith("pb"))

+				Pb = Integer.parseInt(s.substring(2));

+			else if (s.startsWith("eos"))

+				Eos = true;

+			else if (s.startsWith("mf"))

+			{

+				String mfs = s.substring(2);

+				if (mfs.equals("bt2"))

+					MatchFinder = 0;

+				else if (mfs.equals("bt4"))

+					MatchFinder = 1;

+				else if (mfs.equals("bt4b"))

+					MatchFinder = 2;

+				else

+					return false;

+			}

+			else

+				return false;

+			return true;

+		}

+		

+		public boolean Parse(String[] args) throws Exception

+		{

+			int pos = 0;

+			boolean switchMode = true;

+			for (int i = 0; i < args.length; i++)

+			{

+				String s = args[i];

+				if (s.length() == 0)

+					return false;

+				if (switchMode)

+				{

+					if (s.compareTo("--") == 0)

+					{

+						switchMode = false;

+						continue;

+					}

+					if (s.charAt(0) == '-')

+					{

+						String sw = s.substring(1).toLowerCase();

+						if (sw.length() == 0)

+							return false;

+						try

+						{

+							if (!ParseSwitch(sw))

+								return false;

+						}

+						catch (NumberFormatException e)

+						{

+							return false;

+						}

+						continue;

+					}

+				}

+				if (pos == 0)

+				{

+					if (s.equalsIgnoreCase("e"))

+						Command = kEncode;

+					else if (s.equalsIgnoreCase("d"))

+						Command = kDecode;

+					else if (s.equalsIgnoreCase("b"))

+						Command = kBenchmak;

+					else

+						return false;

+				}

+				else if(pos == 1)

+				{

+					if (Command == kBenchmak)

+					{

+						try

+						{

+							NumBenchmarkPasses = Integer.parseInt(s);

+							if (NumBenchmarkPasses < 1)

+								return false;

+						}

+						catch (NumberFormatException e)

+						{

+							return false;

+						}

+					}

+					else

+						InFile = s;

+				}

+				else if(pos == 2)

+					OutFile = s;

+				else

+					return false;

+				pos++;

+				continue;

+			}

+			return true;

+		}

+	}

+	

+	

+	static void PrintHelp()

+	{

+		System.out.println(

+				"\nUsage:  LZMA <e|d> [<switches>...] inputFile outputFile\n" +

+				"  e: encode file\n" +

+				"  d: decode file\n" +

+				"  b: Benchmark\n" +

+				"<Switches>\n" +

+				// "  -a{N}:  set compression mode - [0, 1], default: 1 (max)\n" +

+				"  -d{N}:  set dictionary - [0,28], default: 23 (8MB)\n" +

+				"  -fb{N}: set number of fast bytes - [5, 273], default: 128\n" +

+				"  -lc{N}: set number of literal context bits - [0, 8], default: 3\n" +

+				"  -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" +

+				"  -pb{N}: set number of pos bits - [0, 4], default: 2\n" +

+				"  -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" +

+				"  -eos:   write End Of Stream marker\n"

+				);

+	}

+	

+	public static void main(String[] args) throws Exception

+	{

+		System.out.println("\nLZMA (Java) 4.61  2008-11-23\n");

+		

+		if (args.length < 1)

+		{

+			PrintHelp();

+			return;

+		}

+		

+		CommandLine params = new CommandLine();

+		if (!params.Parse(args))

+		{

+			System.out.println("\nIncorrect command");

+			return;

+		}

+		

+		if (params.Command == CommandLine.kBenchmak)

+		{

+			int dictionary = (1 << 21);

+			if (params.DictionarySizeIsDefined)

+				dictionary = params.DictionarySize;

+			if (params.MatchFinder > 1)

+				throw new Exception("Unsupported match finder");

+			SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary);

+		}

+		else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode)

+		{

+			java.io.File inFile = new java.io.File(params.InFile);

+			java.io.File outFile = new java.io.File(params.OutFile);

+			

+			java.io.BufferedInputStream inStream  = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile));

+			java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile));

+			

+			boolean eos = false;

+			if (params.Eos)

+				eos = true;

+			if (params.Command == CommandLine.kEncode)

+			{

+				SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();

+				if (!encoder.SetAlgorithm(params.Algorithm))

+					throw new Exception("Incorrect compression mode");

+				if (!encoder.SetDictionarySize(params.DictionarySize))

+					throw new Exception("Incorrect dictionary size");

+				if (!encoder.SetNumFastBytes(params.Fb))

+					throw new Exception("Incorrect -fb value");

+				if (!encoder.SetMatchFinder(params.MatchFinder))

+					throw new Exception("Incorrect -mf value");

+				if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb))

+					throw new Exception("Incorrect -lc or -lp or -pb value");

+				encoder.SetEndMarkerMode(eos);

+				encoder.WriteCoderProperties(outStream);

+				long fileSize;

+				if (eos)

+					fileSize = -1;

+				else

+					fileSize = inFile.length();

+				for (int i = 0; i < 8; i++)

+					outStream.write((int)(fileSize >>> (8 * i)) & 0xFF);

+				encoder.Code(inStream, outStream, -1, -1, null);

+			}

+			else

+			{

+				int propertiesSize = 5;

+				byte[] properties = new byte[propertiesSize];

+				if (inStream.read(properties, 0, propertiesSize) != propertiesSize)

+					throw new Exception("input .lzma file is too short");

+				SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();

+				if (!decoder.SetDecoderProperties(properties))

+					throw new Exception("Incorrect stream properties");

+				long outSize = 0;

+				for (int i = 0; i < 8; i++)

+				{

+					int v = inStream.read();

+					if (v < 0)

+						throw new Exception("Can't read stream size");

+					outSize |= ((long)v) << (8 * i);

+				}

+				if (!decoder.Code(inStream, outStream, outSize))

+					throw new Exception("Error in data stream");

+			}

+			outStream.flush();

+			outStream.close();

+			inStream.close();

+		}

+		else

+			throw new Exception("Incorrect command");

+		return;

+	}

+}

diff --git a/Java/SevenZip/LzmaBench.java b/Java/SevenZip/LzmaBench.java
new file mode 100755
index 0000000..cceda24
--- /dev/null
+++ b/Java/SevenZip/LzmaBench.java
@@ -0,0 +1,392 @@
+package SevenZip;

+

+import java.io.ByteArrayOutputStream;

+import java.io.ByteArrayInputStream;

+import java.io.IOException;

+

+public class LzmaBench

+{

+	static final int kAdditionalSize = (1 << 21);

+	static final int kCompressedAdditionalSize = (1 << 10);

+	

+	static class CRandomGenerator

+	{

+		int A1;

+		int A2;

+		public CRandomGenerator() { Init(); }

+		public void Init() { A1 = 362436069; A2 = 521288629; }

+		public int GetRnd()

+		{

+			return

+				((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^

+				((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16)));

+		}

+	};

+	

+	static class CBitRandomGenerator

+	{

+		CRandomGenerator RG = new CRandomGenerator();

+		int Value;

+		int NumBits;

+		public void Init()

+		{

+			Value = 0;

+			NumBits = 0;

+		}

+		public int GetRnd(int numBits)

+		{

+			int result;

+			if (NumBits > numBits)

+			{

+				result = Value & ((1 << numBits) - 1);

+				Value >>>= numBits;

+				NumBits -= numBits;

+				return result;

+			}

+			numBits -= NumBits;

+			result = (Value << numBits);

+			Value = RG.GetRnd();

+			result |= Value & (((int)1 << numBits) - 1);

+			Value >>>= numBits;

+			NumBits = 32 - numBits;

+			return result;

+		}

+	};

+	

+	static class CBenchRandomGenerator

+	{

+		CBitRandomGenerator RG = new CBitRandomGenerator();

+		int Pos;

+		int Rep0;

+

+		public int BufferSize;

+		public byte[] Buffer = null;

+

+		public CBenchRandomGenerator() { }

+		public void Set(int bufferSize)

+		{

+			Buffer = new byte[bufferSize];

+			Pos = 0;

+			BufferSize = bufferSize;

+		}

+		int GetRndBit() { return RG.GetRnd(1); }

+		int GetLogRandBits(int numBits)

+		{

+			int len = RG.GetRnd(numBits);

+			return RG.GetRnd((int)len);

+		}

+		int GetOffset()

+		{

+			if (GetRndBit() == 0)

+				return GetLogRandBits(4);

+			return (GetLogRandBits(4) << 10) | RG.GetRnd(10);

+		}

+		int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); }

+		int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); }

+		public void Generate()

+		{

+			RG.Init();

+			Rep0 = 1;

+			while (Pos < BufferSize)

+			{

+				if (GetRndBit() == 0 || Pos < 1)

+					Buffer[Pos++] = (byte)(RG.GetRnd(8));

+				else

+				{

+					int len;

+					if (RG.GetRnd(3) == 0)

+						len = 1 + GetLen1();

+					else

+					{

+						do

+							Rep0 = GetOffset();

+						while (Rep0 >= Pos);

+						Rep0++;

+						len = 2 + GetLen2();

+					}

+					for (int i = 0; i < len && Pos < BufferSize; i++, Pos++)

+						Buffer[Pos] = Buffer[Pos - Rep0];

+				}

+			}

+		}

+	};

+	

+	static class CrcOutStream extends java.io.OutputStream

+	{

+		public CRC CRC = new CRC();

+		

+		public void Init()

+		{ 

+			CRC.Init(); 

+		}

+		public int GetDigest()

+		{ 

+			return CRC.GetDigest(); 

+		}

+		public void write(byte[] b)

+		{

+			CRC.Update(b);

+		}

+		public void write(byte[] b, int off, int len)

+		{

+			CRC.Update(b, off, len);

+		}

+		public void write(int b)

+		{

+			CRC.UpdateByte(b);

+		}

+	};

+

+	static class MyOutputStream extends java.io.OutputStream

+	{

+		byte[] _buffer;

+		int _size;

+		int _pos;

+		

+		public MyOutputStream(byte[] buffer)

+		{

+			_buffer = buffer;

+			_size = _buffer.length;

+		}

+		

+		public void reset()

+		{ 

+			_pos = 0; 

+		}

+		

+		public void write(int b) throws IOException

+		{

+			if (_pos >= _size)

+				throw new IOException("Error");

+			_buffer[_pos++] = (byte)b;

+		}

+		

+		public int size()

+		{

+			return _pos;

+		}

+	};

+

+	static class MyInputStream extends java.io.InputStream

+	{

+		byte[] _buffer;

+		int _size;

+		int _pos;

+		

+		public MyInputStream(byte[] buffer, int size)

+		{

+			_buffer = buffer;

+			_size = size;

+		}

+		

+		public void reset()

+		{ 

+			_pos = 0; 

+		}

+		

+		public int read()

+		{

+			if (_pos >= _size)

+				return -1;

+			return _buffer[_pos++] & 0xFF;

+		}

+	};

+	

+	static class CProgressInfo implements ICodeProgress

+	{

+		public long ApprovedStart;

+		public long InSize;

+		public long Time;

+		public void Init()

+		{ InSize = 0; }

+		public void SetProgress(long inSize, long outSize)

+		{

+			if (inSize >= ApprovedStart && InSize == 0)

+			{

+				Time = System.currentTimeMillis();

+				InSize = inSize;

+			}

+		}

+	}

+	static final int kSubBits = 8;

+	

+	static int GetLogSize(int size)

+	{

+		for (int i = kSubBits; i < 32; i++)

+			for (int j = 0; j < (1 << kSubBits); j++)

+				if (size <= ((1) << i) + (j << (i - kSubBits)))

+					return (i << kSubBits) + j;

+		return (32 << kSubBits);

+	}

+	

+	static long MyMultDiv64(long value, long elapsedTime)

+	{

+		long freq = 1000; // ms

+		long elTime = elapsedTime;

+		while (freq > 1000000)

+		{

+			freq >>>= 1;

+			elTime >>>= 1;

+		}

+		if (elTime == 0)

+			elTime = 1;

+		return value * freq / elTime;

+	}

+	

+	static long GetCompressRating(int dictionarySize, long elapsedTime, long size)

+	{

+		long t = GetLogSize(dictionarySize) - (18 << kSubBits);

+		long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits));

+		long numCommands = (long)(size) * numCommandsForOne;

+		return MyMultDiv64(numCommands, elapsedTime);

+	}

+	

+	static long GetDecompressRating(long elapsedTime, long outSize, long inSize)

+	{

+		long numCommands = inSize * 220 + outSize * 20;

+		return MyMultDiv64(numCommands, elapsedTime);

+	}

+	

+	static long GetTotalRating(

+			int dictionarySize,

+			long elapsedTimeEn, long sizeEn,

+			long elapsedTimeDe,

+			long inSizeDe, long outSizeDe)

+	{

+		return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) +

+				GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2;

+	}

+	

+	static void PrintValue(long v)

+	{

+		String s = "";

+		s += v;

+		for (int i = 0; i + s.length() < 6; i++)

+			System.out.print(" ");

+		System.out.print(s);

+	}

+	

+	static void PrintRating(long rating)

+	{

+		PrintValue(rating / 1000000);

+		System.out.print(" MIPS");

+	}

+	

+	static void PrintResults(

+			int dictionarySize,

+			long elapsedTime,

+			long size,

+			boolean decompressMode, long secondSize)

+	{

+		long speed = MyMultDiv64(size, elapsedTime);

+		PrintValue(speed / 1024);

+		System.out.print(" KB/s  ");

+		long rating;

+		if (decompressMode)

+			rating = GetDecompressRating(elapsedTime, size, secondSize);

+		else

+			rating = GetCompressRating(dictionarySize, elapsedTime, size);

+		PrintRating(rating);

+	}

+	

+	static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception

+	{

+		if (numIterations <= 0)

+			return 0;

+		if (dictionarySize < (1 << 18))

+		{

+			System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)");

+			return 1;

+		}

+		System.out.print("\n       Compressing                Decompressing\n\n");

+		

+		SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();

+		SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();

+		

+		if (!encoder.SetDictionarySize(dictionarySize))

+			throw new Exception("Incorrect dictionary size");

+		

+		int kBufferSize = dictionarySize + kAdditionalSize;

+		int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;

+		

+		ByteArrayOutputStream propStream = new ByteArrayOutputStream();

+		encoder.WriteCoderProperties(propStream);

+		byte[] propArray = propStream.toByteArray();

+		decoder.SetDecoderProperties(propArray);

+		

+		CBenchRandomGenerator rg = new CBenchRandomGenerator();

+

+		rg.Set(kBufferSize);

+		rg.Generate();

+		CRC crc = new CRC();

+		crc.Init();

+		crc.Update(rg.Buffer, 0, rg.BufferSize);

+		

+		CProgressInfo progressInfo = new CProgressInfo();

+		progressInfo.ApprovedStart = dictionarySize;

+		

+		long totalBenchSize = 0;

+		long totalEncodeTime = 0;

+		long totalDecodeTime = 0;

+		long totalCompressedSize = 0;

+		

+		MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize);

+

+		byte[] compressedBuffer = new byte[kCompressedBufferSize];

+		MyOutputStream compressedStream = new MyOutputStream(compressedBuffer);

+		CrcOutStream crcOutStream = new CrcOutStream();

+		MyInputStream inputCompressedStream = null;

+		int compressedSize = 0;

+		for (int i = 0; i < numIterations; i++)

+		{

+			progressInfo.Init();

+			inStream.reset();

+			compressedStream.reset();

+			encoder.Code(inStream, compressedStream, -1, -1, progressInfo);

+			long encodeTime = System.currentTimeMillis() - progressInfo.Time;

+			

+			if (i == 0)

+			{

+				compressedSize = compressedStream.size();

+				inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize);

+			}

+			else if (compressedSize != compressedStream.size())

+				throw (new Exception("Encoding error"));

+				

+			if (progressInfo.InSize == 0)

+				throw (new Exception("Internal ERROR 1282"));

+

+			long decodeTime = 0;

+			for (int j = 0; j < 2; j++)

+			{

+				inputCompressedStream.reset();

+				crcOutStream.Init();

+				

+				long outSize = kBufferSize;

+				long startTime = System.currentTimeMillis();

+				if (!decoder.Code(inputCompressedStream, crcOutStream, outSize))

+					throw (new Exception("Decoding Error"));;

+				decodeTime = System.currentTimeMillis() - startTime;

+				if (crcOutStream.GetDigest() != crc.GetDigest())

+					throw (new Exception("CRC Error"));

+			}

+			long benchSize = kBufferSize - (long)progressInfo.InSize;

+			PrintResults(dictionarySize, encodeTime, benchSize, false, 0);

+			System.out.print("     ");

+			PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize);

+			System.out.println();

+			

+			totalBenchSize += benchSize;

+			totalEncodeTime += encodeTime;

+			totalDecodeTime += decodeTime;

+			totalCompressedSize += compressedSize;

+		}

+		System.out.println("---------------------------------------------------");

+		PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0);

+		System.out.print("     ");

+		PrintResults(dictionarySize, totalDecodeTime,

+				kBufferSize * (long)numIterations, true, totalCompressedSize);

+		System.out.println("    Average");

+		return 0;

+	}

+}

diff --git a/Methods.txt b/Methods.txt
new file mode 100755
index 0000000..4c3ec68
--- /dev/null
+++ b/Methods.txt
@@ -0,0 +1,152 @@
+7-Zip method IDs (9.18)

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

+

+Each compression or crypto method in 7z has unique binary value (ID).

+The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes).

+

+If you want to add some new ID, you have two ways:

+1) Write request for allocating IDs to 7-zip developers.

+2) Generate 8-bytes ID:

+

+    3F ZZ ZZ ZZ ZZ ZZ MM MM 

+

+    3F              - Prefix for random IDs (1 byte)

+    ZZ ZZ ZZ ZZ ZZ  - Developer ID (5 bytes). Use real random bytes. 

+                      

+    MM MM           - Method ID (2 bytes)

+

+    You can notify 7-Zip developers about your Developer ID / Method ID.

+

+    Note: Use new ID only if old codec can not decode data encoded with new version.

+

+

+List of defined IDs

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

+      

+00 - Copy

+

+03 - Delta

+04 - x86 (BCJ)

+05 - PPC (Big Endian)

+06 - IA64

+07 - ARM (little endian)

+08 - ARM Thumb (little endian)

+09 - SPARC

+21 - LZMA2

+          

+02.. - Common

+   03 Swap

+      - 2 Swap2

+      - 4 Swap4

+

+03.. - 7z

+   01 - LZMA

+      01 - Version

+  

+   03 - Branch

+      01 - x86

+         03  - BCJ

+         1B  - BCJ2

+      02 - PPC

+         05 - PPC (Big Endian)

+      03 - Alpha

+         01 - Alpha

+      04 - IA64

+         01 - IA64

+      05 - ARM

+         01 - ARM

+      06 - M68

+         05 - M68 (Big Endian)

+      07 - ARM Thumb

+         01 - ARMT

+      08 - SPARC

+         05 - SPARC

+

+   04 - PPMD

+      01 - Version

+

+   7F -

+      01 - experimental methods.

+

+

+04.. - Misc

+   00 - Reserved

+   01 - Zip

+      00 - Copy (not used). Use {00} instead

+      01 - Shrink

+      06 - Implode

+      08 - Deflate

+      09 - Deflate64

+      10 - Imploding

+      12 - BZip2 (not used). Use {04 02 02} instead

+      14 - LZMA

+      60 - Jpeg

+      61 - WavPack

+      62 - PPMd

+      63 - wzAES

+   02 - BZip

+      02 - BZip2

+   03 - Rar

+      01 - Rar15

+      02 - Rar20

+      03 - Rar29

+   04 - Arj

+      01 - Arj (1,2,3)

+      02 - Arj 4

+   05 - Z

+   06 - Lzh

+   07 - Reserved for 7z

+   08 - Cab

+   09 - NSIS

+      01 - DeflateNSIS

+      02 - BZip2NSIS

+

+

+06.. - Crypto 

+   00 - 

+   01 - AES

+      0x - AES-128

+      4x - AES-192

+      8x - AES-256

+      Cx - AES

+

+      x0 - ECB

+      x1 - CBC

+      x2 - CFB

+      x3 - OFB

+

+   07 - Reserved

+   0F - Reserved

+

+   F0 - Misc Ciphers (Real Ciphers without hashing algo)

+

+   F1 - Misc Ciphers (Combine)

+      01 - Zip

+         01 - Main Zip crypto algo

+      03 - RAR

+         02 - 

+         03 - Rar29 AES-128 + (modified SHA-1)

+      07 - 7z

+         01 - AES-256 + SHA-256

+

+07.. - Hash (subject to change)

+   00 - 

+   01 - CRC

+   02 - SHA-1

+   03 - SHA-256

+   04 - SHA-384

+   05 - SHA-512

+

+   F0 - Misc Hash

+

+   F1 - Misc

+      03 - RAR

+         03 - Rar29 Password Hashing (modified SHA1)

+      07 - 7z 

+         01 - SHA-256 Password Hashing

+    

+   

+

+

+---

+End of document

diff --git a/history.txt b/history.txt
new file mode 100755
index 0000000..50ff40f
--- /dev/null
+++ b/history.txt
@@ -0,0 +1,271 @@
+HISTORY of the LZMA SDK

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

+

+9.18 beta      2010-11-02

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

+- New small SFX module for installers (SfxSetup).

+

+

+9.12 beta      2010-03-24

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

+- The BUG in LZMA SDK 9.* was fixed: LZMA2 codec didn't work,

+  if more than 10 threads were used (or more than 20 threads in some modes).

+

+

+9.11 beta      2010-03-15

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

+- PPMd compression method support

+   

+

+9.09           2009-12-12

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

+- The bug was fixed:

+   Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c

+   incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8.

+- Some bugs were fixed

+

+

+9.06           2009-08-17

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

+- Some changes in ANSI-C 7z Decoder interfaces.

+

+

+9.04           2009-05-30

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

+- LZMA2 compression method support

+- xz format support

+

+

+4.65           2009-02-03

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

+- Some minor fixes

+

+

+4.63           2008-12-31

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

+- Some minor fixes

+

+

+4.61 beta      2008-11-23

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

+- The bug in ANSI-C LZMA Decoder was fixed:

+    If encoded stream was corrupted, decoder could access memory 

+    outside of allocated range.

+- Some changes in ANSI-C 7z Decoder interfaces.

+- LZMA SDK is placed in the public domain.

+

+

+4.60 beta      2008-08-19

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

+- Some minor fixes.

+

+

+4.59 beta      2008-08-13

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

+- The bug was fixed:

+    LZMA Encoder in fast compression mode could access memory outside of 

+    allocated range in some rare cases.

+

+

+4.58 beta      2008-05-05

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

+- ANSI-C LZMA Decoder was rewritten for speed optimizations.

+- ANSI-C LZMA Encoder was included to LZMA SDK.

+- C++ LZMA code now is just wrapper over ANSI-C code.

+

+

+4.57           2007-12-12

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

+- Speed optimizations in Ñ++ LZMA Decoder. 

+- Small changes for more compatibility with some C/C++ compilers.

+

+

+4.49 beta      2007-07-05

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

+- .7z ANSI-C Decoder:

+     - now it supports BCJ and BCJ2 filters

+     - now it supports files larger than 4 GB.

+     - now it supports "Last Write Time" field for files.

+- C++ code for .7z archives compressing/decompressing from 7-zip 

+  was included to LZMA SDK.

+  

+

+4.43           2006-06-04

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

+- Small changes for more compatibility with some C/C++ compilers.

+  

+

+4.42           2006-05-15

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

+- Small changes in .h files in ANSI-C version.

+  

+

+4.39 beta      2006-04-14

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

+- The bug in versions 4.33b:4.38b was fixed:

+  C++ version of LZMA encoder could not correctly compress 

+  files larger than 2 GB with HC4 match finder (-mfhc4).

+  

+

+4.37 beta      2005-04-06

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

+- Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. 

+

+

+4.35 beta      2005-03-02

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

+- The bug was fixed in C++ version of LZMA Decoder:

+    If encoded stream was corrupted, decoder could access memory 

+    outside of allocated range.

+

+

+4.34 beta      2006-02-27

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

+- Compressing speed and memory requirements for compressing were increased

+- LZMA now can use only these match finders: HC4, BT2, BT3, BT4

+

+

+4.32           2005-12-09

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

+- Java version of LZMA SDK was included

+

+

+4.30           2005-11-20

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

+- Compression ratio was improved in -a2 mode

+- Speed optimizations for compressing in -a2 mode

+- -fb switch now supports values up to 273

+- The bug in 7z_C (7zIn.c) was fixed:

+  It used Alloc/Free functions from different memory pools.

+  So if program used two memory pools, it worked incorrectly.

+- 7z_C: .7z format supporting was improved

+- LZMA# SDK (C#.NET version) was included

+

+

+4.27 (Updated) 2005-09-21

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

+- Some GUIDs/interfaces in C++ were changed.

+ IStream.h:

+   ISequentialInStream::Read now works as old ReadPart

+   ISequentialOutStream::Write now works as old WritePart

+

+

+4.27           2005-08-07

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

+- The bug in LzmaDecodeSize.c was fixed:

+   if _LZMA_IN_CB and _LZMA_OUT_READ were defined,

+   decompressing worked incorrectly.

+

+

+4.26           2005-08-05

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

+- Fixes in 7z_C code and LzmaTest.c:

+  previous versions could work incorrectly,

+  if malloc(0) returns 0

+

+

+4.23           2005-06-29

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

+- Small fixes in C++ code

+

+

+4.22           2005-06-10

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

+- Small fixes

+

+

+4.21           2005-06-08

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

+- Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed

+- New additional version of ANSI-C LZMA Decoder with zlib-like interface:

+    - LzmaStateDecode.h

+    - LzmaStateDecode.c

+    - LzmaStateTest.c

+- ANSI-C LZMA Decoder now can decompress files larger than 4 GB

+

+

+4.17           2005-04-18

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

+- New example for RAM->RAM compressing/decompressing: 

+  LZMA + BCJ (filter for x86 code):

+    - LzmaRam.h

+    - LzmaRam.cpp

+    - LzmaRamDecode.h

+    - LzmaRamDecode.c

+    - -f86 switch for lzma.exe

+

+

+4.16           2005-03-29

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

+- The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): 

+   If _LZMA_OUT_READ was defined, and if encoded stream was corrupted,

+   decoder could access memory outside of allocated range.

+- Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster).

+  Old version of LZMA Decoder now is in file LzmaDecodeSize.c. 

+  LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c

+- Small speed optimization in LZMA C++ code

+- filter for SPARC's code was added

+- Simplified version of .7z ANSI-C Decoder was included

+

+

+4.06           2004-09-05

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

+- The bug in v4.05 was fixed:

+    LZMA-Encoder didn't release output stream in some cases.

+

+

+4.05           2004-08-25

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

+- Source code of filters for x86, IA-64, ARM, ARM-Thumb 

+  and PowerPC code was included to SDK

+- Some internal minor changes

+

+

+4.04           2004-07-28

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

+- More compatibility with some C++ compilers

+

+

+4.03           2004-06-18

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

+- "Benchmark" command was added. It measures compressing 

+  and decompressing speed and shows rating values. 

+  Also it checks hardware errors.

+

+

+4.02           2004-06-10

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

+- C++ LZMA Encoder/Decoder code now is more portable

+  and it can be compiled by GCC on Linux.

+

+

+4.01           2004-02-15

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

+- Some detection of data corruption was enabled.

+    LzmaDecode.c / RangeDecoderReadByte

+    .....

+    {

+      rd->ExtraBytes = 1;

+      return 0xFF;

+    }

+

+

+4.00           2004-02-13

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

+- Original version of LZMA SDK

+

+

+

+HISTORY of the LZMA

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

+  2001-2008:  Improvements to LZMA compressing/decompressing code, 

+              keeping compatibility with original LZMA format

+  1996-2001:  Development of LZMA compression format

+

+  Some milestones:

+

+  2001-08-30: LZMA compression was added to 7-Zip

+  1999-01-02: First version of 7-Zip was released

+  

+

+End of document

diff --git a/lzma.txt b/lzma.txt
new file mode 100755
index 0000000..579f2cc
--- /dev/null
+++ b/lzma.txt
@@ -0,0 +1,598 @@
+LZMA SDK 9.20

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

+

+LZMA SDK provides the documentation, samples, header files, libraries, 

+and tools you need to develop applications that use LZMA compression.

+

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

+

+LZMA is an improved version of famous LZ77 compression algorithm. 

+It was improved in way of maximum increasing of compression ratio,

+keeping high decompression speed and low memory requirements for 

+decompressing.

+

+

+

+LICENSE

+-------

+

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

+

+Some code in LZMA SDK is based on public domain code from another developers:

+  1) PPMd var.H (2001): Dmitry Shkarin

+  2) SHA-256: Wei Dai (Crypto++ library)

+

+

+LZMA SDK Contents

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

+

+LZMA SDK includes:

+

+  - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing

+  - Compiled file->file LZMA compressing/decompressing program for Windows system

+

+

+UNIX/Linux version 

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

+To compile C++ version of file->file LZMA encoding, go to directory

+CPP/7zip/Bundles/LzmaCon

+and call make to recompile it:

+  make -f makefile.gcc clean all

+

+In some UNIX/Linux versions you must compile LZMA with static libraries.

+To compile with static libraries, you can use 

+LIB = -lm -static

+

+

+Files

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

+lzma.txt     - LZMA SDK description (this file)

+7zFormat.txt - 7z Format description

+7zC.txt      - 7z ANSI-C Decoder description

+methods.txt  - Compression method IDs for .7z

+lzma.exe     - Compiled file->file LZMA encoder/decoder for Windows

+7zr.exe      - 7-Zip with 7z/lzma/xz support.

+history.txt  - history of the LZMA SDK

+

+

+Source code structure

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

+

+C/  - C files

+        7zCrc*.*   - CRC code

+        Alloc.*    - Memory allocation functions

+        Bra*.*     - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code

+        LzFind.*   - Match finder for LZ (LZMA) encoders 

+        LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding

+        LzHash.h   - Additional file for LZ match finder

+        LzmaDec.*  - LZMA decoding

+        LzmaEnc.*  - LZMA encoding

+        LzmaLib.*  - LZMA Library for DLL calling

+        Types.h    - Basic types for another .c files

+        Threads.*  - The code for multithreading.

+

+    LzmaLib  - LZMA Library (.DLL for Windows)

+    

+    LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder).

+

+    Archive - files related to archiving

+      7z     - 7z ANSI-C Decoder

+

+CPP/ -- CPP files

+

+  Common  - common files for C++ projects

+  Windows - common files for Windows related code

+

+  7zip    - files related to 7-Zip Project

+

+    Common   - common files for 7-Zip

+

+    Compress - files related to compression/decompression

+

+    Archive - files related to archiving

+

+      Common   - common files for archive handling

+      7z       - 7z C++ Encoder/Decoder

+

+    Bundles    - Modules that are bundles of other modules

+  

+      Alone7z           - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2

+      LzmaCon           - lzma.exe: LZMA compression/decompression

+      Format7zR         - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2

+      Format7zExtractR  - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.

+

+    UI        - User Interface files

+         

+      Client7z - Test application for 7za.dll,  7zr.dll, 7zxr.dll

+      Common   - Common UI files

+      Console  - Code for console archiver

+

+

+

+CS/ - C# files

+  7zip

+    Common   - some common files for 7-Zip

+    Compress - files related to compression/decompression

+      LZ     - files related to LZ (Lempel-Ziv) compression algorithm

+      LZMA         - LZMA compression/decompression

+      LzmaAlone    - file->file LZMA compression/decompression

+      RangeCoder   - Range Coder (special code of compression/decompression)

+

+Java/  - Java files

+  SevenZip

+    Compression    - files related to compression/decompression

+      LZ           - files related to LZ (Lempel-Ziv) compression algorithm

+      LZMA         - LZMA compression/decompression

+      RangeCoder   - Range Coder (special code of compression/decompression)

+

+

+C/C++ source code of LZMA SDK is part of 7-Zip project.

+7-Zip source code can be downloaded from 7-Zip's SourceForge page:

+

+  http://sourceforge.net/projects/sevenzip/

+

+

+

+LZMA features

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

+  - Variable dictionary size (up to 1 GB)

+  - Estimated compressing speed: about 2 MB/s on 2 GHz CPU

+  - Estimated decompressing speed: 

+      - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64

+      - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC

+  - Small memory requirements for decompressing (16 KB + DictionarySize)

+  - Small code size for decompressing: 5-8 KB

+

+LZMA decoder uses only integer operations and can be 

+implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions).

+

+Some critical operations that affect the speed of LZMA decompression:

+  1) 32*16 bit integer multiply

+  2) Misspredicted branches (penalty mostly depends from pipeline length)

+  3) 32-bit shift and arithmetic operations

+

+The speed of LZMA decompressing mostly depends from CPU speed.

+Memory speed has no big meaning. But if your CPU has small data cache, 

+overall weight of memory speed will slightly increase.

+

+

+How To Use

+----------

+

+Using LZMA encoder/decoder executable

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

+

+Usage:  LZMA <e|d> inputFile outputFile [<switches>...]

+

+  e: encode file

+

+  d: decode file

+

+  b: Benchmark. There are two tests: compressing and decompressing 

+     with LZMA method. Benchmark shows rating in MIPS (million 

+     instructions per second). Rating value is calculated from 

+     measured speed and it is normalized with Intel's Core 2 results.

+     Also Benchmark checks possible hardware errors (RAM 

+     errors in most cases). Benchmark uses these settings:

+     (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. 

+     Also you can change the number of iterations. Example for 30 iterations:

+       LZMA b 30

+     Default number of iterations is 10.

+

+<Switches>

+  

+

+  -a{N}:  set compression mode 0 = fast, 1 = normal

+          default: 1 (normal)

+

+  d{N}:   Sets Dictionary size - [0, 30], default: 23 (8MB)

+          The maximum value for dictionary size is 1 GB = 2^30 bytes.

+          Dictionary size is calculated as DictionarySize = 2^N bytes. 

+          For decompressing file compressed by LZMA method with dictionary 

+          size D = 2^N you need about D bytes of memory (RAM).

+

+  -fb{N}: set number of fast bytes - [5, 273], default: 128

+          Usually big number gives a little bit better compression ratio 

+          and slower compression process.

+

+  -lc{N}: set number of literal context bits - [0, 8], default: 3

+          Sometimes lc=4 gives gain for big files.

+

+  -lp{N}: set number of literal pos bits - [0, 4], default: 0

+          lp switch is intended for periodical data when period is 

+          equal 2^N. For example, for 32-bit (4 bytes) 

+          periodical data you can use lp=2. Often it's better to set lc0, 

+          if you change lp switch.

+

+  -pb{N}: set number of pos bits - [0, 4], default: 2

+          pb switch is intended for periodical data 

+          when period is equal 2^N.

+

+  -mf{MF_ID}: set Match Finder. Default: bt4. 

+              Algorithms from hc* group doesn't provide good compression 

+              ratio, but they often works pretty fast in combination with 

+              fast mode (-a0).

+

+              Memory requirements depend from dictionary size 

+              (parameter "d" in table below). 

+

+               MF_ID     Memory                   Description

+

+                bt2    d *  9.5 + 4MB  Binary Tree with 2 bytes hashing.

+                bt3    d * 11.5 + 4MB  Binary Tree with 3 bytes hashing.

+                bt4    d * 11.5 + 4MB  Binary Tree with 4 bytes hashing.

+                hc4    d *  7.5 + 4MB  Hash Chain with 4 bytes hashing.

+

+  -eos:   write End Of Stream marker. By default LZMA doesn't write 

+          eos marker, since LZMA decoder knows uncompressed size 

+          stored in .lzma file header.

+

+  -si:    Read data from stdin (it will write End Of Stream marker).

+  -so:    Write data to stdout

+

+

+Examples:

+

+1) LZMA e file.bin file.lzma -d16 -lc0 

+

+compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K)  

+and 0 literal context bits. -lc0 allows to reduce memory requirements 

+for decompression.

+

+

+2) LZMA e file.bin file.lzma -lc0 -lp2

+

+compresses file.bin to file.lzma with settings suitable 

+for 32-bit periodical data (for example, ARM or MIPS code).

+

+3) LZMA d file.lzma file.bin

+

+decompresses file.lzma to file.bin.

+

+

+Compression ratio hints

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

+

+Recommendations

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

+

+To increase the compression ratio for LZMA compressing it's desirable 

+to have aligned data (if it's possible) and also it's desirable to locate

+data in such order, where code is grouped in one place and data is 

+grouped in other place (it's better than such mixing: code, data, code,

+data, ...).

+

+

+Filters

+-------

+You can increase the compression ratio for some data types, using

+special filters before compressing. For example, it's possible to 

+increase the compression ratio on 5-10% for code for those CPU ISAs: 

+x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC.

+

+You can find C source code of such filters in C/Bra*.* files

+

+You can check the compression ratio gain of these filters with such 

+7-Zip commands (example for ARM code):

+No filter:

+  7z a a1.7z a.bin -m0=lzma

+

+With filter for little-endian ARM code:

+  7z a a2.7z a.bin -m0=arm -m1=lzma        

+

+It works in such manner:

+Compressing    = Filter_encoding + LZMA_encoding

+Decompressing  = LZMA_decoding + Filter_decoding

+

+Compressing and decompressing speed of such filters is very high,

+so it will not increase decompressing time too much.

+Moreover, it reduces decompression time for LZMA_decoding, 

+since compression ratio with filtering is higher.

+

+These filters convert CALL (calling procedure) instructions 

+from relative offsets to absolute addresses, so such data becomes more 

+compressible.

+

+For some ISAs (for example, for MIPS) it's impossible to get gain from such filter.

+

+

+LZMA compressed file format

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

+Offset Size Description

+  0     1   Special LZMA properties (lc,lp, pb in encoded form)

+  1     4   Dictionary size (little endian)

+  5     8   Uncompressed size (little endian). -1 means unknown size

+ 13         Compressed data

+

+

+ANSI-C LZMA Decoder

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

+

+Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58.

+If you want to use old interfaces you can download previous version of LZMA SDK

+from sourceforge.net site.

+

+To use ANSI-C LZMA Decoder you need the following files:

+1) LzmaDec.h + LzmaDec.c + Types.h

+LzmaUtil/LzmaUtil.c is example application that uses these files.

+

+

+Memory requirements for LZMA decoding

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

+

+Stack usage of LZMA decoding function for local variables is not 

+larger than 200-400 bytes.

+

+LZMA Decoder uses dictionary buffer and internal state structure.

+Internal state structure consumes

+  state_size = (4 + (1.5 << (lc + lp))) KB

+by default (lc=3, lp=0), state_size = 16 KB.

+

+

+How To decompress data

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

+

+LZMA Decoder (ANSI-C version) now supports 2 interfaces:

+1) Single-call Decompressing

+2) Multi-call State Decompressing (zlib-like interface)

+

+You must use external allocator:

+Example:

+void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }

+void SzFree(void *p, void *address) { p = p; free(address); }

+ISzAlloc alloc = { SzAlloc, SzFree };

+

+You can use p = p; operator to disable compiler warnings.

+

+

+Single-call Decompressing

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

+When to use: RAM->RAM decompressing

+Compile files: LzmaDec.h + LzmaDec.c + Types.h

+Compile defines: no defines

+Memory Requirements:

+  - Input buffer: compressed size

+  - Output buffer: uncompressed size

+  - LZMA Internal Structures: state_size (16 KB for default settings) 

+

+Interface:

+  int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

+      const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 

+      ELzmaStatus *status, ISzAlloc *alloc);

+  In: 

+    dest     - output data

+    destLen  - output data size

+    src      - input data

+    srcLen   - input data size

+    propData - LZMA properties  (5 bytes)

+    propSize - size of propData buffer (5 bytes)

+    finishMode - It has meaning only if the decoding reaches output limit (*destLen).

+         LZMA_FINISH_ANY - Decode just destLen bytes.

+         LZMA_FINISH_END - Stream must be finished after (*destLen).

+                           You can use LZMA_FINISH_END, when you know that 

+                           current output buffer covers last bytes of stream. 

+    alloc    - Memory allocator.

+

+  Out: 

+    destLen  - processed output size 

+    srcLen   - processed input size 

+

+  Output:

+    SZ_OK

+      status:

+        LZMA_STATUS_FINISHED_WITH_MARK

+        LZMA_STATUS_NOT_FINISHED 

+        LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK

+    SZ_ERROR_DATA - Data error

+    SZ_ERROR_MEM  - Memory allocation error

+    SZ_ERROR_UNSUPPORTED - Unsupported properties

+    SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).

+

+  If LZMA decoder sees end_marker before reaching output limit, it returns OK result,

+  and output value of destLen will be less than output buffer size limit.

+

+  You can use multiple checks to test data integrity after full decompression:

+    1) Check Result and "status" variable.

+    2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.

+    3) Check that output(srcLen) = compressedSize, if you know real compressedSize. 

+       You must use correct finish mode in that case. */ 

+

+

+Multi-call State Decompressing (zlib-like interface)

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

+

+When to use: file->file decompressing 

+Compile files: LzmaDec.h + LzmaDec.c + Types.h

+

+Memory Requirements:

+ - Buffer for input stream: any size (for example, 16 KB)

+ - Buffer for output stream: any size (for example, 16 KB)

+ - LZMA Internal Structures: state_size (16 KB for default settings) 

+ - LZMA dictionary (dictionary size is encoded in LZMA properties header)

+

+1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header:

+   unsigned char header[LZMA_PROPS_SIZE + 8];

+   ReadFile(inFile, header, sizeof(header)

+

+2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties

+

+  CLzmaDec state;

+  LzmaDec_Constr(&state);

+  res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);

+  if (res != SZ_OK)

+    return res;

+

+3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop

+

+  LzmaDec_Init(&state);

+  for (;;)

+  {

+    ... 

+    int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, 

+        const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);

+    ...

+  }

+

+

+4) Free all allocated structures

+  LzmaDec_Free(&state, &g_Alloc);

+

+For full code example, look at C/LzmaUtil/LzmaUtil.c code.

+

+

+How To compress data

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

+

+Compile files: LzmaEnc.h + LzmaEnc.c + Types.h +

+LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h

+

+Memory Requirements:

+  - (dictSize * 11.5 + 6 MB) + state_size

+

+Lzma Encoder can use two memory allocators:

+1) alloc - for small arrays.

+2) allocBig - for big arrays.

+

+For example, you can use Large RAM Pages (2 MB) in allocBig allocator for 

+better compression speed. Note that Windows has bad implementation for 

+Large RAM Pages. 

+It's OK to use same allocator for alloc and allocBig.

+

+

+Single-call Compression with callbacks

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

+

+Check C/LzmaUtil/LzmaUtil.c as example, 

+

+When to use: file->file decompressing 

+

+1) you must implement callback structures for interfaces:

+ISeqInStream

+ISeqOutStream

+ICompressProgress

+ISzAlloc

+

+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

+static void SzFree(void *p, void *address) {  p = p; MyFree(address); }

+static ISzAlloc g_Alloc = { SzAlloc, SzFree };

+

+  CFileSeqInStream inStream;

+  CFileSeqOutStream outStream;

+

+  inStream.funcTable.Read = MyRead;

+  inStream.file = inFile;

+  outStream.funcTable.Write = MyWrite;

+  outStream.file = outFile;

+

+

+2) Create CLzmaEncHandle object;

+

+  CLzmaEncHandle enc;

+

+  enc = LzmaEnc_Create(&g_Alloc);

+  if (enc == 0)

+    return SZ_ERROR_MEM;

+

+

+3) initialize CLzmaEncProps properties;

+

+  LzmaEncProps_Init(&props);

+

+  Then you can change some properties in that structure.

+

+4) Send LZMA properties to LZMA Encoder

+

+  res = LzmaEnc_SetProps(enc, &props);

+

+5) Write encoded properties to header

+

+    Byte header[LZMA_PROPS_SIZE + 8];

+    size_t headerSize = LZMA_PROPS_SIZE;

+    UInt64 fileSize;

+    int i;

+

+    res = LzmaEnc_WriteProperties(enc, header, &headerSize);

+    fileSize = MyGetFileLength(inFile);

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

+      header[headerSize++] = (Byte)(fileSize >> (8 * i));

+    MyWriteFileAndCheck(outFile, header, headerSize)

+

+6) Call encoding function:

+      res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, 

+        NULL, &g_Alloc, &g_Alloc);

+

+7) Destroy LZMA Encoder Object

+  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);

+

+

+If callback function return some error code, LzmaEnc_Encode also returns that code

+or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.

+

+

+Single-call RAM->RAM Compression

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

+

+Single-call RAM->RAM Compression is similar to Compression with callbacks,

+but you provide pointers to buffers instead of pointers to stream callbacks:

+

+HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,

+    CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, 

+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);

+

+Return code:

+  SZ_OK               - OK

+  SZ_ERROR_MEM        - Memory allocation error 

+  SZ_ERROR_PARAM      - Incorrect paramater

+  SZ_ERROR_OUTPUT_EOF - output buffer overflow

+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)

+

+

+

+Defines

+-------

+

+_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.

+

+_LZMA_PROB32   - It can increase the speed on some 32-bit CPUs, but memory usage for 

+                 some structures will be doubled in that case.

+

+_LZMA_UINT32_IS_ULONG  - Define it if int is 16-bit on your compiler and long is 32-bit.

+

+_LZMA_NO_SYSTEM_SIZE_T  - Define it if you don't want to use size_t type.

+

+

+_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder.

+

+

+C++ LZMA Encoder/Decoder 

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

+C++ LZMA code use COM-like interfaces. So if you want to use it, 

+you can study basics of COM/OLE.

+C++ LZMA code is just wrapper over ANSI-C code.

+

+

+C++ Notes

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

+If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling),

+you must check that you correctly work with "new" operator.

+7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator.

+So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator:

+operator new(size_t size)

+{

+  void *p = ::malloc(size);

+  if (p == 0)

+    throw CNewException();

+  return p;

+}

+If you use MSCV that throws exception for "new" operator, you can compile without 

+"NewHandler.cpp". So standard exception will be used. Actually some code of 

+7-Zip catches any exception in internal code and converts it to HRESULT code.

+So you don't need to catch CNewException, if you call COM interfaces of 7-Zip.

+

+---

+

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

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

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