Project import
diff --git a/lzma/Android.bp b/lzma/Android.bp
new file mode 100644
index 0000000..e0454ba
--- /dev/null
+++ b/lzma/Android.bp
@@ -0,0 +1 @@
+subdirs = ["C"]
diff --git a/lzma/Android.mk b/lzma/Android.mk
new file mode 100644
index 0000000..93dd9d4
--- /dev/null
+++ b/lzma/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(call first-makefiles-under,$(LOCAL_PATH))
+
diff --git a/lzma/Asm/arm/7zCrcOpt.asm b/lzma/Asm/arm/7zCrcOpt.asm
new file mode 100644
index 0000000..f008d65
--- /dev/null
+++ b/lzma/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/lzma/Asm/x86/7zAsm.asm b/lzma/Asm/x86/7zAsm.asm
new file mode 100644
index 0000000..53a9e3f
--- /dev/null
+++ b/lzma/Asm/x86/7zAsm.asm
@@ -0,0 +1,105 @@
+; 7zAsm.asm -- ASM macros

+; 2012-12-30 : 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 = numParams

+  ifdef x64

+    proc_name equ name

+  else

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

+  endif

+  proc_name PROC

+endm

+

+MY_ENDP macro

+  ifdef x64

+    ret

+  else

+    if proc_numParams LT 3

+      ret

+    else

+      ret (proc_numParams - 2) * 4

+    endif

+  endif

+  proc_name ENDP

+endm

+

+ifdef x64

+  REG_SIZE equ 8

+  REG_LOGAR_SIZE equ 3

+else

+  REG_SIZE equ 4

+  REG_LOGAR_SIZE equ 2

+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

+  x8 equ r8d

+  x9 equ r9d

+  x10 equ r10d

+  x11 equ r11d

+  x12 equ r12d

+  x13 equ r13d

+  x14 equ r14d

+  x15 equ r15d

+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/lzma/Asm/x86/7zCrcOpt.asm b/lzma/Asm/x86/7zCrcOpt.asm
new file mode 100644
index 0000000..2de5171
--- /dev/null
+++ b/lzma/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/lzma/Asm/x86/AesOpt.asm b/lzma/Asm/x86/AesOpt.asm
new file mode 100644
index 0000000..c32e48f
--- /dev/null
+++ b/lzma/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/lzma/Asm/x86/XzCrc64Opt.asm b/lzma/Asm/x86/XzCrc64Opt.asm
new file mode 100644
index 0000000..3e6d490
--- /dev/null
+++ b/lzma/Asm/x86/XzCrc64Opt.asm
@@ -0,0 +1,205 @@
+; XzCrc64Opt.asm -- CRC64 calculation : optimized version

+; 2011-06-28 : Igor Pavlov : Public domain

+

+include 7zAsm.asm

+

+MY_ASM_START

+

+ifdef x64

+

+    rD   equ  r9

+    rN   equ  r10

+

+    num_VAR     equ  r8

+    table_VAR   equ  r9

+

+    SRCDAT  equ  rN + rD

+

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

+    xor     dest, QWORD PTR [r5 + src * 8 + 0800h * t]

+endm

+

+CRC1b macro

+    movzx   x6, BYTE PTR [rD]

+    inc     rD

+    movzx   x3, x0_L

+    xor     x6, x3

+    shr     r0, 8

+    CRC_XOR r0, r6, 0

+    dec     rN

+endm

+

+MY_PROLOG macro crc_end:req

+    MY_PUSH_4_REGS

+    

+    mov     r0, r1

+    mov     rN, num_VAR

+    mov     r5, table_VAR

+    mov     rD, r2

+    test    rN, rN

+    jz      crc_end

+  @@:

+    test    rD, 3

+    jz      @F

+    CRC1b

+    jnz     @B

+  @@:

+    cmp     rN, 8

+    jb      crc_end

+    add     rN, rD

+    mov     num_VAR, rN

+    sub     rN, 4

+    and     rN, NOT 3

+    sub     rD, rN

+    mov     x1, [SRCDAT]

+    xor     r0, r1

+    add     rN, 4

+endm

+

+MY_EPILOG macro crc_end:req

+    sub     rN, 4

+    mov     x1, [SRCDAT]

+    xor     r0, r1

+    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 XzCrc64UpdateT4, 4

+    MY_PROLOG crc_end_4

+    align 16

+  main_loop_4:

+    mov     x1, [SRCDAT]

+    movzx   x2, x0_L

+    movzx   x3, x0_H

+    shr     r0, 16

+    movzx   x6, x0_L

+    movzx   x7, x0_H

+    shr     r0, 16

+    CRC_XOR r1, r2, 3

+    CRC_XOR r0, r3, 2

+    CRC_XOR r1, r6, 1

+    CRC_XOR r0, r7, 0

+    xor     r0, r1

+

+    add     rD, 4

+    jnz     main_loop_4

+

+    MY_EPILOG crc_end_4

+MY_ENDP

+

+else

+

+    rD   equ  r1

+    rN   equ  r7

+

+    crc_val     equ (REG_SIZE * 5)

+    crc_table   equ (8 + crc_val)

+    table_VAR   equ [r4 + crc_table]

+    num_VAR     equ table_VAR

+

+

+    SRCDAT  equ  rN + rD

+

+CRC macro op0:req, op1:req, dest0:req, dest1:req, src:req, t:req

+    op0     dest0, DWORD PTR [r5 + src * 8 + 0800h * t]

+    op1     dest1, DWORD PTR [r5 + src * 8 + 0800h * t + 4]

+endm

+

+CRC_XOR macro dest0:req, dest1:req, src:req, t:req

+    CRC xor, xor, dest0, dest1, src, t

+endm

+

+

+CRC1b macro

+    movzx   x6, BYTE PTR [rD]

+    inc     rD

+    movzx   x3, x0_L

+    xor     x6, x3

+    shrd    r0, r2, 8

+    shr     r2, 8

+    CRC_XOR r0, r2, r6, 0

+    dec     rN

+endm

+

+MY_PROLOG macro crc_end:req

+    MY_PUSH_4_REGS

+    

+    mov     rN, r2

+

+    mov     x0, [r4 + crc_val]

+    mov     x2, [r4 + crc_val + 4]

+    mov     r5, table_VAR

+    test    rN, rN

+    jz      crc_end

+  @@:

+    test    rD, 3

+    jz      @F

+    CRC1b

+    jnz     @B

+  @@:

+    cmp     rN, 8

+    jb      crc_end

+    add     rN, rD

+

+    mov     num_VAR, rN

+

+    sub     rN, 4

+    and     rN, NOT 3

+    sub     rD, rN

+    xor     r0, [SRCDAT]

+    add     rN, 4

+endm

+

+MY_EPILOG macro crc_end:req

+    sub     rN, 4

+    xor     r0, [SRCDAT]

+

+    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 XzCrc64UpdateT4, 5

+    MY_PROLOG crc_end_4

+    movzx   x6, x0_L

+    align 16

+  main_loop_4:

+    mov     r3, [SRCDAT]

+    xor     r3, r2

+

+    CRC xor, mov, r3, r2, r6, 3

+    movzx   x6, x0_H

+    shr     r0, 16

+    CRC_XOR r3, r2, r6, 2

+

+    movzx   x6, x0_L

+    movzx   x0, x0_H

+    CRC_XOR r3, r2, r6, 1

+    CRC_XOR r3, r2, r0, 0

+    movzx   x6, x3_L

+    mov     r0, r3

+

+    add     rD, 4

+    jnz     main_loop_4

+

+    MY_EPILOG crc_end_4

+MY_ENDP

+

+endif

+

+end

diff --git a/lzma/C/7z.h b/lzma/C/7z.h
new file mode 100644
index 0000000..dc25f53
--- /dev/null
+++ b/lzma/C/7z.h
@@ -0,0 +1,216 @@
+/* 7z.h -- 7z interface

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_H

+#define __7Z_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+#define k7zStartHeaderSize 0x20

+#define k7zSignatureSize 6

+

+extern Byte k7zSignature[k7zSignatureSize];

+

+typedef struct

+{

+  const Byte *Data;

+  size_t Size;

+} CSzData;

+

+/* CSzCoderInfo & CSzFolder support only default methods */

+

+typedef struct

+{

+  size_t PropsOffset;

+  UInt32 MethodID;

+  Byte NumInStreams;

+  Byte NumOutStreams;

+  Byte PropsSize;

+} CSzCoderInfo;

+

+typedef struct

+{

+  UInt32 InIndex;

+  UInt32 OutIndex;

+} CSzBindPair;

+

+#define SZ_NUM_CODERS_IN_FOLDER_MAX 4

+#define SZ_NUM_BINDS_IN_FOLDER_MAX 3

+#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4

+#define SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX 4

+

+typedef struct

+{

+  UInt32 NumCoders;

+  UInt32 NumBindPairs;

+  UInt32 NumPackStreams;

+  UInt32 MainOutStream;

+  UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];

+  CSzBindPair BindPairs[SZ_NUM_BINDS_IN_FOLDER_MAX];

+  CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];

+  UInt64 CodersUnpackSizes[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX];

+} CSzFolder;

+

+/*

+typedef struct

+{

+  size_t CodersDataOffset;

+  size_t UnpackSizeDataOffset;

+  // UInt32 StartCoderUnpackSizesIndex;

+  UInt32 StartPackStreamIndex;

+  // UInt32 IndexOfMainOutStream;

+} CSzFolder2;

+*/

+

+SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes);

+

+typedef struct

+{

+  UInt32 Low;

+  UInt32 High;

+} CNtfsFileTime;

+

+typedef struct

+{

+  Byte *Defs; /* MSB 0 bit numbering */

+  UInt32 *Vals;

+} CSzBitUi32s;

+

+typedef struct

+{

+  Byte *Defs; /* MSB 0 bit numbering */

+  // UInt64 *Vals;

+  CNtfsFileTime *Vals;

+} CSzBitUi64s;

+

+#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)

+

+#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)

+

+typedef struct

+{

+  UInt32 NumPackStreams;

+  UInt32 NumFolders;

+

+  UInt64 *PackPositions; // NumPackStreams + 1

+  CSzBitUi32s FolderCRCs;

+

+  size_t *FoCodersOffsets;

+  size_t *FoSizesOffsets;

+  // UInt32 StartCoderUnpackSizesIndex;

+  UInt32 *FoStartPackStreamIndex;

+

+  // CSzFolder2 *Folders;  // +1 item for sum values

+  Byte *CodersData;

+  Byte *UnpackSizesData;

+  size_t UnpackSizesDataSize;

+  // UInt64 *CoderUnpackSizes;

+} CSzAr;

+

+

+SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,

+    ILookInStream *stream, UInt64 startPos,

+    Byte *outBuffer, size_t outSize,

+    ISzAlloc *allocMain);

+

+/*

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

+

+  UInt64 *UnpackPositions;

+  // Byte *IsEmptyFiles;

+  Byte *IsDirs;

+  CSzBitUi32s CRCs;

+

+  CSzBitUi32s Attribs;

+  // CSzBitUi32s Parents;

+  CSzBitUi64s MTime;

+  CSzBitUi64s CTime;

+

+  // UInt32 *FolderStartPackStreamIndex;

+  UInt32 *FolderStartFileIndex; // + 1

+  UInt32 *FileIndexToFolderIndexMap;

+

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

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

+} CSzArEx;

+

+#define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i))

+

+#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i])

+

+void SzArEx_Init(CSzArEx *p);

+void SzArEx_Free(CSzArEx *p, 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);

+

+/*

+size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex);

+UInt16 *SzArEx_GetFullNameUtf16_Back(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/lzma/C/7zAlloc.c b/lzma/C/7zAlloc.c
new file mode 100644
index 0000000..698071c
--- /dev/null
+++ b/lzma/C/7zAlloc.c
@@ -0,0 +1,78 @@
+/* 7zAlloc.c -- Allocation functions

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

+

+#include "Precomp.h"

+

+#include "7zAlloc.h"

+

+/* #define _SZ_ALLOC_DEBUG */

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

+

+#ifdef _SZ_ALLOC_DEBUG

+

+#ifdef _WIN32

+#include <windows.h>

+#endif

+

+#include <stdio.h>

+int g_allocCount = 0;

+int g_allocCountTemp = 0;

+

+#endif

+

+void *SzAlloc(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/lzma/C/7zAlloc.h b/lzma/C/7zAlloc.h
new file mode 100644
index 0000000..860f116
--- /dev/null
+++ b/lzma/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/lzma/C/7zArcIn.c b/lzma/C/7zArcIn.c
new file mode 100644
index 0000000..5fd4f6b
--- /dev/null
+++ b/lzma/C/7zArcIn.c
@@ -0,0 +1,1839 @@
+/* 7zArcIn.c -- 7z Input functions

+2014-06-16 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#include <string.h>

+

+#include "7z.h"

+#include "7zBuf.h"

+#include "7zCrc.h"

+#include "CpuArch.h"

+

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

+

+#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,

+  k7zIdWinAttrib,

+  k7zIdComment,

+  k7zIdEncodedHeader,

+  k7zIdStartPos,

+  k7zIdDummy

+  // k7zNtSecure,

+  // k7zParent,

+  // k7zIsReal

+};

+

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

+

+#define NUM_FOLDER_CODERS_MAX 32

+#define NUM_CODER_STREAMS_MAX 32

+

+/*

+static int SzFolder_FindBindPairForInStream(const CSzFolder *p, UInt32 inStreamIndex)

+{

+  UInt32 i;

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

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

+      return i;

+  return -1;

+}

+*/

+

+#define SzBitUi32s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; }

+

+static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc)

+{

+  MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc);

+  MY_ALLOC(UInt32, p->Vals, num, alloc);

+  return SZ_OK;

+}

+

+void SzBitUi32s_Free(CSzBitUi32s *p, ISzAlloc *alloc)

+{

+  IAlloc_Free(alloc, p->Defs); p->Defs = 0;

+  IAlloc_Free(alloc, p->Vals); p->Vals = 0;

+}

+

+#define SzBitUi64s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; }

+

+void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc)

+{

+  IAlloc_Free(alloc, p->Defs); p->Defs = 0;

+  IAlloc_Free(alloc, p->Vals); p->Vals = 0;

+}

+

+static void SzAr_Init(CSzAr *p)

+{

+  p->NumPackStreams = 0;

+  p->NumFolders = 0;

+  p->PackPositions = 0;

+  SzBitUi32s_Init(&p->FolderCRCs);

+  // p->Folders = 0;

+  p->FoCodersOffsets = 0;

+  p->FoSizesOffsets = 0;

+  p->FoStartPackStreamIndex = 0;

+

+  p->CodersData = 0;

+  // p->CoderUnpackSizes = 0;

+  p->UnpackSizesData = 0;

+}

+

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

+{

+  IAlloc_Free(alloc, p->UnpackSizesData);

+  IAlloc_Free(alloc, p->CodersData);

+  // IAlloc_Free(alloc, p->CoderUnpackSizes);

+

+  IAlloc_Free(alloc, p->PackPositions);

+ 

+  // IAlloc_Free(alloc, p->Folders);

+  IAlloc_Free(alloc, p->FoCodersOffsets);

+  IAlloc_Free(alloc, p->FoSizesOffsets);

+  IAlloc_Free(alloc, p->FoStartPackStreamIndex);

+  

+  SzBitUi32s_Free(&p->FolderCRCs, alloc);

+

+  SzAr_Init(p);

+}

+

+

+void SzArEx_Init(CSzArEx *p)

+{

+  SzAr_Init(&p->db);

+  p->NumFiles = 0;

+  p->dataPos = 0;

+  // p->Files = 0;

+  p->UnpackPositions = 0;

+  // p->IsEmptyFiles = 0;

+  p->IsDirs = 0;

+  // p->FolderStartPackStreamIndex = 0;

+  // p->PackStreamStartPositions = 0;

+  p->FolderStartFileIndex = 0;

+  p->FileIndexToFolderIndexMap = 0;

+  p->FileNameOffsets = 0;

+  p->FileNames = 0;

+  SzBitUi32s_Init(&p->CRCs);

+  SzBitUi32s_Init(&p->Attribs);

+  // SzBitUi32s_Init(&p->Parents);

+  SzBitUi64s_Init(&p->MTime);

+  SzBitUi64s_Init(&p->CTime);

+}

+

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

+  IAlloc_Free(alloc, p->FileNames);

+

+  SzBitUi64s_Free(&p->CTime, alloc);

+  SzBitUi64s_Free(&p->MTime, alloc);

+  SzBitUi32s_Free(&p->CRCs, alloc);

+  // SzBitUi32s_Free(&p->Parents, alloc);

+  SzBitUi32s_Free(&p->Attribs, alloc);

+  IAlloc_Free(alloc, p->IsDirs);

+  // IAlloc_Free(alloc, p->IsEmptyFiles);

+  IAlloc_Free(alloc, p->UnpackPositions);

+  // IAlloc_Free(alloc, p->Files);

+

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

+  SzArEx_Init(p);

+}

+

+static int TestSignatureCandidate(Byte *testBytes)

+{

+  size_t i;

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

+    if (testBytes[i] != k7zSignature[i])

+      return 0;

+  return 1;

+}

+

+#define SzData_Clear(p) { (p)->Data = 0; (p)->Size = 0; }

+

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

+{

+  if (sd->Size == 0)

+    return SZ_ERROR_ARCHIVE;

+  sd->Size--;

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

+  return SZ_OK;

+}

+

+#define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++;

+#define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest)

+#define SZ_READ_BYTE_2(dest) if (sd.Size == 0) return SZ_ERROR_ARCHIVE; sd.Size--; dest = *sd.Data++;

+

+#define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); }

+#define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); }

+

+#define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \

+   dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4);

+

+static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value)

+{

+  Byte firstByte, mask;

+  unsigned i;

+  UInt32 v;

+

+  SZ_READ_BYTE(firstByte);

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

+  {

+    *value = firstByte;

+    return SZ_OK;

+  }

+  SZ_READ_BYTE(v);

+  if ((firstByte & 0x40) == 0)

+  {

+    *value = (((UInt32)firstByte & 0x3F) << 8) | v;

+    return SZ_OK;

+  }

+  SZ_READ_BYTE(mask);

+  *value = v | ((UInt32)mask << 8);

+  mask = 0x20;

+  for (i = 2; i < 8; i++)

+  {

+    Byte b;

+    if ((firstByte & mask) == 0)

+    {

+      UInt64 highPart = firstByte & (mask - 1);

+      *value |= (highPart << (8 * i));

+      return SZ_OK;

+    }

+    SZ_READ_BYTE(b);

+    *value |= ((UInt64)b << (8 * i));

+    mask >>= 1;

+  }

+  return SZ_OK;

+}

+

+/*

+static MY_NO_INLINE const Byte *SzReadNumbers(const Byte *data, const Byte *dataLim, UInt64 *values, UInt32 num)

+{

+  for (; num != 0; num--)

+  {

+    Byte firstByte;

+    Byte mask;

+

+    unsigned i;

+    UInt32 v;

+    UInt64 value;

+   

+    if (data == dataLim)

+      return NULL;

+    firstByte = *data++;

+

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

+    {

+      *values++ = firstByte;

+      continue;

+    }

+    if (data == dataLim)

+      return NULL;

+    v = *data++;

+    if ((firstByte & 0x40) == 0)

+    {

+      *values++ = (((UInt32)firstByte & 0x3F) << 8) | v;

+      continue;

+    }

+    if (data == dataLim)

+      return NULL;

+    value = v | ((UInt32)*data++ << 8);

+    mask = 0x20;

+    for (i = 2; i < 8; i++)

+    {

+      if ((firstByte & mask) == 0)

+      {

+        UInt64 highPart = firstByte & (mask - 1);

+        value |= (highPart << (8 * i));

+        break;

+      }

+      if (data == dataLim)

+        return NULL;

+      value |= ((UInt64)*data++ << (8 * i));

+      mask >>= 1;

+    }

+    *values++ = value;

+  }

+  return data;

+}

+*/

+

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

+{

+  Byte firstByte;

+  UInt64 value64;

+  if (sd->Size == 0)

+    return SZ_ERROR_ARCHIVE;

+  firstByte = *sd->Data;

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

+  {

+    *value = firstByte;

+    sd->Data++;

+    sd->Size--;

+    return SZ_OK;

+  }

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

+  if (value64 >= (UInt32)0x80000000 - 1)

+    return SZ_ERROR_UNSUPPORTED;

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

+    return SZ_ERROR_UNSUPPORTED;

+  *value = (UInt32)value64;

+  return SZ_OK;

+}

+

+#define ReadID(sd, value) ReadNumber(sd, value)

+

+static SRes SkipData(CSzData *sd)

+{

+  UInt64 size;

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

+  if (size > sd->Size)

+    return SZ_ERROR_ARCHIVE;

+  SKIP_DATA(sd, size);

+  return SZ_OK;

+}

+

+static SRes WaitId(CSzData *sd, UInt64 id)

+{

+  for (;;)

+  {

+    UInt64 type;

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

+    if (type == id)

+      return SZ_OK;

+    if (type == k7zIdEnd)

+      return SZ_ERROR_ARCHIVE;

+    RINOK(SkipData(sd));

+  }

+}

+

+static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v)

+{

+  UInt32 numBytes = (numItems + 7) >> 3;

+  if (numBytes > sd->Size)

+    return SZ_ERROR_ARCHIVE;

+  *v = sd->Data;

+  SKIP_DATA(sd, numBytes);

+  return SZ_OK;

+}

+

+static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)

+{

+  Byte b = 0;

+  unsigned m = 0;

+  UInt32 sum = 0;

+  for (; numItems != 0; numItems--)

+  {

+    if (m == 0)

+    {

+      b = *bits++;

+      m = 8;

+    }

+    m--;

+    sum += ((b >> m) & 1);

+  }

+  return sum ;

+}

+

+static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAlloc *alloc)

+{

+  Byte allAreDefined;

+  UInt32 i;

+  Byte *v2;

+  UInt32 numBytes = (numItems + 7) >> 3;

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

+  if (allAreDefined == 0)

+  {

+    if (numBytes > sd->Size)

+      return SZ_ERROR_ARCHIVE;

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

+    memcpy(*v, sd->Data, numBytes);

+    SKIP_DATA(sd, numBytes);

+    return SZ_OK;

+  }

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

+  v2 = *v;

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

+    v2[i] = 0xFF;

+  {

+    unsigned numBits = (unsigned)numItems & 7;

+    if (numBits != 0)

+      v2[numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));

+  }

+  return SZ_OK;

+}

+

+static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc)

+{

+  UInt32 i;

+  CSzData sd;

+  UInt32 *vals;

+  const Byte *defs;

+  MY_ALLOC(UInt32, crcs->Vals, numItems, alloc);

+  sd = *sd2;

+  defs = crcs->Defs;

+  vals = crcs->Vals;

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

+    if (SzBitArray_Check(defs, i))

+    {

+      SZ_READ_32(vals[i]);

+    }

+    else

+      vals[i] = 0;

+  *sd2 = sd;

+  return SZ_OK;

+}

+

+static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc)

+{

+  SzBitUi32s_Free(crcs, alloc);

+  RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc));

+  return ReadUi32s(sd, numItems, crcs, alloc);

+}

+

+static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems)

+{

+  Byte allAreDefined;

+  UInt32 numDefined = numItems;

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

+  if (!allAreDefined)

+  {

+    size_t numBytes = (numItems + 7) >> 3;

+    if (numBytes > sd->Size)

+      return SZ_ERROR_ARCHIVE;

+    numDefined = CountDefinedBits(sd->Data, numItems);

+    SKIP_DATA(sd, numBytes);

+  }

+  if (numDefined > (sd->Size >> 2))

+    return SZ_ERROR_ARCHIVE;

+  SKIP_DATA(sd, (size_t)numDefined * 4);

+  return SZ_OK;

+}

+

+static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAlloc *alloc)

+{

+  RINOK(SzReadNumber32(sd, &p->NumPackStreams));

+

+  RINOK(WaitId(sd, k7zIdSize));

+  MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc);

+  {

+    UInt64 sum = 0;

+    UInt32 i;

+    UInt32 numPackStreams = p->NumPackStreams;

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

+    {

+      UInt64 packSize;

+      p->PackPositions[i] = sum;

+      RINOK(ReadNumber(sd, &packSize));

+      sum += packSize;

+      if (sum < packSize)

+        return SZ_ERROR_ARCHIVE;

+    }

+    p->PackPositions[i] = sum;

+  }

+

+  for (;;)

+  {

+    UInt64 type;

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

+    if (type == k7zIdEnd)

+      return SZ_OK;

+    if (type == k7zIdCRC)

+    {

+      /* CRC of packed streams is unused now */

+      RINOK(SkipBitUi32s(sd, p->NumPackStreams));

+      continue;

+    }

+    RINOK(SkipData(sd));

+  }

+}

+

+/*

+static SRes SzReadSwitch(CSzData *sd)

+{

+  Byte external;

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

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

+}

+*/

+

+#define SZ_NUM_IN_STREAMS_IN_FOLDER_MAX 16

+

+SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes)

+{

+  UInt32 numCoders, numBindPairs, numPackStreams, i;

+  UInt32 numInStreams = 0, numOutStreams = 0;

+  const Byte *dataStart = sd->Data;

+  Byte inStreamUsed[SZ_NUM_IN_STREAMS_IN_FOLDER_MAX];

+  

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

+  if (numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX)

+    return SZ_ERROR_UNSUPPORTED;

+  f->NumCoders = numCoders;

+  

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

+  {

+    Byte mainByte;

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

+    unsigned idSize, j;

+    UInt64 id;

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

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

+      return SZ_ERROR_UNSUPPORTED;

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

+    if (idSize > sizeof(id))

+      return SZ_ERROR_UNSUPPORTED;

+    if (idSize > sd->Size)

+      return SZ_ERROR_ARCHIVE;

+    id = 0;

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

+    {

+      id = ((id << 8) | *sd->Data);

+      sd->Data++;

+      sd->Size--;

+    }

+    if (id > (UInt32)0xFFFFFFFF)

+      return SZ_ERROR_UNSUPPORTED;

+    coder->MethodID = (UInt32)id;

+    

+    coder->NumInStreams = 1;

+    coder->NumOutStreams = 1;

+    coder->PropsOffset = 0;

+    coder->PropsSize = 0;

+    

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

+    {

+      UInt32 numStreams;

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

+      if (numStreams > NUM_CODER_STREAMS_MAX)

+        return SZ_ERROR_UNSUPPORTED;

+      coder->NumInStreams = (Byte)numStreams;

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

+      if (numStreams > NUM_CODER_STREAMS_MAX)

+        return SZ_ERROR_UNSUPPORTED;

+      coder->NumOutStreams = (Byte)numStreams;

+    }

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

+    {

+      UInt32 propsSize = 0;

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

+      if (propsSize >= 0x40)

+        return SZ_ERROR_UNSUPPORTED;

+      if (propsSize > sd->Size)

+        return SZ_ERROR_ARCHIVE;

+      coder->PropsOffset = sd->Data - dataStart;

+      coder->PropsSize = (Byte)propsSize;

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

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

+    }

+    numInStreams += coder->NumInStreams;

+    numOutStreams += coder->NumOutStreams;

+  }

+

+  if (numOutStreams == 0)

+    return SZ_ERROR_UNSUPPORTED;

+

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

+  if (numInStreams < numBindPairs)

+    return SZ_ERROR_ARCHIVE;

+  if (numInStreams > SZ_NUM_IN_STREAMS_IN_FOLDER_MAX)

+    return SZ_ERROR_UNSUPPORTED;

+  f->MainOutStream = 0;

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

+  if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)

+    return SZ_ERROR_UNSUPPORTED;

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

+    inStreamUsed[i] = False;

+  if (numBindPairs != 0)

+  {

+    Byte outStreamUsed[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX];

+

+    if (numBindPairs > SZ_NUM_BINDS_IN_FOLDER_MAX)

+      return SZ_ERROR_UNSUPPORTED;

+

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

+      outStreamUsed[i] = False;

+

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

+    {

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

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

+      if (bp->InIndex >= numInStreams)

+        return SZ_ERROR_ARCHIVE;

+      inStreamUsed[bp->InIndex] = True;

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

+      if (bp->OutIndex >= numInStreams)

+        return SZ_ERROR_ARCHIVE;

+      outStreamUsed[bp->OutIndex] = True;

+    }

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

+      if (!outStreamUsed[i])

+      {

+        f->MainOutStream = i;

+        break;

+      }

+    if (i == numOutStreams)

+      return SZ_ERROR_ARCHIVE;

+  }

+

+  if (numPackStreams == 1)

+  {

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

+      if (!inStreamUsed[i])

+        break;

+    if (i == numInStreams)

+      return SZ_ERROR_ARCHIVE;

+    f->PackStreams[0] = i;

+  }

+  else

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

+    {

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

+    }

+

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

+  {

+    RINOK(ReadNumber(sdSizes, f->CodersUnpackSizes + i));

+  }

+  

+  return SZ_OK;

+}

+

+static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num)

+{

+  CSzData sd;

+  sd = *sd2;

+  for (; num != 0; num--)

+  {

+    Byte firstByte, mask;

+    unsigned i;

+    SZ_READ_BYTE_2(firstByte);

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

+      continue;

+    if ((firstByte & 0x40) == 0)

+    {

+      if (sd.Size == 0)

+        return SZ_ERROR_ARCHIVE;

+      sd.Size--;

+      sd.Data++;

+      continue;

+    }

+    mask = 0x20;

+    for (i = 2; i < 8 && (firstByte & mask) != 0; i++)

+      mask >>= 1;

+    if (i > sd.Size)

+      return SZ_ERROR_ARCHIVE;

+    SKIP_DATA2(sd, i);

+  }

+  *sd2 = sd;

+  return SZ_OK;

+}

+

+#define k_InStreamUsed_MAX 64

+#define k_OutStreamUsed_MAX 64

+

+static SRes ReadUnpackInfo(CSzAr *p,

+    CSzData *sd2,

+    UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,

+    ISzAlloc *alloc)

+{

+  CSzData sd;

+  Byte inStreamUsed[k_InStreamUsed_MAX];

+  Byte outStreamUsed[k_OutStreamUsed_MAX];

+  UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex;

+  const Byte *startBufPtr;

+  Byte external;

+  

+  RINOK(WaitId(sd2, k7zIdFolder));

+  RINOK(SzReadNumber32(sd2, &numFolders));

+  if (p->NumFolders > numFoldersMax)

+    return SZ_ERROR_UNSUPPORTED;

+  p->NumFolders = numFolders;

+

+  SZ_READ_BYTE_SD(sd2, external);

+  if (external == 0)

+    sd = *sd2;

+  else

+  {

+    UInt32 index;

+    SzReadNumber32(sd2, &index);

+    if (index >= numTempBufs)

+      return SZ_ERROR_ARCHIVE;

+    sd.Data = tempBufs[index].data;

+    sd.Size = tempBufs[index].size;

+  }

+  

+  MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc);

+  MY_ALLOC(size_t, p->FoSizesOffsets, (size_t)numFolders + 1, alloc);

+  MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc);

+  

+  startBufPtr = sd.Data;

+  

+  packStreamIndex = 0;

+  numCodersOutStreams = 0;

+

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

+  {

+    UInt32 numCoders, ci, numInStreams = 0, numOutStreams = 0;

+    

+    p->FoCodersOffsets[fo] = sd.Data - startBufPtr;

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

+    if (numCoders > NUM_FOLDER_CODERS_MAX)

+      return SZ_ERROR_UNSUPPORTED;

+    

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

+    {

+      Byte mainByte;

+      unsigned idSize;

+      UInt32 coderInStreams, coderOutStreams;

+      

+      SZ_READ_BYTE_2(mainByte);

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

+        return SZ_ERROR_UNSUPPORTED;

+      idSize = (mainByte & 0xF);

+      if (idSize > 8)

+        return SZ_ERROR_UNSUPPORTED;

+      if (idSize > sd.Size)

+        return SZ_ERROR_ARCHIVE;

+      SKIP_DATA2(sd, idSize);

+      

+      coderInStreams = 1;

+      coderOutStreams = 1;

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

+      {

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

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

+        if (coderInStreams > NUM_CODER_STREAMS_MAX ||

+            coderOutStreams > NUM_CODER_STREAMS_MAX)

+          return SZ_ERROR_UNSUPPORTED;

+      }

+      numInStreams += coderInStreams;

+      numOutStreams += coderOutStreams;

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

+      {

+        UInt32 propsSize;

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

+        if (propsSize > sd.Size)

+          return SZ_ERROR_ARCHIVE;

+        SKIP_DATA2(sd, propsSize);

+      }

+    }

+    

+    {

+      UInt32 indexOfMainStream = 0;

+      UInt32 numPackStreams = 1;

+      if (numOutStreams != 1 || numInStreams != 1)

+      {

+        UInt32 i;

+        UInt32 numBindPairs = numOutStreams - 1;

+        if (numOutStreams == 0 || numInStreams < numBindPairs)

+          return SZ_ERROR_ARCHIVE;

+        

+        if (numInStreams > k_InStreamUsed_MAX ||

+            numOutStreams > k_OutStreamUsed_MAX)

+          return SZ_ERROR_UNSUPPORTED;

+        

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

+          inStreamUsed[i] = False;

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

+          outStreamUsed[i] = False;

+        

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

+        {

+          UInt32 index;

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

+          if (index >= numInStreams || inStreamUsed[index])

+            return SZ_ERROR_ARCHIVE;

+          inStreamUsed[index] = True;

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

+          if (index >= numInStreams || outStreamUsed[index])

+            return SZ_ERROR_ARCHIVE;

+          outStreamUsed[index] = True;

+        }

+        

+        numPackStreams = numInStreams - numBindPairs;

+        

+        if (numPackStreams != 1)

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

+          {

+            UInt32 temp;

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

+            if (temp >= numInStreams)

+              return SZ_ERROR_ARCHIVE;

+          }

+          

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

+          if (!outStreamUsed[i])

+          {

+            indexOfMainStream = i;

+            break;

+          }

+ 

+        if (i == numOutStreams)

+          return SZ_ERROR_ARCHIVE;

+      }

+      p->FoStartPackStreamIndex[fo] = packStreamIndex;

+      p->FoSizesOffsets[fo] = (numOutStreams << 8) | indexOfMainStream;

+      numCodersOutStreams += numOutStreams;

+      if (numCodersOutStreams < numOutStreams)

+        return SZ_ERROR_UNSUPPORTED;

+      packStreamIndex += numPackStreams;

+      if (packStreamIndex < numPackStreams)

+        return SZ_ERROR_UNSUPPORTED;

+      if (packStreamIndex > p->NumPackStreams)

+        return SZ_ERROR_ARCHIVE;

+    }

+  }

+  

+  {

+    size_t dataSize = sd.Data - startBufPtr;

+    p->FoStartPackStreamIndex[fo] = packStreamIndex;

+    p->FoCodersOffsets[fo] = dataSize;

+    MY_ALLOC(Byte, p->CodersData, dataSize, alloc);

+    memcpy(p->CodersData, startBufPtr, dataSize);

+  }

+  

+  if (external != 0)

+  {

+    if (sd.Size != 0)

+      return SZ_ERROR_ARCHIVE;

+    sd = *sd2;

+  }

+  

+  RINOK(WaitId(&sd, k7zIdCodersUnpackSize));

+  

+  // MY_ALLOC(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc);

+  {

+    size_t dataSize = sd.Size;

+    /*

+    UInt32 i;

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

+    {

+    RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i));

+    }

+    */

+    RINOK(SkipNumbers(&sd, numCodersOutStreams));

+    dataSize -= sd.Size;

+    MY_ALLOC(Byte, p->UnpackSizesData, dataSize, alloc);

+    memcpy(p->UnpackSizesData, sd.Data - dataSize, dataSize);

+    p->UnpackSizesDataSize = dataSize;

+    /*

+    const Byte *data = SzReadNumbers(sd.Data, sd.Data + sd.Size, p->CoderUnpackSizes, numCodersOutStreams);

+    if (data == NULL)

+    return SZ_ERROR_ARCHIVE;

+    sd.Size = sd.Data + sd.Size - data;

+    sd.Data = data;

+    */

+  }

+

+  for (;;)

+  {

+    UInt64 type;

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

+    if (type == k7zIdEnd)

+    {

+      *sd2 = sd;

+      return SZ_OK;

+    }

+    if (type == k7zIdCRC)

+    {

+      RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc));

+      continue;

+    }

+    RINOK(SkipData(&sd));

+  }

+}

+

+typedef struct

+{

+  UInt32 NumTotalSubStreams;

+  UInt32 NumSubDigests;

+  CSzData sdNumSubStreams;

+  CSzData sdSizes;

+  CSzData sdCRCs;

+} CSubStreamInfo;

+

+#define SzUi32IndexMax (((UInt32)1 << 31) - 2)

+

+static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)

+{

+  UInt64 type = 0;

+  UInt32 i;

+  UInt32 numSubDigests = 0;

+  UInt32 numFolders = p->NumFolders;

+  UInt32 numUnpackStreams = numFolders;

+  UInt32 numUnpackSizesInData = 0;

+

+  for (;;)

+  {

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

+    if (type == k7zIdNumUnpackStream)

+    {

+      ssi->sdNumSubStreams.Data = sd->Data;

+      numUnpackStreams = 0;

+      numSubDigests = 0;

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

+      {

+        UInt32 numStreams;

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

+        if (numUnpackStreams > numUnpackStreams + numStreams)

+          return SZ_ERROR_UNSUPPORTED;

+        numUnpackStreams += numStreams;

+        if (numStreams != 0)

+          numUnpackSizesInData += (numStreams - 1);

+        if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i))

+          numSubDigests += numStreams;

+      }

+      ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data;

+      continue;

+    }

+    if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd)

+      break;

+    RINOK(SkipData(sd));

+  }

+

+  if (!ssi->sdNumSubStreams.Data)

+  {

+    numSubDigests = numFolders;

+    if (p->FolderCRCs.Defs)

+      numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders);

+  }

+  

+  ssi->NumTotalSubStreams = numUnpackStreams;

+  ssi->NumSubDigests = numSubDigests;

+

+  if (type == k7zIdSize)

+  {

+    ssi->sdSizes.Data = sd->Data;

+    RINOK(SkipNumbers(sd, numUnpackSizesInData));

+    ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data;

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

+  }

+

+  for (;;)

+  {

+    if (type == k7zIdEnd)

+      return SZ_OK;

+    if (type == k7zIdCRC)

+    {

+      ssi->sdCRCs.Data = sd->Data;

+      RINOK(SkipBitUi32s(sd, numSubDigests));

+      ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data;

+    }

+    else

+    {

+      RINOK(SkipData(sd));

+    }

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

+  }

+}

+

+static SRes SzReadStreamsInfo(CSzAr *p,

+    CSzData *sd,

+    UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,

+    UInt64 *dataOffset,

+    CSubStreamInfo *ssi,

+    ISzAlloc *alloc)

+{

+  UInt64 type;

+

+  SzData_Clear(&ssi->sdSizes);

+  SzData_Clear(&ssi->sdCRCs);

+  SzData_Clear(&ssi->sdNumSubStreams);

+

+  *dataOffset = 0;

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

+  if (type == k7zIdPackInfo)

+  {

+    RINOK(ReadNumber(sd, dataOffset));

+    RINOK(ReadPackInfo(p, sd, alloc));

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

+  }

+  if (type == k7zIdUnpackInfo)

+  {

+    RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc));

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

+  }

+  if (type == k7zIdSubStreamsInfo)

+  {

+    RINOK(ReadSubStreamsInfo(p, sd, ssi));

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

+  }

+  else

+  {

+    ssi->NumTotalSubStreams = p->NumFolders;

+    // ssi->NumSubDigests = 0;

+  }

+

+  return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED);

+}

+

+static SRes SzReadAndDecodePackedStreams(

+    ILookInStream *inStream,

+    CSzData *sd,

+    CBuf *tempBufs,

+    UInt32 numFoldersMax,

+    UInt64 baseOffset,

+    CSzAr *p,

+    ISzAlloc *allocTemp)

+{

+  UInt64 dataStartPos;

+  UInt32 fo;

+  CSubStreamInfo ssi;

+  CSzData sdCodersUnpSizes;

+

+  RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp));

+  

+  dataStartPos += baseOffset;

+  if (p->NumFolders == 0)

+    return SZ_ERROR_ARCHIVE;

+ 

+  sdCodersUnpSizes.Data = p->UnpackSizesData;

+  sdCodersUnpSizes.Size = p->UnpackSizesDataSize;

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

+    Buf_Init(tempBufs + fo);

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

+  {

+    CBuf *tempBuf = tempBufs + fo;

+    // folder = p->Folders;

+    // unpackSize = SzAr_GetFolderUnpackSize(p, 0);

+    UInt32 mix = (UInt32)p->FoSizesOffsets[fo];

+    UInt32 mainIndex = mix & 0xFF;

+    UInt32 numOutStreams = mix >> 8;

+    UInt32 si;

+    UInt64 unpackSize = 0;

+    p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData;

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

+    {

+      UInt64 curSize;

+      RINOK(ReadNumber(&sdCodersUnpSizes, &curSize));

+      if (si == mainIndex)

+      {

+        unpackSize = curSize;

+        break;

+      }

+    }

+    if (si == numOutStreams)

+      return SZ_ERROR_FAIL;

+    if ((size_t)unpackSize != unpackSize)

+      return SZ_ERROR_MEM;

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

+      return SZ_ERROR_MEM;

+  }

+  p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData;

+    

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

+  {

+    const CBuf *tempBuf = tempBufs + fo;

+    RINOK(LookInStream_SeekTo(inStream, dataStartPos));

+    RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp));

+    if (SzBitWithVals_Check(&p->FolderCRCs, fo))

+      if (CrcCalc(tempBuf->data, tempBuf->size) != p->FolderCRCs.Vals[fo])

+        return SZ_ERROR_CRC;

+  }

+  return SZ_OK;

+}

+

+static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets)

+{

+  size_t pos = 0;

+  *offsets++ = 0;

+  if (numFiles == 0)

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

+  if (data[size - 2] != 0 || data[size - 1] != 0)

+    return SZ_ERROR_ARCHIVE;

+  do

+  {

+    const Byte *p;

+    if (pos == size)

+      return SZ_ERROR_ARCHIVE;

+    for (p = data + pos;

+      #ifdef _WIN32

+      *(const UInt16 *)p != 0

+      #else

+      p[0] != 0 || p[1] != 0

+      #endif

+      ; p += 2);

+    pos = p - data + 2;

+    *offsets++ = (pos >> 1);

+  }

+  while (--numFiles);

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

+}

+

+static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,

+    CSzData *sd2,

+    const CBuf *tempBufs, UInt32 numTempBufs,

+    ISzAlloc *alloc)

+{

+  CSzData sd;

+  UInt32 i;

+  CNtfsFileTime *vals;

+  Byte *defs;

+  Byte external;

+  RINOK(ReadBitVector(sd2, num, &p->Defs, alloc));

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

+  if (external == 0)

+    sd = *sd2;

+  else

+  {

+    UInt32 index;

+    SzReadNumber32(sd2, &index);

+    if (index >= numTempBufs)

+      return SZ_ERROR_ARCHIVE;

+    sd.Data = tempBufs[index].data;

+    sd.Size = tempBufs[index].size;

+  }

+  MY_ALLOC(CNtfsFileTime, p->Vals, num, alloc);

+  vals = p->Vals;

+  defs = p->Defs;

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

+    if (SzBitArray_Check(defs, i))

+    {

+      if (sd.Size < 8)

+        return SZ_ERROR_ARCHIVE;

+      vals[i].Low = GetUi32(sd.Data);

+      vals[i].High = GetUi32(sd.Data + 4);

+      SKIP_DATA2(sd, 8);

+    }

+    else

+      vals[i].High = vals[i].Low = 0;

+  if (external == 0)

+    *sd2 = sd;

+  return SZ_OK;

+}

+

+#define NUM_ADDITIONAL_STREAMS_MAX 8

+

+static SRes SzReadHeader2(

+    CSzArEx *p,   /* allocMain */

+    CSzData *sd,

+    // Byte **emptyStreamVector, /* allocTemp */

+    // Byte **emptyFileVector,   /* allocTemp */

+    // Byte **lwtVector,         /* allocTemp */

+    ILookInStream *inStream,

+    CBuf *tempBufs,

+    UInt32 *numTempBufs,

+    ISzAlloc *allocMain,

+    ISzAlloc *allocTemp

+    )

+{

+  UInt64 type;

+  UInt32 numFiles = 0;

+  UInt32 numEmptyStreams = 0;

+  UInt32 i;

+  CSubStreamInfo ssi;

+  const Byte *emptyStreams = 0;

+  const Byte *emptyFiles = 0;

+

+  SzData_Clear(&ssi.sdSizes);

+  SzData_Clear(&ssi.sdCRCs);

+  SzData_Clear(&ssi.sdNumSubStreams);

+

+  ssi.NumSubDigests = 0;

+  ssi.NumTotalSubStreams = 0;

+

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

+

+  if (type == k7zIdArchiveProperties)

+  {

+    for (;;)

+    {

+      UInt64 type;

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

+      if (type == k7zIdEnd)

+        break;

+      RINOK(SkipData(sd));

+    }

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

+  }

+

+  // if (type == k7zIdAdditionalStreamsInfo)     return SZ_ERROR_UNSUPPORTED;

+

+  if (type == k7zIdAdditionalStreamsInfo)

+  {

+    CSzAr tempAr;

+    SRes res;

+    UInt32 numTempFolders;

+    

+    SzAr_Init(&tempAr);

+    res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX,

+        p->startPosAfterHeader, &tempAr, allocTemp);

+    numTempFolders = tempAr.NumFolders;

+    SzAr_Free(&tempAr, allocTemp);

+    if (res != SZ_OK)

+      return res;

+    *numTempBufs = numTempFolders;

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

+  }

+

+  if (type == k7zIdMainStreamsInfo)

+  {

+    RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs,

+        &p->dataPos, &ssi, allocMain));

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

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

+  }

+

+  if (type == k7zIdEnd)

+  {

+    // *sd2 = sd;

+    return SZ_OK;

+  }

+  if (type != k7zIdFilesInfo)

+    return SZ_ERROR_ARCHIVE;

+  

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

+  p->NumFiles = numFiles;

+

+  for (;;)

+  {

+    UInt64 type;

+    UInt64 size;

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

+    if (type == k7zIdEnd)

+      break;

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

+    if (size > sd->Size)

+      return SZ_ERROR_ARCHIVE;

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

+    {

+      SKIP_DATA(sd, size);

+    }

+    else switch((int)type)

+    {

+      case k7zIdName:

+      {

+        size_t namesSize;

+        const Byte *namesData;

+        Byte external;

+

+        SZ_READ_BYTE(external);

+        if (external == 0)

+        {

+          namesSize = (size_t)size - 1;

+          namesData = sd->Data;

+        }

+        else

+        {

+          UInt32 index;

+          SzReadNumber32(sd, &index);

+          if (index >= *numTempBufs)

+            return SZ_ERROR_ARCHIVE;

+          namesData = (tempBufs)[index].data;

+          namesSize = (tempBufs)[index].size;

+        }

+

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

+          return SZ_ERROR_ARCHIVE;

+        MY_ALLOC(Byte, p->FileNames, namesSize, allocMain);

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

+        memcpy(p->FileNames, namesData, namesSize);

+        RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets))

+        if (external == 0)

+        {

+          SKIP_DATA(sd, namesSize);

+        }

+        break;

+      }

+      case k7zIdEmptyStream:

+      {

+        RINOK(RememberBitVector(sd, numFiles, &emptyStreams));

+        numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);

+        break;

+      }

+      case k7zIdEmptyFile:

+      {

+        RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles));

+        break;

+      }

+      case k7zIdWinAttrib:

+      {

+        Byte external;

+        CSzData sdSwitch;

+        CSzData *sdPtr;

+        SzBitUi32s_Free(&p->Attribs, allocMain);

+        RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain));

+

+        SZ_READ_BYTE(external);

+        if (external == 0)

+          sdPtr = sd;

+        else

+        {

+          UInt32 index;

+          SzReadNumber32(sd, &index);

+          if (index >= *numTempBufs)

+            return SZ_ERROR_ARCHIVE;

+          sdSwitch.Data = (tempBufs)[index].data;

+          sdSwitch.Size = (tempBufs)[index].size;

+          sdPtr = &sdSwitch;

+        }

+        RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain));

+        break;

+      }

+      /*

+      case k7zParent:

+      {

+        SzBitUi32s_Free(&p->Parents, allocMain);

+        RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain));

+        RINOK(SzReadSwitch(sd));

+        RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain));

+        break;

+      }

+      */

+      case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;

+      case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;

+      default:

+      {

+        SKIP_DATA(sd, size);

+      }

+    }

+  }

+

+  if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams)

+    return SZ_ERROR_ARCHIVE;

+

+  for (;;)

+  {

+    UInt64 type;

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

+    if (type == k7zIdEnd)

+      break;

+    RINOK(SkipData(sd));

+  }

+

+  {

+    UInt32 emptyFileIndex = 0;

+

+    UInt32 folderIndex = 0;

+    UInt32 indexInFolder = 0;

+    UInt64 unpackPos = 0;

+    const Byte *digestsDefs = 0;

+    const Byte *digestsVals = 0;

+    UInt32 digestsValsIndex = 0;

+    UInt32 digestIndex;

+    Byte allDigestsDefined = 0;

+    UInt32 curNumSubStreams = (UInt32)(Int32)-1;

+    Byte isDirMask = 0;

+    Byte crcMask = 0;

+    Byte mask = 0x80;

+    // size_t unpSizesOffset = 0;

+    CSzData sdCodersUnpSizes;

+    sdCodersUnpSizes.Data = p->db.UnpackSizesData;

+    sdCodersUnpSizes.Size = p->db.UnpackSizesDataSize;

+    

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

+    MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->NumFiles, allocMain);

+    MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain);

+    MY_ALLOC(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain);

+

+    RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain));

+

+    if (ssi.sdCRCs.Size != 0)

+    {

+      RINOK(SzReadByte(&ssi.sdCRCs, &allDigestsDefined));

+      if (allDigestsDefined)

+        digestsVals = ssi.sdCRCs.Data;

+      else

+      {

+        size_t numBytes = (ssi.NumSubDigests + 7) >> 3;

+        digestsDefs = ssi.sdCRCs.Data;

+        digestsVals = digestsDefs + numBytes;

+      }

+    }

+

+    digestIndex = 0;

+    for (i = 0; i < numFiles; i++, mask >>= 1)

+    {

+      if (mask == 0)

+      {

+        UInt32 byteIndex = (i - 1) >> 3;

+        p->IsDirs[byteIndex] = isDirMask;

+        p->CRCs.Defs[byteIndex] = crcMask;

+        isDirMask = 0;

+        crcMask = 0;

+        mask = 0x80;

+      }

+

+      p->UnpackPositions[i] = unpackPos;

+      p->CRCs.Vals[i] = 0;

+      // p->CRCs.Defs[i] = 0;

+      if (emptyStreams && SzBitArray_Check(emptyStreams , i))

+      {

+        if (!emptyFiles || !SzBitArray_Check(emptyFiles, emptyFileIndex))

+          isDirMask |= mask;

+        emptyFileIndex++;

+        if (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 (curNumSubStreams == (UInt32)(Int32)-1);

+          {

+            curNumSubStreams = 1;

+            if (ssi.sdNumSubStreams.Data != 0)

+            {

+              RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &curNumSubStreams));

+            }

+          }

+          if (curNumSubStreams != 0)

+            break;

+          curNumSubStreams = (UInt32)(Int32)-1;

+          folderIndex++; // check it

+        }

+      }

+      p->FileIndexToFolderIndexMap[i] = folderIndex;

+      if (emptyStreams && SzBitArray_Check(emptyStreams , i))

+        continue;

+      

+      indexInFolder++;

+      if (indexInFolder >= curNumSubStreams)

+      {

+        UInt64 folderUnpackSize = 0;

+        UInt64 startFolderUnpackPos;

+        {

+          UInt32 mix = (UInt32)p->db.FoSizesOffsets[folderIndex];

+          UInt32 mainIndex = mix & 0xFF;

+          UInt32 numOutStreams = mix >> 8;

+          UInt32 si;

+          p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData;

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

+          {

+            UInt64 curSize;

+            RINOK(ReadNumber(&sdCodersUnpSizes, &curSize));

+            if (si == mainIndex)

+            {

+              folderUnpackSize = curSize;

+              break;

+            }

+          }

+          if (si == numOutStreams)

+            return SZ_ERROR_FAIL;

+        }

+

+        // UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);

+        startFolderUnpackPos = p->UnpackPositions[p->FolderStartFileIndex[folderIndex]];

+        if (folderUnpackSize < unpackPos - startFolderUnpackPos)

+          return SZ_ERROR_ARCHIVE;

+        unpackPos = startFolderUnpackPos + folderUnpackSize;

+

+        if (curNumSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i))

+        {

+          p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex];

+          crcMask |= mask;

+        }

+        else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))

+        {

+          p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);

+          digestsValsIndex++;

+          crcMask |= mask;

+        }

+        folderIndex++;

+        indexInFolder = 0;

+      }

+      else

+      {

+        UInt64 v;

+        RINOK(ReadNumber(&ssi.sdSizes, &v));

+        unpackPos += v;

+        if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))

+        {

+          p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);

+          digestsValsIndex++;

+          crcMask |= mask;

+        }

+      }

+    }

+    if (mask != 0x80)

+    {

+      UInt32 byteIndex = (i - 1) >> 3;

+      p->IsDirs[byteIndex] = isDirMask;

+      p->CRCs.Defs[byteIndex] = crcMask;

+    }

+    p->UnpackPositions[i] = unpackPos;

+    p->FolderStartFileIndex[folderIndex] = i;

+    p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData;

+  }

+  return SZ_OK;

+}

+

+static SRes SzReadHeader(

+    CSzArEx *p,

+    CSzData *sd,

+    ILookInStream *inStream,

+    ISzAlloc *allocMain

+    ,ISzAlloc *allocTemp

+    )

+{

+  // Byte *emptyStreamVector = 0;

+  // Byte *emptyFileVector = 0;

+  // Byte *lwtVector = 0;

+  UInt32 i;

+  UInt32 numTempBufs = 0;

+  SRes res;

+  CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX];

+

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

+    Buf_Init(tempBufs + i);

+  // SzBitUi32s_Init(&digests);

+  

+  res = SzReadHeader2(p, sd,

+      // &emptyStreamVector,

+      // &emptyFileVector,

+      // &lwtVector,

+      inStream,

+      tempBufs, &numTempBufs,

+      allocMain, allocTemp

+      );

+  

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

+    Buf_Free(tempBufs + i, allocTemp);

+

+  // IAlloc_Free(allocTemp, emptyStreamVector);

+  // IAlloc_Free(allocTemp, emptyFileVector);

+  // IAlloc_Free(allocTemp, lwtVector);

+

+  RINOK(res);

+  {

+    if (sd->Size != 0)

+      return SZ_ERROR_FAIL;

+  }

+

+  return res;

+}

+

+/*

+static UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)

+{

+  const CSzFolder2 *f = p->Folders + folderIndex;

+

+  // return p->CoderUnpackSizes[f->StartCoderUnpackSizesIndex + f->IndexOfMainOutStream];

+

+  UInt32 si;

+  CSzData sdCodersUnpSizes;

+  sdCodersUnpSizes.Data = p->UnpackSizesData + f->UnpackSizeDataOffset;

+  sdCodersUnpSizes.Size = p->UnpackSizesDataSize - f->UnpackSizeDataOffset;

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

+  {

+    UInt64 curSize;

+    ReadNumber(&sdCodersUnpSizes, &curSize);

+    if (si == mainIndex)

+      return curSize;

+  }

+  return 0;

+}

+*/

+

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

+  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(&buf, nextHeaderSizeT, allocTemp))

+    return SZ_ERROR_MEM;

+

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

+  if (res == SZ_OK)

+  {

+    res = SZ_ERROR_ARCHIVE;

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

+    {

+      CSzData sd;

+      UInt64 type;

+      sd.Data = buf.data;

+      sd.Size = buf.size;

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

+      if (res == SZ_OK && type == k7zIdEncodedHeader)

+      {

+        CSzAr tempAr;

+        CBuf tempBuf;

+        Buf_Init(&tempBuf);

+        

+        SzAr_Init(&tempAr);

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

+        SzAr_Free(&tempAr, allocTemp);

+       

+        if (res != SZ_OK)

+        {

+          Buf_Free(&tempBuf, allocTemp);

+        }

+        else

+        {

+          Buf_Free(&buf, allocTemp);

+          buf.data = tempBuf.data;

+          buf.size = tempBuf.size;

+          sd.Data = buf.data;

+          sd.Size = buf.size;

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

+        }

+      }

+      if (res == SZ_OK)

+      {

+        if (type == k7zIdHeader)

+        {

+          CSzData sd2;

+          int ttt;

+          for (ttt = 0; ttt < 1; ttt++)

+          // for (ttt = 0; ttt < 40000; ttt++)

+          {

+            SzArEx_Free(p, allocMain);

+            sd2 = sd;

+            res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp

+              );

+            if (res != SZ_OK)

+              break;

+          }

+

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

+        }

+        else

+          res = SZ_ERROR_UNSUPPORTED;

+      }

+    }

+  }

+  Buf_Free(&buf, allocTemp);

+  return res;

+}

+

+// #include <stdio.h>

+

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

+  // printf ("\nrrr=%d\n", rrr);

+  return res;

+}

+

+SRes SzArEx_Extract(

+    const CSzArEx *p,

+    ILookInStream *inStream,

+    UInt32 fileIndex,

+    UInt32 *blockIndex,

+    Byte **tempBuf,

+    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, *tempBuf);

+    *blockIndex = folderIndex;

+    *tempBuf = 0;

+    *outBufferSize = 0;

+    return SZ_OK;

+  }

+

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

+  {

+    // UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);

+    UInt64 unpackSizeSpec =

+        p->UnpackPositions[p->FolderStartFileIndex[folderIndex + 1]] -

+        p->UnpackPositions[p->FolderStartFileIndex[folderIndex]];

+    size_t unpackSize = (size_t)unpackSizeSpec;

+

+    if (unpackSize != unpackSizeSpec)

+      return SZ_ERROR_MEM;

+    *blockIndex = folderIndex;

+    IAlloc_Free(allocMain, *tempBuf);

+    *tempBuf = 0;

+    

+    // RINOK(LookInStream_SeekTo(inStream, startOffset));

+    

+    if (res == SZ_OK)

+    {

+      *outBufferSize = unpackSize;

+      if (unpackSize != 0)

+      {

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

+        if (*tempBuf == 0)

+          res = SZ_ERROR_MEM;

+      }

+      if (res == SZ_OK)

+      {

+        res = SzAr_DecodeFolder(&p->db, folderIndex,

+          inStream,

+          p->dataPos,

+          *tempBuf, unpackSize, allocTemp);

+        if (res == SZ_OK)

+        {

+          if (SzBitWithVals_Check(&p->db.FolderCRCs, folderIndex))

+          {

+            if (CrcCalc(*tempBuf, unpackSize) != p->db.FolderCRCs.Vals[folderIndex])

+              res = SZ_ERROR_CRC;

+          }

+        }

+      }

+    }

+  }

+  if (res == SZ_OK)

+  {

+    UInt64 unpackPos = p->UnpackPositions[fileIndex];

+    *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]);

+    *outSizeProcessed = (size_t)(p->UnpackPositions[fileIndex + 1] - unpackPos);

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

+      return SZ_ERROR_FAIL;

+    if (SzBitWithVals_Check(&p->CRCs, fileIndex) && CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex])

+      res = SZ_ERROR_CRC;

+  }

+  return res;

+}

+

+

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

+{

+  size_t offs = p->FileNameOffsets[fileIndex];

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

+  if (dest != 0)

+  {

+    size_t i;

+    const Byte *src = p->FileNames + offs * 2;

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

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

+  }

+  return len;

+}

+

+/*

+size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)

+{

+  size_t len;

+  if (!p->FileNameOffsets)

+    return 1;

+  len = 0;

+  for (;;)

+  {

+    UInt32 parent = (UInt32)(Int32)-1;

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

+    if SzBitWithVals_Check(&p->Parents, fileIndex)

+      parent = p->Parents.Vals[fileIndex];

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

+      return len;

+    fileIndex = parent;

+  }

+}

+

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

+{

+  Bool needSlash;

+  if (!p->FileNameOffsets)

+  {

+    *(--dest) = 0;

+    return dest;

+  }

+  needSlash = False;

+  for (;;)

+  {

+    UInt32 parent = (UInt32)(Int32)-1;

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

+    SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen);

+    if (needSlash)

+      *(dest - 1) = '/';

+    needSlash = True;

+    dest -= curLen;

+

+    if SzBitWithVals_Check(&p->Parents, fileIndex)

+      parent = p->Parents.Vals[fileIndex];

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

+      return dest;

+    fileIndex = parent;

+  }

+}

+*/

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

+2013-01-21 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#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/lzma/C/7zBuf.h b/lzma/C/7zBuf.h
new file mode 100644
index 0000000..e5f9218
--- /dev/null
+++ b/lzma/C/7zBuf.h
@@ -0,0 +1,35 @@
+/* 7zBuf.h -- Byte Buffer

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_BUF_H

+#define __7Z_BUF_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+typedef struct

+{

+  Byte *data;

+  size_t size;

+} CBuf;

+

+void Buf_Init(CBuf *p);

+int Buf_Create(CBuf *p, size_t size, 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);

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/7zBuf2.c b/lzma/C/7zBuf2.c
new file mode 100644
index 0000000..9633796
--- /dev/null
+++ b/lzma/C/7zBuf2.c
@@ -0,0 +1,48 @@
+/* 7zBuf2.c -- Byte Buffer

+2013-11-12 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#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/lzma/C/7zCrc.c b/lzma/C/7zCrc.c
new file mode 100644
index 0000000..161d4d1
--- /dev/null
+++ b/lzma/C/7zCrc.c
@@ -0,0 +1,85 @@
+/* 7zCrc.c -- CRC32 init

+2013-11-12 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#include "7zCrc.h"

+#include "CpuArch.h"

+

+#define kCrcPoly 0xEDB88320

+

+#ifdef MY_CPU_X86_OR_AMD64

+  #define CRC_NUM_TABLES 8

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

+#elif defined(MY_CPU_LE)

+  #define CRC_NUM_TABLES 4

+#else

+  #define CRC_NUM_TABLES 5

+  #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))

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

+#endif

+

+#ifndef MY_CPU_BE

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

+#endif

+

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

+

+CRC_FUNC g_CrcUpdate;

+UInt32 g_CrcTable[256 * CRC_NUM_TABLES];

+

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

+  }

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

+  {

+    UInt32 r = g_CrcTable[i - 256];

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

+  }

+  

+  #ifdef MY_CPU_LE

+

+  g_CrcUpdate = CrcUpdateT4;

+  

+  #if CRC_NUM_TABLES == 8

+  if (!CPU_Is_InOrder())

+    g_CrcUpdate = CrcUpdateT8;

+  #endif

+

+  #else

+  {

+    #ifndef MY_CPU_BE

+    UInt32 k = 1;

+    if (*(const Byte *)&k == 1)

+      g_CrcUpdate = CrcUpdateT4;

+    else

+    #endif

+    {

+      for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)

+      {

+        UInt32 x = g_CrcTable[i - 256];

+        g_CrcTable[i] = CRC_UINT32_SWAP(x);

+      }

+      g_CrcUpdate = CrcUpdateT1_BeT4;

+    }

+  }

+  #endif

+}

diff --git a/lzma/C/7zCrc.h b/lzma/C/7zCrc.h
new file mode 100644
index 0000000..3b04594
--- /dev/null
+++ b/lzma/C/7zCrc.h
@@ -0,0 +1,25 @@
+/* 7zCrc.h -- CRC32 calculation

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_CRC_H

+#define __7Z_CRC_H

+

+#include "7zTypes.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/lzma/C/7zCrcOpt.c b/lzma/C/7zCrcOpt.c
new file mode 100644
index 0000000..48b0136
--- /dev/null
+++ b/lzma/C/7zCrcOpt.c
@@ -0,0 +1,66 @@
+/* 7zCrcOpt.c -- CRC32 calculation

+2013-11-12 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#include "CpuArch.h"

+

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

+

+#ifndef MY_CPU_BE

+

+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

+

+

+#ifndef MY_CPU_LE

+

+#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))

+

+UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(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);

+  v = CRC_UINT32_SWAP(v);

+  table += 0x100;

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

+  {

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

+    v =

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

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

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

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

+  }

+  table -= 0x100;

+  v = CRC_UINT32_SWAP(v);

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

+    v = CRC_UPDATE_BYTE_2(v, *p);

+  return v;

+}

+

+#endif

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

+2014-06-16 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#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(const Byte *props, unsigned propsSize, 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 (propsSize != 5)

+    return SZ_ERROR_UNSUPPORTED;

+

+  {

+    unsigned order = props[0];

+    UInt32 memSize = GetUi32(props + 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(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,

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

+{

+  CLzmaDec state;

+  SRes res = SZ_OK;

+

+  LzmaDec_Construct(&state);

+  RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, 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(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,

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

+{

+  CLzma2Dec state;

+  SRes res = SZ_OK;

+

+  Lzma2Dec_Construct(&state);

+  if (propsSize != 1)

+    return SZ_ERROR_DATA;

+  RINOK(Lzma2Dec_AllocateProbs(&state, props[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)

+  {

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

+}

+

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

+

+static SRes SzFolder_Decode2(const CSzFolder *folder,

+    const Byte *propsData,

+    const UInt64 *unpackSizes,

+    const UInt64 *packPositions,

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

+  {

+    const 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 = 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 = packPositions[si];

+      inSize = packPositions[si + 1] - offset;

+      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(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));

+      }

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

+      {

+        RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));

+      }

+      else

+      {

+        #ifdef _7ZIP_PPMD_SUPPPORT

+        RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));

+        #else

+        return SZ_ERROR_UNSUPPORTED;

+        #endif

+      }

+    }

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

+    {

+      UInt64 offset = packPositions[1];

+      UInt64 s3Size = packPositions[2] - offset;

+      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 SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,

+    ILookInStream *inStream, UInt64 startPos,

+    Byte *outBuffer, size_t outSize,

+    ISzAlloc *allocMain)

+{

+  SRes res;

+  CSzFolder folder;

+  CSzData sd;

+  CSzData sdSizes;

+  

+  const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];

+  sd.Data = data;

+  sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex];

+  

+  sdSizes.Data = p->UnpackSizesData + p->FoSizesOffsets[folderIndex];

+  sdSizes.Size =

+      p->FoSizesOffsets[folderIndex + 1] -

+      p->FoSizesOffsets[folderIndex];

+

+  res = SzGetNextFolderItem(&folder, &sd, &sdSizes);

+  

+  if (res != SZ_OK)

+    return res;

+

+  if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.MainOutStream])

+    return SZ_ERROR_FAIL;

+  {

+    int i;

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

+    res = SzFolder_Decode2(&folder, data, folder.CodersUnpackSizes,

+        p->PackPositions + p->FoStartPackStreamIndex[folderIndex],

+        inStream, startPos,

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

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

+      IAlloc_Free(allocMain, tempBuf[i]);

+    return res;

+  }

+}

diff --git a/lzma/C/7zFile.c b/lzma/C/7zFile.c
new file mode 100644
index 0000000..98fe716
--- /dev/null
+++ b/lzma/C/7zFile.c
@@ -0,0 +1,286 @@
+/* 7zFile.c -- File IO

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

+

+#include "Precomp.h"

+

+#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/lzma/C/7zFile.h b/lzma/C/7zFile.h
new file mode 100644
index 0000000..d62a192
--- /dev/null
+++ b/lzma/C/7zFile.h
@@ -0,0 +1,83 @@
+/* 7zFile.h -- File IO

+2013-01-18 : 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 "7zTypes.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/lzma/C/7zStream.c b/lzma/C/7zStream.c
new file mode 100644
index 0000000..5a92d53
--- /dev/null
+++ b/lzma/C/7zStream.c
@@ -0,0 +1,171 @@
+/* 7zStream.c -- 7z Stream functions

+2013-11-12 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#include <string.h>

+

+#include "7zTypes.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/lzma/C/7zTypes.h b/lzma/C/7zTypes.h
new file mode 100644
index 0000000..903047b
--- /dev/null
+++ b/lzma/C/7zTypes.h
@@ -0,0 +1,256 @@
+/* 7zTypes.h -- Basic types

+2013-11-12 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_TYPES_H

+#define __7Z_TYPES_H

+

+#ifdef _WIN32

+/* #include <windows.h> */

+#endif

+

+#include <stddef.h>

+

+#ifndef EXTERN_C_BEGIN

+#ifdef __cplusplus

+#define EXTERN_C_BEGIN extern "C" {

+#define EXTERN_C_END }

+#else

+#define EXTERN_C_BEGIN

+#define EXTERN_C_END

+#endif

+#endif

+

+EXTERN_C_BEGIN

+

+#define SZ_OK 0

+

+#define SZ_ERROR_DATA 1

+#define SZ_ERROR_MEM 2

+#define SZ_ERROR_CRC 3

+#define SZ_ERROR_UNSUPPORTED 4

+#define SZ_ERROR_PARAM 5

+#define SZ_ERROR_INPUT_EOF 6

+#define SZ_ERROR_OUTPUT_EOF 7

+#define SZ_ERROR_READ 8

+#define SZ_ERROR_WRITE 9

+#define SZ_ERROR_PROGRESS 10

+#define SZ_ERROR_FAIL 11

+#define SZ_ERROR_THREAD 12

+

+#define SZ_ERROR_ARCHIVE 16

+#define SZ_ERROR_NO_ARCHIVE 17

+

+typedef int SRes;

+

+#ifdef _WIN32

+/* typedef DWORD WRes; */

+typedef unsigned 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_NO_INLINE

+#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/lzma/C/7zVersion.h b/lzma/C/7zVersion.h
new file mode 100644
index 0000000..feedd30
--- /dev/null
+++ b/lzma/C/7zVersion.h
@@ -0,0 +1,10 @@
+#define MY_VER_MAJOR 9

+#define MY_VER_MINOR 38

+#define MY_VER_BUILD 00

+#define MY_VERSION "9.38 beta"

+// #define MY_7ZIP_VERSION "9.38"

+#define MY_DATE "2015-01-03"

+#undef MY_COPYRIGHT

+#undef MY_VERSION_COPYRIGHT_DATE

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

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

diff --git a/lzma/C/7zVersion.rc b/lzma/C/7zVersion.rc
new file mode 100644
index 0000000..6ed26de
--- /dev/null
+++ b/lzma/C/7zVersion.rc
@@ -0,0 +1,55 @@
+#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>

+

+#ifndef MY_VERSION

+#include "7zVersion.h"

+#endif

+

+#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/lzma/C/Aes.c b/lzma/C/Aes.c
new file mode 100644
index 0000000..06bf9d3
--- /dev/null
+++ b/lzma/C/Aes.c
@@ -0,0 +1,284 @@
+/* Aes.c -- AES encryption / decryption

+2013-11-12 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#include "Aes.h"

+#include "CpuArch.h"

+

+static UInt32 T[256 * 4];

+static Byte Sbox[256] = {

+  0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,

+  0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,

+  0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,

+  0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,

+  0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,

+  0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,

+  0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,

+  0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,

+  0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,

+  0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,

+  0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,

+  0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,

+  0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,

+  0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,

+  0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,

+  0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};

+

+void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);

+

+void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);

+

+AES_CODE_FUNC g_AesCbc_Encode;

+AES_CODE_FUNC g_AesCbc_Decode;

+AES_CODE_FUNC g_AesCtr_Code;

+

+static UInt32 D[256 * 4];

+static Byte InvS[256];

+

+static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };

+

+#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF)

+

+#define Ui32(a0, a1, a2, a3) ((UInt32)(a0) | ((UInt32)(a1) << 8) | ((UInt32)(a2) << 16) | ((UInt32)(a3) << 24))

+

+#define gb0(x) ( (x)          & 0xFF)

+#define gb1(x) (((x) >> ( 8)) & 0xFF)

+#define gb2(x) (((x) >> (16)) & 0xFF)

+#define gb3(x) (((x) >> (24)) & 0xFF)

+

+void AesGenTables(void)

+{

+  unsigned i;

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

+    InvS[Sbox[i]] = (Byte)i;

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

+  {

+    {

+      UInt32 a1 = Sbox[i];

+      UInt32 a2 = xtime(a1);

+      UInt32 a3 = a2 ^ a1;

+      T[        i] = Ui32(a2, a1, a1, a3);

+      T[0x100 + i] = Ui32(a3, a2, a1, a1);

+      T[0x200 + i] = Ui32(a1, a3, a2, a1);

+      T[0x300 + i] = Ui32(a1, a1, a3, a2);

+    }

+    {

+      UInt32 a1 = InvS[i];

+      UInt32 a2 = xtime(a1);

+      UInt32 a4 = xtime(a2);

+      UInt32 a8 = xtime(a4);

+      UInt32 a9 = a8 ^ a1;

+      UInt32 aB = a8 ^ a2 ^ a1;

+      UInt32 aD = a8 ^ a4 ^ a1;

+      UInt32 aE = a8 ^ a4 ^ a2;

+      D[        i] = Ui32(aE, a9, aD, aB);

+      D[0x100 + i] = Ui32(aB, aE, a9, aD);

+      D[0x200 + i] = Ui32(aD, aB, aE, a9);

+      D[0x300 + i] = Ui32(a9, aD, aB, aE);

+    }

+  }

+  g_AesCbc_Encode = AesCbc_Encode;

+  g_AesCbc_Decode = AesCbc_Decode;

+  g_AesCtr_Code = AesCtr_Code;

+  #ifdef MY_CPU_X86_OR_AMD64

+  if (CPU_Is_Aes_Supported())

+  {

+    g_AesCbc_Encode = AesCbc_Encode_Intel;

+    g_AesCbc_Decode = AesCbc_Decode_Intel;

+    g_AesCtr_Code = AesCtr_Code_Intel;

+  }

+  #endif

+}

+

+#define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])]

+#define HT4(m, i, s, p) m[i] = \

+    HT(i, 0, s) ^ \

+    HT(i, 1, s) ^ \

+    HT(i, 2, s) ^ \

+    HT(i, 3, s) ^ w[p + i]

+/* such order (2031) in HT16 is for VC6/K8 speed optimization) */

+#define HT16(m, s, p) \

+    HT4(m, 2, s, p); \

+    HT4(m, 0, s, p); \

+    HT4(m, 3, s, p); \

+    HT4(m, 1, s, p); \

+

+#define FT(i, x) Sbox[gb ## x(m[(i + x) & 3])]

+#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i];

+

+#define HD(i, x, s) (D + (x << 8))[gb ## x(s[(i - x) & 3])]

+#define HD4(m, i, s, p) m[i] = \

+    HD(i, 0, s) ^ \

+    HD(i, 1, s) ^ \

+    HD(i, 2, s) ^ \

+    HD(i, 3, s) ^ w[p + i];

+/* such order (0231) in HD16 is for VC6/K8 speed optimization) */

+#define HD16(m, s, p) \

+    HD4(m, 0, s, p); \

+    HD4(m, 2, s, p); \

+    HD4(m, 3, s, p); \

+    HD4(m, 1, s, p); \

+

+#define FD(i, x) InvS[gb ## x(m[(i - x) & 3])]

+#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i];

+

+void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize)

+{

+  unsigned i, wSize;

+  wSize = keySize + 28;

+  keySize /= 4;

+  w[0] = ((UInt32)keySize / 2) + 3;

+  w += 4;

+

+  for (i = 0; i < keySize; i++, key += 4)

+    w[i] = GetUi32(key);

+

+  for (; i < wSize; i++)

+  {

+    UInt32 t = w[i - 1];

+    unsigned rem = i % keySize;

+    if (rem == 0)

+      t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]);

+    else if (keySize > 6 && rem == 4)

+      t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]);

+    w[i] = w[i - keySize] ^ t;

+  }

+}

+

+void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)

+{

+  unsigned i, num;

+  Aes_SetKey_Enc(w, key, keySize);

+  num = keySize + 20;

+  w += 8;

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

+  {

+    UInt32 r = w[i];

+    w[i] =

+      D[        Sbox[gb0(r)]] ^

+      D[0x100 + Sbox[gb1(r)]] ^

+      D[0x200 + Sbox[gb2(r)]] ^

+      D[0x300 + Sbox[gb3(r)]];

+  }

+}

+

+/* Aes_Encode and Aes_Decode functions work with little-endian words.

+  src and dest are pointers to 4 UInt32 words.

+  arc and dest can point to same block */

+

+static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src)

+{

+  UInt32 s[4];

+  UInt32 m[4];

+  UInt32 numRounds2 = w[0];

+  w += 4;

+  s[0] = src[0] ^ w[0];

+  s[1] = src[1] ^ w[1];

+  s[2] = src[2] ^ w[2];

+  s[3] = src[3] ^ w[3];

+  w += 4;

+  for (;;)

+  {

+    HT16(m, s, 0);

+    if (--numRounds2 == 0)

+      break;

+    HT16(s, m, 4);

+    w += 8;

+  }

+  w += 4;

+  FT4(0); FT4(1); FT4(2); FT4(3);

+}

+

+static void Aes_Decode(const UInt32 *w, UInt32 *dest, const UInt32 *src)

+{

+  UInt32 s[4];

+  UInt32 m[4];

+  UInt32 numRounds2 = w[0];

+  w += 4 + numRounds2 * 8;

+  s[0] = src[0] ^ w[0];

+  s[1] = src[1] ^ w[1];

+  s[2] = src[2] ^ w[2];

+  s[3] = src[3] ^ w[3];

+  for (;;)

+  {

+    w -= 8;

+    HD16(m, s, 4);

+    if (--numRounds2 == 0)

+      break;

+    HD16(s, m, 0);

+  }

+  FD4(0); FD4(1); FD4(2); FD4(3);

+}

+

+void AesCbc_Init(UInt32 *p, const Byte *iv)

+{

+  unsigned i;

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

+    p[i] = GetUi32(iv + i * 4);

+}

+

+void MY_FAST_CALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)

+  {

+    p[0] ^= GetUi32(data);

+    p[1] ^= GetUi32(data + 4);

+    p[2] ^= GetUi32(data + 8);

+    p[3] ^= GetUi32(data + 12);

+    

+    Aes_Encode(p + 4, p, p);

+    

+    SetUi32(data,      p[0]);

+    SetUi32(data + 4,  p[1]);

+    SetUi32(data + 8,  p[2]);

+    SetUi32(data + 12, p[3]);

+  }

+}

+

+void MY_FAST_CALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  UInt32 in[4], out[4];

+  for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)

+  {

+    in[0] = GetUi32(data);

+    in[1] = GetUi32(data + 4);

+    in[2] = GetUi32(data + 8);

+    in[3] = GetUi32(data + 12);

+

+    Aes_Decode(p + 4, out, in);

+

+    SetUi32(data,      p[0] ^ out[0]);

+    SetUi32(data + 4,  p[1] ^ out[1]);

+    SetUi32(data + 8,  p[2] ^ out[2]);

+    SetUi32(data + 12, p[3] ^ out[3]);

+    

+    p[0] = in[0];

+    p[1] = in[1];

+    p[2] = in[2];

+    p[3] = in[3];

+  }

+}

+

+void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  for (; numBlocks != 0; numBlocks--)

+  {

+    UInt32 temp[4];

+    Byte buf[16];

+    int i;

+    if (++p[0] == 0)

+      p[1]++;

+    Aes_Encode(p + 4, temp, p);

+    SetUi32(buf,      temp[0]);

+    SetUi32(buf + 4,  temp[1]);

+    SetUi32(buf + 8,  temp[2]);

+    SetUi32(buf + 12, temp[3]);

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

+      *data++ ^= buf[i];

+  }

+}

diff --git a/lzma/C/Aes.h b/lzma/C/Aes.h
new file mode 100644
index 0000000..381e979
--- /dev/null
+++ b/lzma/C/Aes.h
@@ -0,0 +1,38 @@
+/* Aes.h -- AES encryption / decryption

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __AES_H

+#define __AES_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+#define AES_BLOCK_SIZE 16

+

+/* Call AesGenTables one time before other AES functions */

+void AesGenTables(void);

+

+/* UInt32 pointers must be 16-byte aligned */

+

+/* 16-byte (4 * 32-bit words) blocks: 1 (IV) + 1 (keyMode) + 15 (AES-256 roundKeys) */

+#define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4)

+

+/* aes - 16-byte aligned pointer to keyMode+roundKeys sequence */

+/* keySize = 16 or 24 or 32 (bytes) */

+typedef void (MY_FAST_CALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize);

+void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *aes, const Byte *key, unsigned keySize);

+void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *aes, const Byte *key, unsigned keySize);

+

+/* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */

+void AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */

+/* data - 16-byte aligned pointer to data */

+/* numBlocks - the number of 16-byte blocks in data array */

+typedef void (MY_FAST_CALL *AES_CODE_FUNC)(UInt32 *ivAes, Byte *data, size_t numBlocks);

+extern AES_CODE_FUNC g_AesCbc_Encode;

+extern AES_CODE_FUNC g_AesCbc_Decode;

+extern AES_CODE_FUNC g_AesCtr_Code;

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/AesOpt.c b/lzma/C/AesOpt.c
new file mode 100644
index 0000000..e5d4d26
--- /dev/null
+++ b/lzma/C/AesOpt.c
@@ -0,0 +1,184 @@
+/* AesOpt.c -- Intel's AES

+2013-11-12 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#include "CpuArch.h"

+

+#ifdef MY_CPU_X86_OR_AMD64

+#if _MSC_VER >= 1500

+#define USE_INTEL_AES

+#endif

+#endif

+

+#ifdef USE_INTEL_AES

+

+#include <wmmintrin.h>

+

+void MY_FAST_CALL AesCbc_Encode_Intel(__m128i *p, __m128i *data, size_t numBlocks)

+{

+  __m128i m = *p;

+  for (; numBlocks != 0; numBlocks--, data++)

+  {

+    UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;

+    const __m128i *w = p + 3;

+    m = _mm_xor_si128(m, *data);

+    m = _mm_xor_si128(m, p[2]);

+    do

+    {

+      m = _mm_aesenc_si128(m, w[0]);

+      m = _mm_aesenc_si128(m, w[1]);

+      w += 2;

+    }

+    while (--numRounds2 != 0);

+    m = _mm_aesenc_si128(m, w[0]);

+    m = _mm_aesenclast_si128(m, w[1]);

+    *data = m;

+  }

+  *p = m;

+}

+

+#define NUM_WAYS 3

+

+#define AES_OP_W(op, n) { \

+    const __m128i t = w[n]; \

+    m0 = op(m0, t); \

+    m1 = op(m1, t); \

+    m2 = op(m2, t); \

+    }

+

+#define AES_DEC(n) AES_OP_W(_mm_aesdec_si128, n)

+#define AES_DEC_LAST(n) AES_OP_W(_mm_aesdeclast_si128, n)

+#define AES_ENC(n) AES_OP_W(_mm_aesenc_si128, n)

+#define AES_ENC_LAST(n) AES_OP_W(_mm_aesenclast_si128, n)

+

+void MY_FAST_CALL AesCbc_Decode_Intel(__m128i *p, __m128i *data, size_t numBlocks)

+{

+  __m128i iv = *p;

+  for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)

+  {

+    UInt32 numRounds2 = *(const UInt32 *)(p + 1);

+    const __m128i *w = p + numRounds2 * 2;

+    __m128i m0, m1, m2;

+    {

+      const __m128i t = w[2];

+      m0 = _mm_xor_si128(t, data[0]);

+      m1 = _mm_xor_si128(t, data[1]);

+      m2 = _mm_xor_si128(t, data[2]);

+    }

+    numRounds2--;

+    do

+    {

+      AES_DEC(1)

+      AES_DEC(0)

+      w -= 2;

+    }

+    while (--numRounds2 != 0);

+    AES_DEC(1)

+    AES_DEC_LAST(0)

+

+    {

+      __m128i t;

+      t = _mm_xor_si128(m0, iv); iv = data[0]; data[0] = t;

+      t = _mm_xor_si128(m1, iv); iv = data[1]; data[1] = t;

+      t = _mm_xor_si128(m2, iv); iv = data[2]; data[2] = t;

+    }

+  }

+  for (; numBlocks != 0; numBlocks--, data++)

+  {

+    UInt32 numRounds2 = *(const UInt32 *)(p + 1);

+    const __m128i *w = p + numRounds2 * 2;

+    __m128i m = _mm_xor_si128(w[2], *data);

+    numRounds2--;

+    do

+    {

+      m = _mm_aesdec_si128(m, w[1]);

+      m = _mm_aesdec_si128(m, w[0]);

+      w -= 2;

+    }

+    while (--numRounds2 != 0);

+    m = _mm_aesdec_si128(m, w[1]);

+    m = _mm_aesdeclast_si128(m, w[0]);

+

+    m = _mm_xor_si128(m, iv);

+    iv = *data;

+    *data = m;

+  }

+  *p = iv;

+}

+

+void MY_FAST_CALL AesCtr_Code_Intel(__m128i *p, __m128i *data, size_t numBlocks)

+{

+  __m128i ctr = *p;

+  __m128i one;

+  one.m128i_u64[0] = 1;

+  one.m128i_u64[1] = 0;

+  for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)

+  {

+    UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;

+    const __m128i *w = p;

+    __m128i m0, m1, m2;

+    {

+      const __m128i t = w[2];

+      ctr = _mm_add_epi64(ctr, one); m0 = _mm_xor_si128(ctr, t);

+      ctr = _mm_add_epi64(ctr, one); m1 = _mm_xor_si128(ctr, t);

+      ctr = _mm_add_epi64(ctr, one); m2 = _mm_xor_si128(ctr, t);

+    }

+    w += 3;

+    do

+    {

+      AES_ENC(0)

+      AES_ENC(1)

+      w += 2;

+    }

+    while (--numRounds2 != 0);

+    AES_ENC(0)

+    AES_ENC_LAST(1)

+    data[0] = _mm_xor_si128(data[0], m0);

+    data[1] = _mm_xor_si128(data[1], m1);

+    data[2] = _mm_xor_si128(data[2], m2);

+  }

+  for (; numBlocks != 0; numBlocks--, data++)

+  {

+    UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;

+    const __m128i *w = p;

+    __m128i m;

+    ctr = _mm_add_epi64(ctr, one);

+    m = _mm_xor_si128(ctr, p[2]);

+    w += 3;

+    do

+    {

+      m = _mm_aesenc_si128(m, w[0]);

+      m = _mm_aesenc_si128(m, w[1]);

+      w += 2;

+    }

+    while (--numRounds2 != 0);

+    m = _mm_aesenc_si128(m, w[0]);

+    m = _mm_aesenclast_si128(m, w[1]);

+    *data = _mm_xor_si128(*data, m);

+  }

+  *p = ctr;

+}

+

+#else

+

+void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);

+void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);

+

+void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  AesCbc_Encode(p, data, numBlocks);

+}

+

+void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  AesCbc_Decode(p, data, numBlocks);

+}

+

+void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *p, Byte *data, size_t numBlocks)

+{

+  AesCtr_Code(p, data, numBlocks);

+}

+

+#endif

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

+2013-11-12 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#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/lzma/C/Alloc.h b/lzma/C/Alloc.h
new file mode 100644
index 0000000..6b3f034
--- /dev/null
+++ b/lzma/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/lzma/C/Android.bp b/lzma/C/Android.bp
new file mode 100644
index 0000000..1971bf3
--- /dev/null
+++ b/lzma/C/Android.bp
@@ -0,0 +1,59 @@
+// Copyright 2015 The Android Open Source Project
+
+cc_library {
+    name: "liblzma",
+    host_supported: true,
+    sdk_version: "9",
+    stl: "none",
+
+    cflags: ["-D_7ZIP_ST", "-Wno-empty-body"],
+    clang_cflags: ["-Wno-self-assign"],
+
+    export_include_dirs: ["."],
+
+    srcs: [
+        "7zAlloc.c",
+        "7zArcIn.c",
+        "7zBuf2.c",
+        "7zBuf.c",
+        "7zCrc.c",
+        "7zCrcOpt.c",
+        "7zDec.c",
+        "7zFile.c",
+        "7zStream.c",
+        "Aes.c",
+        "AesOpt.c",
+        "Alloc.c",
+        "Bcj2.c",
+        "Bra86.c",
+        "Bra.c",
+        "BraIA64.c",
+        "CpuArch.c",
+        "Delta.c",
+        "LzFind.c",
+        "Lzma2Dec.c",
+        "Lzma2Enc.c",
+        "Lzma86Dec.c",
+        "Lzma86Enc.c",
+        "LzmaDec.c",
+        "LzmaEnc.c",
+        "LzmaLib.c",
+        "Ppmd7.c",
+        "Ppmd7Dec.c",
+        "Ppmd7Enc.c",
+        "Sha256.c",
+        "Sort.c",
+        "Xz.c",
+        "XzCrc64.c",
+        "XzCrc64Opt.c",
+        "XzDec.c",
+        "XzEnc.c",
+        "XzIn.c",
+    ],
+
+    target: {
+        windows: {
+            enabled: true,
+        },
+    },
+}
diff --git a/lzma/C/Bcj2.c b/lzma/C/Bcj2.c
new file mode 100644
index 0000000..ac4ca0c
--- /dev/null
+++ b/lzma/C/Bcj2.c
@@ -0,0 +1,134 @@
+/* Bcj2.c -- Converter for x86 code (BCJ2)

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

+

+#include "Precomp.h"

+

+#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/lzma/C/Bcj2.h b/lzma/C/Bcj2.h
new file mode 100644
index 0000000..e8304c5
--- /dev/null
+++ b/lzma/C/Bcj2.h
@@ -0,0 +1,34 @@
+/* Bcj2.h -- Converter for x86 code (BCJ2)

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __BCJ2_H

+#define __BCJ2_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+/*

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

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/Bra.c b/lzma/C/Bra.c
new file mode 100644
index 0000000..976810c
--- /dev/null
+++ b/lzma/C/Bra.c
@@ -0,0 +1,135 @@
+/* Bra.c -- Converters for RISC code

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

+

+#include "Precomp.h"

+

+#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/lzma/C/Bra.h b/lzma/C/Bra.h
new file mode 100644
index 0000000..aba8dce
--- /dev/null
+++ b/lzma/C/Bra.h
@@ -0,0 +1,64 @@
+/* Bra.h -- Branch converters for executables

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __BRA_H

+#define __BRA_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+/*

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

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/Bra86.c b/lzma/C/Bra86.c
new file mode 100644
index 0000000..8dd3ed4
--- /dev/null
+++ b/lzma/C/Bra86.c
@@ -0,0 +1,82 @@
+/* Bra86.c -- Converter for x86 code (BCJ)

+2013-11-12 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#include "Bra.h"

+

+#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)

+

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

+{

+  SizeT pos = 0;

+  UInt32 mask = *state & 7;

+  if (size < 5)

+    return 0;

+  size -= 4;

+  ip += 5;

+

+  for (;;)

+  {

+    Byte *p = data + pos;

+    const Byte *limit = data + size;

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

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

+        break;

+

+    {

+      SizeT d = (SizeT)(p - data - pos);

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

+      if (p >= limit)

+      {

+        *state = (d > 2 ? 0 : mask >> (unsigned)d);

+        return pos;

+      }

+      if (d > 2)

+        mask = 0;

+      else

+      {

+        mask >>= (unsigned)d;

+        if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1])))

+        {

+          mask = (mask >> 1) | 4;

+          pos++;

+          continue;

+        }

+      }

+    }

+

+    if (Test86MSByte(p[4]))

+    {

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

+      UInt32 cur = ip + (UInt32)pos;

+      pos += 5;

+      if (encoding)

+        v += cur;

+      else

+        v -= cur;

+      if (mask != 0)

+      {

+        unsigned sh = (mask & 6) << 2;

+        if (Test86MSByte((Byte)(v >> sh)))

+        {

+          v ^= (((UInt32)0x100 << sh) - 1);

+          if (encoding)

+            v += cur;

+          else

+            v -= cur;

+        }

+        mask = 0;

+      }

+      p[1] = (Byte)v;

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

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

+      p[4] = (Byte)(0 - ((v >> 24) & 1));

+    }

+    else

+    {

+      mask = (mask >> 1) | 4;

+      pos++;

+    }

+  }

+}

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

+2013-11-12 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#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/lzma/C/Compiler.h b/lzma/C/Compiler.h
new file mode 100644
index 0000000..0f76670
--- /dev/null
+++ b/lzma/C/Compiler.h
@@ -0,0 +1,28 @@
+/* Compiler.h -- Compiler ypes

+2013-11-12 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_COMPILER_H

+#define __7Z_COMPILER_H

+

+#ifdef _MSC_VER

+

+  #ifdef UNDER_CE

+    #define RPC_NO_WINDOWS_H

+    /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */

+    #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union

+    #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int

+  #endif

+

+  #if _MSC_VER >= 1300

+    #pragma warning(disable : 4996) // This function or variable may be unsafe

+  #else

+    #pragma warning(disable : 4511) // copy constructor could not be generated

+    #pragma warning(disable : 4512) // assignment operator could not be generated

+    #pragma warning(disable : 4702) // unreachable code

+    #pragma warning(disable : 4710) // not inlined

+    #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information

+  #endif

+

+#endif

+

+#endif

diff --git a/lzma/C/CpuArch.c b/lzma/C/CpuArch.c
new file mode 100644
index 0000000..f8ac0c2
--- /dev/null
+++ b/lzma/C/CpuArch.c
@@ -0,0 +1,190 @@
+/* CpuArch.c -- CPU specific code

+2012-05-29: Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#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) && _MSC_VER >= 1500

+#include <intrin.h>

+#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__ (

+  #if defined(MY_CPU_X86) && defined(__PIC__)

+    "mov %%ebx, %%edi;"

+    "cpuid;"

+    "xchgl %%ebx, %%edi;"

+    : "=a" (*a) ,

+      "=D" (*b) ,

+  #else

+    "cpuid"

+    : "=a" (*a) ,

+      "=b" (*b) ,

+  #endif

+      "=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 && (

+        /* Atom CPU */

+           model == 0x100C  /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */

+        || model == 0x2006  /* 45 nm, Z6xx */

+        || model == 0x2007  /* 32 nm, Z2460 */

+        || model == 0x3005  /* 32 nm, Z2760 */

+        || model == 0x3006  /* 32 nm, N2xxx, D2xxx */

+        )));

+    case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));

+    case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));

+  }

+  return True;

+}

+

+#if !defined(MY_CPU_AMD64) && defined(_WIN32)

+#include <windows.h>

+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/lzma/C/CpuArch.h b/lzma/C/CpuArch.h
new file mode 100644
index 0000000..2316205
--- /dev/null
+++ b/lzma/C/CpuArch.h
@@ -0,0 +1,157 @@
+/* CpuArch.h -- CPU specific code

+2013-11-12: Igor Pavlov : Public domain */

+

+#ifndef __CPU_ARCH_H

+#define __CPU_ARCH_H

+

+#include "7zTypes.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__) || defined(__m68k__) ||  defined(__ARMEB__) || defined(__MIPSEB__)

+#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 *)(const void *)(p))

+#define GetUi32(p) (*(const UInt32 *)(const void *)(p))

+#define GetUi64(p) (*(const UInt64 *)(const void *)(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)

+

+#include <stdlib.h>

+

+#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)(((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/lzma/C/Delta.c b/lzma/C/Delta.c
new file mode 100644
index 0000000..6cbbe46
--- /dev/null
+++ b/lzma/C/Delta.c
@@ -0,0 +1,64 @@
+/* Delta.c -- Delta converter

+2009-05-26 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#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/lzma/C/Delta.h b/lzma/C/Delta.h
new file mode 100644
index 0000000..e59d5a2
--- /dev/null
+++ b/lzma/C/Delta.h
@@ -0,0 +1,19 @@
+/* Delta.h -- Delta converter

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __DELTA_H

+#define __DELTA_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+#define DELTA_STATE_SIZE 256

+

+void Delta_Init(Byte *state);

+void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);

+void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/LzFind.c b/lzma/C/LzFind.c
new file mode 100644
index 0000000..df79867
--- /dev/null
+++ b/lzma/C/LzFind.c
@@ -0,0 +1,763 @@
+/* LzFind.c -- Match finder for LZ algorithms

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

+

+#include "Precomp.h"

+

+#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/lzma/C/LzFind.h b/lzma/C/LzFind.h
new file mode 100644
index 0000000..bad5000
--- /dev/null
+++ b/lzma/C/LzFind.h
@@ -0,0 +1,111 @@
+/* LzFind.h -- Match finder for LZ algorithms

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __LZ_FIND_H

+#define __LZ_FIND_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

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

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/LzFindMt.c b/lzma/C/LzFindMt.c
new file mode 100644
index 0000000..5356d4a
--- /dev/null
+++ b/lzma/C/LzFindMt.c
@@ -0,0 +1,794 @@
+/* LzFindMt.c -- multithreaded Match finder for LZ algorithms

+2014-12-29 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#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, THREAD_FUNC_TYPE startAddress, 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, THREAD_FUNC_TYPE startAddress, 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 THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p);  return 0; }

+static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)

+{

+  Byte allocaDummy[0x180];

+  allocaDummy[0] = 0;

+  allocaDummy[1] = allocaDummy[0];

+  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/lzma/C/LzFindMt.h b/lzma/C/LzFindMt.h
new file mode 100644
index 0000000..320d87c
--- /dev/null
+++ b/lzma/C/LzFindMt.h
@@ -0,0 +1,101 @@
+/* LzFindMt.h -- multithreaded Match finder for LZ algorithms

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __LZ_FIND_MT_H

+#define __LZ_FIND_MT_H

+

+#include "LzFind.h"

+#include "Threads.h"

+

+EXTERN_C_BEGIN

+

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

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/LzHash.h b/lzma/C/LzHash.h
new file mode 100644
index 0000000..b2f0e3c
--- /dev/null
+++ b/lzma/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/lzma/C/Lzma2Dec.c b/lzma/C/Lzma2Dec.c
new file mode 100644
index 0000000..ed91619
--- /dev/null
+++ b/lzma/C/Lzma2Dec.c
@@ -0,0 +1,352 @@
+/* Lzma2Dec.c -- LZMA2 Decoder

+2010-12-15 : Igor Pavlov : Public domain */

+

+/* #define SHOW_DEBUG_INFO */

+

+#include "Precomp.h"

+

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

+  SRes res;

+  SizeT outSize = *destLen, inSize = *srcLen;

+  *destLen = *srcLen = 0;

+  *status = LZMA_STATUS_NOT_SPECIFIED;

+  Lzma2Dec_Construct(&p);

+  RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));

+  p.decoder.dic = dest;

+  p.decoder.dicBufSize = outSize;

+  Lzma2Dec_Init(&p);

+  *srcLen = inSize;

+  res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);

+  *destLen = p.decoder.dicPos;

+  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)

+    res = SZ_ERROR_INPUT_EOF;

+  Lzma2Dec_FreeProbs(&p, alloc);

+  return res;

+}

diff --git a/lzma/C/Lzma2Dec.h b/lzma/C/Lzma2Dec.h
new file mode 100644
index 0000000..9254523
--- /dev/null
+++ b/lzma/C/Lzma2Dec.h
@@ -0,0 +1,80 @@
+/* Lzma2Dec.h -- LZMA2 Decoder

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA2_DEC_H

+#define __LZMA2_DEC_H

+

+#include "LzmaDec.h"

+

+EXTERN_C_BEGIN

+

+/* ---------- 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);

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/Lzma2Enc.c b/lzma/C/Lzma2Enc.c
new file mode 100644
index 0000000..34a97f3
--- /dev/null
+++ b/lzma/C/Lzma2Enc.c
@@ -0,0 +1,493 @@
+/* Lzma2Enc.c -- LZMA2 Encoder

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

+

+#include "Precomp.h"

+

+/* #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;

+

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

+  }

+  if (t2 > 1)

+  {

+    UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1;

+    if (temp > p->lzmaProps.reduceSize)

+    {

+      UInt64 numBlocks = temp / p->blockSize;

+      if (numBlocks < t2)

+      {

+        t2 = (UInt32)numBlocks;

+        t3 = t1 * t2;

+      }

+    }

+  }

+  p->numBlockThreads = t2;

+  p->numTotalThreads = t3;

+}

+

+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/lzma/C/Lzma2Enc.h b/lzma/C/Lzma2Enc.h
new file mode 100644
index 0000000..061178a
--- /dev/null
+++ b/lzma/C/Lzma2Enc.h
@@ -0,0 +1,62 @@
+/* Lzma2Enc.h -- LZMA2 Encoder

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA2_ENC_H

+#define __LZMA2_ENC_H

+

+#include "LzmaEnc.h"

+

+EXTERN_C_BEGIN

+

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

+*/

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/Lzma86.h b/lzma/C/Lzma86.h
new file mode 100644
index 0000000..83057e5
--- /dev/null
+++ b/lzma/C/Lzma86.h
@@ -0,0 +1,111 @@
+/* Lzma86.h -- LZMA + x86 (BCJ) Filter

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA86_H

+#define __LZMA86_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+#define LZMA86_SIZE_OFFSET (1 + 5)

+#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)

+

+/*

+It's an example for LZMA + x86 Filter use.

+You can use .lzma86 extension, if you write that stream to file.

+.lzma86 header adds one additional byte to standard .lzma header.

+.lzma86 header (14 bytes):

+  Offset Size  Description

+    0     1    = 0 - no filter, pure LZMA

+               = 1 - x86 filter + LZMA

+    1     1    lc, lp and pb in encoded form

+    2     4    dictSize (little endian)

+    6     8    uncompressed size (little endian)

+

+

+Lzma86_Encode

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

+level - compression level: 0 <= level <= 9, the default value for "level" is 5.

+

+dictSize - The dictionary size in bytes. The maximum value is

+        128 MB = (1 << 27) bytes for 32-bit version

+          1 GB = (1 << 30) bytes for 64-bit version

+     The default value is 16 MB = (1 << 24) bytes, for level = 5.

+     It's recommended to use the dictionary that is larger than 4 KB and

+     that can be calculated as (1 << N) or (3 << N) sizes.

+     For better compression ratio dictSize must be >= inSize.

+

+filterMode:

+    SZ_FILTER_NO   - no Filter

+    SZ_FILTER_YES  - x86 Filter

+    SZ_FILTER_AUTO - it tries both alternatives to select best.

+              Encoder will use 2 or 3 passes:

+              2 passes when FILTER_NO provides better compression.

+              3 passes when FILTER_YES provides better compression.

+

+Lzma86Encode allocates Data with MyAlloc functions.

+RAM Requirements for compressing:

+  RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize

+      filterMode     FilterBlockSize

+     SZ_FILTER_NO         0

+     SZ_FILTER_YES      inSize

+     SZ_FILTER_AUTO     inSize

+

+

+Return code:

+  SZ_OK               - OK

+  SZ_ERROR_MEM        - Memory allocation error

+  SZ_ERROR_PARAM      - Incorrect paramater

+  SZ_ERROR_OUTPUT_EOF - output buffer overflow

+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)

+*/

+

+enum ESzFilterMode

+{

+  SZ_FILTER_NO,

+  SZ_FILTER_YES,

+  SZ_FILTER_AUTO

+};

+

+SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,

+    int level, UInt32 dictSize, int filterMode);

+

+

+/*

+Lzma86_GetUnpackSize:

+  In:

+    src      - input data

+    srcLen   - input data size

+  Out:

+    unpackSize - size of uncompressed stream

+  Return code:

+    SZ_OK               - OK

+    SZ_ERROR_INPUT_EOF  - Error in headers

+*/

+

+SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize);

+

+/*

+Lzma86_Decode:

+  In:

+    dest     - output data

+    destLen  - output data size

+    src      - input data

+    srcLen   - input data size

+  Out:

+    destLen  - processed output size

+    srcLen   - processed input size

+  Return code:

+    SZ_OK           - OK

+    SZ_ERROR_DATA  - Data error

+    SZ_ERROR_MEM   - Memory allocation error

+    SZ_ERROR_UNSUPPORTED - unsupported file

+    SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer

+*/

+

+SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/Lzma86Dec.c b/lzma/C/Lzma86Dec.c
new file mode 100644
index 0000000..760a447
--- /dev/null
+++ b/lzma/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/lzma/C/Lzma86Enc.c b/lzma/C/Lzma86Enc.c
new file mode 100644
index 0000000..41b488c
--- /dev/null
+++ b/lzma/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] = (Byte)(bestIsFiltered ? 1 : 0);

+    *destLen = LZMA86_HEADER_SIZE + minSize;

+  }

+  if (useFilter)

+    MyFree(filteredStream);

+  return mainResult;

+}

diff --git a/lzma/C/LzmaDec.c b/lzma/C/LzmaDec.c
new file mode 100644
index 0000000..38cd9d6
--- /dev/null
+++ b/lzma/C/LzmaDec.c
@@ -0,0 +1,1025 @@
+/* LzmaDec.c -- LZMA Decoder

+2015-01-01 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#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 NORMAL_LITER_DEC GET_BIT(prob + symbol, symbol)

+#define MATCHED_LITER_DEC \

+  matchByte <<= 1; \

+  bit = (matchByte & offs); \

+  probLit = prob + offs + bit + symbol; \

+  GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)

+

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

+        #ifdef _LZMA_SIZE_OPT

+        do { NORMAL_LITER_DEC } while (symbol < 0x100);

+        #else

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        NORMAL_LITER_DEC

+        #endif

+      }

+      else

+      {

+        unsigned matchByte = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];

+        unsigned offs = 0x100;

+        state -= (state < 10) ? 3 : 6;

+        symbol = 1;

+        #ifdef _LZMA_SIZE_OPT

+        do

+        {

+          unsigned bit;

+          CLzmaProb *probLit;

+          MATCHED_LITER_DEC

+        }

+        while (symbol < 0x100);

+        #else

+        {

+          unsigned bit;

+          CLzmaProb *probLit;

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+          MATCHED_LITER_DEC

+        }

+        #endif

+      }

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

+    {

+      len--;

+      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 outSize = *destLen, inSize = *srcLen;

+  *destLen = *srcLen = 0;

+  *status = LZMA_STATUS_NOT_SPECIFIED;

+  if (inSize < RC_INIT_SIZE)

+    return SZ_ERROR_INPUT_EOF;

+  LzmaDec_Construct(&p);

+  RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc));

+  p.dic = dest;

+  p.dicBufSize = outSize;

+  LzmaDec_Init(&p);

+  *srcLen = inSize;

+  res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);

+  *destLen = p.dicPos;

+  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)

+    res = SZ_ERROR_INPUT_EOF;

+  LzmaDec_FreeProbs(&p, alloc);

+  return res;

+}

diff --git a/lzma/C/LzmaDec.h b/lzma/C/LzmaDec.h
new file mode 100644
index 0000000..2633abe
--- /dev/null
+++ b/lzma/C/LzmaDec.h
@@ -0,0 +1,227 @@
+/* LzmaDec.h -- LZMA Decoder

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA_DEC_H

+#define __LZMA_DEC_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+/* #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);

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/LzmaEnc.c b/lzma/C/LzmaEnc.c
new file mode 100644
index 0000000..40ee6a4
--- /dev/null
+++ b/lzma/C/LzmaEnc.c
@@ -0,0 +1,2278 @@
+/* LzmaEnc.c -- LZMA Encoder

+2014-12-29 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#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 unsigned g_STAT_OFFSET = 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->reduceSize = (UInt64)(Int64)-1;

+  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->dictSize > p->reduceSize)

+  {

+    unsigned i;

+    for (i = 11; i <= 30; i++)

+    {

+      if ((UInt32)p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }

+      if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }

+    }

+  }

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

+

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

+  {

+    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 || (unsigned)(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, unsigned 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

+  g_STAT_OFFSET += 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    ", g_STAT_OFFSET, numPairs / 2);

+  g_STAT_OFFSET++;

+  {

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

+  if (!RangeEnc_Alloc(&p->rc, alloc))

+    return SZ_ERROR_MEM;

+  #ifndef _7ZIP_ST

+  p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));

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

+  allocaDummy[0] = 0;

+  allocaDummy[1] = allocaDummy[0];

+  #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/lzma/C/LzmaEnc.h b/lzma/C/LzmaEnc.h
new file mode 100644
index 0000000..c2806b4
--- /dev/null
+++ b/lzma/C/LzmaEnc.h
@@ -0,0 +1,78 @@
+/*  LzmaEnc.h -- LZMA Encoder

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA_ENC_H

+#define __LZMA_ENC_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+#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) */

+  UInt64 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF.

+                        Encoder uses this value to reduce dictionary size */

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

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/LzmaLib.c b/lzma/C/LzmaLib.c
new file mode 100644
index 0000000..3e3cf40
--- /dev/null
+++ b/lzma/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/lzma/C/LzmaLib.h b/lzma/C/LzmaLib.h
new file mode 100644
index 0000000..5c35e53
--- /dev/null
+++ b/lzma/C/LzmaLib.h
@@ -0,0 +1,131 @@
+/* LzmaLib.h -- LZMA library interface

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA_LIB_H

+#define __LZMA_LIB_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

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

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/MtCoder.c b/lzma/C/MtCoder.c
new file mode 100644
index 0000000..303b435
--- /dev/null
+++ b/lzma/C/MtCoder.c
@@ -0,0 +1,329 @@
+/* MtCoder.c -- Multi-thread Coder

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

+

+#include "Precomp.h"

+

+#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/lzma/C/MtCoder.h b/lzma/C/MtCoder.h
new file mode 100644
index 0000000..705208e
--- /dev/null
+++ b/lzma/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/lzma/C/Ppmd.h b/lzma/C/Ppmd.h
new file mode 100644
index 0000000..25ce2d2
--- /dev/null
+++ b/lzma/C/Ppmd.h
@@ -0,0 +1,85 @@
+/* Ppmd.h -- PPMD codec common code

+2013-01-18 : Igor Pavlov : Public domain

+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

+

+#ifndef __PPMD_H

+#define __PPMD_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)

+

+#pragma pack(push, 1)

+/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */

+

+/* SEE-contexts for PPM-contexts with masked symbols */

+typedef struct

+{

+  UInt16 Summ; /* Freq */

+  Byte Shift;  /* Speed of Freq change; low Shift is for fast change */

+  Byte Count;  /* Count to next change of Shift */

+} CPpmd_See;

+

+#define Ppmd_See_Update(p)  if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \

+    { (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }

+

+typedef struct

+{

+  Byte Symbol;

+  Byte Freq;

+  UInt16 SuccessorLow;

+  UInt16 SuccessorHigh;

+} CPpmd_State;

+

+#pragma pack(pop)

+

+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/lzma/C/Ppmd7.c b/lzma/C/Ppmd7.c
new file mode 100644
index 0000000..798c118
--- /dev/null
+++ b/lzma/C/Ppmd7.c
@@ -0,0 +1,710 @@
+/* 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 "Precomp.h"

+

+#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/lzma/C/Ppmd7.h b/lzma/C/Ppmd7.h
new file mode 100644
index 0000000..56e81eb
--- /dev/null
+++ b/lzma/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/lzma/C/Ppmd7Dec.c b/lzma/C/Ppmd7Dec.c
new file mode 100644
index 0000000..3d01d76
--- /dev/null
+++ b/lzma/C/Ppmd7Dec.c
@@ -0,0 +1,189 @@
+/* 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 "Precomp.h"

+

+#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/lzma/C/Ppmd7Enc.c b/lzma/C/Ppmd7Enc.c
new file mode 100644
index 0000000..d82ea90
--- /dev/null
+++ b/lzma/C/Ppmd7Enc.c
@@ -0,0 +1,187 @@
+/* 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 "Precomp.h"

+

+#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/lzma/C/Precomp.h b/lzma/C/Precomp.h
new file mode 100644
index 0000000..edb5814
--- /dev/null
+++ b/lzma/C/Precomp.h
@@ -0,0 +1,10 @@
+/* Precomp.h -- StdAfx

+2013-11-12 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_PRECOMP_H

+#define __7Z_PRECOMP_H

+

+#include "Compiler.h"

+/* #include "7zTypes.h" */

+

+#endif

diff --git a/lzma/C/RotateDefs.h b/lzma/C/RotateDefs.h
new file mode 100644
index 0000000..ad7d164
--- /dev/null
+++ b/lzma/C/RotateDefs.h
@@ -0,0 +1,26 @@
+/* RotateDefs.h -- Rotate functions

+2013-11-12 : Igor Pavlov : Public domain */

+

+#ifndef __ROTATE_DEFS_H

+#define __ROTATE_DEFS_H

+

+#ifdef _MSC_VER

+

+#include <stdlib.h>

+

+// #if (_MSC_VER >= 1200)

+#pragma intrinsic(_rotl)

+#pragma intrinsic(_rotr)

+// #endif

+

+#define rotlFixed(x, n) _rotl((x), (n))

+#define rotrFixed(x, n) _rotr((x), (n))

+

+#else

+

+#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n))))

+#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n))))

+

+#endif

+

+#endif

diff --git a/lzma/C/Sha256.c b/lzma/C/Sha256.c
new file mode 100644
index 0000000..91208d3
--- /dev/null
+++ b/lzma/C/Sha256.c
@@ -0,0 +1,206 @@
+/* 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 "Precomp.h"

+

+#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/lzma/C/Sha256.h b/lzma/C/Sha256.h
new file mode 100644
index 0000000..7f17ccf
--- /dev/null
+++ b/lzma/C/Sha256.h
@@ -0,0 +1,26 @@
+/* Sha256.h -- SHA-256 Hash

+2013-01-18 : Igor Pavlov : Public domain */

+

+#ifndef __CRYPTO_SHA256_H

+#define __CRYPTO_SHA256_H

+

+#include "7zTypes.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/lzma/C/Sort.c b/lzma/C/Sort.c
new file mode 100644
index 0000000..73dcbf0
--- /dev/null
+++ b/lzma/C/Sort.c
@@ -0,0 +1,141 @@
+/* Sort.c -- Sort functions

+2014-04-05 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#include "Sort.h"

+

+#define HeapSortDown(p, k, size, temp) \

+  { for (;;) { \

+    size_t s = (k << 1); \

+    if (s > size) break; \

+    if (s < size && p[s + 1] > p[s]) s++; \

+    if (temp >= p[s]) break; \

+    p[k] = p[s]; k = s; \

+  } p[k] = temp; }

+

+void HeapSort(UInt32 *p, size_t size)

+{

+  if (size <= 1)

+    return;

+  p--;

+  {

+    size_t i = size / 2;

+    do

+    {

+      UInt32 temp = p[i];

+      size_t k = i;

+      HeapSortDown(p, k, size, temp)

+    }

+    while (--i != 0);

+  }

+  /*

+  do

+  {

+    size_t k = 1;

+    UInt32 temp = p[size];

+    p[size--] = p[1];

+    HeapSortDown(p, k, size, temp)

+  }

+  while (size > 1);

+  */

+  while (size > 3)

+  {

+    UInt32 temp = p[size];

+    size_t k = (p[3] > p[2]) ? 3 : 2;

+    p[size--] = p[1];

+    p[1] = p[k];

+    HeapSortDown(p, k, size, temp)

+  }

+  {

+    UInt32 temp = p[size];

+    p[size] = p[1];

+    if (size > 2 && p[2] < temp)

+    {

+      p[1] = p[2];

+      p[2] = temp;

+    }

+    else

+      p[1] = temp;

+  }

+}

+

+void HeapSort64(UInt64 *p, size_t size)

+{

+  if (size <= 1)

+    return;

+  p--;

+  {

+    size_t i = size / 2;

+    do

+    {

+      UInt64 temp = p[i];

+      size_t k = i;

+      HeapSortDown(p, k, size, temp)

+    }

+    while (--i != 0);

+  }

+  /*

+  do

+  {

+    size_t k = 1;

+    UInt64 temp = p[size];

+    p[size--] = p[1];

+    HeapSortDown(p, k, size, temp)

+  }

+  while (size > 1);

+  */

+  while (size > 3)

+  {

+    UInt64 temp = p[size];

+    size_t k = (p[3] > p[2]) ? 3 : 2;

+    p[size--] = p[1];

+    p[1] = p[k];

+    HeapSortDown(p, k, size, temp)

+  }

+  {

+    UInt64 temp = p[size];

+    p[size] = p[1];

+    if (size > 2 && p[2] < temp)

+    {

+      p[1] = p[2];

+      p[2] = temp;

+    }

+    else

+      p[1] = temp;

+  }

+}

+

+/*

+#define HeapSortRefDown(p, vals, n, size, temp) \

+  { size_t k = n; UInt32 val = vals[temp]; for (;;) { \

+    size_t s = (k << 1); \

+    if (s > size) break; \

+    if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \

+    if (val >= vals[p[s]]) break; \

+    p[k] = p[s]; k = s; \

+  } p[k] = temp; }

+

+void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size)

+{

+  if (size <= 1)

+    return;

+  p--;

+  {

+    size_t i = size / 2;

+    do

+    {

+      UInt32 temp = p[i];

+      HeapSortRefDown(p, vals, i, size, temp);

+    }

+    while (--i != 0);

+  }

+  do

+  {

+    UInt32 temp = p[size];

+    p[size--] = p[1];

+    HeapSortRefDown(p, vals, 1, size, temp);

+  }

+  while (size > 1);

+}

+*/

diff --git a/lzma/C/Sort.h b/lzma/C/Sort.h
new file mode 100644
index 0000000..7209d78
--- /dev/null
+++ b/lzma/C/Sort.h
@@ -0,0 +1,18 @@
+/* Sort.h -- Sort functions

+2014-04-05 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_SORT_H

+#define __7Z_SORT_H

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+void HeapSort(UInt32 *p, size_t size);

+void HeapSort64(UInt64 *p, size_t size);

+

+/* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/Threads.c b/lzma/C/Threads.c
new file mode 100644
index 0000000..18ba1e8
--- /dev/null
+++ b/lzma/C/Threads.c
@@ -0,0 +1,93 @@
+/* Threads.c -- multithreading library

+2013-11-12 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#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)

+{

+  /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */

+  

+  #ifdef UNDER_CE

+  

+  DWORD threadId;

+  *p = CreateThread(0, 0, func, param, 0, &threadId);

+

+  #else

+

+  unsigned threadId;

+  *p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);

+   

+  #endif

+

+  /* maybe we must use errno here, but probably GetLastError() is also OK. */

+  return HandleToWRes(*p);

+}

+

+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/lzma/C/Threads.h b/lzma/C/Threads.h
new file mode 100644
index 0000000..e927208
--- /dev/null
+++ b/lzma/C/Threads.h
@@ -0,0 +1,67 @@
+/* Threads.h -- multithreading library

+2013-11-12 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_THREADS_H

+#define __7Z_THREADS_H

+

+#ifdef _WIN32

+#include <windows.h>

+#endif

+

+#include "7zTypes.h"

+

+EXTERN_C_BEGIN

+

+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

+#ifdef UNDER_CE

+  DWORD

+#else

+  unsigned

+#endif

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

+

+EXTERN_C_END

+

+#endif

diff --git a/lzma/C/Util/7z/7z.dsp b/lzma/C/Util/7z/7z.dsp
new file mode 100644
index 0000000..73122f7
--- /dev/null
+++ b/lzma/C/Util/7z/7z.dsp
@@ -0,0 +1,229 @@
+# 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 /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /Yu"Precomp.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\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 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.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\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=..\..\7zArcIn.c

+# 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=..\..\7zStream.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zTypes.h

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

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Ppmd7.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Ppmd7Dec.c

+# End Source File

+# End Group

+# Begin Group "Spec"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\Compiler.h

+# End Source File

+# Begin Source File

+

+SOURCE=.\Precomp.c

+# ADD CPP /Yc"Precomp.h"

+# End Source File

+# Begin Source File

+

+SOURCE=.\Precomp.h

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=.\7zMain.c

+# End Source File

+# End Target

+# End Project

diff --git a/lzma/C/Util/7z/7z.dsw b/lzma/C/Util/7z/7z.dsw
new file mode 100644
index 0000000..23089fb
--- /dev/null
+++ b/lzma/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/lzma/C/Util/7z/7zMain.c b/lzma/C/Util/7z/7zMain.c
new file mode 100644
index 0000000..736a7fe
--- /dev/null
+++ b/lzma/C/Util/7z/7zMain.c
@@ -0,0 +1,546 @@
+/* 7zMain.c - Test application for 7z Decoder

+2015-01-02 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

+

+#include <stdio.h>

+#include <string.h>

+

+#include "../../7z.h"

+#include "../../7zAlloc.h"

+#include "../../7zBuf.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

+    #ifdef _WIN32

+    , UINT codePage

+    #endif

+    )

+{

+  unsigned len = 0;

+  for (len = 0; s[len] != 0; len++);

+

+  #ifdef _WIN32

+  {

+    unsigned size = len * 3 + 100;

+    if (!Buf_EnsureSize(buf, size))

+      return SZ_ERROR_MEM;

+    {

+      buf->data[0] = 0;

+      if (len != 0)

+      {

+        char defaultChar = '_';

+        BOOL defUsed;

+        unsigned numChars = 0;

+        numChars = WideCharToMultiByte(codePage, 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

+  return Utf16_To_Utf8Buf(buf, s, len);

+  #endif

+}

+

+#ifdef _WIN32

+  #ifndef USE_WINDOWS_FILE

+    static UINT g_FileCodePage = CP_ACP;

+  #endif

+  #define MY_FILE_CODE_PAGE_PARAM ,g_FileCodePage

+#else

+  #define MY_FILE_CODE_PAGE_PARAM

+#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 MY_FILE_CODE_PAGE_PARAM));

+

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

+  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

+      #ifdef _WIN32

+      , CP_OEMCP

+      #endif

+      );

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

+}

+

+static void UIntToStr_2(char *s, unsigned value)

+{

+  s[0] = (char)('0' + (value / 10));

+  s[1] = (char)('0' + (value % 10));

+}

+

+#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 *nt, char *s)

+{

+  unsigned year, mon, hour, min, sec;

+  Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

+  unsigned t;

+  UInt32 v;

+  UInt64 v64 = nt->Low | ((UInt64)nt->High << 32);

+  v64 /= 10000000;

+  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 = 0;; mon++)

+  {

+    unsigned s = ms[mon];

+    if (v < s)

+      break;

+    v -= s;

+  }

+  s = UIntToStr(s, year, 4); *s++ = '-';

+  UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3;

+  UIntToStr_2(s, (unsigned)v + 1); s[2] = ' '; s += 3;

+  UIntToStr_2(s, hour); s[2] = ':'; s += 3;

+  UIntToStr_2(s, min); s[2] = ':'; s += 3;

+  UIntToStr_2(s, sec); s[2] = 0;

+}

+

+void PrintError(const char *sz)

+{

+  printf("\nERROR: %s\n", sz);

+}

+

+#ifdef USE_WINDOWS_FILE

+static void GetAttribString(UInt32 wa, Bool isDir, char *s)

+{

+  s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.');

+  s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.');

+  s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN   ) != 0) ? 'H': '.');

+  s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM   ) != 0) ? 'S': '.');

+  s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE  ) != 0) ? 'A': '.');

+  s[5] = '\0';

+}

+#else

+static void GetAttribString(UInt32, Bool, char *s)

+{

+  s[0] = '\0';

+}

+#endif

+

+// #define NUM_PARENTS_MAX 128

+

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

+  // UInt32 parents[NUM_PARENTS_MAX];

+

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

+  }

+

+  #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE)

+  g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;

+  #endif

+

+  allocImp.Alloc = SzAlloc;

+  allocImp.Free = SzFree;

+

+  allocTempImp.Alloc = SzAllocTemp;

+  allocTempImp.Free = SzFreeTemp;

+

+  #ifdef UNDER_CE

+  if (InFile_OpenW(&archiveStream.file, L"\test.7z"))

+  #else

+  if (InFile_Open(&archiveStream.file, args[2]))

+  #endif

+  {

+    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, fullPaths = 0;

+    if (strcmp(command, "l") == 0) listCommand = 1;

+    else if (strcmp(command, "t") == 0) testCommand = 1;

+    else if (strcmp(command, "e") == 0) { }

+    else if (strcmp(command, "x") == 0) { 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.NumFiles; i++)

+      {

+        size_t offset = 0;

+        size_t outSizeProcessed = 0;

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

+        size_t len;

+        int isDir = SzArEx_IsDir(&db, i);

+        if (listCommand == 0 && isDir && !fullPaths)

+          continue;

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

+        // len = SzArEx_GetFullNameLen(&db, i);

+

+        if (len > tempSize)

+        {

+          SzFree(NULL, temp);

+          tempSize = len;

+          temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0]));

+          if (!temp)

+          {

+            res = SZ_ERROR_MEM;

+            break;

+          }

+        }

+

+        SzArEx_GetFileNameUtf16(&db, i, temp);

+        /*

+        if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp)

+        {

+          res = SZ_ERROR_FAIL;

+          break;

+        }

+        */

+

+        if (listCommand)

+        {

+          char attr[8], s[32], t[32];

+          UInt64 fileSize;

+

+          GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr);

+

+          fileSize = SzArEx_GetFileSize(&db, i);

+          UInt64ToStr(fileSize, s);

+          if (SzBitWithVals_Check(&db.MTime, i))

+            ConvertFileTimeToString(&db.MTime.Vals[i], 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 (isDir)

+            printf("/");

+          printf("\n");

+          continue;

+        }

+        fputs(testCommand ?

+            "Testing    ":

+            "Extracting ",

+            stdout);

+        res = PrintString(temp);

+        if (res != SZ_OK)

+          break;

+        if (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 (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 (SzBitWithVals_Check(&db.Attribs, i))

+            SetFileAttributesW(destPath, db.Attribs.Vals[i]);

+          #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/lzma/C/Util/7z/Precomp.c b/lzma/C/Util/7z/Precomp.c
new file mode 100644
index 0000000..34b60f8
--- /dev/null
+++ b/lzma/C/Util/7z/Precomp.c
@@ -0,0 +1,4 @@
+/* Precomp.c -- StdAfx

+2013-01-21 : Igor Pavlov : Public domain */

+

+#include "Precomp.h"

diff --git a/lzma/C/Util/7z/Precomp.h b/lzma/C/Util/7z/Precomp.h
new file mode 100644
index 0000000..9f398d0
--- /dev/null
+++ b/lzma/C/Util/7z/Precomp.h
@@ -0,0 +1,10 @@
+/* Precomp.h -- StdAfx

+2013-06-16 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_PRECOMP_H

+#define __7Z_PRECOMP_H

+

+#include "../../Compiler.h"

+#include "../../7zTypes.h"

+

+#endif

diff --git a/lzma/C/Util/7z/makefile b/lzma/C/Util/7z/makefile
new file mode 100644
index 0000000..08e6f68
--- /dev/null
+++ b/lzma/C/Util/7z/makefile
@@ -0,0 +1,39 @@
+# MY_STATIC_LINK=1

+CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT

+

+PROG = 7zDec.exe

+

+C_OBJS = \

+  $O\7zAlloc.obj \

+  $O\7zBuf.obj \

+  $O\7zCrc.obj \

+  $O\7zCrcOpt.obj \

+  $O\7zFile.obj \

+  $O\7zDec.obj \

+  $O\7zArcIn.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 = \

+  $O\Precomp.obj \

+  $(7Z_OBJS) \

+  $(C_OBJS) \

+

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

+

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

+	$(CCOMPL_USE)

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

+	$(CCOMPL_USE)

+$O\Precomp.obj: Precomp.c

+	$(CCOMPL_PCH)

diff --git a/lzma/C/Util/7z/makefile.gcc b/lzma/C/Util/7z/makefile.gcc
new file mode 100644
index 0000000..63c59ca
--- /dev/null
+++ b/lzma/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 7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.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

+

+7zArcIn.o: ../../7zArcIn.c

+	$(CXX) $(CFLAGS) ../../7zArcIn.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

+

+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/lzma/C/Util/Lzma/LzmaUtil.c b/lzma/C/Util/Lzma/LzmaUtil.c
new file mode 100644
index 0000000..ee659ba
--- /dev/null
+++ b/lzma/C/Util/Lzma/LzmaUtil.c
@@ -0,0 +1,254 @@
+/* LzmaUtil.c -- Test application for LZMA compression

+2014-12-31 : Igor Pavlov : Public domain */

+

+#include "../../Precomp.h"

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>