Compare commits

...

43 Commits
4.63 ... 18.03

Author SHA1 Message Date
Igor Pavlov
f19b649c73 18.03 2018-03-12 11:19:46 +00:00
Igor Pavlov
866a06f5a0 18.01 2018-01-30 00:35:06 +00:00
Igor Pavlov
da28077952 18.00 2018-01-11 22:16:32 +01:00
Igor Pavlov
b5dc853b24 17.01 2017-08-29 20:49:43 +01:00
Igor Pavlov
2efa10565a 17.00 2017-05-05 18:56:20 +01:00
Igor Pavlov
603abd5528 16.04 2016-12-08 12:13:50 +00:00
Igor Pavlov
232ce79574 16.03 2016-12-08 12:12:54 +00:00
Igor Pavlov
1eddf527ca 16.02 2016-05-28 00:17:00 +01:00
Igor Pavlov
bec3b479dc 16.01 2016-05-28 00:16:59 +01:00
Igor Pavlov
66ac98bb02 16.00 2016-05-28 00:16:59 +01:00
Igor Pavlov
c20d013055 15.14 2016-05-28 00:16:58 +01:00
Igor Pavlov
9608215ad8 15.13 2016-05-28 00:16:58 +01:00
Igor Pavlov
5de23c1deb 15.12 2016-05-28 00:16:58 +01:00
Igor Pavlov
e24f7fba53 15.11 2016-05-28 00:16:57 +01:00
Igor Pavlov
7c8a265a15 15.10 2016-05-28 00:16:57 +01:00
Igor Pavlov
a663a6deb7 15.09 2016-05-28 00:16:56 +01:00
Igor Pavlov
6543c28020 15.08 2016-05-28 00:16:56 +01:00
Igor Pavlov
f6444c3256 15.07 2016-05-28 00:16:55 +01:00
Igor Pavlov
cba375916f 15.06 2016-05-28 00:16:55 +01:00
Igor Pavlov
54490d51d5 15.05 2016-05-28 00:16:54 +01:00
Igor Pavlov
0713a3ab80 9.38 2016-05-28 00:16:53 +01:00
Igor Pavlov
7e021179cd 9.36 2016-05-28 00:16:53 +01:00
Igor Pavlov
0dc16c691d 9.35 2016-05-28 00:16:53 +01:00
Igor Pavlov
f08f4dcc3c 9.34 2016-05-28 00:16:51 +01:00
Igor Pavlov
83f8ddcc5b 9.22 2016-05-28 00:16:06 +01:00
Igor Pavlov
35596517f2 9.21 2016-05-28 00:16:05 +01:00
Igor Pavlov
de4f8c22fe 9.20 2016-05-28 00:16:05 +01:00
Igor Pavlov
b75af1bba6 9.19 2016-05-28 00:16:04 +01:00
Igor Pavlov
c65230d858 9.18 2016-05-28 00:16:04 +01:00
Igor Pavlov
2eb60a0598 9.17 2016-05-28 00:16:04 +01:00
Igor Pavlov
044e4bb741 9.16 2016-05-28 00:16:03 +01:00
Igor Pavlov
e279500d76 9.15 2016-05-28 00:16:03 +01:00
Igor Pavlov
708873490e 9.14 2016-05-28 00:16:03 +01:00
Igor Pavlov
3dacb5eb8a 9.13 2016-05-28 00:16:03 +01:00
Igor Pavlov
76b173af78 9.12 2016-05-28 00:16:02 +01:00
Igor Pavlov
993daef9cb 9.11 2016-05-28 00:16:02 +01:00
Igor Pavlov
db5eb6d638 9.10 beta 2016-05-28 00:16:02 +01:00
Igor Pavlov
1fbaf0aac5 9.09 beta 2016-05-28 00:16:01 +01:00
Igor Pavlov
2fed872194 9.07 beta 2016-05-28 00:16:01 +01:00
Igor Pavlov
c99f3ebdd6 9.06 beta 2016-05-28 00:16:00 +01:00
Igor Pavlov
829409452d 9.04 beta 2016-05-28 00:15:59 +01:00
Igor Pavlov
8874e4fbc9 4.65 2016-05-28 00:15:59 +01:00
Igor Pavlov
1dc92281fa 4.64 2016-05-28 00:15:59 +01:00
1343 changed files with 198205 additions and 70701 deletions

100
Asm/arm/7zCrcOpt.asm Normal file
View File

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

View File

@@ -1,101 +0,0 @@
.code
CRC1b macro
movzx EDX, BYTE PTR [RSI]
inc RSI
movzx EBX, AL
xor EDX, EBX
shr EAX, 8
xor EAX, [RDI + RDX * 4]
dec R8
endm
align 16
CrcUpdateT8 PROC
push RBX
push RSI
push RDI
push RBP
mov EAX, ECX
mov RSI, RDX
mov RDI, R9
test R8, R8
jz sl_end
sl:
test RSI, 7
jz sl_end
CRC1b
jnz sl
sl_end:
cmp R8, 16
jb crc_end
mov R9, R8
and R8, 7
add R8, 8
sub R9, R8
add R9, RSI
xor EAX, [RSI]
mov EBX, [RSI + 4]
movzx ECX, BL
align 16
main_loop:
mov EDX, [RDI + RCX*4 + 0C00h]
movzx EBP, BH
xor EDX, [RDI + RBP*4 + 0800h]
shr EBX, 16
movzx ECX, BL
xor EDX, [RSI + 8]
xor EDX, [RDI + RCX*4 + 0400h]
movzx ECX, AL
movzx EBP, BH
xor EDX, [RDI + RBP*4 + 0000h]
mov EBX, [RSI + 12]
xor EDX, [RDI + RCX*4 + 01C00h]
movzx EBP, AH
shr EAX, 16
movzx ECX, AL
xor EDX, [RDI + RBP*4 + 01800h]
movzx EBP, AH
mov EAX, [RDI + RCX*4 + 01400h]
add RSI, 8
xor EAX, [RDI + RBP*4 + 01000h]
movzx ECX, BL
xor EAX,EDX
cmp RSI, R9
jne main_loop
xor EAX, [RSI]
crc_end:
test R8, R8
jz fl_end
fl:
CRC1b
jnz fl
fl_end:
pop RBP
pop RDI
pop RSI
pop RBX
ret
CrcUpdateT8 ENDP
end

147
Asm/x86/7zAsm.asm Normal file
View File

@@ -0,0 +1,147 @@
; 7zAsm.asm -- ASM macros
; 2018-02-03 : 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_W equ AX
x1_W equ CX
x2_W equ DX
x3_W equ BX
x5_W equ BP
x6_W equ SI
x7_W equ DI
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
x5_L equ BPL
x6_L equ SIL
x7_L equ DIL
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
ifdef x64
; for WIN64-x64 ABI:
REG_PARAM_0 equ r1
REG_PARAM_1 equ r2
REG_PARAM_2 equ r8
REG_PARAM_3 equ r9
MY_PUSH_PRESERVED_REGS macro
MY_PUSH_4_REGS
push r12
push r13
push r14
push r15
endm
MY_POP_PRESERVED_REGS macro
pop r15
pop r14
pop r13
pop r12
MY_POP_4_REGS
endm
endif

147
Asm/x86/7zCrcOpt.asm Normal file
View File

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

View File

@@ -1,101 +0,0 @@
.386
.model flat
_TEXT$00 SEGMENT PARA PUBLIC 'CODE'
CRC1b macro
movzx EDX, BYTE PTR [ESI]
inc ESI
movzx EBX, AL
xor EDX, EBX
shr EAX, 8
xor EAX, [EBP + EDX * 4]
dec EDI
endm
data_size equ (4 + 4*4)
crc_table equ (data_size + 4)
align 16
public @CrcUpdateT8@16
@CrcUpdateT8@16:
push EBX
push ESI
push EDI
push EBP
mov EAX, ECX
mov ESI, EDX
mov EDI, [ESP + data_size]
mov EBP, [ESP + crc_table]
test EDI, EDI
jz sl_end
sl:
test ESI, 7
jz sl_end
CRC1b
jnz sl
sl_end:
cmp EDI, 16
jb crc_end
mov [ESP + data_size], EDI
sub EDI, 8
and EDI, NOT 7
sub [ESP + data_size], EDI
add EDI, ESI
xor EAX, [ESI]
mov EBX, [ESI + 4]
movzx ECX, BL
align 16
main_loop:
mov EDX, [EBP + ECX*4 + 0C00h]
movzx ECX, BH
xor EDX, [EBP + ECX*4 + 0800h]
shr EBX, 16
movzx ECX, BL
xor EDX, [EBP + ECX*4 + 0400h]
xor EDX, [ESI + 8]
movzx ECX, AL
movzx EBX, BH
xor EDX, [EBP + EBX*4 + 0000h]
mov EBX, [ESI + 12]
xor EDX, [EBP + ECX*4 + 01C00h]
movzx ECX, AH
add ESI, 8
shr EAX, 16
xor EDX, [EBP + ECX*4 + 01800h]
movzx ECX, AL
xor EDX, [EBP + ECX*4 + 01400h]
movzx ECX, AH
mov EAX, [EBP + ECX*4 + 01000h]
movzx ECX, BL
xor EAX,EDX
cmp ESI, EDI
jne main_loop
xor EAX, [ESI]
mov EDI, [ESP + data_size]
crc_end:
test EDI, EDI
jz fl_end
fl:
CRC1b
jnz fl
fl_end:
pop EBP
pop EDI
pop ESI
pop EBX
ret 8
end

237
Asm/x86/AesOpt.asm Normal file
View File

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

1258
Asm/x86/LzmaDecOpt.asm Normal file
View File

File diff suppressed because it is too large Load Diff

205
Asm/x86/XzCrc64Opt.asm Normal file
View File

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

202
C/7z.h Normal file
View File

@@ -0,0 +1,202 @@
/* 7z.h -- 7z interface
2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_H
#define __7Z_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define k7zStartHeaderSize 0x20
#define k7zSignatureSize 6
extern const 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 NumStreams;
Byte PropsSize;
} CSzCoderInfo;
typedef struct
{
UInt32 InIndex;
UInt32 OutIndex;
} CSzBond;
#define SZ_NUM_CODERS_IN_FOLDER_MAX 4
#define SZ_NUM_BONDS_IN_FOLDER_MAX 3
#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4
typedef struct
{
UInt32 NumCoders;
UInt32 NumBonds;
UInt32 NumPackStreams;
UInt32 UnpackStream;
UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
} CSzFolder;
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd);
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; // NumFolders
size_t *FoCodersOffsets; // NumFolders + 1
UInt32 *FoStartPackStreamIndex; // NumFolders + 1
UInt32 *FoToCoderUnpackSizes; // NumFolders + 1
Byte *FoToMainUnpackSizeIndex; // NumFolders
UInt64 *CoderUnpackSizes; // for all coders in all folders
Byte *CodersData;
} CSzAr;
UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize,
ISzAllocPtr allocMain);
typedef struct
{
CSzAr db;
UInt64 startPosAfterHeader;
UInt64 dataPos;
UInt32 NumFiles;
UInt64 *UnpackPositions; // NumFiles + 1
// Byte *IsEmptyFiles;
Byte *IsDirs;
CSzBitUi32s CRCs;
CSzBitUi32s Attribs;
// CSzBitUi32s Parents;
CSzBitUi64s MTime;
CSzBitUi64s CTime;
UInt32 *FolderToFile; // NumFolders + 1
UInt32 *FileToFolder; // NumFiles
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, ISzAllocPtr 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);
*/
/*
SzArEx_Extract 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.
*/
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 */
ISzAllocPtr allocMain,
ISzAllocPtr 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,
ISzAllocPtr allocMain, ISzAllocPtr allocTemp);
EXTERN_C_END
#endif

25
C/Archive/7z/7zAlloc.c → C/7zAlloc.c Executable file → Normal file
View File

@@ -1,7 +1,10 @@
/* 7zAlloc.c -- Allocation functions /* 7zAlloc.c -- Allocation functions
2008-10-04 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include <stdlib.h> #include <stdlib.h>
#include "7zAlloc.h" #include "7zAlloc.h"
/* #define _SZ_ALLOC_DEBUG */ /* #define _SZ_ALLOC_DEBUG */
@@ -19,21 +22,21 @@ int g_allocCountTemp = 0;
#endif #endif
void *SzAlloc(void *p, size_t size) void *SzAlloc(ISzAllocPtr p, size_t size)
{ {
p = p; UNUSED_VAR(p);
if (size == 0) if (size == 0)
return 0; return 0;
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); fprintf(stderr, "\nAlloc %10u bytes; count = %10d", (unsigned)size, g_allocCount);
g_allocCount++; g_allocCount++;
#endif #endif
return malloc(size); return malloc(size);
} }
void SzFree(void *p, void *address) void SzFree(ISzAllocPtr p, void *address)
{ {
p = p; UNUSED_VAR(p);
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
if (address != 0) if (address != 0)
{ {
@@ -44,13 +47,13 @@ void SzFree(void *p, void *address)
free(address); free(address);
} }
void *SzAllocTemp(void *p, size_t size) void *SzAllocTemp(ISzAllocPtr p, size_t size)
{ {
p = p; UNUSED_VAR(p);
if (size == 0) if (size == 0)
return 0; return 0;
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); fprintf(stderr, "\nAlloc_temp %10u bytes; count = %10d", (unsigned)size, g_allocCountTemp);
g_allocCountTemp++; g_allocCountTemp++;
#ifdef _WIN32 #ifdef _WIN32
return HeapAlloc(GetProcessHeap(), 0, size); return HeapAlloc(GetProcessHeap(), 0, size);
@@ -59,9 +62,9 @@ void *SzAllocTemp(void *p, size_t size)
return malloc(size); return malloc(size);
} }
void SzFreeTemp(void *p, void *address) void SzFreeTemp(ISzAllocPtr p, void *address)
{ {
p = p; UNUSED_VAR(p);
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
if (address != 0) if (address != 0)
{ {

19
C/7zAlloc.h Normal file
View File

@@ -0,0 +1,19 @@
/* 7zAlloc.h -- Allocation functions
2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H
#include "7zTypes.h"
EXTERN_C_BEGIN
void *SzAlloc(ISzAllocPtr p, size_t size);
void SzFree(ISzAllocPtr p, void *address);
void *SzAllocTemp(ISzAllocPtr p, size_t size);
void SzFreeTemp(ISzAllocPtr p, void *address);
EXTERN_C_END
#endif

1771
C/7zArcIn.c Normal file
View File

File diff suppressed because it is too large Load Diff

16
C/7zBuf.c Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* 7zBuf.c -- Byte Buffer /* 7zBuf.c -- Byte Buffer
2008-03-28 2017-04-03 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */ #include "Precomp.h"
#include "7zBuf.h" #include "7zBuf.h"
@@ -11,7 +11,7 @@ void Buf_Init(CBuf *p)
p->size = 0; p->size = 0;
} }
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc)
{ {
p->size = 0; p->size = 0;
if (size == 0) if (size == 0)
@@ -19,8 +19,8 @@ int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
p->data = 0; p->data = 0;
return 1; return 1;
} }
p->data = (Byte *)alloc->Alloc(alloc, size); p->data = (Byte *)ISzAlloc_Alloc(alloc, size);
if (p->data != 0) if (p->data)
{ {
p->size = size; p->size = size;
return 1; return 1;
@@ -28,9 +28,9 @@ int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
return 0; return 0;
} }
void Buf_Free(CBuf *p, ISzAlloc *alloc) void Buf_Free(CBuf *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->data); ISzAlloc_Free(alloc, p->data);
p->data = 0; p->data = 0;
p->size = 0; p->size = 0;
} }

16
C/7zBuf.h Executable file → Normal file
View File

@@ -1,10 +1,12 @@
/* 7zBuf.h -- Byte Buffer /* 7zBuf.h -- Byte Buffer
2008-10-04 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_BUF_H #ifndef __7Z_BUF_H
#define __7Z_BUF_H #define __7Z_BUF_H
#include "Types.h" #include "7zTypes.h"
EXTERN_C_BEGIN
typedef struct typedef struct
{ {
@@ -13,8 +15,8 @@ typedef struct
} CBuf; } CBuf;
void Buf_Init(CBuf *p); void Buf_Init(CBuf *p);
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc);
void Buf_Free(CBuf *p, ISzAlloc *alloc); void Buf_Free(CBuf *p, ISzAllocPtr alloc);
typedef struct typedef struct
{ {
@@ -25,7 +27,9 @@ typedef struct
void DynBuf_Construct(CDynBuf *p); void DynBuf_Construct(CDynBuf *p);
void DynBuf_SeekToBeg(CDynBuf *p); void DynBuf_SeekToBeg(CDynBuf *p);
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc);
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc);
EXTERN_C_END
#endif #endif

27
C/7zBuf2.c Executable file → Normal file
View File

@@ -1,7 +1,10 @@
/* 7zBuf2.c -- Byte Buffer /* 7zBuf2.c -- Byte Buffer
2008-10-04 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include <string.h> #include <string.h>
#include "7zBuf.h" #include "7zBuf.h"
void DynBuf_Construct(CDynBuf *p) void DynBuf_Construct(CDynBuf *p)
@@ -16,29 +19,33 @@ void DynBuf_SeekToBeg(CDynBuf *p)
p->pos = 0; p->pos = 0;
} }
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc) int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc)
{ {
if (size > p->size - p->pos) if (size > p->size - p->pos)
{ {
size_t newSize = p->pos + size; size_t newSize = p->pos + size;
Byte *data; Byte *data;
newSize += newSize / 4; newSize += newSize / 4;
data = (Byte *)alloc->Alloc(alloc, newSize); data = (Byte *)ISzAlloc_Alloc(alloc, newSize);
if (data == 0) if (!data)
return 0; return 0;
p->size = newSize; p->size = newSize;
memcpy(data, p->data, p->pos); if (p->pos != 0)
alloc->Free(alloc, p->data); memcpy(data, p->data, p->pos);
ISzAlloc_Free(alloc, p->data);
p->data = data; p->data = data;
} }
memcpy(p->data + p->pos, buf, size); if (size != 0)
p->pos += size; {
memcpy(p->data + p->pos, buf, size);
p->pos += size;
}
return 1; return 1;
} }
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc) void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->data); ISzAlloc_Free(alloc, p->data);
p->data = 0; p->data = 0;
p->size = 0; p->size = 0;
p->pos = 0; p->pos = 0;

131
C/7zCrc.c Executable file → Normal file
View File

@@ -1,35 +1,128 @@
/* 7zCrc.c -- CRC32 calculation /* 7zCrc.c -- CRC32 init
2008-08-05 2017-06-06 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */ #include "Precomp.h"
#include "7zCrc.h" #include "7zCrc.h"
#include "CpuArch.h"
#define kCrcPoly 0xEDB88320 #define kCrcPoly 0xEDB88320
UInt32 g_CrcTable[256];
void MY_FAST_CALL CrcGenerateTable(void) #ifdef MY_CPU_LE
#define CRC_NUM_TABLES 8
#else
#define CRC_NUM_TABLES 9
#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);
UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(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);
UInt32 MY_FAST_CALL CrcUpdateT8(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_CrcUpdateT4;
CRC_FUNC g_CrcUpdateT8;
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;
}
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
const Byte *pEnd = p + size;
for (; p != pEnd; p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
void MY_FAST_CALL CrcGenerateTable()
{ {
UInt32 i; UInt32 i;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
UInt32 r = i; UInt32 r = i;
int j; unsigned j;
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
g_CrcTable[i] = r; g_CrcTable[i] = r;
} }
} for (i = 256; i < 256 * CRC_NUM_TABLES; i++)
{
UInt32 r = g_CrcTable[(size_t)i - 256];
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
}
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) #if CRC_NUM_TABLES < 4
{
const Byte *p = (const Byte *)data;
for (; size > 0 ; size--, p++)
v = CRC_UPDATE_BYTE(v, *p);
return v;
}
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) g_CrcUpdate = CrcUpdateT1;
{
return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; #else
#ifdef MY_CPU_LE
g_CrcUpdateT4 = CrcUpdateT4;
g_CrcUpdate = CrcUpdateT4;
#if CRC_NUM_TABLES >= 8
g_CrcUpdateT8 = CrcUpdateT8;
#ifdef MY_CPU_X86_OR_AMD64
if (!CPU_Is_InOrder())
#endif
g_CrcUpdate = CrcUpdateT8;
#endif
#else
{
#ifndef MY_CPU_BE
UInt32 k = 0x01020304;
const Byte *p = (const Byte *)&k;
if (p[0] == 4 && p[1] == 3)
{
g_CrcUpdateT4 = CrcUpdateT4;
g_CrcUpdate = CrcUpdateT4;
#if CRC_NUM_TABLES >= 8
g_CrcUpdateT8 = CrcUpdateT8;
g_CrcUpdate = CrcUpdateT8;
#endif
}
else if (p[0] != 1 || p[1] != 2)
g_CrcUpdate = CrcUpdateT1;
else
#endif
{
for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
{
UInt32 x = g_CrcTable[(size_t)i - 256];
g_CrcTable[i] = CRC_UINT32_SWAP(x);
}
g_CrcUpdateT4 = CrcUpdateT1_BeT4;
g_CrcUpdate = CrcUpdateT1_BeT4;
#if CRC_NUM_TABLES >= 8
g_CrcUpdateT8 = CrcUpdateT1_BeT8;
g_CrcUpdate = CrcUpdateT1_BeT8;
#endif
}
}
#endif
#endif
} }

13
C/7zCrc.h Executable file → Normal file
View File

@@ -1,24 +1,25 @@
/* 7zCrc.h -- CRC32 calculation /* 7zCrc.h -- CRC32 calculation
2008-03-13 2013-01-18 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __7Z_CRC_H #ifndef __7Z_CRC_H
#define __7Z_CRC_H #define __7Z_CRC_H
#include <stddef.h> #include "7zTypes.h"
#include "Types.h" EXTERN_C_BEGIN
extern UInt32 g_CrcTable[]; extern UInt32 g_CrcTable[];
/* Call CrcGenerateTable one time before other CRC functions */
void MY_FAST_CALL CrcGenerateTable(void); void MY_FAST_CALL CrcGenerateTable(void);
#define CRC_INIT_VAL 0xFFFFFFFF #define CRC_INIT_VAL 0xFFFFFFFF
#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) #define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #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 CrcUpdate(UInt32 crc, const void *data, size_t size);
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
EXTERN_C_END
#endif #endif

115
C/7zCrcOpt.c Normal file
View File

@@ -0,0 +1,115 @@
/* 7zCrcOpt.c -- CRC32 calculation
2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "CpuArch.h"
#ifndef MY_CPU_BE
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
for (; size >= 4; size -= 4, p += 4)
{
v ^= *(const UInt32 *)p;
v =
(table + 0x300)[((v ) & 0xFF)]
^ (table + 0x200)[((v >> 8) & 0xFF)]
^ (table + 0x100)[((v >> 16) & 0xFF)]
^ (table + 0x000)[((v >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
for (; size >= 8; size -= 8, p += 8)
{
UInt32 d;
v ^= *(const UInt32 *)p;
v =
(table + 0x700)[((v ) & 0xFF)]
^ (table + 0x600)[((v >> 8) & 0xFF)]
^ (table + 0x500)[((v >> 16) & 0xFF)]
^ (table + 0x400)[((v >> 24))];
d = *((const UInt32 *)p + 1);
v ^=
(table + 0x300)[((d ) & 0xFF)]
^ (table + 0x200)[((d >> 8) & 0xFF)]
^ (table + 0x100)[((d >> 16) & 0xFF)]
^ (table + 0x000)[((d >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
#endif
#ifndef MY_CPU_LE
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8))
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
table += 0x100;
v = CRC_UINT32_SWAP(v);
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p);
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))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p);
return CRC_UINT32_SWAP(v);
}
UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
table += 0x100;
v = CRC_UINT32_SWAP(v);
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p);
for (; size >= 8; size -= 8, p += 8)
{
UInt32 d;
v ^= *(const UInt32 *)p;
v =
(table + 0x400)[((v ) & 0xFF)]
^ (table + 0x500)[((v >> 8) & 0xFF)]
^ (table + 0x600)[((v >> 16) & 0xFF)]
^ (table + 0x700)[((v >> 24))];
d = *((const UInt32 *)p + 1);
v ^=
(table + 0x000)[((d ) & 0xFF)]
^ (table + 0x100)[((d >> 8) & 0xFF)]
^ (table + 0x200)[((d >> 16) & 0xFF)]
^ (table + 0x300)[((d >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p);
return CRC_UINT32_SWAP(v);
}
#endif

View File

@@ -1,43 +0,0 @@
/* 7zCrcT8.c -- CRC32 calculation with 8 tables
2008-03-19
Igor Pavlov
Public domain */
#include "7zCrc.h"
#define kCrcPoly 0xEDB88320
#define CRC_NUM_TABLES 8
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
void MY_FAST_CALL CrcGenerateTable()
{
UInt32 i;
for (i = 0; i < 256; i++)
{
UInt32 r = i;
int j;
for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
g_CrcTable[i] = r;
}
#if CRC_NUM_TABLES > 1
for (; i < 256 * CRC_NUM_TABLES; i++)
{
UInt32 r = g_CrcTable[i - 256];
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
}
#endif
}
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
{
return CrcUpdateT8(v, data, size, g_CrcTable);
}
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
{
return CrcUpdateT8(CRC_INIT_VAL, data, size, g_CrcTable) ^ 0xFFFFFFFF;
}

591
C/7zDec.c Normal file
View File

@@ -0,0 +1,591 @@
/* 7zDec.c -- Decoding from 7z folder
2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include <string.h>
/* #define _7ZIP_PPMD_SUPPPORT */
#include "7z.h"
#include "7zCrc.h"
#include "Bcj2.h"
#include "Bra.h"
#include "CpuArch.h"
#include "Delta.h"
#include "LzmaDec.h"
#include "Lzma2Dec.h"
#ifdef _7ZIP_PPMD_SUPPPORT
#include "Ppmd7.h"
#endif
#define k_Copy 0
#define k_Delta 3
#define k_LZMA2 0x21
#define k_LZMA 0x30101
#define k_BCJ 0x3030103
#define k_BCJ2 0x303011B
#define k_PPC 0x3030205
#define k_IA64 0x3030401
#define k_ARM 0x3030501
#define k_ARMT 0x3030701
#define k_SPARC 0x3030805
#ifdef _7ZIP_PPMD_SUPPPORT
#define k_PPMD 0x30401
typedef struct
{
IByteIn vt;
const Byte *cur;
const Byte *end;
const Byte *begin;
UInt64 processed;
Bool extra;
SRes res;
const ILookInStream *inStream;
} CByteInToLook;
static Byte ReadByte(const IByteIn *pp)
{
CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt);
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 = ILookInStream_Skip(p->inStream, size);
size = (1 << 25);
p->res = ILookInStream_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, const ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
{
CPpmd7 ppmd;
CByteInToLook s;
SRes res = SZ_OK;
s.vt.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.vt;
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.vt);
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, ISzAllocPtr 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 (;;)
{
const void *inBuf = NULL;
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
res = ILookInStream_Look(inStream, &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 (status == LZMA_STATUS_FINISHED_WITH_MARK)
{
if (outSize != state.dicPos || inSize != 0)
res = SZ_ERROR_DATA;
break;
}
if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
break;
if (inProcessed == 0 && dicPos == state.dicPos)
{
res = SZ_ERROR_DATA;
break;
}
res = ILookInStream_Skip(inStream, inProcessed);
if (res != SZ_OK)
break;
}
}
LzmaDec_FreeProbs(&state, allocMain);
return res;
}
#ifndef _7Z_NO_METHOD_LZMA2
static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAllocPtr 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 (;;)
{
const void *inBuf = NULL;
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
res = ILookInStream_Look(inStream, &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 (status == LZMA_STATUS_FINISHED_WITH_MARK)
{
if (outSize != state.decoder.dicPos || inSize != 0)
res = SZ_ERROR_DATA;
break;
}
if (inProcessed == 0 && dicPos == state.decoder.dicPos)
{
res = SZ_ERROR_DATA;
break;
}
res = ILookInStream_Skip(inStream, inProcessed);
if (res != SZ_OK)
break;
}
}
Lzma2Dec_FreeProbs(&state, allocMain);
return res;
}
#endif
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
{
while (inSize > 0)
{
const void *inBuf;
size_t curSize = (1 << 18);
if (curSize > inSize)
curSize = (size_t)inSize;
RINOK(ILookInStream_Look(inStream, &inBuf, &curSize));
if (curSize == 0)
return SZ_ERROR_INPUT_EOF;
memcpy(outBuffer, inBuf, curSize);
outBuffer += curSize;
inSize -= curSize;
RINOK(ILookInStream_Skip(inStream, curSize));
}
return SZ_OK;
}
static Bool IS_MAIN_METHOD(UInt32 m)
{
switch (m)
{
case k_Copy:
case k_LZMA:
#ifndef _7Z_NO_METHOD_LZMA2
case k_LZMA2:
#endif
#ifdef _7ZIP_PPMD_SUPPPORT
case k_PPMD:
#endif
return True;
}
return False;
}
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
{
return
c->NumStreams == 1
/* && c->MethodID <= (UInt32)0xFFFFFFFF */
&& IS_MAIN_METHOD((UInt32)c->MethodID);
}
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4)
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->NumBonds != 0)
return SZ_ERROR_UNSUPPORTED;
return SZ_OK;
}
#ifndef _7Z_NO_METHODS_FILTERS
if (f->NumCoders == 2)
{
const CSzCoderInfo *c = &f->Coders[1];
if (
/* c->MethodID > (UInt32)0xFFFFFFFF || */
c->NumStreams != 1
|| f->NumPackStreams != 1
|| f->PackStreams[0] != 0
|| f->NumBonds != 1
|| f->Bonds[0].InIndex != 1
|| f->Bonds[0].OutIndex != 0)
return SZ_ERROR_UNSUPPORTED;
switch ((UInt32)c->MethodID)
{
case k_Delta:
case k_BCJ:
case k_PPC:
case k_IA64:
case k_SPARC:
case k_ARM:
case k_ARMT:
break;
default:
return SZ_ERROR_UNSUPPORTED;
}
return SZ_OK;
}
#endif
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->NumBonds != 3
|| f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0
|| f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1
|| f->Bonds[2].InIndex != 3 || f->Bonds[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, ISzAllocPtr 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 *)ISzAlloc_Alloc(allocMain, outSizeCur);
if (!temp && 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[(size_t)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));
}
#ifndef _7Z_NO_METHOD_LZMA2
else if (coder->MethodID == k_LZMA2)
{
RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
#endif
#ifdef _7ZIP_PPMD_SUPPPORT
else if (coder->MethodID == k_PPMD)
{
RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
#endif
else
return SZ_ERROR_UNSUPPORTED;
}
else if (coder->MethodID == k_BCJ2)
{
UInt64 offset = packPositions[1];
UInt64 s3Size = packPositions[2] - offset;
if (ci != 3)
return SZ_ERROR_UNSUPPORTED;
tempSizes[2] = (SizeT)s3Size;
if (tempSizes[2] != s3Size)
return SZ_ERROR_MEM;
tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]);
if (!tempBuf[2] && tempSizes[2] != 0)
return SZ_ERROR_MEM;
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2]));
if ((tempSizes[0] & 3) != 0 ||
(tempSizes[1] & 3) != 0 ||
tempSize3 + tempSizes[0] + tempSizes[1] != outSize)
return SZ_ERROR_DATA;
{
CBcj2Dec p;
p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3;
p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0];
p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1];
p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2];
p.dest = outBuffer;
p.destLim = outBuffer + outSize;
Bcj2Dec_Init(&p);
RINOK(Bcj2Dec_Decode(&p));
{
unsigned i;
for (i = 0; i < 4; i++)
if (p.bufs[i] != p.lims[i])
return SZ_ERROR_DATA;
if (!Bcj2Dec_IsFinished(&p))
return SZ_ERROR_DATA;
if (p.dest != p.destLim
|| p.state != BCJ2_STREAM_MAIN)
return SZ_ERROR_DATA;
}
}
}
#ifndef _7Z_NO_METHODS_FILTERS
else if (ci == 1)
{
if (coder->MethodID == k_Delta)
{
if (coder->PropsSize != 1)
return SZ_ERROR_UNSUPPORTED;
{
Byte state[DELTA_STATE_SIZE];
Delta_Init(state);
Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize);
}
}
else
{
if (coder->PropsSize != 0)
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(PPC)
CASE_BRA_CONV(IA64)
CASE_BRA_CONV(SPARC)
CASE_BRA_CONV(ARM)
CASE_BRA_CONV(ARMT)
default:
return SZ_ERROR_UNSUPPORTED;
}
}
}
#endif
else
return SZ_ERROR_UNSUPPORTED;
}
return SZ_OK;
}
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, size_t outSize,
ISzAllocPtr allocMain)
{
SRes res;
CSzFolder folder;
CSzData sd;
const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
sd.Data = data;
sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex];
res = SzGetNextFolderItem(&folder, &sd);
if (res != SZ_OK)
return res;
if (sd.Size != 0
|| folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex]
|| outSize != SzAr_GetFolderUnpackSize(p, folderIndex))
return SZ_ERROR_FAIL;
{
unsigned i;
Byte *tempBuf[3] = { 0, 0, 0};
res = SzFolder_Decode2(&folder, data,
&p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]],
p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
inStream, startPos,
outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++)
ISzAlloc_Free(allocMain, tempBuf[i]);
if (res == SZ_OK)
if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))
if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex])
res = SZ_ERROR_CRC;
return res;
}
}

55
C/7zFile.c Executable file → Normal file
View File

@@ -1,15 +1,17 @@
/* 7zFile.c -- File IO /* 7zFile.c -- File IO
2008-11-22 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "7zFile.h" #include "7zFile.h"
#ifndef USE_WINDOWS_FILE #ifndef USE_WINDOWS_FILE
#ifndef UNDER_CE
#include <errno.h> #include <errno.h>
#endif #endif
#ifdef USE_WINDOWS_FILE #else
/* /*
ReadFile and WriteFile functions in Windows have BUG: ReadFile and WriteFile functions in Windows have BUG:
@@ -34,6 +36,7 @@ void File_Construct(CSzFile *p)
#endif #endif
} }
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
static WRes File_Open(CSzFile *p, const char *name, int writeMode) static WRes File_Open(CSzFile *p, const char *name, int writeMode)
{ {
#ifdef USE_WINDOWS_FILE #ifdef USE_WINDOWS_FILE
@@ -45,12 +48,32 @@ static WRes File_Open(CSzFile *p, const char *name, int writeMode)
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
#else #else
p->file = fopen(name, writeMode ? "wb+" : "rb"); p->file = fopen(name, writeMode ? "wb+" : "rb");
return (p->file != 0) ? 0 : errno; return (p->file != 0) ? 0 :
#ifdef UNDER_CE
2; /* ENOENT */
#else
errno;
#endif
#endif #endif
} }
WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } 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); } 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) WRes File_Close(CSzFile *p)
{ {
@@ -215,49 +238,49 @@ WRes File_GetLength(CSzFile *p, UInt64 *length)
/* ---------- FileSeqInStream ---------- */ /* ---------- FileSeqInStream ---------- */
static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) static SRes FileSeqInStream_Read(const ISeqInStream *pp, void *buf, size_t *size)
{ {
CFileSeqInStream *p = (CFileSeqInStream *)pp; CFileSeqInStream *p = CONTAINER_FROM_VTBL(pp, CFileSeqInStream, vt);
return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
} }
void FileSeqInStream_CreateVTable(CFileSeqInStream *p) void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
{ {
p->s.Read = FileSeqInStream_Read; p->vt.Read = FileSeqInStream_Read;
} }
/* ---------- FileInStream ---------- */ /* ---------- FileInStream ---------- */
static SRes FileInStream_Read(void *pp, void *buf, size_t *size) static SRes FileInStream_Read(const ISeekInStream *pp, void *buf, size_t *size)
{ {
CFileInStream *p = (CFileInStream *)pp; CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
} }
static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) static SRes FileInStream_Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin)
{ {
CFileInStream *p = (CFileInStream *)pp; CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
return File_Seek(&p->file, pos, origin); return File_Seek(&p->file, pos, origin);
} }
void FileInStream_CreateVTable(CFileInStream *p) void FileInStream_CreateVTable(CFileInStream *p)
{ {
p->s.Read = FileInStream_Read; p->vt.Read = FileInStream_Read;
p->s.Seek = FileInStream_Seek; p->vt.Seek = FileInStream_Seek;
} }
/* ---------- FileOutStream ---------- */ /* ---------- FileOutStream ---------- */
static size_t FileOutStream_Write(void *pp, const void *data, size_t size) static size_t FileOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size)
{ {
CFileOutStream *p = (CFileOutStream *)pp; CFileOutStream *p = CONTAINER_FROM_VTBL(pp, CFileOutStream, vt);
File_Write(&p->file, data, &size); File_Write(&p->file, data, &size);
return size; return size;
} }
void FileOutStream_CreateVTable(CFileOutStream *p) void FileOutStream_CreateVTable(CFileOutStream *p)
{ {
p->s.Write = FileOutStream_Write; p->vt.Write = FileOutStream_Write;
} }

19
C/7zFile.h Executable file → Normal file
View File

@@ -1,5 +1,5 @@
/* 7zFile.h -- File IO /* 7zFile.h -- File IO
2008-11-22 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_FILE_H #ifndef __7Z_FILE_H
#define __7Z_FILE_H #define __7Z_FILE_H
@@ -14,8 +14,9 @@
#include <stdio.h> #include <stdio.h>
#endif #endif
#include "Types.h" #include "7zTypes.h"
EXTERN_C_BEGIN
/* ---------- File ---------- */ /* ---------- File ---------- */
@@ -29,8 +30,14 @@ typedef struct
} CSzFile; } CSzFile;
void File_Construct(CSzFile *p); void File_Construct(CSzFile *p);
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
WRes InFile_Open(CSzFile *p, const char *name); WRes InFile_Open(CSzFile *p, const char *name);
WRes OutFile_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); WRes File_Close(CSzFile *p);
/* reads max(*size, remain file's size) bytes */ /* reads max(*size, remain file's size) bytes */
@@ -47,7 +54,7 @@ WRes File_GetLength(CSzFile *p, UInt64 *length);
typedef struct typedef struct
{ {
ISeqInStream s; ISeqInStream vt;
CSzFile file; CSzFile file;
} CFileSeqInStream; } CFileSeqInStream;
@@ -56,7 +63,7 @@ void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
typedef struct typedef struct
{ {
ISeekInStream s; ISeekInStream vt;
CSzFile file; CSzFile file;
} CFileInStream; } CFileInStream;
@@ -65,10 +72,12 @@ void FileInStream_CreateVTable(CFileInStream *p);
typedef struct typedef struct
{ {
ISeqOutStream s; ISeqOutStream vt;
CSzFile file; CSzFile file;
} CFileOutStream; } CFileOutStream;
void FileOutStream_CreateVTable(CFileOutStream *p); void FileOutStream_CreateVTable(CFileOutStream *p);
EXTERN_C_END
#endif #endif

117
C/7zStream.c Executable file → Normal file
View File

@@ -1,16 +1,18 @@
/* 7zStream.c -- 7z Stream functions /* 7zStream.c -- 7z Stream functions
2008-11-23 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include <string.h> #include <string.h>
#include "Types.h" #include "7zTypes.h"
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType)
{ {
while (size != 0) while (size != 0)
{ {
size_t processed = size; size_t processed = size;
RINOK(stream->Read(stream, buf, &processed)); RINOK(ISeqInStream_Read(stream, buf, &processed));
if (processed == 0) if (processed == 0)
return errorType; return errorType;
buf = (void *)((Byte *)buf + processed); buf = (void *)((Byte *)buf + processed);
@@ -19,40 +21,42 @@ SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorT
return SZ_OK; return SZ_OK;
} }
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size)
{ {
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
} }
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf)
{ {
size_t processed = 1; size_t processed = 1;
RINOK(stream->Read(stream, buf, &processed)); RINOK(ISeqInStream_Read(stream, buf, &processed));
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
} }
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset)
{ {
Int64 t = offset; Int64 t = offset;
return stream->Seek(stream, &t, SZ_SEEK_SET); return ILookInStream_Seek(stream, &t, SZ_SEEK_SET);
} }
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size)
{ {
void *lookBuf; const void *lookBuf;
if (*size == 0) if (*size == 0)
return SZ_OK; return SZ_OK;
RINOK(stream->Look(stream, &lookBuf, size)); RINOK(ILookInStream_Look(stream, &lookBuf, size));
memcpy(buf, lookBuf, *size); memcpy(buf, lookBuf, *size);
return stream->Skip(stream, *size); return ILookInStream_Skip(stream, *size);
} }
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType)
{ {
while (size != 0) while (size != 0)
{ {
size_t processed = size; size_t processed = size;
RINOK(stream->Read(stream, buf, &processed)); RINOK(ILookInStream_Read(stream, buf, &processed));
if (processed == 0) if (processed == 0)
return errorType; return errorType;
buf = (void *)((Byte *)buf + processed); buf = (void *)((Byte *)buf + processed);
@@ -61,61 +65,67 @@ SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes erro
return SZ_OK; return SZ_OK;
} }
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size)
{ {
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
} }
static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size)
#define GET_LookToRead2 CLookToRead2 *p = CONTAINER_FROM_VTBL(pp, CLookToRead2, vt);
static SRes LookToRead2_Look_Lookahead(const ILookInStream *pp, const void **buf, size_t *size)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp; GET_LookToRead2
size_t size2 = p->size - p->pos; size_t size2 = p->size - p->pos;
if (size2 == 0 && *size > 0) if (size2 == 0 && *size != 0)
{ {
p->pos = 0; p->pos = 0;
size2 = LookToRead_BUF_SIZE; p->size = 0;
res = p->realStream->Read(p->realStream, p->buf, &size2); size2 = p->bufSize;
res = ISeekInStream_Read(p->realStream, p->buf, &size2);
p->size = size2; p->size = size2;
} }
if (size2 < *size) if (*size > size2)
*size = size2; *size = size2;
*buf = p->buf + p->pos; *buf = p->buf + p->pos;
return res; return res;
} }
static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) static SRes LookToRead2_Look_Exact(const ILookInStream *pp, const void **buf, size_t *size)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp; GET_LookToRead2
size_t size2 = p->size - p->pos; size_t size2 = p->size - p->pos;
if (size2 == 0 && *size > 0) if (size2 == 0 && *size != 0)
{ {
p->pos = 0; p->pos = 0;
if (*size > LookToRead_BUF_SIZE) p->size = 0;
*size = LookToRead_BUF_SIZE; if (*size > p->bufSize)
res = p->realStream->Read(p->realStream, p->buf, size); *size = p->bufSize;
res = ISeekInStream_Read(p->realStream, p->buf, size);
size2 = p->size = *size; size2 = p->size = *size;
} }
if (size2 < *size) if (*size > size2)
*size = size2; *size = size2;
*buf = p->buf + p->pos; *buf = p->buf + p->pos;
return res; return res;
} }
static SRes LookToRead_Skip(void *pp, size_t offset) static SRes LookToRead2_Skip(const ILookInStream *pp, size_t offset)
{ {
CLookToRead *p = (CLookToRead *)pp; GET_LookToRead2
p->pos += offset; p->pos += offset;
return SZ_OK; return SZ_OK;
} }
static SRes LookToRead_Read(void *pp, void *buf, size_t *size) static SRes LookToRead2_Read(const ILookInStream *pp, void *buf, size_t *size)
{ {
CLookToRead *p = (CLookToRead *)pp; GET_LookToRead2
size_t rem = p->size - p->pos; size_t rem = p->size - p->pos;
if (rem == 0) if (rem == 0)
return p->realStream->Read(p->realStream, buf, size); return ISeekInStream_Read(p->realStream, buf, size);
if (rem > *size) if (rem > *size)
rem = *size; rem = *size;
memcpy(buf, p->buf + p->pos, rem); memcpy(buf, p->buf + p->pos, rem);
@@ -124,46 +134,43 @@ static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
return SZ_OK; return SZ_OK;
} }
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) static SRes LookToRead2_Seek(const ILookInStream *pp, Int64 *pos, ESzSeek origin)
{ {
CLookToRead *p = (CLookToRead *)pp; GET_LookToRead2
p->pos = p->size = 0; p->pos = p->size = 0;
return p->realStream->Seek(p->realStream, pos, origin); return ISeekInStream_Seek(p->realStream, pos, origin);
} }
void LookToRead_CreateVTable(CLookToRead *p, int lookahead) void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead)
{ {
p->s.Look = lookahead ? p->vt.Look = lookahead ?
LookToRead_Look_Lookahead : LookToRead2_Look_Lookahead :
LookToRead_Look_Exact; LookToRead2_Look_Exact;
p->s.Skip = LookToRead_Skip; p->vt.Skip = LookToRead2_Skip;
p->s.Read = LookToRead_Read; p->vt.Read = LookToRead2_Read;
p->s.Seek = LookToRead_Seek; p->vt.Seek = LookToRead2_Seek;
} }
void LookToRead_Init(CLookToRead *p)
{
p->pos = p->size = 0;
}
static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
static SRes SecToLook_Read(const ISeqInStream *pp, void *buf, size_t *size)
{ {
CSecToLook *p = (CSecToLook *)pp; CSecToLook *p = CONTAINER_FROM_VTBL(pp, CSecToLook, vt);
return LookInStream_LookRead(p->realStream, buf, size); return LookInStream_LookRead(p->realStream, buf, size);
} }
void SecToLook_CreateVTable(CSecToLook *p) void SecToLook_CreateVTable(CSecToLook *p)
{ {
p->s.Read = SecToLook_Read; p->vt.Read = SecToLook_Read;
} }
static SRes SecToRead_Read(void *pp, void *buf, size_t *size) static SRes SecToRead_Read(const ISeqInStream *pp, void *buf, size_t *size)
{ {
CSecToRead *p = (CSecToRead *)pp; CSecToRead *p = CONTAINER_FROM_VTBL(pp, CSecToRead, vt);
return p->realStream->Read(p->realStream, buf, size); return ILookInStream_Read(p->realStream, buf, size);
} }
void SecToRead_CreateVTable(CSecToRead *p) void SecToRead_CreateVTable(CSecToRead *p)
{ {
p->s.Read = SecToRead_Read; p->vt.Read = SecToRead_Read;
} }

374
C/7zTypes.h Normal file
View File

@@ -0,0 +1,374 @@
/* 7zTypes.h -- Basic types
2017-07-17 : 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;
#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)
#else
typedef int WRes;
#define MY__FACILITY_WIN32 7
#define MY__FACILITY__WRes MY__FACILITY_WIN32
#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000)))
#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_FORCE_INLINE __forceinline
#define MY_CDECL __cdecl
#define MY_FAST_CALL __fastcall
#else
#define MY_NO_INLINE
#define MY_FORCE_INLINE
#define MY_CDECL
#define MY_FAST_CALL
/* inline keyword : for C++ / C99 */
/* GCC, clang: */
/*
#if defined (__GNUC__) && (__GNUC__ >= 4)
#define MY_FORCE_INLINE __attribute__((always_inline))
#define MY_NO_INLINE __attribute__((noinline))
#endif
*/
#endif
/* The following interfaces use first parameter as pointer to structure */
typedef struct IByteIn IByteIn;
struct IByteIn
{
Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */
};
#define IByteIn_Read(p) (p)->Read(p)
typedef struct IByteOut IByteOut;
struct IByteOut
{
void (*Write)(const IByteOut *p, Byte b);
};
#define IByteOut_Write(p, b) (p)->Write(p, b)
typedef struct ISeqInStream ISeqInStream;
struct ISeqInStream
{
SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */
};
#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)
/* it can return SZ_ERROR_INPUT_EOF */
SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size);
SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType);
SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf);
typedef struct ISeqOutStream ISeqOutStream;
struct ISeqOutStream
{
size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes.
(result < size) means error */
};
#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)
typedef enum
{
SZ_SEEK_SET = 0,
SZ_SEEK_CUR = 1,
SZ_SEEK_END = 2
} ESzSeek;
typedef struct ISeekInStream ISeekInStream;
struct ISeekInStream
{
SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin);
};
#define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size)
#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
typedef struct ILookInStream ILookInStream;
struct ILookInStream
{
SRes (*Look)(const ILookInStream *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)(const ILookInStream *p, size_t offset);
/* offset must be <= output(*size) of Look */
SRes (*Read)(const ILookInStream *p, void *buf, size_t *size);
/* reads directly (without buffer). It's same as ISeqInStream::Read */
SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin);
};
#define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size)
#define ILookInStream_Skip(p, offset) (p)->Skip(p, offset)
#define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size)
#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size);
SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset);
/* reads via ILookInStream::Read */
SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType);
SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size);
typedef struct
{
ILookInStream vt;
const ISeekInStream *realStream;
size_t pos;
size_t size; /* it's data size */
/* the following variables must be set outside */
Byte *buf;
size_t bufSize;
} CLookToRead2;
void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead);
#define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; }
typedef struct
{
ISeqInStream vt;
const ILookInStream *realStream;
} CSecToLook;
void SecToLook_CreateVTable(CSecToLook *p);
typedef struct
{
ISeqInStream vt;
const ILookInStream *realStream;
} CSecToRead;
void SecToRead_CreateVTable(CSecToRead *p);
typedef struct ICompressProgress ICompressProgress;
struct ICompressProgress
{
SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize);
/* Returns: result. (result != SZ_OK) means break.
Value (UInt64)(Int64)-1 for size means unknown value. */
};
#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)
typedef struct ISzAlloc ISzAlloc;
typedef const ISzAlloc * ISzAllocPtr;
struct ISzAlloc
{
void *(*Alloc)(ISzAllocPtr p, size_t size);
void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */
};
#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size)
#define ISzAlloc_Free(p, a) (p)->Free(p, a)
/* deprecated */
#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size)
#define IAlloc_Free(p, a) ISzAlloc_Free(p, a)
#ifndef MY_offsetof
#ifdef offsetof
#define MY_offsetof(type, m) offsetof(type, m)
/*
#define MY_offsetof(type, m) FIELD_OFFSET(type, m)
*/
#else
#define MY_offsetof(type, m) ((size_t)&(((type *)0)->m))
#endif
#endif
#ifndef MY_container_of
/*
#define MY_container_of(ptr, type, m) container_of(ptr, type, m)
#define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m)
#define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m)))
#define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m))))
*/
/*
GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly"
GCC 3.4.4 : classes with constructor
GCC 4.8.1 : classes with non-public variable members"
*/
#define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m)))
#endif
#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr))
/*
#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
*/
#define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m)
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
/*
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m)
*/
#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

32
C/7zVersion.h Executable file → Normal file
View File

@@ -1,7 +1,27 @@
#define MY_VER_MAJOR 4 #define MY_VER_MAJOR 18
#define MY_VER_MINOR 63 #define MY_VER_MINOR 03
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION "4.63" #define MY_VERSION_NUMBERS "18.03 beta"
#define MY_DATE "2008-12-31" #define MY_VERSION MY_VERSION_NUMBERS
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE #ifdef MY_CPU_NAME
#define MY_VERSION_CPU MY_VERSION " (" MY_CPU_NAME ")"
#else
#define MY_VERSION_CPU MY_VERSION
#endif
#define MY_DATE "2018-03-04"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2018 Igor Pavlov"
#ifdef USE_COPYRIGHT_CR
#define MY_COPYRIGHT MY_COPYRIGHT_CR
#else
#define MY_COPYRIGHT MY_COPYRIGHT_PD
#endif
#define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE

55
C/7zVersion.rc Normal file
View File

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

234
C/Aes.c Executable file → Normal file
View File

@@ -1,13 +1,13 @@
/* Aes.c -- AES encryption / decryption /* Aes.c -- AES encryption / decryption
2008-08-05 2017-01-24 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */ #include "Precomp.h"
#include "Aes.h" #include "Aes.h"
#include "CpuArch.h" #include "CpuArch.h"
static UInt32 T[256 * 4]; static UInt32 T[256 * 4];
static Byte Sbox[256] = { static const Byte Sbox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 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, 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, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
@@ -25,10 +25,22 @@ static Byte Sbox[256] = {
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 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}; 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 UInt32 D[256 * 4];
static Byte InvS[256]; static Byte InvS[256];
static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; static const 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 xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF)
@@ -37,23 +49,30 @@ static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0
#define gb0(x) ( (x) & 0xFF) #define gb0(x) ( (x) & 0xFF)
#define gb1(x) (((x) >> ( 8)) & 0xFF) #define gb1(x) (((x) >> ( 8)) & 0xFF)
#define gb2(x) (((x) >> (16)) & 0xFF) #define gb2(x) (((x) >> (16)) & 0xFF)
#define gb3(x) (((x) >> (24)) & 0xFF) #define gb3(x) (((x) >> (24)))
#define gb(n, x) gb ## n(x)
#define TT(x) (T + (x << 8))
#define DD(x) (D + (x << 8))
void AesGenTables(void) void AesGenTables(void)
{ {
unsigned i; unsigned i;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
InvS[Sbox[i]] = (Byte)i; InvS[Sbox[i]] = (Byte)i;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
{ {
UInt32 a1 = Sbox[i]; UInt32 a1 = Sbox[i];
UInt32 a2 = xtime(a1); UInt32 a2 = xtime(a1);
UInt32 a3 = xtime(a1) ^ a1; UInt32 a3 = a2 ^ a1;
T[ i] = Ui32(a2, a1, a1, a3); TT(0)[i] = Ui32(a2, a1, a1, a3);
T[0x100 + i] = Ui32(a3, a2, a1, a1); TT(1)[i] = Ui32(a3, a2, a1, a1);
T[0x200 + i] = Ui32(a1, a3, a2, a1); TT(2)[i] = Ui32(a1, a3, a2, a1);
T[0x300 + i] = Ui32(a1, a1, a3, a2); TT(3)[i] = Ui32(a1, a1, a3, a2);
} }
{ {
UInt32 a1 = InvS[i]; UInt32 a1 = InvS[i];
@@ -64,62 +83,77 @@ void AesGenTables(void)
UInt32 aB = a8 ^ a2 ^ a1; UInt32 aB = a8 ^ a2 ^ a1;
UInt32 aD = a8 ^ a4 ^ a1; UInt32 aD = a8 ^ a4 ^ a1;
UInt32 aE = a8 ^ a4 ^ a2; UInt32 aE = a8 ^ a4 ^ a2;
D[ i] = Ui32(aE, a9, aD, aB); DD(0)[i] = Ui32(aE, a9, aD, aB);
D[0x100 + i] = Ui32(aB, aE, a9, aD); DD(1)[i] = Ui32(aB, aE, a9, aD);
D[0x200 + i] = Ui32(aD, aB, aE, a9); DD(2)[i] = Ui32(aD, aB, aE, a9);
D[0x300 + i] = Ui32(a9, aD, aB, aE); DD(3)[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 HT(i, x, s) TT(x)[gb(x, s[(i + x) & 3])]
#define HT4(m, i, s, p) m[i] = \ #define HT4(m, i, s, p) m[i] = \
HT(i, 0, s) ^ \ HT(i, 0, s) ^ \
HT(i, 1, s) ^ \ HT(i, 1, s) ^ \
HT(i, 2, s) ^ \ HT(i, 2, s) ^ \
HT(i, 3, s) ^ w[p + i] 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 HT16(m, s, p) \
HT4(m, 0, s, p); \
HT4(m, 1, s, p); \
HT4(m, 2, s, p); \
HT4(m, 3, 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 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 HD(i, x, s) DD(x)[gb(x, s[(i - x) & 3])]
#define HD4(m, i, s, p) m[i] = \ #define HD4(m, i, s, p) m[i] = \
HD(i, 0, s) ^ \ HD(i, 0, s) ^ \
HD(i, 1, s) ^ \ HD(i, 1, s) ^ \
HD(i, 2, s) ^ \ HD(i, 2, s) ^ \
HD(i, 3, s) ^ w[p + i]; HD(i, 3, s) ^ w[p + i];
/* such order (0231) in HD16 is for VC6/K8 speed optimization) */
#define HD16(m, s, p) \ #define HD16(m, s, p) \
HD4(m, 0, s, p); \ HD4(m, 0, s, p); \
HD4(m, 1, s, p); \
HD4(m, 2, s, p); \ HD4(m, 2, s, p); \
HD4(m, 3, s, p); \ HD4(m, 3, s, p); \
HD4(m, 1, s, p); \
#define FD(i, x) InvS[gb ## x(m[(i - x) & 3])] #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]; #define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i];
void Aes_SetKeyEncode(CAes *p, const Byte *key, unsigned keySize) void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize)
{ {
unsigned i, wSize; unsigned i, wSize;
UInt32 *w; wSize = keySize + 28;
keySize /= 4; keySize /= 4;
p->numRounds2 = keySize / 2 + 3; w[0] = ((UInt32)keySize / 2) + 3;
w += 4;
wSize = (p->numRounds2 * 2 + 1) * 4;
w = p->rkey;
for (i = 0; i < keySize; i++, key += 4) for (i = 0; i < keySize; i++, key += 4)
w[i] = Ui32(key[0], key[1], key[2], key[3]); w[i] = GetUi32(key);
for (; i < wSize; i++) for (; i < wSize; i++)
{ {
UInt32 t = w[i - 1]; UInt32 t = w[(size_t)i - 1];
unsigned rem = i % keySize; unsigned rem = i % keySize;
if (rem == 0) if (rem == 0)
t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]); t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]);
@@ -129,28 +163,33 @@ void Aes_SetKeyEncode(CAes *p, const Byte *key, unsigned keySize)
} }
} }
void Aes_SetKeyDecode(CAes *p, const Byte *key, unsigned keySize) void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)
{ {
unsigned i, num; unsigned i, num;
UInt32 *w; Aes_SetKey_Enc(w, key, keySize);
Aes_SetKeyEncode(p, key, keySize); num = keySize + 20;
num = p->numRounds2 * 8 - 4; w += 8;
w = p->rkey + 4;
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
{ {
UInt32 r = w[i]; UInt32 r = w[i];
w[i] = w[i] =
D[ Sbox[gb0(r)]] ^ DD(0)[Sbox[gb0(r)]] ^
D[0x100 + Sbox[gb1(r)]] ^ DD(1)[Sbox[gb1(r)]] ^
D[0x200 + Sbox[gb2(r)]] ^ DD(2)[Sbox[gb2(r)]] ^
D[0x300 + Sbox[gb3(r)]]; DD(3)[Sbox[gb3(r)]];
} }
} }
static void AesEncode32(UInt32 *dest, const UInt32 *src, const UInt32 *w, unsigned numRounds2) /* Aes_Encode and Aes_Decode functions work with little-endian words.
src and dest are pointers to 4 UInt32 words.
src and dest can point to same block */
static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src)
{ {
UInt32 s[4]; UInt32 s[4];
UInt32 m[4]; UInt32 m[4];
UInt32 numRounds2 = w[0];
w += 4;
s[0] = src[0] ^ w[0]; s[0] = src[0] ^ w[0];
s[1] = src[1] ^ w[1]; s[1] = src[1] ^ w[1];
s[2] = src[2] ^ w[2]; s[2] = src[2] ^ w[2];
@@ -168,11 +207,12 @@ static void AesEncode32(UInt32 *dest, const UInt32 *src, const UInt32 *w, unsign
FT4(0); FT4(1); FT4(2); FT4(3); FT4(0); FT4(1); FT4(2); FT4(3);
} }
static void AesDecode32(UInt32 *dest, const UInt32 *src, const UInt32 *w, unsigned numRounds2) static void Aes_Decode(const UInt32 *w, UInt32 *dest, const UInt32 *src)
{ {
UInt32 s[4]; UInt32 s[4];
UInt32 m[4]; UInt32 m[4];
w += numRounds2 * 8; UInt32 numRounds2 = w[0];
w += 4 + numRounds2 * 8;
s[0] = src[0] ^ w[0]; s[0] = src[0] ^ w[0];
s[1] = src[1] ^ w[1]; s[1] = src[1] ^ w[1];
s[2] = src[2] ^ w[2]; s[2] = src[2] ^ w[2];
@@ -188,75 +228,79 @@ static void AesDecode32(UInt32 *dest, const UInt32 *src, const UInt32 *w, unsign
FD4(0); FD4(1); FD4(2); FD4(3); FD4(0); FD4(1); FD4(2); FD4(3);
} }
void Aes_Encode32(const CAes *p, UInt32 *dest, const UInt32 *src) void AesCbc_Init(UInt32 *p, const Byte *iv)
{
AesEncode32(dest, src, p->rkey, p->numRounds2);
}
void Aes_Decode32(const CAes *p, UInt32 *dest, const UInt32 *src)
{
AesDecode32(dest, src, p->rkey, p->numRounds2);
}
void AesCbc_Init(CAesCbc *p, const Byte *iv)
{ {
unsigned i; unsigned i;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
p->prev[i] = GetUi32(iv + i * 4); p[i] = GetUi32(iv + i * 4);
} }
SizeT AesCbc_Encode(CAesCbc *p, Byte *data, SizeT size) void MY_FAST_CALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks)
{ {
SizeT i; for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)
if (size == 0)
return 0;
if (size < AES_BLOCK_SIZE)
return AES_BLOCK_SIZE;
size -= AES_BLOCK_SIZE;
for (i = 0; i <= size; i += AES_BLOCK_SIZE, data += AES_BLOCK_SIZE)
{ {
p->prev[0] ^= GetUi32(data); p[0] ^= GetUi32(data);
p->prev[1] ^= GetUi32(data + 4); p[1] ^= GetUi32(data + 4);
p->prev[2] ^= GetUi32(data + 8); p[2] ^= GetUi32(data + 8);
p->prev[3] ^= GetUi32(data + 12); p[3] ^= GetUi32(data + 12);
AesEncode32(p->prev, p->prev, p->aes.rkey, p->aes.numRounds2); Aes_Encode(p + 4, p, p);
SetUi32(data, p->prev[0]); SetUi32(data, p[0]);
SetUi32(data + 4, p->prev[1]); SetUi32(data + 4, p[1]);
SetUi32(data + 8, p->prev[2]); SetUi32(data + 8, p[2]);
SetUi32(data + 12, p->prev[3]); SetUi32(data + 12, p[3]);
} }
return i;
} }
SizeT AesCbc_Decode(CAesCbc *p, Byte *data, SizeT size) void MY_FAST_CALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks)
{ {
SizeT i;
UInt32 in[4], out[4]; UInt32 in[4], out[4];
if (size == 0) for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)
return 0;
if (size < AES_BLOCK_SIZE)
return AES_BLOCK_SIZE;
size -= AES_BLOCK_SIZE;
for (i = 0; i <= size; i += AES_BLOCK_SIZE, data += AES_BLOCK_SIZE)
{ {
in[0] = GetUi32(data); in[0] = GetUi32(data);
in[1] = GetUi32(data + 4); in[1] = GetUi32(data + 4);
in[2] = GetUi32(data + 8); in[2] = GetUi32(data + 8);
in[3] = GetUi32(data + 12); in[3] = GetUi32(data + 12);
AesDecode32(out, in, p->aes.rkey, p->aes.numRounds2); Aes_Decode(p + 4, out, in);
SetUi32(data, p->prev[0] ^ out[0]); SetUi32(data, p[0] ^ out[0]);
SetUi32(data + 4, p->prev[1] ^ out[1]); SetUi32(data + 4, p[1] ^ out[1]);
SetUi32(data + 8, p->prev[2] ^ out[2]); SetUi32(data + 8, p[2] ^ out[2]);
SetUi32(data + 12, p->prev[3] ^ out[3]); SetUi32(data + 12, p[3] ^ out[3]);
p->prev[0] = in[0]; p[0] = in[0];
p->prev[1] = in[1]; p[1] = in[1];
p->prev[2] = in[2]; p[2] = in[2];
p->prev[3] = in[3]; p[3] = in[3];
}
}
void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)
{
for (; numBlocks != 0; numBlocks--)
{
UInt32 temp[4];
unsigned i;
if (++p[0] == 0)
p[1]++;
Aes_Encode(p + 4, temp, p);
for (i = 0; i < 4; i++, data += 4)
{
UInt32 t = temp[i];
#ifdef MY_CPU_LE_UNALIGN
*((UInt32 *)data) ^= t;
#else
data[0] ^= (t & 0xFF);
data[1] ^= ((t >> 8) & 0xFF);
data[2] ^= ((t >> 16) & 0xFF);
data[3] ^= ((t >> 24));
#endif
}
} }
return i;
} }

54
C/Aes.h Executable file → Normal file
View File

@@ -1,48 +1,38 @@
/* Aes.h -- AES encryption / decryption /* Aes.h -- AES encryption / decryption
2008-08-05 2013-01-18 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __AES_H #ifndef __AES_H
#define __AES_H #define __AES_H
#include "Types.h" #include "7zTypes.h"
EXTERN_C_BEGIN
#define AES_BLOCK_SIZE 16 #define AES_BLOCK_SIZE 16
typedef struct
{
unsigned numRounds2; /* = numRounds / 2 */
UInt32 rkey[(14 + 1) * 4];
} CAes;
/* Call AesGenTables one time before other AES functions */ /* Call AesGenTables one time before other AES functions */
void AesGenTables(void); 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) */ /* keySize = 16 or 24 or 32 (bytes) */
void Aes_SetKeyEncode(CAes *p, const Byte *key, unsigned keySize); typedef void (MY_FAST_CALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize);
void Aes_SetKeyDecode(CAes *p, 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);
/* Aes_Encode32 and Aes_Decode32 functions work with little-endian words. /* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */
src and dest are pointers to 4 UInt32 words. void AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */
arc and dest can point to same block */ /* data - 16-byte aligned pointer to data */
void Aes_Encode32(const CAes *p, UInt32 *dest, const UInt32 *src); /* numBlocks - the number of 16-byte blocks in data array */
void Aes_Decode32(const CAes *p, UInt32 *dest, const UInt32 *src); 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;
typedef struct EXTERN_C_END
{
UInt32 prev[4];
CAes aes;
} CAesCbc;
void AesCbc_Init(CAesCbc *p, const Byte *iv); /* iv size is AES_BLOCK_SIZE */
/* AesCbc_Encode and AesCbc_Decode:
if (res <= size): Filter have converted res bytes
if (res > size): Filter have not converted anything. And it needs at
least res = AES_BLOCK_SIZE bytes to convert one block */
SizeT AesCbc_Encode(CAesCbc *p, Byte *data, SizeT size);
SizeT AesCbc_Decode(CAesCbc *p, Byte *data, SizeT size);
#endif #endif

184
C/AesOpt.c Normal file
View File

@@ -0,0 +1,184 @@
/* AesOpt.c -- Intel's AES
2017-06-08 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "CpuArch.h"
#ifdef MY_CPU_X86_OR_AMD64
#if (_MSC_VER > 1500) || (_MSC_FULL_VER >= 150030729)
#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

400
C/Alloc.c Executable file → Normal file
View File

@@ -1,7 +1,9 @@
/* Alloc.c -- Memory allocation functions /* Alloc.c -- Memory allocation functions
2008-09-24 2018-03-01 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */ #include "Precomp.h"
#include <stdio.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
@@ -14,20 +16,127 @@ Public domain */
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
#include <stdio.h> #include <stdio.h>
int g_allocCount = 0; int g_allocCount = 0;
int g_allocCountMid = 0; int g_allocCountMid = 0;
int g_allocCountBig = 0; int g_allocCountBig = 0;
#define CONVERT_INT_TO_STR(charType, tempSize) \
unsigned char temp[tempSize]; unsigned i = 0; \
while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \
*s++ = (charType)('0' + (unsigned)val); \
while (i != 0) { i--; *s++ = temp[i]; } \
*s = 0;
static void ConvertUInt64ToString(UInt64 val, char *s)
{
CONVERT_INT_TO_STR(char, 24);
}
#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
static void ConvertUInt64ToHex(UInt64 val, char *s)
{
UInt64 v = val;
unsigned i;
for (i = 1;; i++)
{
v >>= 4;
if (v == 0)
break;
}
s[i] = 0;
do
{
unsigned t = (unsigned)(val & 0xF);
val >>= 4;
s[--i] = GET_HEX_CHAR(t);
}
while (i);
}
#define DEBUG_OUT_STREAM stderr
static void Print(const char *s)
{
fputs(s, DEBUG_OUT_STREAM);
}
static void PrintAligned(const char *s, size_t align)
{
size_t len = strlen(s);
for(;;)
{
fputc(' ', DEBUG_OUT_STREAM);
if (len >= align)
break;
++len;
}
Print(s);
}
static void PrintLn()
{
Print("\n");
}
static void PrintHex(UInt64 v, size_t align)
{
char s[32];
ConvertUInt64ToHex(v, s);
PrintAligned(s, align);
}
static void PrintDec(UInt64 v, size_t align)
{
char s[32];
ConvertUInt64ToString(v, s);
PrintAligned(s, align);
}
static void PrintAddr(void *p)
{
PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12);
}
#define PRINT_ALLOC(name, cnt, size, ptr) \
Print(name " "); \
PrintDec(cnt++, 10); \
PrintHex(size, 10); \
PrintAddr(ptr); \
PrintLn();
#define PRINT_FREE(name, cnt, ptr) if (ptr) { \
Print(name " "); \
PrintDec(--cnt, 10); \
PrintAddr(ptr); \
PrintLn(); }
#else
#define PRINT_ALLOC(name, cnt, size, ptr)
#define PRINT_FREE(name, cnt, ptr)
#define Print(s)
#define PrintLn()
#define PrintHex(v, align)
#define PrintDec(v, align)
#define PrintAddr(p)
#endif #endif
void *MyAlloc(size_t size) void *MyAlloc(size_t size)
{ {
if (size == 0) if (size == 0)
return 0; return NULL;
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
{ {
void *p = malloc(size); void *p = malloc(size);
fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); PRINT_ALLOC("Alloc ", g_allocCount, size, p);
return p; return p;
} }
#else #else
@@ -37,10 +146,8 @@ void *MyAlloc(size_t size)
void MyFree(void *address) void MyFree(void *address)
{ {
#ifdef _SZ_ALLOC_DEBUG PRINT_FREE("Free ", g_allocCount, address);
if (address != 0)
fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address);
#endif
free(address); free(address);
} }
@@ -49,20 +156,18 @@ void MyFree(void *address)
void *MidAlloc(size_t size) void *MidAlloc(size_t size)
{ {
if (size == 0) if (size == 0)
return 0; return NULL;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, NULL);
#endif
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
} }
void MidFree(void *address) void MidFree(void *address)
{ {
#ifdef _SZ_ALLOC_DEBUG PRINT_FREE("Free-Mid", g_allocCountMid, address);
if (address != 0)
fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); if (!address)
#endif
if (address == 0)
return; return;
VirtualFree(address, 0, MEM_RELEASE); VirtualFree(address, 0, MEM_RELEASE);
} }
@@ -79,10 +184,10 @@ typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
void SetLargePageSize() void SetLargePageSize()
{ {
#ifdef _7ZIP_LARGE_PAGES #ifdef _7ZIP_LARGE_PAGES
SIZE_T size = 0; SIZE_T size;
GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
if (largePageMinimum == 0) if (!largePageMinimum)
return; return;
size = largePageMinimum(); size = largePageMinimum();
if (size == 0 || (size & (size - 1)) != 0) if (size == 0 || (size & (size - 1)) != 0)
@@ -95,33 +200,256 @@ void SetLargePageSize()
void *BigAlloc(size_t size) void *BigAlloc(size_t size)
{ {
if (size == 0) if (size == 0)
return 0; return NULL;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL);
#endif
#ifdef _7ZIP_LARGE_PAGES #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)), SIZE_T ps = g_LargePageSize;
MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (ps != 0 && ps <= (1 << 30) && size > (ps / 2))
if (res != 0) {
return res; size_t size2;
ps--;
size2 = (size + ps) & ~ps;
if (size2 >= size)
{
void *res = VirtualAlloc(NULL, size2, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
if (res)
return res;
}
}
} }
#endif #endif
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
} }
void BigFree(void *address) void BigFree(void *address)
{ {
#ifdef _SZ_ALLOC_DEBUG PRINT_FREE("Free-Big", g_allocCountBig, address);
if (address != 0)
fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
#endif
if (address == 0) if (!address)
return; return;
VirtualFree(address, 0, MEM_RELEASE); VirtualFree(address, 0, MEM_RELEASE);
} }
#endif #endif
static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MyFree(address); }
const ISzAlloc g_Alloc = { SzAlloc, SzFree };
static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MidAlloc(size); }
static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MidFree(address); }
const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };
static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); }
static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); BigFree(address); }
const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
/*
uintptr_t : <stdint.h> C99 (optional)
: unsupported in VS6
*/
#ifdef _WIN32
typedef UINT_PTR UIntPtr;
#else
/*
typedef uintptr_t UIntPtr;
*/
typedef ptrdiff_t UIntPtr;
#endif
#define ADJUST_ALLOC_SIZE 0
/*
#define ADJUST_ALLOC_SIZE (sizeof(void *) - 1)
*/
/*
Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if
MyAlloc() can return address that is NOT multiple of sizeof(void *).
*/
/*
#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1))))
*/
#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1))))
#define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align)
#if (_POSIX_C_SOURCE >= 200112L)
#define USE_posix_memalign
#endif
/*
This posix_memalign() is for test purposes only.
We also need special Free() function instead of free(),
if this posix_memalign() is used.
*/
/*
static int posix_memalign(void **ptr, size_t align, size_t size)
{
size_t newSize = size + align;
void *p;
void *pAligned;
*ptr = NULL;
if (newSize < size)
return 12; // ENOMEM
p = MyAlloc(newSize);
if (!p)
return 12; // ENOMEM
pAligned = MY_ALIGN_PTR_UP_PLUS(p, align);
((void **)pAligned)[-1] = p;
*ptr = pAligned;
return 0;
}
*/
/*
ALLOC_ALIGN_SIZE >= sizeof(void *)
ALLOC_ALIGN_SIZE >= cache_line_size
*/
#define ALLOC_ALIGN_SIZE ((size_t)1 << 7)
static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
{
#ifndef USE_posix_memalign
void *p;
void *pAligned;
size_t newSize;
UNUSED_VAR(pp);
/* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
block to prevent cache line sharing with another allocated blocks */
newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE;
if (newSize < size)
return NULL;
p = MyAlloc(newSize);
if (!p)
return NULL;
pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE);
Print(" size="); PrintHex(size, 8);
Print(" a_size="); PrintHex(newSize, 8);
Print(" ptr="); PrintAddr(p);
Print(" a_ptr="); PrintAddr(pAligned);
PrintLn();
((void **)pAligned)[-1] = p;
return pAligned;
#else
void *p;
UNUSED_VAR(pp);
if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size))
return NULL;
Print(" posix_memalign="); PrintAddr(p);
PrintLn();
return p;
#endif
}
static void SzAlignedFree(ISzAllocPtr pp, void *address)
{
UNUSED_VAR(pp);
#ifndef USE_posix_memalign
if (address)
MyFree(((void **)address)[-1]);
#else
free(address);
#endif
}
const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree };
#define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *))
/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */
#define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1]
/*
#define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1]
*/
static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)
{
CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt);
void *adr;
void *pAligned;
size_t newSize;
size_t extra;
size_t alignSize = (size_t)1 << p->numAlignBits;
if (alignSize < sizeof(void *))
alignSize = sizeof(void *);
if (p->offset >= alignSize)
return NULL;
/* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
block to prevent cache line sharing with another allocated blocks */
extra = p->offset & (sizeof(void *) - 1);
newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE;
if (newSize < size)
return NULL;
adr = ISzAlloc_Alloc(p->baseAlloc, newSize);
if (!adr)
return NULL;
pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr +
alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset;
PrintLn();
Print("- Aligned: ");
Print(" size="); PrintHex(size, 8);
Print(" a_size="); PrintHex(newSize, 8);
Print(" ptr="); PrintAddr(adr);
Print(" a_ptr="); PrintAddr(pAligned);
PrintLn();
REAL_BLOCK_PTR_VAR(pAligned) = adr;
return pAligned;
}
static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address)
{
if (address)
{
CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt);
PrintLn();
Print("- Aligned Free: ");
PrintLn();
ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address));
}
}
void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p)
{
p->vt.Alloc = AlignOffsetAlloc_Alloc;
p->vt.Free = AlignOffsetAlloc_Free;
}

27
C/Alloc.h Executable file → Normal file
View File

@@ -1,12 +1,12 @@
/* Alloc.h -- Memory allocation functions /* Alloc.h -- Memory allocation functions
2008-03-13 2018-02-19 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __COMMON_ALLOC_H #ifndef __COMMON_ALLOC_H
#define __COMMON_ALLOC_H #define __COMMON_ALLOC_H
#include <stddef.h> #include "7zTypes.h"
EXTERN_C_BEGIN
void *MyAlloc(size_t size); void *MyAlloc(size_t size);
void MyFree(void *address); void MyFree(void *address);
@@ -29,4 +29,23 @@ void BigFree(void *address);
#endif #endif
extern const ISzAlloc g_Alloc;
extern const ISzAlloc g_BigAlloc;
extern const ISzAlloc g_MidAlloc;
extern const ISzAlloc g_AlignedAlloc;
typedef struct
{
ISzAlloc vt;
ISzAllocPtr baseAlloc;
unsigned numAlignBits; /* ((1 << numAlignBits) >= sizeof(void *)) */
size_t offset; /* (offset == (k * sizeof(void *)) && offset < (1 << numAlignBits) */
} CAlignOffsetAlloc;
void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p);
EXTERN_C_END
#endif #endif

View File

@@ -1,15 +0,0 @@
/* 7zAlloc.h -- Allocation functions
2008-10-04 : Igor Pavlov : Public domain */
#ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H
#include <stddef.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

View File

@@ -1,254 +0,0 @@
/* 7zDecode.c -- Decoding from 7z folder
2008-11-23 : Igor Pavlov : Public domain */
#include <string.h>
#include "../../Bcj2.h"
#include "../../Bra.h"
#include "../../LzmaDec.h"
#include "7zDecode.h"
#define k_Copy 0
#define k_LZMA 0x30101
#define k_BCJ 0x03030103
#define k_BCJ2 0x0303011B
static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
CLzmaDec state;
SRes res = SZ_OK;
LzmaDec_Construct(&state);
RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
state.dic = outBuffer;
state.dicBufSize = outSize;
LzmaDec_Init(&state);
for (;;)
{
Byte *inBuf = NULL;
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (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 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, (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;
}
#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
SRes CheckSupportedFolder(const CSzFolder *f)
{
if (f->NumCoders < 1 || f->NumCoders > 4)
return SZ_ERROR_UNSUPPORTED;
if (IS_UNSUPPORTED_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)
{
if (IS_NO_BCJ(f->Coders[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;
return SZ_OK;
}
if (f->NumCoders == 4)
{
if (IS_UNSUPPORTED_CODER(f->Coders[1]) ||
IS_UNSUPPORTED_CODER(f->Coders[2]) ||
IS_NO_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;
}
UInt64 GetSum(const UInt64 *values, UInt32 index)
{
UInt64 sum = 0;
UInt32 i;
for (i = 0; i < index; i++)
sum += values[i];
return sum;
}
SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
Byte *tempBuf[])
{
UInt32 ci;
SizeT tempSizes[3] = { 0, 0, 0};
SizeT tempSize3 = 0;
Byte *tempBuf3 = 0;
RINOK(CheckSupportedFolder(folder));
for (ci = 0; ci < folder->NumCoders; ci++)
{
CSzCoderInfo *coder = &folder->Coders[ci];
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
{
UInt32 si = 0;
UInt64 offset;
UInt64 inSize;
Byte *outBufCur = outBuffer;
SizeT outSizeCur = outSize;
if (folder->NumCoders == 4)
{
UInt32 indices[] = { 3, 2, 0 };
UInt64 unpackSize = folder->UnpackSizes[ci];
si = indices[ci];
if (ci < 2)
{
Byte *temp;
outSizeCur = (SizeT)unpackSize;
if (outSizeCur != unpackSize)
return SZ_ERROR_MEM;
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
if (temp == 0 && outSizeCur != 0)
return SZ_ERROR_MEM;
outBufCur = tempBuf[1 - ci] = temp;
tempSizes[1 - ci] = outSizeCur;
}
else if (ci == 2)
{
if (unpackSize > outSize) /* check it */
return SZ_ERROR_PARAM;
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
tempSize3 = outSizeCur = (SizeT)unpackSize;
}
else
return SZ_ERROR_UNSUPPORTED;
}
offset = GetSum(packSizes, si);
inSize = packSizes[si];
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
if (coder->MethodID == k_Copy)
{
if (inSize != outSizeCur) /* check it */
return SZ_ERROR_DATA;
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
}
else
{
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
}
else if (coder->MethodID == k_BCJ)
{
UInt32 state;
if (ci != 1)
return SZ_ERROR_UNSUPPORTED;
x86_Convert_Init(state);
x86_Convert(outBuffer, outSize, 0, &state, 0);
}
else if (coder->MethodID == k_BCJ2)
{
UInt64 offset = GetSum(packSizes, 1);
UInt64 s3Size = packSizes[1];
SRes res;
if (ci != 3)
return SZ_ERROR_UNSUPPORTED;
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
tempSizes[2] = (SizeT)s3Size;
if (tempSizes[2] != s3Size)
return SZ_ERROR_MEM;
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
if (tempBuf[2] == 0 && tempSizes[2] != 0)
return SZ_ERROR_MEM;
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
RINOK(res)
res = Bcj2_Decode(
tempBuf3, tempSize3,
tempBuf[0], tempSizes[0],
tempBuf[1], tempSizes[1],
tempBuf[2], tempSizes[2],
outBuffer, outSize);
RINOK(res)
}
else
return SZ_ERROR_UNSUPPORTED;
}
return SZ_OK;
}
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
{
Byte *tempBuf[3] = { 0, 0, 0};
int i;
SRes res = SzDecode2(packSizes, folder, inStream, startPos,
outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++)
IAlloc_Free(allocMain, tempBuf[i]);
return res;
}

View File

@@ -1,13 +0,0 @@
/* 7zDecode.h -- Decoding from 7z folder
2008-11-23 : Igor Pavlov : Public domain */
#ifndef __7Z_DECODE_H
#define __7Z_DECODE_H
#include "7zItem.h"
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
#endif

View File

@@ -1,93 +0,0 @@
/* 7zExtract.c -- Extracting from 7z archive
2008-11-23 : Igor Pavlov : Public domain */
#include "../../7zCrc.h"
#include "7zDecode.h"
#include "7zExtract.h"
SRes SzAr_Extract(
const CSzArEx *p,
ILookInStream *inStream,
UInt32 fileIndex,
UInt32 *blockIndex,
Byte **outBuffer,
size_t *outBufferSize,
size_t *offset,
size_t *outSizeProcessed,
ISzAlloc *allocMain,
ISzAlloc *allocTemp)
{
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
SRes res = SZ_OK;
*offset = 0;
*outSizeProcessed = 0;
if (folderIndex == (UInt32)-1)
{
IAlloc_Free(allocMain, *outBuffer);
*blockIndex = folderIndex;
*outBuffer = 0;
*outBufferSize = 0;
return SZ_OK;
}
if (*outBuffer == 0 || *blockIndex != folderIndex)
{
CSzFolder *folder = p->db.Folders + folderIndex;
UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
size_t unpackSize = (size_t)unpackSizeSpec;
UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
if (unpackSize != unpackSizeSpec)
return SZ_ERROR_MEM;
*blockIndex = folderIndex;
IAlloc_Free(allocMain, *outBuffer);
*outBuffer = 0;
RINOK(LookInStream_SeekTo(inStream, startOffset));
if (res == SZ_OK)
{
*outBufferSize = unpackSize;
if (unpackSize != 0)
{
*outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
if (*outBuffer == 0)
res = SZ_ERROR_MEM;
}
if (res == SZ_OK)
{
res = SzDecode(p->db.PackSizes +
p->FolderStartPackStreamIndex[folderIndex], folder,
inStream, startOffset,
*outBuffer, unpackSize, allocTemp);
if (res == SZ_OK)
{
if (folder->UnpackCRCDefined)
{
if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
res = SZ_ERROR_CRC;
}
}
}
}
}
if (res == SZ_OK)
{
UInt32 i;
CSzFileItem *fileItem = p->db.Files + fileIndex;
*offset = 0;
for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
*offset += (UInt32)p->db.Files[i].Size;
*outSizeProcessed = (size_t)fileItem->Size;
if (*offset + *outSizeProcessed > *outBufferSize)
return SZ_ERROR_FAIL;
{
if (fileItem->FileCRCDefined)
{
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
res = SZ_ERROR_CRC;
}
}
}
return res;
}

View File

@@ -1,41 +0,0 @@
/* 7zExtract.h -- Extracting from 7z archive
2008-11-23 : Igor Pavlov : Public domain */
#ifndef __7Z_EXTRACT_H
#define __7Z_EXTRACT_H
#include "7zIn.h"
/*
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.
*/
SRes SzAr_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);
#endif

View File

@@ -1,6 +0,0 @@
/* 7zHeader.c -- 7z Headers
2008-10-04 : Igor Pavlov : Public domain */
#include "7zHeader.h"
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};

View File

@@ -1,57 +0,0 @@
/* 7zHeader.h -- 7z Headers
2008-10-04 : Igor Pavlov : Public domain */
#ifndef __7Z_HEADER_H
#define __7Z_HEADER_H
#include "../../Types.h"
#define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize];
#define k7zMajorVersion 0
#define k7zStartHeaderSize 0x20
enum EIdEnum
{
k7zIdEnd,
k7zIdHeader,
k7zIdArchiveProperties,
k7zIdAdditionalStreamsInfo,
k7zIdMainStreamsInfo,
k7zIdFilesInfo,
k7zIdPackInfo,
k7zIdUnpackInfo,
k7zIdSubStreamsInfo,
k7zIdSize,
k7zIdCRC,
k7zIdFolder,
k7zIdCodersUnpackSize,
k7zIdNumUnpackStream,
k7zIdEmptyStream,
k7zIdEmptyFile,
k7zIdAnti,
k7zIdName,
k7zIdCTime,
k7zIdATime,
k7zIdMTime,
k7zIdWinAttributes,
k7zIdComment,
k7zIdEncodedHeader,
k7zIdStartPos,
k7zIdDummy
};
#endif

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,41 +0,0 @@
/* 7zIn.h -- 7z Input functions
2008-11-23 : Igor Pavlov : Public domain */
#ifndef __7Z_IN_H
#define __7Z_IN_H
#include "7zHeader.h"
#include "7zItem.h"
typedef struct
{
CSzAr db;
UInt64 startPosAfterHeader;
UInt64 dataPos;
UInt32 *FolderStartPackStreamIndex;
UInt64 *PackStreamStartPositions;
UInt32 *FolderStartFileIndex;
UInt32 *FileIndexToFolderIndexMap;
} CSzArEx;
void SzArEx_Init(CSzArEx *p);
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
/*
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);
#endif

View File

@@ -1,127 +0,0 @@
/* 7zItem.c -- 7z Items
2008-10-04 : Igor Pavlov : Public domain */
#include "7zItem.h"
void SzCoderInfo_Init(CSzCoderInfo *p)
{
Buf_Init(&p->Props);
}
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
{
Buf_Free(&p->Props, alloc);
SzCoderInfo_Init(p);
}
void SzFolder_Init(CSzFolder *p)
{
p->Coders = 0;
p->BindPairs = 0;
p->PackStreams = 0;
p->UnpackSizes = 0;
p->NumCoders = 0;
p->NumBindPairs = 0;
p->NumPackStreams = 0;
p->UnpackCRCDefined = 0;
p->UnpackCRC = 0;
p->NumUnpackStreams = 0;
}
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
{
UInt32 i;
if (p->Coders)
for (i = 0; i < p->NumCoders; i++)
SzCoderInfo_Free(&p->Coders[i], alloc);
IAlloc_Free(alloc, p->Coders);
IAlloc_Free(alloc, p->BindPairs);
IAlloc_Free(alloc, p->PackStreams);
IAlloc_Free(alloc, p->UnpackSizes);
SzFolder_Init(p);
}
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
{
UInt32 result = 0;
UInt32 i;
for (i = 0; i < p->NumCoders; i++)
result += p->Coders[i].NumOutStreams;
return result;
}
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
{
UInt32 i;
for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].InIndex == inStreamIndex)
return i;
return -1;
}
int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
{
UInt32 i;
for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].OutIndex == outStreamIndex)
return i;
return -1;
}
UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
{
int i = (int)SzFolder_GetNumOutStreams(p);
if (i == 0)
return 0;
for (i--; i >= 0; i--)
if (SzFolder_FindBindPairForOutStream(p, i) < 0)
return p->UnpackSizes[i];
/* throw 1; */
return 0;
}
void SzFile_Init(CSzFileItem *p)
{
p->HasStream = 1;
p->IsDir = 0;
p->IsAnti = 0;
p->FileCRCDefined = 0;
p->MTimeDefined = 0;
p->Name = 0;
}
static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc)
{
IAlloc_Free(alloc, p->Name);
SzFile_Init(p);
}
void SzAr_Init(CSzAr *p)
{
p->PackSizes = 0;
p->PackCRCsDefined = 0;
p->PackCRCs = 0;
p->Folders = 0;
p->Files = 0;
p->NumPackStreams = 0;
p->NumFolders = 0;
p->NumFiles = 0;
}
void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
{
UInt32 i;
if (p->Folders)
for (i = 0; i < p->NumFolders; i++)
SzFolder_Free(&p->Folders[i], alloc);
if (p->Files)
for (i = 0; i < p->NumFiles; i++)
SzFile_Free(&p->Files[i], alloc);
IAlloc_Free(alloc, p->PackSizes);
IAlloc_Free(alloc, p->PackCRCsDefined);
IAlloc_Free(alloc, p->PackCRCs);
IAlloc_Free(alloc, p->Folders);
IAlloc_Free(alloc, p->Files);
SzAr_Init(p);
}

View File

@@ -1,84 +0,0 @@
/* 7zItem.h -- 7z Items
2008-10-04 : Igor Pavlov : Public domain */
#ifndef __7Z_ITEM_H
#define __7Z_ITEM_H
#include "../../7zBuf.h"
typedef struct
{
UInt32 NumInStreams;
UInt32 NumOutStreams;
UInt64 MethodID;
CBuf Props;
} CSzCoderInfo;
void SzCoderInfo_Init(CSzCoderInfo *p);
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
typedef struct
{
UInt32 InIndex;
UInt32 OutIndex;
} CBindPair;
typedef struct
{
CSzCoderInfo *Coders;
CBindPair *BindPairs;
UInt32 *PackStreams;
UInt64 *UnpackSizes;
UInt32 NumCoders;
UInt32 NumBindPairs;
UInt32 NumPackStreams;
int UnpackCRCDefined;
UInt32 UnpackCRC;
UInt32 NumUnpackStreams;
} CSzFolder;
void SzFolder_Init(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
typedef struct
{
UInt32 Low;
UInt32 High;
} CNtfsFileTime;
typedef struct
{
CNtfsFileTime MTime;
UInt64 Size;
char *Name;
UInt32 FileCRC;
Byte HasStream;
Byte IsDir;
Byte IsAnti;
Byte FileCRCDefined;
Byte MTimeDefined;
} CSzFileItem;
void SzFile_Init(CSzFileItem *p);
typedef struct
{
UInt64 *PackSizes;
Byte *PackCRCsDefined;
UInt32 *PackCRCs;
CSzFolder *Folders;
CSzFileItem *Files;
UInt32 NumPackStreams;
UInt32 NumFolders;
UInt32 NumFiles;
} CSzAr;
void SzAr_Init(CSzAr *p);
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
#endif

View File

@@ -1,262 +0,0 @@
/* 7zMain.c - Test application for 7z Decoder
2008-11-23 : Igor Pavlov : Public domain */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../../7zCrc.h"
#include "../../7zFile.h"
#include "../../7zVersion.h"
#include "7zAlloc.h"
#include "7zExtract.h"
#include "7zIn.h"
static void ConvertNumberToString(UInt64 value, char *s)
{
char temp[32];
int pos = 0;
do
{
temp[pos++] = (char)('0' + (int)(value % 10));
value /= 10;
}
while (value != 0);
do
*s++ = temp[--pos];
while (pos > 0);
*s = '\0';
}
#define PERIOD_4 (4 * 365 + 1)
#define PERIOD_100 (PERIOD_4 * 25 - 1)
#define PERIOD_400 (PERIOD_100 * 4 + 1)
static void ConvertFileTimeToString(CNtfsFileTime *ft, char *s)
{
unsigned year, mon, day, hour, min, sec;
UInt64 v64 = ft->Low | ((UInt64)ft->High << 32);
Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
unsigned temp;
UInt32 v;
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;
temp = (unsigned)(v / PERIOD_100);
if (temp == 4)
temp = 3;
year += temp * 100;
v -= temp * PERIOD_100;
temp = v / PERIOD_4;
if (temp == 25)
temp = 24;
year += temp * 4;
v -= temp * PERIOD_4;
temp = v / 365;
if (temp == 4)
temp = 3;
year += temp;
v -= temp * 365;
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
ms[1] = 29;
for (mon = 1; mon <= 12; mon++)
{
unsigned s = ms[mon - 1];
if (v < s)
break;
v -= s;
}
day = (unsigned)v + 1;
sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec);
}
void PrintError(char *sz)
{
printf("\nERROR: %s\n", sz);
}
int MY_CDECL main(int numargs, char *args[])
{
CFileInStream archiveStream;
CLookToRead lookStream;
CSzArEx db;
SRes res;
ISzAlloc allocImp;
ISzAlloc allocTempImp;
printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n");
if (numargs == 1)
{
printf(
"\nUsage: 7zDec <command> <archive_name>\n\n"
"<Commands>\n"
" e: Extract files from archive\n"
" l: List contents of archive\n"
" t: Test integrity of archive\n");
return 0;
}
if (numargs < 3)
{
PrintError("incorrect command");
return 1;
}
if (InFile_Open(&archiveStream.file, args[2]))
{
PrintError("can not open input file");
return 1;
}
FileInStream_CreateVTable(&archiveStream);
LookToRead_CreateVTable(&lookStream, False);
lookStream.realStream = &archiveStream.s;
LookToRead_Init(&lookStream);
allocImp.Alloc = SzAlloc;
allocImp.Free = SzFree;
allocTempImp.Alloc = SzAllocTemp;
allocTempImp.Free = SzFreeTemp;
CrcGenerateTable();
SzArEx_Init(&db);
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
if (res == SZ_OK)
{
char *command = args[1];
int listCommand = 0, testCommand = 0, extractCommand = 0;
if (strcmp(command, "l") == 0) listCommand = 1;
else if (strcmp(command, "t") == 0) testCommand = 1;
else if (strcmp(command, "e") == 0) extractCommand = 1;
if (listCommand)
{
UInt32 i;
for (i = 0; i < db.db.NumFiles; i++)
{
CSzFileItem *f = db.db.Files + i;
char s[32], t[32];
ConvertNumberToString(f->Size, s);
if (f->MTimeDefined)
ConvertFileTimeToString(&f->MTime, t);
else
strcpy(t, " ");
printf("%s %10s %s\n", t, s, f->Name);
}
}
else if (testCommand || extractCommand)
{
UInt32 i;
/*
if you need cache, use these 3 variables.
if you use external function, you can make these variable as static.
*/
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
printf("\n");
for (i = 0; i < db.db.NumFiles; i++)
{
size_t offset;
size_t outSizeProcessed;
CSzFileItem *f = db.db.Files + i;
if (f->IsDir)
printf("Directory ");
else
printf(testCommand ?
"Testing ":
"Extracting");
printf(" %s", f->Name);
if (f->IsDir)
{
printf("\n");
continue;
}
res = SzAr_Extract(&db, &lookStream.s, i,
&blockIndex, &outBuffer, &outBufferSize,
&offset, &outSizeProcessed,
&allocImp, &allocTempImp);
if (res != SZ_OK)
break;
if (!testCommand)
{
CSzFile outFile;
size_t processedSize;
char *fileName = f->Name;
size_t nameLen = strlen(f->Name);
for (; nameLen > 0; nameLen--)
if (f->Name[nameLen - 1] == '/')
{
fileName = f->Name + nameLen;
break;
}
if (OutFile_Open(&outFile, fileName))
{
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;
}
}
printf("\n");
}
IAlloc_Free(&allocImp, outBuffer);
}
else
{
PrintError("incorrect command");
res = SZ_ERROR_FAIL;
}
}
SzArEx_Free(&db, &allocImp);
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;
}

View File

@@ -1,61 +0,0 @@
PROG = 7zDec
CXX = g++
LIB =
RM = rm -f
CFLAGS = -c -O2 -Wall
OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o
all: $(PROG)
$(PROG): $(OBJS)
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
7zAlloc.o: 7zAlloc.c
$(CXX) $(CFLAGS) 7zAlloc.c
7zBuf.o: ../../7zBuf.c
$(CXX) $(CFLAGS) ../../7zBuf.c
7zBuf2.o: ../../7zBuf2.c
$(CXX) $(CFLAGS) ../../7zBuf2.c
7zCrc.o: ../../7zCrc.c
$(CXX) $(CFLAGS) ../../7zCrc.c
7zDecode.o: 7zDecode.c
$(CXX) $(CFLAGS) 7zDecode.c
7zExtract.o: 7zExtract.c
$(CXX) $(CFLAGS) 7zExtract.c
7zHeader.o: 7zHeader.c
$(CXX) $(CFLAGS) 7zHeader.c
7zIn.o: 7zIn.c
$(CXX) $(CFLAGS) 7zIn.c
7zItem.o: 7zItem.c
$(CXX) $(CFLAGS) 7zItem.c
7zMain.o: 7zMain.c
$(CXX) $(CFLAGS) 7zMain.c
LzmaDec.o: ../../LzmaDec.c
$(CXX) $(CFLAGS) ../../LzmaDec.c
Bra86.o: ../../Bra86.c
$(CXX) $(CFLAGS) ../../Bra86.c
Bcj2.o: ../../Bcj2.c
$(CXX) $(CFLAGS) ../../Bcj2.c
7zFile.o: ../../7zFile.c
$(CXX) $(CFLAGS) ../../7zFile.c
7zStream.o: ../../7zStream.c
$(CXX) $(CFLAGS) ../../7zStream.c
clean:
-$(RM) $(PROG) $(OBJS)

335
C/Bcj2.c Executable file → Normal file
View File

@@ -1,132 +1,257 @@
/* Bcj2.c -- Converter for x86 code (BCJ2) /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
2008-10-04 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "Bcj2.h" #include "Bcj2.h"
#include "CpuArch.h"
#ifdef _LZMA_PROB32
#define CProb UInt32
#else
#define CProb UInt16 #define CProb UInt16
#endif
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) #define kTopValue ((UInt32)1 << 24)
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) #define kNumModelBits 11
#define kBitModelTotal (1 << kNumModelBits)
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5 #define kNumMoveBits 5
#define RC_READ_BYTE (*buffer++) #define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } #define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ #define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));
{ 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; } void Bcj2Dec_Init(CBcj2Dec *p)
#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]; unsigned i;
SizeT inPos = 0, outPos = 0;
const Byte *buffer, *bufferLim; p->state = BCJ2_DEC_STATE_OK;
UInt32 range, code; p->ip = 0;
Byte prevByte = 0; p->temp[3] = 0;
p->range = 0;
p->code = 0;
for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)
p->probs[i] = kBitModelTotal >> 1;
}
unsigned int i; SRes Bcj2Dec_Decode(CBcj2Dec *p)
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) {
p[i] = kBitModelTotal >> 1; if (p->range <= 5)
{
p->state = BCJ2_DEC_STATE_OK;
for (; p->range != 5; p->range++)
{
if (p->range == 1 && p->code != 0)
return SZ_ERROR_DATA;
buffer = buf3; if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
bufferLim = buffer + size3; {
RC_INIT2 p->state = BCJ2_STREAM_RC;
return SZ_OK;
}
if (outSize == 0) p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
return SZ_OK; }
if (p->code == 0xFFFFFFFF)
return SZ_ERROR_DATA;
p->range = 0xFFFFFFFF;
}
else if (p->state >= BCJ2_DEC_STATE_ORIG_0)
{
while (p->state <= BCJ2_DEC_STATE_ORIG_3)
{
Byte *dest = p->dest;
if (dest == p->destLim)
return SZ_OK;
*dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0];
p->state++;
p->dest = dest + 1;
}
}
/*
if (BCJ2_IS_32BIT_STREAM(p->state))
{
const Byte *cur = p->bufs[p->state];
if (cur == p->lims[p->state])
return SZ_OK;
p->bufs[p->state] = cur + 4;
{
UInt32 val;
Byte *dest;
SizeT rem;
p->ip += 4;
val = GetBe32(cur) - p->ip;
dest = p->dest;
rem = p->destLim - dest;
if (rem < 4)
{
SizeT i;
SetUi32(p->temp, val);
for (i = 0; i < rem; i++)
dest[i] = p->temp[i];
p->dest = dest + rem;
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
return SZ_OK;
}
SetUi32(dest, val);
p->temp[3] = (Byte)(val >> 24);
p->dest = dest + 4;
p->state = BCJ2_DEC_STATE_OK;
}
}
*/
for (;;) for (;;)
{ {
Byte b; if (BCJ2_IS_32BIT_STREAM(p->state))
CProb *prob; p->state = BCJ2_DEC_STATE_OK;
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 else
{ {
UInt32 dest; if (p->range < kTopValue)
const Byte *v;
UPDATE_1(prob)
if (b == 0xE8)
{ {
v = buf1; if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
if (size1 < 4) {
return SZ_ERROR_DATA; p->state = BCJ2_STREAM_RC;
buf1 += 4; return SZ_OK;
size1 -= 4; }
p->range <<= 8;
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
} }
else
{ {
v = buf2; const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
if (size2 < 4) const Byte *srcLim;
return SZ_ERROR_DATA; Byte *dest;
buf2 += 4; SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;
size2 -= 4;
if (num == 0)
{
p->state = BCJ2_STREAM_MAIN;
return SZ_OK;
}
dest = p->dest;
if (num > (SizeT)(p->destLim - dest))
{
num = p->destLim - dest;
if (num == 0)
{
p->state = BCJ2_DEC_STATE_ORIG;
return SZ_OK;
}
}
srcLim = src + num;
if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)
*dest = src[0];
else for (;;)
{
Byte b = *src;
*dest = b;
if (b != 0x0F)
{
if ((b & 0xFE) == 0xE8)
break;
dest++;
if (++src != srcLim)
continue;
break;
}
dest++;
if (++src == srcLim)
break;
if ((*src & 0xF0) != 0x80)
continue;
*dest = *src;
break;
}
num = src - p->bufs[BCJ2_STREAM_MAIN];
if (src == srcLim)
{
p->temp[3] = src[-1];
p->bufs[BCJ2_STREAM_MAIN] = src;
p->ip += (UInt32)num;
p->dest += num;
p->state =
p->bufs[BCJ2_STREAM_MAIN] ==
p->lims[BCJ2_STREAM_MAIN] ?
(unsigned)BCJ2_STREAM_MAIN :
(unsigned)BCJ2_DEC_STATE_ORIG;
return SZ_OK;
}
{
UInt32 bound, ttt;
CProb *prob;
Byte b = src[0];
Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);
p->temp[3] = b;
p->bufs[BCJ2_STREAM_MAIN] = src + 1;
num++;
p->ip += (UInt32)num;
p->dest += num;
prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));
_IF_BIT_0
{
_UPDATE_0
continue;
}
_UPDATE_1
}
} }
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) UInt32 val;
unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
const Byte *cur = p->bufs[cj];
Byte *dest;
SizeT rem;
if (cur == p->lims[cj])
{
p->state = cj;
break; break;
outBuf[outPos++] = (Byte)(dest >> 8); }
if (outPos == outSize)
val = GetBe32(cur);
p->bufs[cj] = cur + 4;
p->ip += 4;
val -= p->ip;
dest = p->dest;
rem = p->destLim - dest;
if (rem < 4)
{
SizeT i;
SetUi32(p->temp, val);
for (i = 0; i < rem; i++)
dest[i] = p->temp[i];
p->dest = dest + rem;
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
break; break;
outBuf[outPos++] = (Byte)(dest >> 16); }
if (outPos == outSize)
break; SetUi32(dest, val);
outBuf[outPos++] = prevByte = (Byte)(dest >> 24); p->temp[3] = (Byte)(val >> 24);
p->dest = dest + 4;
} }
} }
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])
{
p->range <<= 8;
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
}
return SZ_OK;
} }

156
C/Bcj2.h Executable file → Normal file
View File

@@ -1,30 +1,146 @@
/* Bcj2.h -- Converter for x86 code (BCJ2) /* Bcj2.h -- BCJ2 Converter for x86 code
2008-10-04 : Igor Pavlov : Public domain */ 2014-11-10 : Igor Pavlov : Public domain */
#ifndef __BCJ2_H #ifndef __BCJ2_H
#define __BCJ2_H #define __BCJ2_H
#include "Types.h" #include "7zTypes.h"
EXTERN_C_BEGIN
#define BCJ2_NUM_STREAMS 4
enum
{
BCJ2_STREAM_MAIN,
BCJ2_STREAM_CALL,
BCJ2_STREAM_JUMP,
BCJ2_STREAM_RC
};
enum
{
BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS,
BCJ2_DEC_STATE_ORIG_1,
BCJ2_DEC_STATE_ORIG_2,
BCJ2_DEC_STATE_ORIG_3,
BCJ2_DEC_STATE_ORIG,
BCJ2_DEC_STATE_OK
};
enum
{
BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS,
BCJ2_ENC_STATE_OK
};
#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP)
/* /*
Conditions: CBcj2Dec / CBcj2Enc
outSize <= FullOutputSize, bufs sizes:
where FullOutputSize is full size of output stream of x86_2 filter. BUF_SIZE(n) = lims[n] - bufs[n]
bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4:
If buf0 overlaps outBuf, there are two required conditions: (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0
1) (buf0 >= outBuf) (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0
2) (buf0 + size0 >= outBuf + FullOutputSize).
Returns:
SZ_OK
SZ_ERROR_DATA - Data error
*/ */
int Bcj2_Decode( /*
const Byte *buf0, SizeT size0, CBcj2Dec:
const Byte *buf1, SizeT size1, dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions:
const Byte *buf2, SizeT size2, bufs[BCJ2_STREAM_MAIN] >= dest &&
const Byte *buf3, SizeT size3, bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv +
Byte *outBuf, SizeT outSize); BUF_SIZE(BCJ2_STREAM_CALL) +
BUF_SIZE(BCJ2_STREAM_JUMP)
tempReserv = 0 : for first call of Bcj2Dec_Decode
tempReserv = 4 : for any other calls of Bcj2Dec_Decode
overlap with offset = 1 is not allowed
*/
typedef struct
{
const Byte *bufs[BCJ2_NUM_STREAMS];
const Byte *lims[BCJ2_NUM_STREAMS];
Byte *dest;
const Byte *destLim;
unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */
UInt32 ip;
Byte temp[4];
UInt32 range;
UInt32 code;
UInt16 probs[2 + 256];
} CBcj2Dec;
void Bcj2Dec_Init(CBcj2Dec *p);
/* Returns: SZ_OK or SZ_ERROR_DATA */
SRes Bcj2Dec_Decode(CBcj2Dec *p);
#define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0)
typedef enum
{
BCJ2_ENC_FINISH_MODE_CONTINUE,
BCJ2_ENC_FINISH_MODE_END_BLOCK,
BCJ2_ENC_FINISH_MODE_END_STREAM
} EBcj2Enc_FinishMode;
typedef struct
{
Byte *bufs[BCJ2_NUM_STREAMS];
const Byte *lims[BCJ2_NUM_STREAMS];
const Byte *src;
const Byte *srcLim;
unsigned state;
EBcj2Enc_FinishMode finishMode;
Byte prevByte;
Byte cache;
UInt32 range;
UInt64 low;
UInt64 cacheSize;
UInt32 ip;
/* 32-bit ralative offset in JUMP/CALL commands is
- (mod 4 GB) in 32-bit mode
- signed Int32 in 64-bit mode
We use (mod 4 GB) check for fileSize.
Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */
UInt32 fileIp;
UInt32 fileSize; /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */
UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */
UInt32 tempTarget;
unsigned tempPos;
Byte temp[4 * 2];
unsigned flushPos;
UInt16 probs[2 + 256];
} CBcj2Enc;
void Bcj2Enc_Init(CBcj2Enc *p);
void Bcj2Enc_Encode(CBcj2Enc *p);
#define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos)
#define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5)
#define BCJ2_RELAT_LIMIT_NUM_BITS 26
#define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS)
/* limit for CBcj2Enc::fileSize variable */
#define BCJ2_FileSize_MAX ((UInt32)1 << 31)
EXTERN_C_END
#endif #endif

312
C/Bcj2Enc.c Normal file
View File

@@ -0,0 +1,312 @@
/* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code)
2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
/* #define SHOW_STAT */
#ifdef SHOW_STAT
#include <stdio.h>
#define PRF(x) x
#else
#define PRF(x)
#endif
#include <windows.h>
#include <string.h>
#include "Bcj2.h"
#include "CpuArch.h"
#define CProb UInt16
#define kTopValue ((UInt32)1 << 24)
#define kNumModelBits 11
#define kBitModelTotal (1 << kNumModelBits)
#define kNumMoveBits 5
void Bcj2Enc_Init(CBcj2Enc *p)
{
unsigned i;
p->state = BCJ2_ENC_STATE_OK;
p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;
p->prevByte = 0;
p->cache = 0;
p->range = 0xFFFFFFFF;
p->low = 0;
p->cacheSize = 1;
p->ip = 0;
p->fileIp = 0;
p->fileSize = 0;
p->relatLimit = BCJ2_RELAT_LIMIT;
p->tempPos = 0;
p->flushPos = 0;
for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)
p->probs[i] = kBitModelTotal >> 1;
}
static Bool MY_FAST_CALL RangeEnc_ShiftLow(CBcj2Enc *p)
{
if ((UInt32)p->low < (UInt32)0xFF000000 || (UInt32)(p->low >> 32) != 0)
{
Byte *buf = p->bufs[BCJ2_STREAM_RC];
do
{
if (buf == p->lims[BCJ2_STREAM_RC])
{
p->state = BCJ2_STREAM_RC;
p->bufs[BCJ2_STREAM_RC] = buf;
return True;
}
*buf++ = (Byte)(p->cache + (Byte)(p->low >> 32));
p->cache = 0xFF;
}
while (--p->cacheSize);
p->bufs[BCJ2_STREAM_RC] = buf;
p->cache = (Byte)((UInt32)p->low >> 24);
}
p->cacheSize++;
p->low = (UInt32)p->low << 8;
return False;
}
static void Bcj2Enc_Encode_2(CBcj2Enc *p)
{
if (BCJ2_IS_32BIT_STREAM(p->state))
{
Byte *cur = p->bufs[p->state];
if (cur == p->lims[p->state])
return;
SetBe32(cur, p->tempTarget);
p->bufs[p->state] = cur + 4;
}
p->state = BCJ2_ENC_STATE_ORIG;
for (;;)
{
if (p->range < kTopValue)
{
if (RangeEnc_ShiftLow(p))
return;
p->range <<= 8;
}
{
{
const Byte *src = p->src;
const Byte *srcLim;
Byte *dest;
SizeT num = p->srcLim - src;
if (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE)
{
if (num <= 4)
return;
num -= 4;
}
else if (num == 0)
break;
dest = p->bufs[BCJ2_STREAM_MAIN];
if (num > (SizeT)(p->lims[BCJ2_STREAM_MAIN] - dest))
{
num = p->lims[BCJ2_STREAM_MAIN] - dest;
if (num == 0)
{
p->state = BCJ2_STREAM_MAIN;
return;
}
}
srcLim = src + num;
if (p->prevByte == 0x0F && (src[0] & 0xF0) == 0x80)
*dest = src[0];
else for (;;)
{
Byte b = *src;
*dest = b;
if (b != 0x0F)
{
if ((b & 0xFE) == 0xE8)
break;
dest++;
if (++src != srcLim)
continue;
break;
}
dest++;
if (++src == srcLim)
break;
if ((*src & 0xF0) != 0x80)
continue;
*dest = *src;
break;
}
num = src - p->src;
if (src == srcLim)
{
p->prevByte = src[-1];
p->bufs[BCJ2_STREAM_MAIN] = dest;
p->src = src;
p->ip += (UInt32)num;
continue;
}
{
Byte context = (Byte)(num == 0 ? p->prevByte : src[-1]);
Bool needConvert;
p->bufs[BCJ2_STREAM_MAIN] = dest + 1;
p->ip += (UInt32)num + 1;
src++;
needConvert = False;
if ((SizeT)(p->srcLim - src) >= 4)
{
UInt32 relatVal = GetUi32(src);
if ((p->fileSize == 0 || (UInt32)(p->ip + 4 + relatVal - p->fileIp) < p->fileSize)
&& ((relatVal + p->relatLimit) >> 1) < p->relatLimit)
needConvert = True;
}
{
UInt32 bound;
unsigned ttt;
Byte b = src[-1];
CProb *prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)context : (b == 0xE9 ? 1 : 0));
ttt = *prob;
bound = (p->range >> kNumModelBits) * ttt;
if (!needConvert)
{
p->range = bound;
*prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
p->src = src;
p->prevByte = b;
continue;
}
p->low += bound;
p->range -= bound;
*prob = (CProb)(ttt - (ttt >> kNumMoveBits));
{
UInt32 relatVal = GetUi32(src);
UInt32 absVal;
p->ip += 4;
absVal = p->ip + relatVal;
p->prevByte = src[3];
src += 4;
p->src = src;
{
unsigned cj = (b == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
Byte *cur = p->bufs[cj];
if (cur == p->lims[cj])
{
p->state = cj;
p->tempTarget = absVal;
return;
}
SetBe32(cur, absVal);
p->bufs[cj] = cur + 4;
}
}
}
}
}
}
}
if (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM)
return;
for (; p->flushPos < 5; p->flushPos++)
if (RangeEnc_ShiftLow(p))
return;
p->state = BCJ2_ENC_STATE_OK;
}
void Bcj2Enc_Encode(CBcj2Enc *p)
{
PRF(printf("\n"));
PRF(printf("---- ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));
if (p->tempPos != 0)
{
unsigned extra = 0;
for (;;)
{
const Byte *src = p->src;
const Byte *srcLim = p->srcLim;
unsigned finishMode = p->finishMode;
p->src = p->temp;
p->srcLim = p->temp + p->tempPos;
if (src != srcLim)
p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;
PRF(printf(" ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));
Bcj2Enc_Encode_2(p);
{
unsigned num = (unsigned)(p->src - p->temp);
unsigned tempPos = p->tempPos - num;
unsigned i;
p->tempPos = tempPos;
for (i = 0; i < tempPos; i++)
p->temp[i] = p->temp[(size_t)i + num];
p->src = src;
p->srcLim = srcLim;
p->finishMode = finishMode;
if (p->state != BCJ2_ENC_STATE_ORIG || src == srcLim)
return;
if (extra >= tempPos)
{
p->src = src - tempPos;
p->tempPos = 0;
break;
}
p->temp[tempPos] = src[0];
p->tempPos = tempPos + 1;
p->src = src + 1;
extra++;
}
}
}
PRF(printf("++++ ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));
Bcj2Enc_Encode_2(p);
if (p->state == BCJ2_ENC_STATE_ORIG)
{
const Byte *src = p->src;
unsigned rem = (unsigned)(p->srcLim - src);
unsigned i;
for (i = 0; i < rem; i++)
p->temp[i] = src[i];
p->tempPos = rem;
p->src = src + rem;
}
}

48
C/Blake2.h Normal file
View File

@@ -0,0 +1,48 @@
/* Blake2.h -- BLAKE2 Hash
2015-06-30 : Igor Pavlov : Public domain
2015 : Samuel Neves : Public domain */
#ifndef __BLAKE2_H
#define __BLAKE2_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define BLAKE2S_BLOCK_SIZE 64
#define BLAKE2S_DIGEST_SIZE 32
#define BLAKE2SP_PARALLEL_DEGREE 8
typedef struct
{
UInt32 h[8];
UInt32 t[2];
UInt32 f[2];
Byte buf[BLAKE2S_BLOCK_SIZE];
UInt32 bufPos;
UInt32 lastNode_f1;
UInt32 dummy[2]; /* for sizeof(CBlake2s) alignment */
} CBlake2s;
/* You need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */
/*
void Blake2s_Init0(CBlake2s *p);
void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size);
void Blake2s_Final(CBlake2s *p, Byte *digest);
*/
typedef struct
{
CBlake2s S[BLAKE2SP_PARALLEL_DEGREE];
unsigned bufPos;
} CBlake2sp;
void Blake2sp_Init(CBlake2sp *p);
void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size);
void Blake2sp_Final(CBlake2sp *p, Byte *digest);
EXTERN_C_END
#endif

244
C/Blake2s.c Normal file
View File

@@ -0,0 +1,244 @@
/* Blake2s.c -- BLAKE2s and BLAKE2sp Hash
2015-06-30 : Igor Pavlov : Public domain
2015 : Samuel Neves : Public domain */
#include <string.h>
#include "Blake2.h"
#include "CpuArch.h"
#include "RotateDefs.h"
#define rotr32 rotrFixed
#define BLAKE2S_NUM_ROUNDS 10
#define BLAKE2S_FINAL_FLAG (~(UInt32)0)
static const UInt32 k_Blake2s_IV[8] =
{
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
static const Byte k_Blake2s_Sigma[BLAKE2S_NUM_ROUNDS][16] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
};
void Blake2s_Init0(CBlake2s *p)
{
unsigned i;
for (i = 0; i < 8; i++)
p->h[i] = k_Blake2s_IV[i];
p->t[0] = 0;
p->t[1] = 0;
p->f[0] = 0;
p->f[1] = 0;
p->bufPos = 0;
p->lastNode_f1 = 0;
}
static void Blake2s_Compress(CBlake2s *p)
{
UInt32 m[16];
UInt32 v[16];
{
unsigned i;
for (i = 0; i < 16; i++)
m[i] = GetUi32(p->buf + i * sizeof(m[i]));
for (i = 0; i < 8; i++)
v[i] = p->h[i];
}
v[ 8] = k_Blake2s_IV[0];
v[ 9] = k_Blake2s_IV[1];
v[10] = k_Blake2s_IV[2];
v[11] = k_Blake2s_IV[3];
v[12] = p->t[0] ^ k_Blake2s_IV[4];
v[13] = p->t[1] ^ k_Blake2s_IV[5];
v[14] = p->f[0] ^ k_Blake2s_IV[6];
v[15] = p->f[1] ^ k_Blake2s_IV[7];
#define G(r,i,a,b,c,d) \
a += b + m[sigma[2*i+0]]; d ^= a; d = rotr32(d, 16); c += d; b ^= c; b = rotr32(b, 12); \
a += b + m[sigma[2*i+1]]; d ^= a; d = rotr32(d, 8); c += d; b ^= c; b = rotr32(b, 7); \
#define R(r) \
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
{
unsigned r;
for (r = 0; r < BLAKE2S_NUM_ROUNDS; r++)
{
const Byte *sigma = k_Blake2s_Sigma[r];
R(r);
}
/* R(0); R(1); R(2); R(3); R(4); R(5); R(6); R(7); R(8); R(9); */
}
#undef G
#undef R
{
unsigned i;
for (i = 0; i < 8; i++)
p->h[i] ^= v[i] ^ v[i + 8];
}
}
#define Blake2s_Increment_Counter(S, inc) \
{ p->t[0] += (inc); p->t[1] += (p->t[0] < (inc)); }
#define Blake2s_Set_LastBlock(p) \
{ p->f[0] = BLAKE2S_FINAL_FLAG; p->f[1] = p->lastNode_f1; }
static void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size)
{
while (size != 0)
{
unsigned pos = (unsigned)p->bufPos;
unsigned rem = BLAKE2S_BLOCK_SIZE - pos;
if (size <= rem)
{
memcpy(p->buf + pos, data, size);
p->bufPos += (UInt32)size;
return;
}
memcpy(p->buf + pos, data, rem);
Blake2s_Increment_Counter(S, BLAKE2S_BLOCK_SIZE);
Blake2s_Compress(p);
p->bufPos = 0;
data += rem;
size -= rem;
}
}
static void Blake2s_Final(CBlake2s *p, Byte *digest)
{
unsigned i;
Blake2s_Increment_Counter(S, (UInt32)p->bufPos);
Blake2s_Set_LastBlock(p);
memset(p->buf + p->bufPos, 0, BLAKE2S_BLOCK_SIZE - p->bufPos);
Blake2s_Compress(p);
for (i = 0; i < 8; i++)
SetUi32(digest + sizeof(p->h[i]) * i, p->h[i]);
}
/* ---------- BLAKE2s ---------- */
/* we need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */
/*
typedef struct
{
Byte digest_length;
Byte key_length;
Byte fanout;
Byte depth;
UInt32 leaf_length;
Byte node_offset[6];
Byte node_depth;
Byte inner_length;
Byte salt[BLAKE2S_SALTBYTES];
Byte personal[BLAKE2S_PERSONALBYTES];
} CBlake2sParam;
*/
static void Blake2sp_Init_Spec(CBlake2s *p, unsigned node_offset, unsigned node_depth)
{
Blake2s_Init0(p);
p->h[0] ^= (BLAKE2S_DIGEST_SIZE | ((UInt32)BLAKE2SP_PARALLEL_DEGREE << 16) | ((UInt32)2 << 24));
p->h[2] ^= ((UInt32)node_offset);
p->h[3] ^= ((UInt32)node_depth << 16) | ((UInt32)BLAKE2S_DIGEST_SIZE << 24);
/*
P->digest_length = BLAKE2S_DIGEST_SIZE;
P->key_length = 0;
P->fanout = BLAKE2SP_PARALLEL_DEGREE;
P->depth = 2;
P->leaf_length = 0;
store48(P->node_offset, node_offset);
P->node_depth = node_depth;
P->inner_length = BLAKE2S_DIGEST_SIZE;
*/
}
void Blake2sp_Init(CBlake2sp *p)
{
unsigned i;
p->bufPos = 0;
for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++)
Blake2sp_Init_Spec(&p->S[i], i, 0);
p->S[BLAKE2SP_PARALLEL_DEGREE - 1].lastNode_f1 = BLAKE2S_FINAL_FLAG;
}
void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size)
{
unsigned pos = p->bufPos;
while (size != 0)
{
unsigned index = pos / BLAKE2S_BLOCK_SIZE;
unsigned rem = BLAKE2S_BLOCK_SIZE - (pos & (BLAKE2S_BLOCK_SIZE - 1));
if (rem > size)
rem = (unsigned)size;
Blake2s_Update(&p->S[index], data, rem);
size -= rem;
data += rem;
pos += rem;
pos &= (BLAKE2S_BLOCK_SIZE * BLAKE2SP_PARALLEL_DEGREE - 1);
}
p->bufPos = pos;
}
void Blake2sp_Final(CBlake2sp *p, Byte *digest)
{
CBlake2s R;
unsigned i;
Blake2sp_Init_Spec(&R, 0, 1);
R.lastNode_f1 = BLAKE2S_FINAL_FLAG;
for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++)
{
Byte hash[BLAKE2S_DIGEST_SIZE];
Blake2s_Final(&p->S[i], hash);
Blake2s_Update(&R, hash, BLAKE2S_DIGEST_SIZE);
}
Blake2s_Final(&R, digest);
}

281
C/Bra.c Executable file → Normal file
View File

@@ -1,133 +1,230 @@
/* Bra.c -- Converters for RISC code /* Bra.c -- Converters for RISC code
2008-10-04 : Igor Pavlov : Public domain */ 2017-04-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "CpuArch.h"
#include "Bra.h" #include "Bra.h"
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
SizeT i; Byte *p;
if (size < 4) const Byte *lim;
return 0; size &= ~(size_t)3;
size -= 4; ip += 4;
ip += 8; p = data;
for (i = 0; i <= size; i += 4) lim = data + size;
if (encoding)
for (;;)
{ {
if (data[i + 3] == 0xEB) for (;;)
{ {
UInt32 dest; if (p >= lim)
UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); return p - data;
src <<= 2; p += 4;
if (encoding) if (p[-1] == 0xEB)
dest = ip + (UInt32)i + src; break;
else }
dest = src - (ip + (UInt32)i); {
dest >>= 2; UInt32 v = GetUi32(p - 4);
data[i + 2] = (Byte)(dest >> 16); v <<= 2;
data[i + 1] = (Byte)(dest >> 8); v += ip + (UInt32)(p - data);
data[i + 0] = (Byte)dest; v >>= 2;
v &= 0x00FFFFFF;
v |= 0xEB000000;
SetUi32(p - 4, v);
}
}
for (;;)
{
for (;;)
{
if (p >= lim)
return p - data;
p += 4;
if (p[-1] == 0xEB)
break;
}
{
UInt32 v = GetUi32(p - 4);
v <<= 2;
v -= ip + (UInt32)(p - data);
v >>= 2;
v &= 0x00FFFFFF;
v |= 0xEB000000;
SetUi32(p - 4, v);
} }
} }
return i;
} }
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
SizeT i; Byte *p;
if (size < 4) const Byte *lim;
return 0; size &= ~(size_t)1;
size -= 4; p = data;
ip += 4; lim = data + size - 4;
for (i = 0; i <= size; i += 2)
if (encoding)
for (;;)
{ {
if ((data[i + 1] & 0xF8) == 0xF0 && UInt32 b1;
(data[i + 3] & 0xF8) == 0xF8) for (;;)
{ {
UInt32 dest; UInt32 b3;
UInt32 src = if (p > lim)
(((UInt32)data[i + 1] & 0x7) << 19) | return p - data;
((UInt32)data[i + 0] << 11) | b1 = p[1];
(((UInt32)data[i + 3] & 0x7) << 8) | b3 = p[3];
(data[i + 2]); p += 2;
b1 ^= 8;
if ((b3 & b1) >= 0xF8)
break;
}
{
UInt32 v =
((UInt32)b1 << 19)
+ (((UInt32)p[1] & 0x7) << 8)
+ (((UInt32)p[-2] << 11))
+ (p[0]);
src <<= 1; p += 2;
if (encoding) {
dest = ip + (UInt32)i + src; UInt32 cur = (ip + (UInt32)(p - data)) >> 1;
else v += cur;
dest = src - (ip + (UInt32)i); }
dest >>= 1;
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); p[-4] = (Byte)(v >> 11);
data[i + 0] = (Byte)(dest >> 11); p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7));
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); p[-2] = (Byte)v;
data[i + 2] = (Byte)dest; p[-1] = (Byte)(0xF8 | (v >> 8));
i += 2; }
}
for (;;)
{
UInt32 b1;
for (;;)
{
UInt32 b3;
if (p > lim)
return p - data;
b1 = p[1];
b3 = p[3];
p += 2;
b1 ^= 8;
if ((b3 & b1) >= 0xF8)
break;
}
{
UInt32 v =
((UInt32)b1 << 19)
+ (((UInt32)p[1] & 0x7) << 8)
+ (((UInt32)p[-2] << 11))
+ (p[0]);
p += 2;
{
UInt32 cur = (ip + (UInt32)(p - data)) >> 1;
v -= cur;
}
/*
SetUi16(p - 4, (UInt16)(((v >> 11) & 0x7FF) | 0xF000));
SetUi16(p - 2, (UInt16)(v | 0xF800));
*/
p[-4] = (Byte)(v >> 11);
p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7));
p[-2] = (Byte)v;
p[-1] = (Byte)(0xF8 | (v >> 8));
} }
} }
return i;
} }
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
SizeT i; Byte *p;
if (size < 4) const Byte *lim;
return 0; size &= ~(size_t)3;
size -= 4; ip -= 4;
for (i = 0; i <= size; i += 4) p = data;
{ lim = data + size;
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; for (;;)
{
for (;;)
{
if (p >= lim)
return p - data;
p += 4;
/* if ((v & 0xFC000003) == 0x48000001) */
if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1)
break;
}
{
UInt32 v = GetBe32(p - 4);
if (encoding) if (encoding)
dest = ip + (UInt32)i + src; v += ip + (UInt32)(p - data);
else else
dest = src - (ip + (UInt32)i); v -= ip + (UInt32)(p - data);
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); v &= 0x03FFFFFF;
data[i + 1] = (Byte)(dest >> 16); v |= 0x48000000;
data[i + 2] = (Byte)(dest >> 8); SetBe32(p - 4, v);
data[i + 3] &= 0x3;
data[i + 3] |= dest;
} }
} }
return i;
} }
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
UInt32 i; Byte *p;
if (size < 4) const Byte *lim;
return 0; size &= ~(size_t)3;
size -= 4; ip -= 4;
for (i = 0; i <= size; i += 4) p = data;
lim = data + size;
for (;;)
{ {
if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || for (;;)
data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)
{ {
UInt32 src = if (p >= lim)
((UInt32)data[i + 0] << 24) | return p - data;
((UInt32)data[i + 1] << 16) | /*
((UInt32)data[i + 2] << 8) | v = GetBe32(p);
((UInt32)data[i + 3]); p += 4;
UInt32 dest; m = v + ((UInt32)5 << 29);
m ^= (UInt32)7 << 29;
src <<= 2; m += (UInt32)1 << 22;
if ((m & ((UInt32)0x1FF << 23)) == 0)
break;
*/
p += 4;
if ((p[-4] == 0x40 && (p[-3] & 0xC0) == 0) ||
(p[-4] == 0x7F && (p[-3] >= 0xC0)))
break;
}
{
UInt32 v = GetBe32(p - 4);
v <<= 2;
if (encoding) if (encoding)
dest = ip + i + src; v += ip + (UInt32)(p - data);
else else
dest = src - (ip + i); v -= ip + (UInt32)(p - data);
dest >>= 2;
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; v &= 0x01FFFFFF;
v -= (UInt32)1 << 24;
data[i + 0] = (Byte)(dest >> 24); v ^= 0xFF000000;
data[i + 1] = (Byte)(dest >> 16); v >>= 2;
data[i + 2] = (Byte)(dest >> 8); v |= 0x40000000;
data[i + 3] = (Byte)dest; SetBe32(p - 4, v);
} }
} }
return i;
} }

8
C/Bra.h Executable file → Normal file
View File

@@ -1,10 +1,12 @@
/* Bra.h -- Branch converters for executables /* Bra.h -- Branch converters for executables
2008-10-04 : Igor Pavlov : Public domain */ 2013-01-18 : Igor Pavlov : Public domain */
#ifndef __BRA_H #ifndef __BRA_H
#define __BRA_H #define __BRA_H
#include "Types.h" #include "7zTypes.h"
EXTERN_C_BEGIN
/* /*
These functions convert relative addresses to absolute addresses These functions convert relative addresses to absolute addresses
@@ -57,4 +59,6 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT SPARC_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); SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
EXTERN_C_END
#endif #endif

99
C/Bra86.c Executable file → Normal file
View File

@@ -1,85 +1,82 @@
/* Bra86.c -- Converter for x86 code (BCJ) /* Bra86.c -- Converter for x86 code (BCJ)
2008-10-04 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "Bra.h" #include "Bra.h"
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) #define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)
const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
{ {
SizeT bufferPos = 0, prevPosT; SizeT pos = 0;
UInt32 prevMask = *state & 0x7; UInt32 mask = *state & 7;
if (size < 5) if (size < 5)
return 0; return 0;
size -= 4;
ip += 5; ip += 5;
prevPosT = (SizeT)0 - 1;
for (;;) for (;;)
{ {
Byte *p = data + bufferPos; Byte *p = data + pos;
Byte *limit = data + size - 4; const Byte *limit = data + size;
for (; p < limit; p++) for (; p < limit; p++)
if ((*p & 0xFE) == 0xE8) if ((*p & 0xFE) == 0xE8)
break; break;
bufferPos = (SizeT)(p - data);
if (p >= limit)
break;
prevPosT = bufferPos - prevPosT;
if (prevPosT > 3)
prevMask = 0;
else
{ {
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; SizeT d = (SizeT)(p - data - pos);
if (prevMask != 0) pos = (SizeT)(p - data);
if (p >= limit)
{ {
Byte b = p[4 - kMaskToBitNumber[prevMask]]; *state = (d > 2 ? 0 : mask >> (unsigned)d);
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) return pos;
}
if (d > 2)
mask = 0;
else
{
mask >>= (unsigned)d;
if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(size_t)(mask >> 1) + 1])))
{ {
prevPosT = bufferPos; mask = (mask >> 1) | 4;
prevMask = ((prevMask << 1) & 0x7) | 1; pos++;
bufferPos++;
continue; continue;
} }
} }
} }
prevPosT = bufferPos;
if (Test86MSByte(p[4])) if (Test86MSByte(p[4]))
{ {
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
UInt32 dest; UInt32 cur = ip + (UInt32)pos;
for (;;) pos += 5;
if (encoding)
v += cur;
else
v -= cur;
if (mask != 0)
{ {
Byte b; unsigned sh = (mask & 6) << 2;
int index; if (Test86MSByte((Byte)(v >> sh)))
if (encoding) {
dest = (ip + (UInt32)bufferPos) + src; v ^= (((UInt32)0x100 << sh) - 1);
else if (encoding)
dest = src - (ip + (UInt32)bufferPos); v += cur;
if (prevMask == 0) else
break; v -= cur;
index = kMaskToBitNumber[prevMask] * 8; }
b = (Byte)(dest >> (24 - index)); mask = 0;
if (!Test86MSByte(b))
break;
src = dest ^ ((1 << (32 - index)) - 1);
} }
p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); p[1] = (Byte)v;
p[3] = (Byte)(dest >> 16); p[2] = (Byte)(v >> 8);
p[2] = (Byte)(dest >> 8); p[3] = (Byte)(v >> 16);
p[1] = (Byte)dest; p[4] = (Byte)(0 - ((v >> 24) & 1));
bufferPos += 5;
} }
else else
{ {
prevMask = ((prevMask << 1) & 0x7) | 1; mask = (mask >> 1) | 4;
bufferPos++; pos++;
} }
} }
prevPosT = bufferPos - prevPosT;
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
return bufferPos;
} }

80
C/BraIA64.c Executable file → Normal file
View File

@@ -1,67 +1,53 @@
/* BraIA64.c -- Converter for IA-64 code /* BraIA64.c -- Converter for IA-64 code
2008-10-04 : Igor Pavlov : Public domain */ 2017-01-26 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "CpuArch.h"
#include "Bra.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 IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
SizeT i; SizeT i;
if (size < 16) if (size < 16)
return 0; return 0;
size -= 16; size -= 16;
for (i = 0; i <= size; i += 16) i = 0;
do
{ {
UInt32 instrTemplate = data[i] & 0x1F; unsigned m = ((UInt32)0x334B0000 >> (data[i] & 0x1E)) & 3;
UInt32 mask = kBranchTable[instrTemplate]; if (m)
UInt32 bitPos = 5;
int slot;
for (slot = 0; slot < 3; slot++, bitPos += 41)
{ {
UInt32 bytePos, bitRes; m++;
UInt64 instruction, instNorm; do
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); Byte *p = data + (i + (size_t)m * 5 - 8);
UInt32 dest; if (((p[3] >> m) & 15) == 5
src |= ((UInt32)(instNorm >> 36) & 1) << 20; && (((p[-1] | ((UInt32)p[0] << 8)) >> m) & 0x70) == 0)
{
unsigned raw = GetUi32(p);
unsigned v = raw >> m;
v = (v & 0xFFFFF) | ((v & (1 << 23)) >> 3);
src <<= 4; v <<= 4;
if (encoding)
v += ip + (UInt32)i;
else
v -= ip + (UInt32)i;
v >>= 4;
if (encoding) v &= 0x1FFFFF;
dest = ip + (UInt32)i + src; v += 0x700000;
else v &= 0x8FFFFF;
dest = src - (ip + (UInt32)i); raw &= ~((UInt32)0x8FFFFF << m);
raw |= (v << m);
dest >>= 4; SetUi32(p, raw);
}
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));
} }
while (++m <= 4);
} }
i += 16;
} }
while (i <= size);
return i; return i;
} }

25
C/BwtSort.c Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* BwtSort.c -- BWT block sorting /* BwtSort.c -- BWT block sorting
2008-08-17 2017-04-03 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */ #include "Precomp.h"
#include "BwtSort.h" #include "BwtSort.h"
#include "Sort.h" #include "Sort.h"
@@ -314,7 +314,7 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
#ifndef BLOCK_SORT_EXTERNAL_FLAGS #ifndef BLOCK_SORT_EXTERNAL_FLAGS
UInt32 subGroupSize = ((ind2[j] & ~0xC0000000) >> kNumBitsMax); UInt32 subGroupSize = ((ind2[j] & ~0xC0000000) >> kNumBitsMax);
if ((ind2[j] & 0x40000000) != 0) if ((ind2[j] & 0x40000000) != 0)
subGroupSize += ((ind2[j + 1] >> kNumBitsMax) << kNumExtra0Bits); subGroupSize += ((ind2[(size_t)j + 1] >> kNumBitsMax) << kNumExtra0Bits);
subGroupSize++; subGroupSize++;
for (;;) for (;;)
{ {
@@ -362,7 +362,7 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
for (i = 0; i < kNumHashValues; i++) for (i = 0; i < kNumHashValues; i++)
counters[i] = 0; counters[i] = 0;
for (i = 0; i < blockSize - 1; i++) for (i = 0; i < blockSize - 1; i++)
counters[((UInt32)data[i] << 8) | data[i + 1]]++; counters[((UInt32)data[i] << 8) | data[(size_t)i + 1]]++;
counters[((UInt32)data[i] << 8) | data[0]]++; counters[((UInt32)data[i] << 8) | data[0]]++;
Groups = counters + BS_TEMP_SIZE; Groups = counters + BS_TEMP_SIZE;
@@ -392,11 +392,11 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
} }
for (i = 0; i < blockSize - 1; i++) for (i = 0; i < blockSize - 1; i++)
Groups[i] = counters[((UInt32)data[i] << 8) | data[i + 1]]; Groups[i] = counters[((UInt32)data[i] << 8) | data[(size_t)i + 1]];
Groups[i] = counters[((UInt32)data[i] << 8) | data[0]]; Groups[i] = counters[((UInt32)data[i] << 8) | data[0]];
for (i = 0; i < blockSize - 1; i++) for (i = 0; i < blockSize - 1; i++)
Indices[counters[((UInt32)data[i] << 8) | data[i + 1]]++] = i; Indices[counters[((UInt32)data[i] << 8) | data[(size_t)i + 1]]++] = i;
Indices[counters[((UInt32)data[i] << 8) | data[0]]++] = i; Indices[counters[((UInt32)data[i] << 8) | data[0]]++] = i;
#ifndef BLOCK_SORT_EXTERNAL_FLAGS #ifndef BLOCK_SORT_EXTERNAL_FLAGS
@@ -451,8 +451,8 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
Bool finishedGroup = ((Indices[i] & 0x80000000) == 0); Bool finishedGroup = ((Indices[i] & 0x80000000) == 0);
if ((Indices[i] & 0x40000000) != 0) if ((Indices[i] & 0x40000000) != 0)
{ {
groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits); groupSize += ((Indices[(size_t)i + 1] >> kNumBitsMax) << kNumExtra0Bits);
Indices[i + 1] &= kIndexMask; Indices[(size_t)i + 1] &= kIndexMask;
} }
Indices[i] &= kIndexMask; Indices[i] &= kIndexMask;
groupSize++; groupSize++;
@@ -460,7 +460,7 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
{ {
Indices[i - finishedGroupSize] &= kIndexMask; Indices[i - finishedGroupSize] &= kIndexMask;
if (finishedGroupSize > 1) if (finishedGroupSize > 1)
Indices[i - finishedGroupSize + 1] &= kIndexMask; Indices[(size_t)(i - finishedGroupSize) + 1] &= kIndexMask;
{ {
UInt32 newGroupSize = groupSize + finishedGroupSize; UInt32 newGroupSize = groupSize + finishedGroupSize;
SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize); SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize);
@@ -503,8 +503,8 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
UInt32 groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax); UInt32 groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax);
if ((Indices[i] & 0x40000000) != 0) if ((Indices[i] & 0x40000000) != 0)
{ {
groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits); groupSize += ((Indices[(size_t)i + 1] >> kNumBitsMax) << kNumExtra0Bits);
Indices[i + 1] &= kIndexMask; Indices[(size_t)i + 1] &= kIndexMask;
} }
Indices[i] &= kIndexMask; Indices[i] &= kIndexMask;
groupSize++; groupSize++;
@@ -513,4 +513,3 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
#endif #endif
return Groups[0]; return Groups[0];
} }

14
C/BwtSort.h Executable file → Normal file
View File

@@ -1,12 +1,12 @@
/* BwtSort.h -- BWT block sorting /* BwtSort.h -- BWT block sorting
2008-03-26 2013-01-18 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __BWTSORT_H #ifndef __BWT_SORT_H
#define __BWTSORT_H #define __BWT_SORT_H
#include "Types.h" #include "7zTypes.h"
EXTERN_C_BEGIN
/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */ /* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */
/* #define BLOCK_SORT_EXTERNAL_FLAGS */ /* #define BLOCK_SORT_EXTERNAL_FLAGS */
@@ -21,4 +21,6 @@ Public domain */
UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize); UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize);
EXTERN_C_END
#endif #endif

33
C/Compiler.h Normal file
View File

@@ -0,0 +1,33 @@
/* Compiler.h
2017-04-03 : 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 : 4514) // unreferenced inline function has been removed
#pragma warning(disable : 4702) // unreachable code
#pragma warning(disable : 4710) // not inlined
#pragma warning(disable : 4714) // function marked as __forceinline not inlined
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
#endif
#endif
#define UNUSED_VAR(x) (void)x;
/* #define UNUSED_VAR(x) x=x; */
#endif

200
C/CpuArch.c Normal file
View File

@@ -0,0 +1,200 @@
/* CpuArch.c -- CPU specific code
2016-02-25: 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) :
"%eax", "%edx");
#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
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_AMD64) && defined(__PIC__)
"mov %%rbx, %%rdi;"
"cpuid;"
"xchg %%rbx, %%rdi;"
: "=a" (*a) ,
"=D" (*b) ,
#elif 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 const 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.ver);
model = x86cpuid_GetModel(p.ver);
firm = x86cpuid_GetFirm(&p);
switch (firm)
{
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
/* In-Order Atom CPU */
model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */
|| model == 0x26 /* 45 nm, Z6xx */
|| model == 0x27 /* 32 nm, Z2460 */
|| model == 0x35 /* 32 nm, Z2760 */
|| model == 0x36 /* 32 nm, N2xxx, D2xxx */
)));
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
}
return 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

322
C/CpuArch.h Executable file → Normal file
View File

@@ -1,33 +1,216 @@
/* CpuArch.h /* CpuArch.h -- CPU specific code
2008-08-05 2017-09-04 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __CPUARCH_H #ifndef __CPU_ARCH_H
#define __CPUARCH_H #define __CPU_ARCH_H
#include "7zTypes.h"
EXTERN_C_BEGIN
/* /*
LITTLE_ENDIAN_UNALIGN means: MY_CPU_LE means that CPU is LITTLE ENDIAN.
1) CPU is LITTLE_ENDIAN MY_CPU_BE means that CPU is BIG ENDIAN.
2) it's allowed to make unaligned memory accesses If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform.
if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know
about these properties of platform. MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
*/ */
#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #if defined(_M_X64) \
#define LITTLE_ENDIAN_UNALIGN || defined(_M_AMD64) \
|| defined(__x86_64__) \
|| defined(__AMD64__) \
|| defined(__amd64__)
#define MY_CPU_AMD64
#ifdef __ILP32__
#define MY_CPU_NAME "x32"
#else
#define MY_CPU_NAME "x64"
#endif
#define MY_CPU_64BIT
#endif #endif
#ifdef LITTLE_ENDIAN_UNALIGN
#define GetUi16(p) (*(const UInt16 *)(p)) #if defined(_M_IX86) \
#define GetUi32(p) (*(const UInt32 *)(p)) || defined(__i386__)
#define GetUi64(p) (*(const UInt64 *)(p)) #define MY_CPU_X86
#define SetUi32(p, d) *(UInt32 *)(p) = (d); #define MY_CPU_NAME "x86"
#define MY_CPU_32BIT
#endif
#if defined(_M_ARM64) \
|| defined(__AARCH64EL__) \
|| defined(__AARCH64EB__) \
|| defined(__aarch64__)
#define MY_CPU_ARM64
#define MY_CPU_NAME "arm64"
#define MY_CPU_64BIT
#endif
#if defined(_M_ARM) \
|| defined(_M_ARM_NT) \
|| defined(_M_ARMT) \
|| defined(__arm__) \
|| defined(__thumb__) \
|| defined(__ARMEL__) \
|| defined(__ARMEB__) \
|| defined(__THUMBEL__) \
|| defined(__THUMBEB__)
#define MY_CPU_ARM
#define MY_CPU_NAME "arm"
#define MY_CPU_32BIT
#endif
#if defined(_M_IA64) \
|| defined(__ia64__)
#define MY_CPU_IA64
#define MY_CPU_NAME "ia64"
#define MY_CPU_64BIT
#endif
#if defined(__mips64) \
|| defined(__mips64__) \
|| (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3))
#define MY_CPU_NAME "mips64"
#define MY_CPU_64BIT
#elif defined(__mips__)
#define MY_CPU_NAME "mips"
/* #define MY_CPU_32BIT */
#endif
#if defined(__ppc64__) \
|| defined(__powerpc64__)
#ifdef __ILP32__
#define MY_CPU_NAME "ppc64-32"
#else
#define MY_CPU_NAME "ppc64"
#endif
#define MY_CPU_64BIT
#elif defined(__ppc__) \
|| defined(__powerpc__)
#define MY_CPU_NAME "ppc"
#define MY_CPU_32BIT
#endif
#if defined(__sparc64__)
#define MY_CPU_NAME "sparc64"
#define MY_CPU_64BIT
#elif defined(__sparc__)
#define MY_CPU_NAME "sparc"
/* #define MY_CPU_32BIT */
#endif
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
#define MY_CPU_X86_OR_AMD64
#endif
#ifdef _WIN32
#ifdef MY_CPU_ARM
#define MY_CPU_ARM_LE
#endif
#ifdef MY_CPU_ARM64
#define MY_CPU_ARM64_LE
#endif
#ifdef _M_IA64
#define MY_CPU_IA64_LE
#endif
#endif
#if defined(MY_CPU_X86_OR_AMD64) \
|| defined(MY_CPU_ARM_LE) \
|| defined(MY_CPU_ARM64_LE) \
|| defined(MY_CPU_IA64_LE) \
|| defined(__LITTLE_ENDIAN__) \
|| defined(__ARMEL__) \
|| defined(__THUMBEL__) \
|| defined(__AARCH64EL__) \
|| defined(__MIPSEL__) \
|| defined(__MIPSEL) \
|| defined(_MIPSEL) \
|| defined(__BFIN__) \
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
#define MY_CPU_LE
#endif
#if defined(__BIG_ENDIAN__) \
|| defined(__ARMEB__) \
|| defined(__THUMBEB__) \
|| defined(__AARCH64EB__) \
|| defined(__MIPSEB__) \
|| defined(__MIPSEB) \
|| defined(_MIPSEB) \
|| defined(__m68k__) \
|| defined(__s390__) \
|| defined(__s390x__) \
|| defined(__zarch__) \
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
#define MY_CPU_BE
#endif
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
#error Stop_Compiling_Bad_Endian
#endif
#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT)
#error Stop_Compiling_Bad_32_64_BIT
#endif
#ifndef MY_CPU_NAME
#ifdef MY_CPU_LE
#define MY_CPU_NAME "LE"
#elif defined(MY_CPU_BE)
#define MY_CPU_NAME "BE"
#else
/*
#define MY_CPU_NAME ""
*/
#endif
#endif
#ifdef MY_CPU_LE
#if defined(MY_CPU_X86_OR_AMD64) \
|| defined(MY_CPU_ARM64) \
|| defined(__ARM_FEATURE_UNALIGNED)
#define MY_CPU_LE_UNALIGN
#endif
#endif
#ifdef MY_CPU_LE_UNALIGN
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
#define GetUi64(p) (*(const UInt64 *)(const void *)(p))
#define SetUi16(p, v) { *(UInt16 *)(p) = (v); }
#define SetUi32(p, v) { *(UInt32 *)(p) = (v); }
#define SetUi64(p, v) { *(UInt64 *)(p) = (v); }
#else #else
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) #define GetUi16(p) ( (UInt16) ( \
((const Byte *)(p))[0] | \
((UInt16)((const Byte *)(p))[1] << 8) ))
#define GetUi32(p) ( \ #define GetUi32(p) ( \
((const Byte *)(p))[0] | \ ((const Byte *)(p))[0] | \
@@ -37,21 +220,54 @@ about these properties of platform.
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
#define SetUi32(p, d) { UInt32 _x_ = (d); \ #define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
((Byte *)(p))[0] = (Byte)_x_; \ _ppp_[0] = (Byte)_vvv_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ _ppp_[1] = (Byte)(_vvv_ >> 8); }
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
((Byte *)(p))[3] = (Byte)(_x_ >> 24); } #define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
_ppp_[0] = (Byte)_vvv_; \
_ppp_[1] = (Byte)(_vvv_ >> 8); \
_ppp_[2] = (Byte)(_vvv_ >> 16); \
_ppp_[3] = (Byte)(_vvv_ >> 24); }
#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \
SetUi32(_ppp2_ , (UInt32)_vvv2_); \
SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); }
#endif #endif
#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) #ifdef __has_builtin
#define MY__has_builtin(x) __has_builtin(x)
#else
#define MY__has_builtin(x) 0
#endif
#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
/* Note: we use bswap instruction, that is unsupported in 386 cpu */
#include <stdlib.h>
#pragma intrinsic(_byteswap_ushort)
#pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_ulong)
#pragma intrinsic(_byteswap_uint64) #pragma intrinsic(_byteswap_uint64)
/* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v)
#elif defined(MY_CPU_LE_UNALIGN) && ( \
(defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \
|| (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) )
/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const Byte *)(p)) */
#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p))
#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p))
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v)
#else #else
#define GetBe32(p) ( \ #define GetBe32(p) ( \
@@ -62,8 +278,58 @@ about these properties of platform.
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
#endif #define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
_ppp_[0] = (Byte)(_vvv_ >> 24); \
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) _ppp_[1] = (Byte)(_vvv_ >> 16); \
_ppp_[2] = (Byte)(_vvv_ >> 8); \
_ppp_[3] = (Byte)_vvv_; }
#endif
#ifndef GetBe16
#define GetBe16(p) ( (UInt16) ( \
((UInt16)((const Byte *)(p))[0] << 8) | \
((const Byte *)(p))[1] ))
#endif
#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
};
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
int x86cpuid_GetFirm(const Cx86cpuid *p);
#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
#define x86cpuid_GetStepping(ver) (ver & 0xF)
Bool CPU_Is_InOrder();
Bool CPU_Is_Aes_Supported();
#endif
EXTERN_C_END
#endif #endif

64
C/Delta.c Normal file
View File

@@ -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);
}

19
C/Delta.h Normal file
View File

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

87
C/DllSecur.c Normal file
View File

@@ -0,0 +1,87 @@
/* DllSecur.c -- DLL loading security
2016-10-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
#ifdef _WIN32
#include <windows.h>
#include "DllSecur.h"
#ifndef UNDER_CE
typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags);
#define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400
#define MY_LOAD_LIBRARY_SEARCH_SYSTEM32 0x800
static const char * const g_Dlls =
#ifndef _CONSOLE
"UXTHEME\0"
#endif
"USERENV\0"
"SETUPAPI\0"
"APPHELP\0"
"PROPSYS\0"
"DWMAPI\0"
"CRYPTBASE\0"
"OLEACC\0"
"CLBCATQ\0"
;
#endif
void LoadSecurityDlls()
{
#ifndef UNDER_CE
wchar_t buf[MAX_PATH + 100];
{
// at Vista (ver 6.0) : CoCreateInstance(CLSID_ShellLink, ...) doesn't work after SetDefaultDllDirectories() : Check it ???
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0)
{
Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories)
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories");
if (setDllDirs)
if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS))
return;
}
}
{
unsigned len = GetSystemDirectoryW(buf, MAX_PATH + 2);
if (len == 0 || len > MAX_PATH)
return;
}
{
const char *dll;
unsigned pos = (unsigned)lstrlenW(buf);
if (buf[pos - 1] != '\\')
buf[pos++] = '\\';
for (dll = g_Dlls; dll[0] != 0;)
{
unsigned k = 0;
for (;;)
{
char c = *dll++;
buf[pos + k] = c;
k++;
if (c == 0)
break;
}
lstrcatW(buf, L".dll");
LoadLibraryExW(buf, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
}
#endif
}
#endif

19
C/DllSecur.h Normal file
View File

@@ -0,0 +1,19 @@
/* DllSecur.h -- DLL loading for security
2016-06-08 : Igor Pavlov : Public domain */
#ifndef __DLL_SECUR_H
#define __DLL_SECUR_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#ifdef _WIN32
void LoadSecurityDlls();
#endif
EXTERN_C_END
#endif

26
C/HuffEnc.c Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* HuffEnc.c -- functions for Huffman encoding /* HuffEnc.c -- functions for Huffman encoding
2008-08-05 2017-04-03 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */ #include "Precomp.h"
#include "HuffEnc.h" #include "HuffEnc.h"
#include "Sort.h" #include "Sort.h"
@@ -67,11 +67,11 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
if (num < 2) if (num < 2)
{ {
int minCode = 0; unsigned minCode = 0;
int maxCode = 1; unsigned maxCode = 1;
if (num == 1) if (num == 1)
{ {
maxCode = (int)(p[0] & MASK); maxCode = (unsigned)p[0] & MASK;
if (maxCode == 0) if (maxCode == 0)
maxCode++; maxCode++;
} }
@@ -113,7 +113,7 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
if (len >= maxLen) if (len >= maxLen)
for (len = maxLen - 1; lenCounters[len] == 0; len--); for (len = maxLen - 1; lenCounters[len] == 0; len--);
lenCounters[len]--; lenCounters[len]--;
lenCounters[len + 1] += 2; lenCounters[(size_t)len + 1] += 2;
} }
{ {
@@ -121,8 +121,8 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
i = 0; i = 0;
for (len = maxLen; len != 0; len--) for (len = maxLen; len != 0; len--)
{ {
UInt32 num; UInt32 k;
for (num = lenCounters[len]; num != 0; num--) for (k = lenCounters[len]; k != 0; k--)
lens[p[i++] & MASK] = (Byte)len; lens[p[i++] & MASK] = (Byte)len;
} }
} }
@@ -133,14 +133,14 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
UInt32 code = 0; UInt32 code = 0;
UInt32 len; UInt32 len;
for (len = 1; len <= kMaxLen; len++) for (len = 1; len <= kMaxLen; len++)
nextCodes[len] = code = (code + lenCounters[len - 1]) << 1; nextCodes[len] = code = (code + lenCounters[(size_t)len - 1]) << 1;
} }
/* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */ /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */
{ {
UInt32 i; UInt32 k;
for (i = 0; i < numSymbols; i++) for (k = 0; k < numSymbols; k++)
p[i] = nextCodes[lens[i]]++; p[k] = nextCodes[lens[k]]++;
} }
} }
} }

16
C/HuffEnc.h Executable file → Normal file
View File

@@ -1,12 +1,12 @@
/* HuffEnc.h -- functions for Huffman encoding /* HuffEnc.h -- Huffman encoding
2008-03-26 2013-01-18 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __HUFFENC_H #ifndef __HUFF_ENC_H
#define __HUFFENC_H #define __HUFF_ENC_H
#include "Types.h" #include "7zTypes.h"
EXTERN_C_BEGIN
/* /*
Conditions: Conditions:
@@ -18,4 +18,6 @@ Conditions:
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen); void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);
EXTERN_C_END
#endif #endif

568
C/LzFind.c Executable file → Normal file
View File

@@ -1,5 +1,7 @@
/* LzFind.c -- Match finder for LZ algorithms /* LzFind.c -- Match finder for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */ 2017-06-10 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include <string.h> #include <string.h>
@@ -9,23 +11,23 @@
#define kEmptyHashValue 0 #define kEmptyHashValue 0
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
#define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
#define kMaxHistorySize ((UInt32)3 << 30) #define kMaxHistorySize ((UInt32)7 << 29)
#define kStartMaxLen 3 #define kStartMaxLen 3
static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc)
{ {
if (!p->directInput) if (!p->directInput)
{ {
alloc->Free(alloc, p->bufferBase); ISzAlloc_Free(alloc, p->bufferBase);
p->bufferBase = 0; p->bufferBase = NULL;
} }
} }
/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc)
{ {
UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
if (p->directInput) if (p->directInput)
@@ -33,17 +35,16 @@ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *a
p->blockSize = blockSize; p->blockSize = blockSize;
return 1; return 1;
} }
if (p->bufferBase == 0 || p->blockSize != blockSize) if (!p->bufferBase || p->blockSize != blockSize)
{ {
LzInWindow_Free(p, alloc); LzInWindow_Free(p, alloc);
p->blockSize = blockSize; p->blockSize = blockSize;
p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, (size_t)blockSize);
} }
return (p->bufferBase != 0); return (p->bufferBase != NULL);
} }
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } 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; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
@@ -58,13 +59,29 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
{ {
if (p->streamEndWasReached || p->result != SZ_OK) if (p->streamEndWasReached || p->result != SZ_OK)
return; return;
/* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
if (p->directInput)
{
UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);
if (curSize > p->directInputRem)
curSize = (UInt32)p->directInputRem;
p->directInputRem -= curSize;
p->streamPos += curSize;
if (p->directInputRem == 0)
p->streamEndWasReached = 1;
return;
}
for (;;) for (;;)
{ {
Byte *dest = p->buffer + (p->streamPos - p->pos); Byte *dest = p->buffer + (p->streamPos - p->pos);
size_t size = (p->bufferBase + p->blockSize - dest); size_t size = (p->bufferBase + p->blockSize - dest);
if (size == 0) if (size == 0)
return; return;
p->result = p->stream->Read(p->stream, dest, &size);
p->result = ISeqInStream_Read(p->stream, dest, &size);
if (p->result != SZ_OK) if (p->result != SZ_OK)
return; return;
if (size == 0) if (size == 0)
@@ -81,13 +98,15 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
void MatchFinder_MoveBlock(CMatchFinder *p) void MatchFinder_MoveBlock(CMatchFinder *p)
{ {
memmove(p->bufferBase, memmove(p->bufferBase,
p->buffer - p->keepSizeBefore, p->buffer - p->keepSizeBefore,
(size_t)(p->streamPos - p->pos + p->keepSizeBefore)); (size_t)(p->streamPos - p->pos) + p->keepSizeBefore);
p->buffer = p->bufferBase + p->keepSizeBefore; p->buffer = p->bufferBase + p->keepSizeBefore;
} }
int MatchFinder_NeedMove(CMatchFinder *p) int MatchFinder_NeedMove(CMatchFinder *p)
{ {
if (p->directInput)
return 0;
/* if (p->streamEndWasReached) return 0; */ /* if (p->streamEndWasReached) return 0; */
return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
} }
@@ -112,8 +131,6 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
p->cutValue = 32; p->cutValue = 32;
p->btMode = 1; p->btMode = 1;
p->numHashBytes = 4; p->numHashBytes = 4;
/* p->skipModeBits = 0; */
p->directInput = 0;
p->bigHash = 0; p->bigHash = 0;
} }
@@ -122,62 +139,68 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
void MatchFinder_Construct(CMatchFinder *p) void MatchFinder_Construct(CMatchFinder *p)
{ {
UInt32 i; UInt32 i;
p->bufferBase = 0; p->bufferBase = NULL;
p->directInput = 0; p->directInput = 0;
p->hash = 0; p->hash = NULL;
p->expectedDataSize = (UInt64)(Int64)-1;
MatchFinder_SetDefaultSettings(p); MatchFinder_SetDefaultSettings(p);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
UInt32 r = i; UInt32 r = i;
int j; unsigned j;
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
p->crc[i] = r; p->crc[i] = r;
} }
} }
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->hash); ISzAlloc_Free(alloc, p->hash);
p->hash = 0; p->hash = NULL;
} }
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc)
{ {
MatchFinder_FreeThisClassMemory(p, alloc); MatchFinder_FreeThisClassMemory(p, alloc);
LzInWindow_Free(p, alloc); LzInWindow_Free(p, alloc);
} }
static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc)
{ {
size_t sizeInBytes = (size_t)num * sizeof(CLzRef); size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
if (sizeInBytes / sizeof(CLzRef) != num) if (sizeInBytes / sizeof(CLzRef) != num)
return 0; return NULL;
return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes);
} }
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAlloc *alloc) ISzAllocPtr alloc)
{ {
UInt32 sizeReserv; UInt32 sizeReserv;
if (historySize > kMaxHistorySize) if (historySize > kMaxHistorySize)
{ {
MatchFinder_Free(p, alloc); MatchFinder_Free(p, alloc);
return 0; return 0;
} }
sizeReserv = historySize >> 1; sizeReserv = historySize >> 1;
if (historySize > ((UInt32)2 << 30)) if (historySize >= ((UInt32)3 << 30)) sizeReserv = historySize >> 3;
sizeReserv = historySize >> 2; else if (historySize >= ((UInt32)2 << 30)) sizeReserv = historySize >> 2;
sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
if (LzInWindow_Create(p, sizeReserv, alloc)) if (LzInWindow_Create(p, sizeReserv, alloc))
{ {
UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 newCyclicBufferSize = historySize + 1;
UInt32 hs; UInt32 hs;
p->matchMaxLen = matchMaxLen; p->matchMaxLen = matchMaxLen;
{ {
@@ -186,13 +209,16 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
hs = (1 << 16) - 1; hs = (1 << 16) - 1;
else else
{ {
hs = historySize - 1; hs = historySize;
if (hs > p->expectedDataSize)
hs = (UInt32)p->expectedDataSize;
if (hs != 0)
hs--;
hs |= (hs >> 1); hs |= (hs >> 1);
hs |= (hs >> 2); hs |= (hs >> 2);
hs |= (hs >> 4); hs |= (hs >> 4);
hs |= (hs >> 8); hs |= (hs >> 8);
hs >>= 1; hs >>= 1;
/* hs >>= p->skipModeBits; */
hs |= 0xFFFF; /* don't change it! It's required for Deflate */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */
if (hs > (1 << 24)) if (hs > (1 << 24))
{ {
@@ -200,6 +226,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
hs = (1 << 24) - 1; hs = (1 << 24) - 1;
else else
hs >>= 1; hs >>= 1;
/* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */
} }
} }
p->hashMask = hs; p->hashMask = hs;
@@ -211,24 +238,32 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
} }
{ {
UInt32 prevSize = p->hashSizeSum + p->numSons; size_t newSize;
UInt32 newSize; size_t numSons;
p->historySize = historySize; p->historySize = historySize;
p->hashSizeSum = hs; p->hashSizeSum = hs;
p->cyclicBufferSize = newCyclicBufferSize; p->cyclicBufferSize = newCyclicBufferSize;
p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
newSize = p->hashSizeSum + p->numSons; numSons = newCyclicBufferSize;
if (p->hash != 0 && prevSize == newSize) if (p->btMode)
numSons <<= 1;
newSize = hs + numSons;
if (p->hash && p->numRefs == newSize)
return 1; return 1;
MatchFinder_FreeThisClassMemory(p, alloc); MatchFinder_FreeThisClassMemory(p, alloc);
p->numRefs = newSize;
p->hash = AllocRefs(newSize, alloc); p->hash = AllocRefs(newSize, alloc);
if (p->hash != 0)
if (p->hash)
{ {
p->son = p->hash + p->hashSizeSum; p->son = p->hash + p->hashSizeSum;
return 1; return 1;
} }
} }
} }
MatchFinder_Free(p, alloc); MatchFinder_Free(p, alloc);
return 0; return 0;
} }
@@ -237,9 +272,11 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
{ {
UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit = kMaxValForNormalize - p->pos;
UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
if (limit2 < limit) if (limit2 < limit)
limit = limit2; limit = limit2;
limit2 = p->streamPos - p->pos; limit2 = p->streamPos - p->pos;
if (limit2 <= p->keepSizeAfter) if (limit2 <= p->keepSizeAfter)
{ {
if (limit2 > 0) if (limit2 > 0)
@@ -247,8 +284,10 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
} }
else else
limit2 -= p->keepSizeAfter; limit2 -= p->keepSizeAfter;
if (limit2 < limit) if (limit2 < limit)
limit = limit2; limit = limit2;
{ {
UInt32 lenLimit = p->streamPos - p->pos; UInt32 lenLimit = p->streamPos - p->pos;
if (lenLimit > p->matchMaxLen) if (lenLimit > p->matchMaxLen)
@@ -258,28 +297,59 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
p->posLimit = p->pos + limit; p->posLimit = p->pos + limit;
} }
void MatchFinder_Init(CMatchFinder *p)
void MatchFinder_Init_LowHash(CMatchFinder *p)
{
size_t i;
CLzRef *items = p->hash;
size_t numItems = p->fixedHashSize;
for (i = 0; i < numItems; i++)
items[i] = kEmptyHashValue;
}
void MatchFinder_Init_HighHash(CMatchFinder *p)
{
size_t i;
CLzRef *items = p->hash + p->fixedHashSize;
size_t numItems = (size_t)p->hashMask + 1;
for (i = 0; i < numItems; i++)
items[i] = kEmptyHashValue;
}
void MatchFinder_Init_3(CMatchFinder *p, int readData)
{ {
UInt32 i;
for (i = 0; i < p->hashSizeSum; i++)
p->hash[i] = kEmptyHashValue;
p->cyclicBufferPos = 0; p->cyclicBufferPos = 0;
p->buffer = p->bufferBase; p->buffer = p->bufferBase;
p->pos = p->streamPos = p->cyclicBufferSize; p->pos =
p->streamPos = p->cyclicBufferSize;
p->result = SZ_OK; p->result = SZ_OK;
p->streamEndWasReached = 0; p->streamEndWasReached = 0;
MatchFinder_ReadBlock(p);
if (readData)
MatchFinder_ReadBlock(p);
MatchFinder_SetLimits(p); MatchFinder_SetLimits(p);
} }
void MatchFinder_Init(CMatchFinder *p)
{
MatchFinder_Init_HighHash(p);
MatchFinder_Init_LowHash(p);
MatchFinder_Init_3(p, True);
}
static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
{ {
return (p->pos - p->historySize - 1) & kNormalizeMask; return (p->pos - p->historySize - 1) & kNormalizeMask;
} }
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems)
{ {
UInt32 i; size_t i;
for (i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
{ {
UInt32 value = items[i]; UInt32 value = items[i];
@@ -294,7 +364,7 @@ void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
static void MatchFinder_Normalize(CMatchFinder *p) static void MatchFinder_Normalize(CMatchFinder *p)
{ {
UInt32 subValue = MatchFinder_GetSubValue(p); UInt32 subValue = MatchFinder_GetSubValue(p);
MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_Normalize3(subValue, p->hash, p->numRefs);
MatchFinder_ReduceOffsets(p, subValue); MatchFinder_ReduceOffsets(p, subValue);
} }
@@ -455,7 +525,7 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define GET_MATCHES_HEADER2(minLen, ret_op) \ #define GET_MATCHES_HEADER2(minLen, ret_op) \
UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
cur = p->buffer; cur = p->buffer;
@@ -471,13 +541,20 @@ static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define SKIP_FOOTER \ #define SKIP_FOOTER \
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
#define UPDATE_maxLen { \
ptrdiff_t diff = (ptrdiff_t)0 - d2; \
const Byte *c = cur + maxLen; \
const Byte *lim = cur + lenLimit; \
for (; c != lim; c++) if (*(c + diff) != *c) break; \
maxLen = (UInt32)(c - cur); }
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 offset; UInt32 offset;
GET_MATCHES_HEADER(2) GET_MATCHES_HEADER(2)
HASH2_CALC; HASH2_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
offset = 0; offset = 0;
GET_MATCHES_FOOTER(offset, 1) GET_MATCHES_FOOTER(offset, 1)
} }
@@ -487,35 +564,38 @@ UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
UInt32 offset; UInt32 offset;
GET_MATCHES_HEADER(3) GET_MATCHES_HEADER(3)
HASH_ZIP_CALC; HASH_ZIP_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
offset = 0; offset = 0;
GET_MATCHES_FOOTER(offset, 2) GET_MATCHES_FOOTER(offset, 2)
} }
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 hash2Value, delta2, maxLen, offset; UInt32 h2, d2, maxLen, offset, pos;
UInt32 *hash;
GET_MATCHES_HEADER(3) GET_MATCHES_HEADER(3)
HASH3_CALC; HASH3_CALC;
delta2 = p->pos - p->hash[hash2Value]; hash = p->hash;
curMatch = p->hash[kFix3HashSize + hashValue]; pos = p->pos;
p->hash[hash2Value] = d2 = pos - hash[h2];
p->hash[kFix3HashSize + hashValue] = p->pos;
curMatch = (hash + kFix3HashSize)[hv];
hash[h2] = pos;
(hash + kFix3HashSize)[hv] = pos;
maxLen = 2; maxLen = 2;
offset = 0; offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{ {
for (; maxLen != lenLimit; maxLen++) UPDATE_maxLen
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
break;
distances[0] = maxLen; distances[0] = maxLen;
distances[1] = delta2 - 1; distances[1] = d2 - 1;
offset = 2; offset = 2;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
@@ -523,114 +603,287 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
MOVE_POS_RET; MOVE_POS_RET;
} }
} }
GET_MATCHES_FOOTER(offset, maxLen) GET_MATCHES_FOOTER(offset, maxLen)
} }
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; UInt32 h2, h3, d2, d3, maxLen, offset, pos;
UInt32 *hash;
GET_MATCHES_HEADER(4) GET_MATCHES_HEADER(4)
HASH4_CALC; HASH4_CALC;
delta2 = p->pos - p->hash[ hash2Value]; hash = p->hash;
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; pos = p->pos;
curMatch = p->hash[kFix4HashSize + hashValue];
p->hash[ hash2Value] = d2 = pos - hash[ h2];
p->hash[kFix3HashSize + hash3Value] = d3 = pos - (hash + kFix3HashSize)[h3];
p->hash[kFix4HashSize + hashValue] = p->pos;
maxLen = 1; curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[hv] = pos;
maxLen = 0;
offset = 0; offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{ {
distances[0] = maxLen = 2; distances[0] = maxLen = 2;
distances[1] = delta2 - 1; distances[1] = d2 - 1;
offset = 2; offset = 2;
} }
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{ {
maxLen = 3; maxLen = 3;
distances[offset + 1] = delta3 - 1; distances[(size_t)offset + 1] = d3 - 1;
offset += 2; offset += 2;
delta2 = delta3; d2 = d3;
} }
if (offset != 0) if (offset != 0)
{ {
for (; maxLen != lenLimit; maxLen++) UPDATE_maxLen
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) distances[(size_t)offset - 2] = maxLen;
break;
distances[offset - 2] = maxLen;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET; MOVE_POS_RET;
} }
} }
if (maxLen < 3) if (maxLen < 3)
maxLen = 3; maxLen = 3;
GET_MATCHES_FOOTER(offset, maxLen) GET_MATCHES_FOOTER(offset, maxLen)
} }
/*
static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
UInt32 *hash;
GET_MATCHES_HEADER(5)
HASH5_CALC;
hash = p->hash;
pos = p->pos;
d2 = pos - hash[ h2];
d3 = pos - (hash + kFix3HashSize)[h3];
d4 = pos - (hash + kFix4HashSize)[h4];
curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[h4] = pos;
(hash + kFix5HashSize)[hv] = pos;
maxLen = 0;
offset = 0;
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
distances[0] = maxLen = 2;
distances[1] = d2 - 1;
offset = 2;
if (*(cur - d2 + 2) == cur[2])
distances[0] = maxLen = 3;
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
distances[2] = maxLen = 3;
distances[3] = d3 - 1;
offset = 4;
d2 = d3;
}
}
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
distances[0] = maxLen = 3;
distances[1] = d3 - 1;
offset = 2;
d2 = d3;
}
if (d2 != d4 && d4 < p->cyclicBufferSize
&& *(cur - d4) == *cur
&& *(cur - d4 + 3) == *(cur + 3))
{
maxLen = 4;
distances[(size_t)offset + 1] = d4 - 1;
offset += 2;
d2 = d4;
}
if (offset != 0)
{
UPDATE_maxLen
distances[(size_t)offset - 2] = maxLen;
if (maxLen == lenLimit)
{
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
if (maxLen < 4)
maxLen = 4;
GET_MATCHES_FOOTER(offset, maxLen)
}
*/
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; UInt32 h2, h3, d2, d3, maxLen, offset, pos;
UInt32 *hash;
GET_MATCHES_HEADER(4) GET_MATCHES_HEADER(4)
HASH4_CALC; HASH4_CALC;
delta2 = p->pos - p->hash[ hash2Value]; hash = p->hash;
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; pos = p->pos;
curMatch = p->hash[kFix4HashSize + hashValue];
p->hash[ hash2Value] = d2 = pos - hash[ h2];
p->hash[kFix3HashSize + hash3Value] = d3 = pos - (hash + kFix3HashSize)[h3];
p->hash[kFix4HashSize + hashValue] = p->pos;
maxLen = 1; curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[hv] = pos;
maxLen = 0;
offset = 0; offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{ {
distances[0] = maxLen = 2; distances[0] = maxLen = 2;
distances[1] = delta2 - 1; distances[1] = d2 - 1;
offset = 2; offset = 2;
} }
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{ {
maxLen = 3; maxLen = 3;
distances[offset + 1] = delta3 - 1; distances[(size_t)offset + 1] = d3 - 1;
offset += 2; offset += 2;
delta2 = delta3; d2 = d3;
} }
if (offset != 0) if (offset != 0)
{ {
for (; maxLen != lenLimit; maxLen++) UPDATE_maxLen
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) distances[(size_t)offset - 2] = maxLen;
break;
distances[offset - 2] = maxLen;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
p->son[p->cyclicBufferPos] = curMatch; p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS_RET; MOVE_POS_RET;
} }
} }
if (maxLen < 3) if (maxLen < 3)
maxLen = 3; maxLen = 3;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances + offset, maxLen) - (distances)); distances + offset, maxLen) - (distances));
MOVE_POS_RET MOVE_POS_RET
} }
/*
static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
UInt32 *hash;
GET_MATCHES_HEADER(5)
HASH5_CALC;
hash = p->hash;
pos = p->pos;
d2 = pos - hash[ h2];
d3 = pos - (hash + kFix3HashSize)[h3];
d4 = pos - (hash + kFix4HashSize)[h4];
curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[h4] = pos;
(hash + kFix5HashSize)[hv] = pos;
maxLen = 0;
offset = 0;
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
distances[0] = maxLen = 2;
distances[1] = d2 - 1;
offset = 2;
if (*(cur - d2 + 2) == cur[2])
distances[0] = maxLen = 3;
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
distances[2] = maxLen = 3;
distances[3] = d3 - 1;
offset = 4;
d2 = d3;
}
}
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
distances[0] = maxLen = 3;
distances[1] = d3 - 1;
offset = 2;
d2 = d3;
}
if (d2 != d4 && d4 < p->cyclicBufferSize
&& *(cur - d4) == *cur
&& *(cur - d4 + 3) == *(cur + 3))
{
maxLen = 4;
distances[(size_t)offset + 1] = d4 - 1;
offset += 2;
d2 = d4;
}
if (offset != 0)
{
UPDATE_maxLen
distances[(size_t)offset - 2] = maxLen;
if (maxLen == lenLimit)
{
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS_RET;
}
}
if (maxLen < 4)
maxLen = 4;
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 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 offset; UInt32 offset;
GET_MATCHES_HEADER(3) GET_MATCHES_HEADER(3)
HASH_ZIP_CALC; HASH_ZIP_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances, 2) - (distances)); distances, 2) - (distances));
MOVE_POS_RET MOVE_POS_RET
} }
@@ -640,8 +893,8 @@ static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
SKIP_HEADER(2) SKIP_HEADER(2)
HASH2_CALC; HASH2_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
SKIP_FOOTER SKIP_FOOTER
} }
while (--num != 0); while (--num != 0);
@@ -653,8 +906,8 @@ void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
SKIP_HEADER(3) SKIP_HEADER(3)
HASH_ZIP_CALC; HASH_ZIP_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
SKIP_FOOTER SKIP_FOOTER
} }
while (--num != 0); while (--num != 0);
@@ -664,12 +917,14 @@ static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
do do
{ {
UInt32 hash2Value; UInt32 h2;
UInt32 *hash;
SKIP_HEADER(3) SKIP_HEADER(3)
HASH3_CALC; HASH3_CALC;
curMatch = p->hash[kFix3HashSize + hashValue]; hash = p->hash;
p->hash[hash2Value] = curMatch = (hash + kFix3HashSize)[hv];
p->hash[kFix3HashSize + hashValue] = p->pos; hash[h2] =
(hash + kFix3HashSize)[hv] = p->pos;
SKIP_FOOTER SKIP_FOOTER
} }
while (--num != 0); while (--num != 0);
@@ -679,43 +934,90 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
do do
{ {
UInt32 hash2Value, hash3Value; UInt32 h2, h3;
UInt32 *hash;
SKIP_HEADER(4) SKIP_HEADER(4)
HASH4_CALC; HASH4_CALC;
curMatch = p->hash[kFix4HashSize + hashValue]; hash = p->hash;
p->hash[ hash2Value] = curMatch = (hash + kFix4HashSize)[hv];
p->hash[kFix3HashSize + hash3Value] = p->pos; hash[ h2] =
p->hash[kFix4HashSize + hashValue] = p->pos; (hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[hv] = p->pos;
SKIP_FOOTER SKIP_FOOTER
} }
while (--num != 0); while (--num != 0);
} }
/*
static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
UInt32 h2, h3, h4;
UInt32 *hash;
SKIP_HEADER(5)
HASH5_CALC;
hash = p->hash;
curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] =
(hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[h4] =
(hash + kFix5HashSize)[hv] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
}
*/
static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
do do
{ {
UInt32 hash2Value, hash3Value; UInt32 h2, h3;
UInt32 *hash;
SKIP_HEADER(4) SKIP_HEADER(4)
HASH4_CALC; HASH4_CALC;
curMatch = p->hash[kFix4HashSize + hashValue]; hash = p->hash;
p->hash[ hash2Value] = curMatch = (hash + kFix4HashSize)[hv];
p->hash[kFix3HashSize + hash3Value] = hash[ h2] =
p->hash[kFix4HashSize + hashValue] = p->pos; (hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch; p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS MOVE_POS
} }
while (--num != 0); while (--num != 0);
} }
/*
static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
UInt32 h2, h3, h4;
UInt32 *hash;
SKIP_HEADER(5)
HASH5_CALC;
hash = p->hash;
curMatch = hash + kFix5HashSize)[hv];
hash[ h2] =
(hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[h4] =
(hash + kFix5HashSize)[hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS
}
while (--num != 0);
}
*/
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
do do
{ {
SKIP_HEADER(3) SKIP_HEADER(3)
HASH_ZIP_CALC; HASH_ZIP_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch; p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS MOVE_POS
} }
@@ -725,13 +1027,22 @@ void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
{ {
vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->Init = (Mf_Init_Func)MatchFinder_Init;
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
if (!p->btMode) if (!p->btMode)
{ {
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; /* if (p->numHashBytes <= 4) */
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; {
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
}
/*
else
{
vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
}
*/
} }
else if (p->numHashBytes == 2) else if (p->numHashBytes == 2)
{ {
@@ -743,9 +1054,16 @@ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
} }
else else /* if (p->numHashBytes == 4) */
{ {
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
} }
/*
else
{
vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;
}
*/
} }

46
C/LzFind.h Executable file → Normal file
View File

@@ -1,10 +1,12 @@
/* LzFind.h -- Match finder for LZ algorithms /* LzFind.h -- Match finder for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */ 2017-06-10 : Igor Pavlov : Public domain */
#ifndef __LZFIND_H #ifndef __LZ_FIND_H
#define __LZFIND_H #define __LZ_FIND_H
#include "Types.h" #include "7zTypes.h"
EXTERN_C_BEGIN
typedef UInt32 CLzRef; typedef UInt32 CLzRef;
@@ -19,6 +21,11 @@ typedef struct _CMatchFinder
UInt32 cyclicBufferPos; UInt32 cyclicBufferPos;
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
Byte streamEndWasReached;
Byte btMode;
Byte bigHash;
Byte directInput;
UInt32 matchMaxLen; UInt32 matchMaxLen;
CLzRef *hash; CLzRef *hash;
CLzRef *son; CLzRef *son;
@@ -27,30 +34,32 @@ typedef struct _CMatchFinder
Byte *bufferBase; Byte *bufferBase;
ISeqInStream *stream; ISeqInStream *stream;
int streamEndWasReached;
UInt32 blockSize; UInt32 blockSize;
UInt32 keepSizeBefore; UInt32 keepSizeBefore;
UInt32 keepSizeAfter; UInt32 keepSizeAfter;
UInt32 numHashBytes; UInt32 numHashBytes;
int directInput; size_t directInputRem;
int btMode;
/* int skipModeBits; */
int bigHash;
UInt32 historySize; UInt32 historySize;
UInt32 fixedHashSize; UInt32 fixedHashSize;
UInt32 hashSizeSum; UInt32 hashSizeSum;
UInt32 numSons;
SRes result; SRes result;
UInt32 crc[256]; UInt32 crc[256];
size_t numRefs;
UInt64 expectedDataSize;
} CMatchFinder; } CMatchFinder;
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
#define Inline_MatchFinder_IsFinishedOK(p) \
((p)->streamEndWasReached \
&& (p)->streamPos == (p)->pos \
&& (!(p)->directInput || (p)->directInputRem == 0))
int MatchFinder_NeedMove(CMatchFinder *p); int MatchFinder_NeedMove(CMatchFinder *p);
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p);
@@ -64,9 +73,9 @@ void MatchFinder_Construct(CMatchFinder *p);
*/ */
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAlloc *alloc); ISzAllocPtr alloc);
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc);
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
@@ -80,7 +89,6 @@ Conditions:
*/ */
typedef void (*Mf_Init_Func)(void *object); typedef void (*Mf_Init_Func)(void *object);
typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
@@ -89,7 +97,6 @@ typedef void (*Mf_Skip_Func)(void *object, UInt32);
typedef struct _IMatchFinder typedef struct _IMatchFinder
{ {
Mf_Init_Func Init; Mf_Init_Func Init;
Mf_GetIndexByte_Func GetIndexByte;
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
Mf_GetMatches_Func GetMatches; Mf_GetMatches_Func GetMatches;
@@ -98,10 +105,17 @@ typedef struct _IMatchFinder
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
void MatchFinder_Init_LowHash(CMatchFinder *p);
void MatchFinder_Init_HighHash(CMatchFinder *p);
void MatchFinder_Init_3(CMatchFinder *p, int readData);
void MatchFinder_Init(CMatchFinder *p); void MatchFinder_Init(CMatchFinder *p);
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
EXTERN_C_END
#endif #endif

257
C/LzFindMt.c Executable file → Normal file
View File

@@ -1,11 +1,13 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms /* LzFindMt.c -- multithreaded Match finder for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */ 2017-06-10 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "LzHash.h" #include "LzHash.h"
#include "LzFindMt.h" #include "LzFindMt.h"
void MtSync_Construct(CMtSync *p) static void MtSync_Construct(CMtSync *p)
{ {
p->wasCreated = False; p->wasCreated = False;
p->csWasInitialized = False; p->csWasInitialized = False;
@@ -18,7 +20,7 @@ void MtSync_Construct(CMtSync *p)
Semaphore_Construct(&p->filledSemaphore); Semaphore_Construct(&p->filledSemaphore);
} }
void MtSync_GetNextBlock(CMtSync *p) static void MtSync_GetNextBlock(CMtSync *p)
{ {
if (p->needStart) if (p->needStart)
{ {
@@ -31,6 +33,8 @@ void MtSync_GetNextBlock(CMtSync *p)
Event_Set(&p->canStart); Event_Set(&p->canStart);
Event_Wait(&p->wasStarted); Event_Wait(&p->wasStarted);
// if (mt) MatchFinder_Init_LowHash(mt->MatchFinder);
} }
else else
{ {
@@ -46,7 +50,7 @@ void MtSync_GetNextBlock(CMtSync *p)
/* MtSync_StopWriting must be called if Writing was started */ /* MtSync_StopWriting must be called if Writing was started */
void MtSync_StopWriting(CMtSync *p) static void MtSync_StopWriting(CMtSync *p)
{ {
UInt32 myNumBlocks = p->numProcessedBlocks; UInt32 myNumBlocks = p->numProcessedBlocks;
if (!Thread_WasCreated(&p->thread) || p->needStart) if (!Thread_WasCreated(&p->thread) || p->needStart)
@@ -69,7 +73,7 @@ void MtSync_StopWriting(CMtSync *p)
p->needStart = True; p->needStart = True;
} }
void MtSync_Destruct(CMtSync *p) static void MtSync_Destruct(CMtSync *p)
{ {
if (Thread_WasCreated(&p->thread)) if (Thread_WasCreated(&p->thread))
{ {
@@ -97,7 +101,7 @@ void MtSync_Destruct(CMtSync *p)
#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)
{ {
if (p->wasCreated) if (p->wasCreated)
return SZ_OK; return SZ_OK;
@@ -119,7 +123,7 @@ static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void
return SZ_OK; return SZ_OK;
} }
static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)
{ {
SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
if (res != SZ_OK) if (res != SZ_OK)
@@ -132,20 +136,20 @@ void MtSync_Init(CMtSync *p) { p->needStart = True; }
#define kMtMaxValForNormalize 0xFFFFFFFF #define kMtMaxValForNormalize 0xFFFFFFFF
#define DEF_GetHeads2(name, v, action) \ #define DEF_GetHeads2(name, v, action) \
static void GetHeads ## name(const Byte *p, UInt32 pos, \ static void GetHeads ## name(const Byte *p, UInt32 pos, \
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
{ action; for (; numHeads != 0; numHeads--) { \ { action; for (; numHeads != 0; numHeads--) { \
const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; ) DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), UNUSED_VAR(hashMask); UNUSED_VAR(crc); )
DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) 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(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(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) /* 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) static void HashThreadFunc(CMatchFinderMt *mt)
{ {
CMtSync *p = &mt->hashSync; CMtSync *p = &mt->hashSync;
for (;;) for (;;)
@@ -153,6 +157,9 @@ void HashThreadFunc(CMatchFinderMt *mt)
UInt32 numProcessedBlocks = 0; UInt32 numProcessedBlocks = 0;
Event_Wait(&p->canStart); Event_Wait(&p->canStart);
Event_Set(&p->wasStarted); Event_Set(&p->wasStarted);
MatchFinder_Init_HighHash(mt->MatchFinder);
for (;;) for (;;)
{ {
if (p->exit) if (p->exit)
@@ -171,12 +178,12 @@ void HashThreadFunc(CMatchFinderMt *mt)
CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->btSync.cs);
CriticalSection_Enter(&mt->hashSync.cs); CriticalSection_Enter(&mt->hashSync.cs);
{ {
const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf);
const Byte *afterPtr; ptrdiff_t offset;
MatchFinder_MoveBlock(mf); MatchFinder_MoveBlock(mf);
afterPtr = MatchFinder_GetPointerToCurrentPos(mf); offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf);
mt->pointerToCurPos -= beforePtr - afterPtr; mt->pointerToCurPos -= offset;
mt->buffer -= beforePtr - afterPtr; mt->buffer -= offset;
} }
CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->btSync.cs);
CriticalSection_Leave(&mt->hashSync.cs); CriticalSection_Leave(&mt->hashSync.cs);
@@ -190,7 +197,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
{ {
UInt32 subValue = (mf->pos - mf->historySize - 1); UInt32 subValue = (mf->pos - mf->historySize - 1);
MatchFinder_ReduceOffsets(mf, subValue); MatchFinder_ReduceOffsets(mf, subValue);
MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1);
} }
{ {
UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
@@ -203,7 +210,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
if (num > kMtHashBlockSize - 2) if (num > kMtHashBlockSize - 2)
num = kMtHashBlockSize - 2; num = kMtHashBlockSize - 2;
mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);
heads[0] += num; heads[0] = 2 + num;
} }
mf->pos += num; mf->pos += num;
mf->buffer += num; mf->buffer += num;
@@ -215,7 +222,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
} }
} }
void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
{ {
MtSync_GetNextBlock(&p->hashSync); MtSync_GetNextBlock(&p->hashSync);
p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
@@ -231,7 +238,7 @@ void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
#define NO_INLINE MY_FAST_CALL #define NO_INLINE MY_FAST_CALL
Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
{ {
@@ -308,12 +315,14 @@ Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CL
#endif #endif
void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
{ {
UInt32 numProcessed = 0; UInt32 numProcessed = 0;
UInt32 curPos = 2; UInt32 curPos = 2;
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
distances[1] = p->hashNumAvail; distances[1] = p->hashNumAvail;
while (curPos < limit) while (curPos < limit)
{ {
if (p->hashBufPos == p->hashBufPosLimit) if (p->hashBufPos == p->hashBufPosLimit)
@@ -322,9 +331,11 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
distances[1] = numProcessed + p->hashNumAvail; distances[1] = numProcessed + p->hashNumAvail;
if (p->hashNumAvail >= p->numHashBytes) if (p->hashNumAvail >= p->numHashBytes)
continue; continue;
distances[0] = curPos + p->hashNumAvail;
distances += curPos;
for (; p->hashNumAvail != 0; p->hashNumAvail--) for (; p->hashNumAvail != 0; p->hashNumAvail--)
distances[curPos++] = 0; *distances++ = 0;
break; return;
} }
{ {
UInt32 size = p->hashBufPosLimit - p->hashBufPos; UInt32 size = p->hashBufPosLimit - p->hashBufPos;
@@ -341,13 +352,14 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
if (size2 < size) if (size2 < size)
size = size2; size = size2;
} }
#ifndef MFMT_GM_INLINE #ifndef MFMT_GM_INLINE
while (curPos < limit && size-- != 0) while (curPos < limit && size-- != 0)
{ {
UInt32 *startDistances = distances + curPos; UInt32 *startDistances = distances + curPos;
UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
startDistances + 1, p->numHashBytes - 1) - startDistances); startDistances + 1, p->numHashBytes - 1) - startDistances);
*startDistances = num - 1; *startDistances = num - 1;
curPos += num; curPos += num;
cyclicBufferPos++; cyclicBufferPos++;
@@ -358,7 +370,7 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
{ {
UInt32 posRes; UInt32 posRes;
curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, 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); distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos), size, &posRes);
p->hashBufPos += posRes - pos; p->hashBufPos += posRes - pos;
cyclicBufferPos += posRes - pos; cyclicBufferPos += posRes - pos;
p->buffer += posRes - pos; p->buffer += posRes - pos;
@@ -374,10 +386,11 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
p->cyclicBufferPos = cyclicBufferPos; p->cyclicBufferPos = cyclicBufferPos;
} }
} }
distances[0] = curPos; distances[0] = curPos;
} }
void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
{ {
CMtSync *sync = &p->hashSync; CMtSync *sync = &p->hashSync;
if (!sync->needStart) if (!sync->needStart)
@@ -391,7 +404,7 @@ void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
{ {
UInt32 subValue = p->pos - p->cyclicBufferSize; UInt32 subValue = p->pos - p->cyclicBufferSize;
MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2);
p->pos -= subValue; p->pos -= subValue;
} }
@@ -430,18 +443,18 @@ void BtThreadFunc(CMatchFinderMt *mt)
void MatchFinderMt_Construct(CMatchFinderMt *p) void MatchFinderMt_Construct(CMatchFinderMt *p)
{ {
p->hashBuf = 0; p->hashBuf = NULL;
MtSync_Construct(&p->hashSync); MtSync_Construct(&p->hashSync);
MtSync_Construct(&p->btSync); MtSync_Construct(&p->btSync);
} }
void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->hashBuf); ISzAlloc_Free(alloc, p->hashBuf);
p->hashBuf = 0; p->hashBuf = NULL;
} }
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc)
{ {
MtSync_Destruct(&p->hashSync); MtSync_Destruct(&p->hashSync);
MtSync_Destruct(&p->btSync); MtSync_Destruct(&p->btSync);
@@ -451,28 +464,29 @@ void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
static unsigned MY_STD_CALL BtThreadFunc2(void *p) static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)
{ {
Byte allocaDummy[0x180]; Byte allocaDummy[0x180];
int i = 0; unsigned i = 0;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
allocaDummy[i] = (Byte)i; allocaDummy[i] = (Byte)0;
BtThreadFunc((CMatchFinderMt *)p); if (allocaDummy[0] == 0)
BtThreadFunc((CMatchFinderMt *)p);
return 0; return 0;
} }
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc)
{ {
CMatchFinder *mf = p->MatchFinder; CMatchFinder *mf = p->MatchFinder;
p->historySize = historySize; p->historySize = historySize;
if (kMtBtBlockSize <= matchMaxLen * 4) if (kMtBtBlockSize <= matchMaxLen * 4)
return SZ_ERROR_PARAM; return SZ_ERROR_PARAM;
if (p->hashBuf == 0) if (!p->hashBuf)
{ {
p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
if (p->hashBuf == 0) if (!p->hashBuf)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
p->btBuf = p->hashBuf + kHashBufferSize; p->btBuf = p->hashBuf + kHashBufferSize;
} }
@@ -487,13 +501,20 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
} }
/* Call it after ReleaseStream / SetStream */ /* Call it after ReleaseStream / SetStream */
void MatchFinderMt_Init(CMatchFinderMt *p) static void MatchFinderMt_Init(CMatchFinderMt *p)
{ {
CMatchFinder *mf = p->MatchFinder; CMatchFinder *mf = p->MatchFinder;
p->btBufPos = p->btBufPosLimit = 0;
p->hashBufPos = p->hashBufPosLimit = 0; p->btBufPos =
MatchFinder_Init(mf); p->btBufPosLimit = 0;
p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); p->hashBufPos =
p->hashBufPosLimit = 0;
/* Init without data reading. We don't want to read data in this thread */
MatchFinder_Init_3(mf, False);
MatchFinder_Init_LowHash(mf);
p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf);
p->btNumAvailBytes = 0; p->btNumAvailBytes = 0;
p->lzPos = p->historySize + 1; p->lzPos = p->historySize + 1;
@@ -518,13 +539,13 @@ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
/* p->MatchFinder->ReleaseStream(); */ /* p->MatchFinder->ReleaseStream(); */
} }
void MatchFinderMt_Normalize(CMatchFinderMt *p) static void MatchFinderMt_Normalize(CMatchFinderMt *p)
{ {
MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
p->lzPos = p->historySize + 1; p->lzPos = p->historySize + 1;
} }
void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) static void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
{ {
UInt32 blockIndex; UInt32 blockIndex;
MtSync_GetNextBlock(&p->btSync); MtSync_GetNextBlock(&p->btSync);
@@ -536,34 +557,29 @@ void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
MatchFinderMt_Normalize(p); MatchFinderMt_Normalize(p);
} }
const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
{ {
return p->pointerToCurPos; return p->pointerToCurPos;
} }
#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
{ {
GET_NEXT_BLOCK_IF_REQUIRED; GET_NEXT_BLOCK_IF_REQUIRED;
return p->btNumAvailBytes; return p->btNumAvailBytes;
} }
Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{ {
return p->pointerToCurPos[index]; UInt32 h2, curMatch2;
}
UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{
UInt32 hash2Value, curMatch2;
UInt32 *hash = p->hash; UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos; const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos; UInt32 lzPos = p->lzPos;
MT_HASH2_CALC MT_HASH2_CALC
curMatch2 = hash[hash2Value]; curMatch2 = hash[h2];
hash[hash2Value] = lzPos; hash[h2] = lzPos;
if (curMatch2 >= matchMinPos) if (curMatch2 >= matchMinPos)
if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
@@ -571,23 +587,23 @@ UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
*distances++ = 2; *distances++ = 2;
*distances++ = lzPos - curMatch2 - 1; *distances++ = lzPos - curMatch2 - 1;
} }
return distances; return distances;
} }
UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{ {
UInt32 hash2Value, hash3Value, curMatch2, curMatch3; UInt32 h2, h3, curMatch2, curMatch3;
UInt32 *hash = p->hash; UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos; const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos; UInt32 lzPos = p->lzPos;
MT_HASH3_CALC MT_HASH3_CALC
curMatch2 = hash[ hash2Value]; curMatch2 = hash[ h2];
curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch3 = (hash + kFix3HashSize)[h3];
hash[ hash2Value] = hash[ h2] = lzPos;
hash[kFix3HashSize + hash3Value] = (hash + kFix3HashSize)[h3] = lzPos;
lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{ {
@@ -600,43 +616,45 @@ UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
distances[0] = 2; distances[0] = 2;
distances += 2; distances += 2;
} }
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
{ {
*distances++ = 3; *distances++ = 3;
*distances++ = lzPos - curMatch3 - 1; *distances++ = lzPos - curMatch3 - 1;
} }
return distances; return distances;
} }
/* /*
UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{ {
UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; UInt32 h2, h3, h4, curMatch2, curMatch3, curMatch4;
UInt32 *hash = p->hash; UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos; const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos; UInt32 lzPos = p->lzPos;
MT_HASH4_CALC MT_HASH4_CALC
curMatch2 = hash[ hash2Value]; curMatch2 = hash[ h2];
curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch3 = (hash + kFix3HashSize)[h3];
curMatch4 = hash[kFix4HashSize + hash4Value]; curMatch4 = (hash + kFix4HashSize)[h4];
hash[ hash2Value] = hash[ h2] = lzPos;
hash[kFix3HashSize + hash3Value] = (hash + kFix3HashSize)[h3] = lzPos;
hash[kFix4HashSize + hash4Value] = (hash + kFix4HashSize)[h4] = lzPos;
lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{ {
distances[1] = lzPos - curMatch2 - 1; distances[1] = lzPos - curMatch2 - 1;
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
{ {
distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
return distances + 2; return distances + 2;
} }
distances[0] = 2; distances[0] = 2;
distances += 2; distances += 2;
} }
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
{ {
distances[1] = lzPos - curMatch3 - 1; distances[1] = lzPos - curMatch3 - 1;
@@ -658,13 +676,14 @@ UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
*distances++ = 4; *distances++ = 4;
*distances++ = lzPos - curMatch4 - 1; *distances++ = lzPos - curMatch4 - 1;
} }
return distances; return distances;
} }
*/ */
#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) static UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
{ {
const UInt32 *btBuf = p->btBuf + p->btBufPos; const UInt32 *btBuf = p->btBuf + p->btBufPos;
UInt32 len = *btBuf++; UInt32 len = *btBuf++;
@@ -674,15 +693,19 @@ UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
UInt32 i; UInt32 i;
for (i = 0; i < len; i += 2) for (i = 0; i < len; i += 2)
{ {
*distances++ = *btBuf++; UInt32 v0 = btBuf[0];
*distances++ = *btBuf++; UInt32 v1 = btBuf[1];
btBuf += 2;
distances[0] = v0;
distances[1] = v1;
distances += 2;
} }
} }
INCREASE_LZ_POS INCREASE_LZ_POS
return len; return len;
} }
UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) static UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
{ {
const UInt32 *btBuf = p->btBuf + p->btBufPos; const UInt32 *btBuf = p->btBuf + p->btBufPos;
UInt32 len = *btBuf++; UInt32 len = *btBuf++;
@@ -690,6 +713,7 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
if (len == 0) if (len == 0)
{ {
/* change for bt5 ! */
if (p->btNumAvailBytes-- >= 4) if (p->btNumAvailBytes-- >= 4)
len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
} }
@@ -701,72 +725,76 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
do do
{ {
*distances2++ = *btBuf++; UInt32 v0 = btBuf[0];
*distances2++ = *btBuf++; UInt32 v1 = btBuf[1];
btBuf += 2;
distances2[0] = v0;
distances2[1] = v1;
distances2 += 2;
} }
while ((len -= 2) != 0); while ((len -= 2) != 0);
len = (UInt32)(distances2 - (distances)); len = (UInt32)(distances2 - (distances));
} }
INCREASE_LZ_POS INCREASE_LZ_POS
return len; return len;
} }
#define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED #define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED
#define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
#define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); #define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
{ {
SKIP_HEADER2 { p->btNumAvailBytes--; SKIP_HEADER2_MT { p->btNumAvailBytes--;
SKIP_FOOTER SKIP_FOOTER_MT
} }
void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
{ {
SKIP_HEADER(2) SKIP_HEADER_MT(2)
UInt32 hash2Value; UInt32 h2;
MT_HASH2_CALC MT_HASH2_CALC
hash[hash2Value] = p->lzPos; hash[h2] = p->lzPos;
SKIP_FOOTER SKIP_FOOTER_MT
} }
void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
{ {
SKIP_HEADER(3) SKIP_HEADER_MT(3)
UInt32 hash2Value, hash3Value; UInt32 h2, h3;
MT_HASH3_CALC MT_HASH3_CALC
hash[kFix3HashSize + hash3Value] = (hash + kFix3HashSize)[h3] =
hash[ hash2Value] = hash[ h2] =
p->lzPos; p->lzPos;
SKIP_FOOTER SKIP_FOOTER_MT
} }
/* /*
void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
{ {
SKIP_HEADER(4) SKIP_HEADER_MT(4)
UInt32 hash2Value, hash3Value, hash4Value; UInt32 h2, h3, h4;
MT_HASH4_CALC MT_HASH4_CALC
hash[kFix4HashSize + hash4Value] = (hash + kFix4HashSize)[h4] =
hash[kFix3HashSize + hash3Value] = (hash + kFix3HashSize)[h3] =
hash[ hash2Value] = hash[ h2] =
p->lzPos; p->lzPos;
SKIP_FOOTER SKIP_FOOTER_MT
} }
*/ */
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
{ {
vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
switch(p->MatchFinder->numHashBytes)
switch (p->MatchFinder->numHashBytes)
{ {
case 2: case 2:
p->GetHeadsFunc = GetHeads2; p->GetHeadsFunc = GetHeads2;
p->MixMatchesFunc = (Mf_Mix_Matches)0; p->MixMatchesFunc = (Mf_Mix_Matches)NULL;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
break; break;
@@ -778,7 +806,6 @@ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
default: default:
/* case 4: */ /* case 4: */
p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
/* p->GetHeadsFunc = GetHeads4; */
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
break; break;

18
C/LzFindMt.h Executable file → Normal file
View File

@@ -1,11 +1,13 @@
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms /* LzFindMt.h -- multithreaded Match finder for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#ifndef __LZFINDMT_H #ifndef __LZ_FIND_MT_H
#define __LZFINDMT_H #define __LZ_FIND_MT_H
#include "Threads.h"
#include "LzFind.h" #include "LzFind.h"
#include "Threads.h"
EXTERN_C_BEGIN
#define kMtHashBlockSize (1 << 13) #define kMtHashBlockSize (1 << 13)
#define kMtHashNumBlocks (1 << 3) #define kMtHashNumBlocks (1 << 3)
@@ -73,7 +75,7 @@ typedef struct _CMatchFinderMt
UInt32 matchMaxLen; UInt32 matchMaxLen;
UInt32 numHashBytes; UInt32 numHashBytes;
UInt32 pos; UInt32 pos;
Byte *buffer; const Byte *buffer;
UInt32 cyclicBufferPos; UInt32 cyclicBufferPos;
UInt32 cyclicBufferSize; /* it must be historySize + 1 */ UInt32 cyclicBufferSize; /* it must be historySize + 1 */
UInt32 cutValue; UInt32 cutValue;
@@ -88,10 +90,12 @@ typedef struct _CMatchFinderMt
} CMatchFinderMt; } CMatchFinderMt;
void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Construct(CMatchFinderMt *p);
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc);
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc);
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
EXTERN_C_END
#endif #endif

47
C/LzHash.h Executable file → Normal file
View File

@@ -1,8 +1,8 @@
/* LzHash.h -- HASH functions for LZ algorithms /* LzHash.h -- HASH functions for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */ 2015-04-12 : Igor Pavlov : Public domain */
#ifndef __LZHASH_H #ifndef __LZ_HASH_H
#define __LZHASH_H #define __LZ_HASH_H
#define kHash2Size (1 << 10) #define kHash2Size (1 << 10)
#define kHash3Size (1 << 16) #define kHash3Size (1 << 16)
@@ -12,43 +12,46 @@
#define kFix4HashSize (kHash2Size + kHash3Size) #define kFix4HashSize (kHash2Size + kHash3Size)
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);
#define HASH3_CALC { \ #define HASH3_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \ h2 = temp & (kHash2Size - 1); \
hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
#define HASH4_CALC { \ #define HASH4_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \ h2 = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ temp ^= ((UInt32)cur[2] << 8); \
hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } h3 = temp & (kHash3Size - 1); \
hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
#define HASH5_CALC { \ #define HASH5_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \ h2 = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ temp ^= ((UInt32)cur[2] << 8); \
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ h3 = temp & (kHash3Size - 1); \
hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ temp ^= (p->crc[cur[3]] << 5); \
hash4Value &= (kHash4Size - 1); } h4 = temp & (kHash4Size - 1); \
hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }
/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ /* #define HASH_ZIP_CALC hv = ((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 HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
#define MT_HASH2_CALC \ #define MT_HASH2_CALC \
hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
#define MT_HASH3_CALC { \ #define MT_HASH3_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \ h2 = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
#define MT_HASH4_CALC { \ #define MT_HASH4_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \ h2 = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ temp ^= ((UInt32)cur[2] << 8); \
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } h3 = temp & (kHash3Size - 1); \
h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
#endif #endif

488
C/Lzma2Dec.c Normal file
View File

@@ -0,0 +1,488 @@
/* Lzma2Dec.c -- LZMA2 Decoder
2018-02-19 : 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 - End of data
00000001 U U - Uncompressed, reset dic, need reset state and set new prop
00000010 U U - Uncompressed, no reset
100uuuuu U U P P - LZMA, no reset
101uuuuu U U P P - LZMA, reset state
110uuuuu U U P P S - LZMA, reset state + set new prop
111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic
u, U - Unpack Size
P - Pack Size
S - Props
*/
#define LZMA2_CONTROL_COPY_RESET_DIC 1
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
#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, ISzAllocPtr 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, ISzAllocPtr 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->needInitLevel = 0xE0;
p->isExtraMode = False;
p->unpackSize = 0;
// p->decoder.dicPos = 0; // we can use it instead of full init
LzmaDec_Init(&p->decoder);
}
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
{
switch (p->state)
{
case LZMA2_STATE_CONTROL:
p->isExtraMode = False;
p->control = b;
PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
PRF(printf(" %02X", (unsigned)b));
if (b == 0)
return LZMA2_STATE_FINISHED;
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{
if (b == LZMA2_CONTROL_COPY_RESET_DIC)
p->needInitLevel = 0xC0;
else if (b > 2 || p->needInitLevel == 0xE0)
return LZMA2_STATE_ERROR;
}
else
{
if (b < p->needInitLevel)
return LZMA2_STATE_ERROR;
p->needInitLevel = 0;
p->unpackSize = (UInt32)(b & 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(" %7u", (unsigned)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++;
// if (p->packSize < 5) return LZMA2_STATE_ERROR;
PRF(printf(" %5u", (unsigned)p->packSize));
return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
case LZMA2_STATE_PROP:
{
unsigned lc, lp;
if (b >= (9 * 5 * 5))
return LZMA2_STATE_ERROR;
lc = b % 9;
b /= 9;
p->decoder.prop.pb = (Byte)(b / 5);
lp = b % 5;
if (lc + lp > LZMA2_LCLP_MAX)
return LZMA2_STATE_ERROR;
p->decoder.prop.lc = (Byte)lc;
p->decoder.prop.lp = (Byte)lp;
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_ERROR)
{
SizeT dicPos;
if (p->state == LZMA2_STATE_FINISHED)
{
*status = LZMA_STATUS_FINISHED_WITH_MARK;
return SZ_OK;
}
dicPos = p->decoder.dicPos;
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
{
*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++);
if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
break;
continue;
}
{
SizeT inCur = inSize - *srcLen;
SizeT outCur = dicLimit - dicPos;
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
if (outCur >= p->unpackSize)
{
outCur = (SizeT)p->unpackSize;
curFinishMode = LZMA_FINISH_END;
}
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{
if (inCur == 0)
{
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
if (p->state == LZMA2_STATE_DATA)
{
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
}
if (inCur > outCur)
inCur = outCur;
if (inCur == 0)
break;
LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
src += inCur;
*srcLen += inCur;
p->unpackSize -= (UInt32)inCur;
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
}
else
{
SRes res;
if (p->state == LZMA2_STATE_DATA)
{
Bool initDic = (p->control >= 0xE0);
Bool initState = (p->control >= 0xA0);
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
p->state = LZMA2_STATE_DATA_CONT;
}
if (inCur > p->packSize)
inCur = (SizeT)p->packSize;
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
src += inCur;
*srcLen += inCur;
p->packSize -= (UInt32)inCur;
outCur = p->decoder.dicPos - dicPos;
p->unpackSize -= (UInt32)outCur;
if (res != 0)
break;
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
{
if (p->packSize == 0)
break;
return SZ_OK;
}
if (inCur == 0 && outCur == 0)
{
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|| p->unpackSize != 0
|| p->packSize != 0)
break;
p->state = LZMA2_STATE_CONTROL;
}
*status = LZMA_STATUS_NOT_SPECIFIED;
}
}
}
*status = LZMA_STATUS_NOT_SPECIFIED;
p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
}
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
SizeT outSize,
const Byte *src, SizeT *srcLen,
int checkFinishBlock)
{
SizeT inSize = *srcLen;
*srcLen = 0;
while (p->state != LZMA2_STATE_ERROR)
{
if (p->state == LZMA2_STATE_FINISHED)
return LZMA_STATUS_FINISHED_WITH_MARK;
if (outSize == 0 && !checkFinishBlock)
return LZMA_STATUS_NOT_FINISHED;
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
{
if (*srcLen == inSize)
return LZMA_STATUS_NEEDS_MORE_INPUT;
(*srcLen)++;
p->state = Lzma2Dec_UpdateState(p, *src++);
if (p->state == LZMA2_STATE_UNPACK0)
{
// if (p->decoder.dicPos != 0)
if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
return LZMA2_PARSE_STATUS_NEW_BLOCK;
// if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
}
// The following code can be commented.
// It's not big problem, if we read additional input bytes.
// It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
{
// checkFinishBlock is true. So we expect that block must be finished,
// We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
// break;
return LZMA_STATUS_NOT_FINISHED;
}
if (p->state == LZMA2_STATE_DATA)
return LZMA2_PARSE_STATUS_NEW_CHUNK;
continue;
}
if (outSize == 0)
return LZMA_STATUS_NOT_FINISHED;
{
SizeT inCur = inSize - *srcLen;
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{
if (inCur == 0)
return LZMA_STATUS_NEEDS_MORE_INPUT;
if (inCur > p->unpackSize)
inCur = p->unpackSize;
if (inCur > outSize)
inCur = outSize;
p->decoder.dicPos += inCur;
src += inCur;
*srcLen += inCur;
outSize -= inCur;
p->unpackSize -= (UInt32)inCur;
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
}
else
{
p->isExtraMode = True;
if (inCur == 0)
{
if (p->packSize != 0)
return LZMA_STATUS_NEEDS_MORE_INPUT;
}
else if (p->state == LZMA2_STATE_DATA)
{
p->state = LZMA2_STATE_DATA_CONT;
if (*src != 0)
{
// first byte of lzma chunk must be Zero
*srcLen += 1;
p->packSize--;
break;
}
}
if (inCur > p->packSize)
inCur = (SizeT)p->packSize;
src += inCur;
*srcLen += inCur;
p->packSize -= (UInt32)inCur;
if (p->packSize == 0)
{
SizeT rem = outSize;
if (rem > p->unpackSize)
rem = p->unpackSize;
p->decoder.dicPos += rem;
p->unpackSize -= (UInt32)rem;
outSize -= rem;
if (p->unpackSize == 0)
p->state = LZMA2_STATE_CONTROL;
}
}
}
}
p->state = LZMA2_STATE_ERROR;
return LZMA_STATUS_NOT_SPECIFIED;
}
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 inCur = inSize, outCur, dicPos;
ELzmaFinishMode curFinishMode;
SRes res;
if (p->decoder.dicPos == p->decoder.dicBufSize)
p->decoder.dicPos = 0;
dicPos = p->decoder.dicPos;
curFinishMode = LZMA_FINISH_ANY;
outCur = p->decoder.dicBufSize - dicPos;
if (outCur >= outSize)
{
outCur = outSize;
curFinishMode = finishMode;
}
res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
src += inCur;
inSize -= inCur;
*srcLen += inCur;
outCur = p->decoder.dicPos - dicPos;
memcpy(dest, p->decoder.dic + dicPos, outCur);
dest += outCur;
outSize -= outCur;
*destLen += outCur;
if (res != 0)
return res;
if (outCur == 0 || outSize == 0)
return SZ_OK;
}
}
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr 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;
}

120
C/Lzma2Dec.h Normal file
View File

@@ -0,0 +1,120 @@
/* Lzma2Dec.h -- LZMA2 Decoder
2018-02-19 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_H
#define __LZMA2_DEC_H
#include "LzmaDec.h"
EXTERN_C_BEGIN
/* ---------- State Interface ---------- */
typedef struct
{
unsigned state;
Byte control;
Byte needInitLevel;
Byte isExtraMode;
Byte _pad_;
UInt32 packSize;
UInt32 unpackSize;
CLzmaDec decoder;
} 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, ISzAllocPtr alloc);
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr 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);
/* ---------- LZMA2 block and chunk parsing ---------- */
/*
Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data.
It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code:
- LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input.
- LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read.
CLzma2Dec::unpackSize contains unpack size of that chunk
*/
typedef enum
{
/*
LZMA_STATUS_NOT_SPECIFIED // data error
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED //
LZMA_STATUS_NEEDS_MORE_INPUT
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused
*/
LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1,
LZMA2_PARSE_STATUS_NEW_CHUNK
} ELzma2ParseStatus;
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
SizeT outSize, // output size
const Byte *src, SizeT *srcLen,
int checkFinishBlock // set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position.
);
/*
LZMA2 parser doesn't decode LZMA chunks, so we must read
full input LZMA chunk to decode some part of LZMA chunk.
Lzma2Dec_GetUnpackExtra() returns the value that shows
max possible number of output bytes that can be output by decoder
at current input positon.
*/
#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0);
/* ---------- One Call Interface ---------- */
/*
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, ISzAllocPtr alloc);
EXTERN_C_END
#endif

1082
C/Lzma2DecMt.c Normal file
View File

File diff suppressed because it is too large Load Diff

79
C/Lzma2DecMt.h Normal file
View File

@@ -0,0 +1,79 @@
/* Lzma2DecMt.h -- LZMA2 Decoder Multi-thread
2018-02-17 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_MT_H
#define __LZMA2_DEC_MT_H
#include "7zTypes.h"
EXTERN_C_BEGIN
typedef struct
{
size_t inBufSize_ST;
size_t outStep_ST;
#ifndef _7ZIP_ST
unsigned numThreads;
size_t inBufSize_MT;
size_t outBlockMax;
size_t inBlockMax;
#endif
} CLzma2DecMtProps;
/* init to single-thread mode */
void Lzma2DecMtProps_Init(CLzma2DecMtProps *p);
/* ---------- CLzma2DecMtHandle Interface ---------- */
/* Lzma2DecMt_ * functions can return the following exit codes:
SRes:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - ISeqOutStream write callback error
// SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
*/
typedef void * CLzma2DecMtHandle;
CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid);
void Lzma2DecMt_Destroy(CLzma2DecMtHandle p);
SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p,
Byte prop,
const CLzma2DecMtProps *props,
ISeqOutStream *outStream,
const UInt64 *outDataSize, // NULL means undefined
int finishMode, // 0 - partial unpacking is allowed, 1 - if lzma2 stream must be finished
// Byte *outBuf, size_t *outBufSize,
ISeqInStream *inStream,
// const Byte *inData, size_t inDataSize,
// out variables:
UInt64 *inProcessed,
int *isMT, /* out: (*isMT == 0), if single thread decoding was used */
// UInt64 *outProcessed,
ICompressProgress *progress);
/* ---------- Read from CLzma2DecMtHandle Interface ---------- */
SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,
Byte prop,
const CLzma2DecMtProps *props,
const UInt64 *outDataSize, int finishMode,
ISeqInStream *inStream);
SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,
Byte *data, size_t *outSize,
UInt64 *inStreamProcessed);
EXTERN_C_END
#endif

801
C/Lzma2Enc.c Normal file
View File

@@ -0,0 +1,801 @@
/* Lzma2Enc.c -- LZMA2 Encoder
2018-02-08 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include <string.h>
/* #define _7ZIP_ST */
#include "Lzma2Enc.h"
#ifndef _7ZIP_ST
#include "MtCoder.h"
#else
#define MTCODER__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 */
/* ---------- CLimitedSeqInStream ---------- */
typedef struct
{
ISeqInStream vt;
ISeqInStream *realStream;
UInt64 limit;
UInt64 processed;
int finished;
} CLimitedSeqInStream;
static void LimitedSeqInStream_Init(CLimitedSeqInStream *p)
{
p->limit = (UInt64)(Int64)-1;
p->processed = 0;
p->finished = 0;
}
static SRes LimitedSeqInStream_Read(const ISeqInStream *pp, void *data, size_t *size)
{
CLimitedSeqInStream *p = CONTAINER_FROM_VTBL(pp, CLimitedSeqInStream, vt);
size_t size2 = *size;
SRes res = SZ_OK;
if (p->limit != (UInt64)(Int64)-1)
{
UInt64 rem = p->limit - p->processed;
if (size2 > rem)
size2 = (size_t)rem;
}
if (size2 != 0)
{
res = ISeqInStream_Read(p->realStream, data, &size2);
p->finished = (size2 == 0 ? 1 : 0);
p->processed += size2;
}
*size = size2;
return res;
}
/* ---------- CLzma2EncInt ---------- */
typedef struct
{
CLzmaEncHandle enc;
Byte propsAreSet;
Byte propsByte;
Byte needInitState;
Byte needInitProp;
UInt64 srcPos;
} CLzma2EncInt;
static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props)
{
if (!p->propsAreSet)
{
SizeT propsSize = LZMA_PROPS_SIZE;
Byte propsEncoded[LZMA_PROPS_SIZE];
RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
p->propsByte = propsEncoded[0];
p->propsAreSet = True;
}
return SZ_OK;
}
static void Lzma2EncInt_InitBlock(CLzma2EncInt *p)
{
p->srcPos = 0;
p->needInitState = True;
p->needInitProp = True;
}
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
ISzAllocPtr alloc, ISzAllocPtr allocBig);
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr 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);
/*
UInt32 LzmaEnc_GetNumAvailableBytes(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 (ISeqOutStream_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->propsByte;
p->needInitProp = False;
p->needInitState = False;
destPos += packSize;
p->srcPos += unpackSize;
if (outStream)
if (ISeqOutStream_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->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO;
p->numBlockThreads_Reduced = -1;
p->numBlockThreads_Max = -1;
p->numTotalThreads = -1;
}
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
{
UInt64 fileSize;
int t1, t1n, t2, t2r, t3;
{
CLzmaEncProps lzmaProps = p->lzmaProps;
LzmaEncProps_Normalize(&lzmaProps);
t1n = lzmaProps.numThreads;
}
t1 = p->lzmaProps.numThreads;
t2 = p->numBlockThreads_Max;
t3 = p->numTotalThreads;
if (t2 > MTCODER__THREADS_MAX)
t2 = MTCODER__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 > MTCODER__THREADS_MAX)
t2 = MTCODER__THREADS_MAX;
}
else if (t1 <= 0)
{
t1 = t3 / t2;
if (t1 == 0)
t1 = 1;
}
else
t3 = t1n * t2;
p->lzmaProps.numThreads = t1;
t2r = t2;
fileSize = p->lzmaProps.reduceSize;
if ( p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
&& p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO
&& (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))
p->lzmaProps.reduceSize = p->blockSize;
LzmaEncProps_Normalize(&p->lzmaProps);
p->lzmaProps.reduceSize = fileSize;
t1 = p->lzmaProps.numThreads;
if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID)
{
t2r = t2 = 1;
t3 = t1;
}
else if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO && t2 <= 1)
{
/* if there is no block multi-threading, we use SOLID block */
p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID;
}
else
{
if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO)
{
const UInt32 kMinSize = (UInt32)1 << 20;
const UInt32 kMaxSize = (UInt32)1 << 28;
const UInt32 dictSize = p->lzmaProps.dictSize;
UInt64 blockSize = (UInt64)dictSize << 2;
if (blockSize < kMinSize) blockSize = kMinSize;
if (blockSize > kMaxSize) blockSize = kMaxSize;
if (blockSize < dictSize) blockSize = dictSize;
blockSize += (kMinSize - 1);
blockSize &= ~(UInt64)(kMinSize - 1);
p->blockSize = blockSize;
}
if (t2 > 1 && fileSize != (UInt64)(Int64)-1)
{
UInt64 numBlocks = fileSize / p->blockSize;
if (numBlocks * p->blockSize != fileSize)
numBlocks++;
if (numBlocks < (unsigned)t2)
{
t2r = (unsigned)numBlocks;
if (t2r == 0)
t2r = 1;
t3 = t1 * t2r;
}
}
}
p->numBlockThreads_Max = t2;
p->numBlockThreads_Reduced = t2r;
p->numTotalThreads = t3;
}
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
{
return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
}
/* ---------- Lzma2 ---------- */
typedef struct
{
Byte propEncoded;
CLzma2EncProps props;
UInt64 expectedDataSize;
Byte *tempBufLzma;
ISzAllocPtr alloc;
ISzAllocPtr allocBig;
CLzma2EncInt coders[MTCODER__THREADS_MAX];
#ifndef _7ZIP_ST
ISeqOutStream *outStream;
Byte *outBuf;
size_t outBufSize;
size_t outBufsDataSizes[MTCODER__BLOCKS_MAX];
Bool mtCoder_WasConstructed;
CMtCoder mtCoder;
Byte *outBufs[MTCODER__BLOCKS_MAX];
#endif
} CLzma2Enc;
CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)
{
CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc));
if (!p)
return NULL;
Lzma2EncProps_Init(&p->props);
Lzma2EncProps_Normalize(&p->props);
p->expectedDataSize = (UInt64)(Int64)-1;
p->tempBufLzma = NULL;
p->alloc = alloc;
p->allocBig = allocBig;
{
unsigned i;
for (i = 0; i < MTCODER__THREADS_MAX; i++)
p->coders[i].enc = NULL;
}
#ifndef _7ZIP_ST
p->mtCoder_WasConstructed = False;
{
unsigned i;
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
p->outBufs[i] = NULL;
p->outBufSize = 0;
}
#endif
return p;
}
#ifndef _7ZIP_ST
static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p)
{
unsigned i;
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
if (p->outBufs[i])
{
ISzAlloc_Free(p->alloc, p->outBufs[i]);
p->outBufs[i] = NULL;
}
p->outBufSize = 0;
}
#endif
void Lzma2Enc_Destroy(CLzma2EncHandle pp)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
unsigned i;
for (i = 0; i < MTCODER__THREADS_MAX; i++)
{
CLzma2EncInt *t = &p->coders[i];
if (t->enc)
{
LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
t->enc = NULL;
}
}
#ifndef _7ZIP_ST
if (p->mtCoder_WasConstructed)
{
MtCoder_Destruct(&p->mtCoder);
p->mtCoder_WasConstructed = False;
}
Lzma2Enc_FreeOutBufs(p);
#endif
ISzAlloc_Free(p->alloc, p->tempBufLzma);
p->tempBufLzma = NULL;
ISzAlloc_Free(p->alloc, 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;
}
void Lzma2Enc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
p->expectedDataSize = expectedDataSiize;
}
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;
}
static SRes Lzma2Enc_EncodeMt1(
CLzma2Enc *me,
CLzma2EncInt *p,
ISeqOutStream *outStream,
Byte *outBuf, size_t *outBufSize,
ISeqInStream *inStream,
const Byte *inData, size_t inDataSize,
int finished,
ICompressProgress *progress)
{
UInt64 unpackTotal = 0;
UInt64 packTotal = 0;
size_t outLim = 0;
CLimitedSeqInStream limitedInStream;
if (outBuf)
{
outLim = *outBufSize;
*outBufSize = 0;
}
if (!p->enc)
{
p->propsAreSet = False;
p->enc = LzmaEnc_Create(me->alloc);
if (!p->enc)
return SZ_ERROR_MEM;
}
limitedInStream.realStream = inStream;
if (inStream)
{
limitedInStream.vt.Read = LimitedSeqInStream_Read;
}
if (!outBuf)
{
// outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma
if (!me->tempBufLzma)
{
me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
if (!me->tempBufLzma)
return SZ_ERROR_MEM;
}
}
RINOK(Lzma2EncInt_InitStream(p, &me->props));
for (;;)
{
SRes res = SZ_OK;
size_t inSizeCur = 0;
Lzma2EncInt_InitBlock(p);
LimitedSeqInStream_Init(&limitedInStream);
limitedInStream.limit = me->props.blockSize;
if (inStream)
{
UInt64 expected = (UInt64)(Int64)-1;
// inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize
if (me->expectedDataSize != (UInt64)(Int64)-1
&& me->expectedDataSize >= unpackTotal)
expected = me->expectedDataSize - unpackTotal;
if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
&& expected > me->props.blockSize)
expected = (size_t)me->props.blockSize;
LzmaEnc_SetDataSize(p->enc, expected);
RINOK(LzmaEnc_PrepareForLzma2(p->enc,
&limitedInStream.vt,
LZMA2_KEEP_WINDOW_SIZE,
me->alloc,
me->allocBig));
}
else
{
inSizeCur = inDataSize - (size_t)unpackTotal;
if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
&& inSizeCur > me->props.blockSize)
inSizeCur = (size_t)me->props.blockSize;
// LzmaEnc_SetDataSize(p->enc, inSizeCur);
RINOK(LzmaEnc_MemPrepare(p->enc,
inData + (size_t)unpackTotal, inSizeCur,
LZMA2_KEEP_WINDOW_SIZE,
me->alloc,
me->allocBig));
}
for (;;)
{
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
if (outBuf)
packSize = outLim - (size_t)packTotal;
res = Lzma2EncInt_EncodeSubblock(p,
outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize,
outBuf ? NULL : outStream);
if (res != SZ_OK)
break;
packTotal += packSize;
if (outBuf)
*outBufSize = (size_t)packTotal;
res = Progress(progress, unpackTotal + p->srcPos, packTotal);
if (res != SZ_OK)
break;
/*
if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0)
break;
*/
if (packSize == 0)
break;
}
LzmaEnc_Finish(p->enc);
unpackTotal += p->srcPos;
RINOK(res);
if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur))
return SZ_ERROR_FAIL;
if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize))
{
if (finished)
{
if (outBuf)
{
size_t destPos = *outBufSize;
if (destPos >= outLim)
return SZ_ERROR_OUTPUT_EOF;
outBuf[destPos] = 0;
*outBufSize = destPos + 1;
}
else
{
Byte b = 0;
if (ISeqOutStream_Write(outStream, &b, 1) != 1)
return SZ_ERROR_WRITE;
}
}
return SZ_OK;
}
}
}
#ifndef _7ZIP_ST
static SRes Lzma2Enc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex,
const Byte *src, size_t srcSize, int finished)
{
CLzma2Enc *me = (CLzma2Enc *)pp;
size_t destSize = me->outBufSize;
SRes res;
CMtProgressThunk progressThunk;
Byte *dest = me->outBufs[outBufIndex];
me->outBufsDataSizes[outBufIndex] = 0;
if (!dest)
{
dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);
if (!dest)
return SZ_ERROR_MEM;
me->outBufs[outBufIndex] = dest;
}
MtProgressThunk_CreateVTable(&progressThunk);
progressThunk.mtProgress = &me->mtCoder.mtProgress;
progressThunk.inSize = 0;
progressThunk.outSize = 0;
res = Lzma2Enc_EncodeMt1(me,
&me->coders[coderIndex],
NULL, dest, &destSize,
NULL, src, srcSize,
finished,
&progressThunk.vt);
me->outBufsDataSizes[outBufIndex] = destSize;
return res;
}
static SRes Lzma2Enc_MtCallback_Write(void *pp, unsigned outBufIndex)
{
CLzma2Enc *me = (CLzma2Enc *)pp;
size_t size = me->outBufsDataSizes[outBufIndex];
const Byte *data = me->outBufs[outBufIndex];
if (me->outStream)
return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE;
if (size > me->outBufSize)
return SZ_ERROR_OUTPUT_EOF;
memcpy(me->outBuf, data, size);
me->outBufSize -= size;
me->outBuf += size;
return SZ_OK;
}
#endif
SRes Lzma2Enc_Encode2(CLzma2EncHandle pp,
ISeqOutStream *outStream,
Byte *outBuf, size_t *outBufSize,
ISeqInStream *inStream,
const Byte *inData, size_t inDataSize,
ICompressProgress *progress)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
if (inStream && inData)
return SZ_ERROR_PARAM;
if (outStream && outBuf)
return SZ_ERROR_PARAM;
{
unsigned i;
for (i = 0; i < MTCODER__THREADS_MAX; i++)
p->coders[i].propsAreSet = False;
}
#ifndef _7ZIP_ST
if (p->props.numBlockThreads_Reduced > 1)
{
IMtCoderCallback2 vt;
if (!p->mtCoder_WasConstructed)
{
p->mtCoder_WasConstructed = True;
MtCoder_Construct(&p->mtCoder);
}
vt.Code = Lzma2Enc_MtCallback_Code;
vt.Write = Lzma2Enc_MtCallback_Write;
p->outStream = outStream;
p->outBuf = NULL;
p->outBufSize = 0;
if (!outStream)
{
p->outBuf = outBuf;
p->outBufSize = *outBufSize;
*outBufSize = 0;
}
p->mtCoder.allocBig = p->allocBig;
p->mtCoder.progress = progress;
p->mtCoder.inStream = inStream;
p->mtCoder.inData = inData;
p->mtCoder.inDataSize = inDataSize;
p->mtCoder.mtCallback = &vt;
p->mtCoder.mtCallbackObject = p;
p->mtCoder.blockSize = (size_t)p->props.blockSize;
if (p->mtCoder.blockSize != p->props.blockSize)
return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */
{
size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16;
if (destBlockSize < p->mtCoder.blockSize)
return SZ_ERROR_PARAM;
if (p->outBufSize != destBlockSize)
Lzma2Enc_FreeOutBufs(p);
p->outBufSize = destBlockSize;
}
p->mtCoder.numThreadsMax = p->props.numBlockThreads_Max;
p->mtCoder.expectedDataSize = p->expectedDataSize;
{
SRes res = MtCoder_Code(&p->mtCoder);
if (!outStream)
*outBufSize = p->outBuf - outBuf;
return res;
}
}
#endif
return Lzma2Enc_EncodeMt1(p,
&p->coders[0],
outStream, outBuf, outBufSize,
inStream, inData, inDataSize,
True, /* finished */
progress);
}

55
C/Lzma2Enc.h Normal file
View File

@@ -0,0 +1,55 @@
/* Lzma2Enc.h -- LZMA2 Encoder
2017-07-27 : Igor Pavlov : Public domain */
#ifndef __LZMA2_ENC_H
#define __LZMA2_ENC_H
#include "LzmaEnc.h"
EXTERN_C_BEGIN
#define LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO 0
#define LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID ((UInt64)(Int64)-1)
typedef struct
{
CLzmaEncProps lzmaProps;
UInt64 blockSize;
int numBlockThreads_Reduced;
int numBlockThreads_Max;
int numTotalThreads;
} CLzma2EncProps;
void Lzma2EncProps_Init(CLzma2EncProps *p);
void Lzma2EncProps_Normalize(CLzma2EncProps *p);
/* ---------- CLzmaEnc2Handle Interface ---------- */
/* Lzma2Enc_* functions can return the following exit codes:
SRes:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - ISeqOutStream write callback error
SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
*/
typedef void * CLzma2EncHandle;
CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig);
void Lzma2Enc_Destroy(CLzma2EncHandle p);
SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize);
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
SRes Lzma2Enc_Encode2(CLzma2EncHandle p,
ISeqOutStream *outStream,
Byte *outBuf, size_t *outBufSize,
ISeqInStream *inStream,
const Byte *inData, size_t inDataSize,
ICompressProgress *progress);
EXTERN_C_END
#endif

59
C/LzmaUtil/Lzma86Enc.h → C/Lzma86.h Executable file → Normal file
View File

@@ -1,12 +1,15 @@
/* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder /* Lzma86.h -- LZMA + x86 (BCJ) Filter
2008-08-05 2013-01-18 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __LZMA86ENC_H #ifndef __LZMA86_H
#define __LZMA86ENC_H #define __LZMA86_H
#include "../Types.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. It's an example for LZMA + x86 Filter use.
@@ -14,8 +17,8 @@ You can use .lzma86 extension, if you write that stream to file.
.lzma86 header adds one additional byte to standard .lzma header. .lzma86 header adds one additional byte to standard .lzma header.
.lzma86 header (14 bytes): .lzma86 header (14 bytes):
Offset Size Description Offset Size Description
0 1 = 0 - no filter, 0 1 = 0 - no filter, pure LZMA
= 1 - x86 filter = 1 - x86 filter + LZMA
1 1 lc, lp and pb in encoded form 1 1 lc, lp and pb in encoded form
2 4 dictSize (little endian) 2 4 dictSize (little endian)
6 8 uncompressed size (little endian) 6 8 uncompressed size (little endian)
@@ -25,7 +28,6 @@ Lzma86_Encode
------------- -------------
level - compression level: 0 <= level <= 9, the default value for "level" is 5. level - compression level: 0 <= level <= 9, the default value for "level" is 5.
dictSize - The dictionary size in bytes. The maximum value is dictSize - The dictionary size in bytes. The maximum value is
128 MB = (1 << 27) bytes for 32-bit version 128 MB = (1 << 27) bytes for 32-bit version
1 GB = (1 << 30) bytes for 64-bit version 1 GB = (1 << 30) bytes for 64-bit version
@@ -69,4 +71,41 @@ enum ESzFilterMode
SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
int level, UInt32 dictSize, int filterMode); 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 #endif

19
C/LzmaUtil/Lzma86Dec.c → C/Lzma86Dec.c Executable file → Normal file
View File

@@ -1,20 +1,13 @@
/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder /* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder
2008-04-07 2016-05-16 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#include "Lzma86Dec.h" #include "Precomp.h"
#include "../Alloc.h" #include "Lzma86.h"
#include "../Bra.h"
#include "../LzmaDec.h"
#define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) #include "Alloc.h"
#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) #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); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)
{ {

23
C/LzmaUtil/Lzma86Enc.c → C/Lzma86Enc.c Executable file → Normal file
View File

@@ -1,25 +1,18 @@
/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
2008-08-05 2016-05-16 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */ #include "Precomp.h"
#include <string.h> #include <string.h>
#include "Lzma86Enc.h" #include "Lzma86.h"
#include "../Alloc.h" #include "Alloc.h"
#include "../Bra.h" #include "Bra.h"
#include "../LzmaEnc.h" #include "LzmaEnc.h"
#define SZE_OUT_OVERFLOW SZE_DATA_ERROR #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); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
#define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE)
#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)
int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
int level, UInt32 dictSize, int filterMode) int level, UInt32 dictSize, int filterMode)
{ {
@@ -104,7 +97,7 @@ int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
} }
} }
} }
dest[0] = (bestIsFiltered ? 1 : 0); dest[0] = (Byte)(bestIsFiltered ? 1 : 0);
*destLen = LZMA86_HEADER_SIZE + minSize; *destLen = LZMA86_HEADER_SIZE + minSize;
} }
if (useFilter) if (useFilter)

606
C/LzmaDec.c Executable file → Normal file
View File

File diff suppressed because it is too large Load Diff

45
C/LzmaDec.h Executable file → Normal file
View File

@@ -1,10 +1,12 @@
/* LzmaDec.h -- LZMA Decoder /* LzmaDec.h -- LZMA Decoder
2008-10-04 : Igor Pavlov : Public domain */ 2018-02-06 : Igor Pavlov : Public domain */
#ifndef __LZMADEC_H #ifndef __LZMA_DEC_H
#define __LZMADEC_H #define __LZMA_DEC_H
#include "Types.h" #include "7zTypes.h"
EXTERN_C_BEGIN
/* #define _LZMA_PROB32 */ /* #define _LZMA_PROB32 */
/* _LZMA_PROB32 can increase the speed on some CPUs, /* _LZMA_PROB32 can increase the speed on some CPUs,
@@ -23,7 +25,10 @@
typedef struct _CLzmaProps typedef struct _CLzmaProps
{ {
unsigned lc, lp, pb; Byte lc;
Byte lp;
Byte pb;
Byte _pad_;
UInt32 dicSize; UInt32 dicSize;
} CLzmaProps; } CLzmaProps;
@@ -45,26 +50,28 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
typedef struct typedef struct
{ {
/* Don't change this structure. ASM code can use it. */
CLzmaProps prop; CLzmaProps prop;
CLzmaProb *probs; CLzmaProb *probs;
CLzmaProb *probs_1664;
Byte *dic; Byte *dic;
const Byte *buf;
UInt32 range, code;
SizeT dicPos;
SizeT dicBufSize; SizeT dicBufSize;
SizeT dicPos;
const Byte *buf;
UInt32 range;
UInt32 code;
UInt32 processedPos; UInt32 processedPos;
UInt32 checkDicSize; UInt32 checkDicSize;
unsigned state;
UInt32 reps[4]; UInt32 reps[4];
unsigned remainLen; UInt32 state;
int needFlush; UInt32 remainLen;
int needInitState;
UInt32 numProbs; UInt32 numProbs;
unsigned tempBufSize; unsigned tempBufSize;
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
} CLzmaDec; } CLzmaDec;
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } #define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; }
void LzmaDec_Init(CLzmaDec *p); void LzmaDec_Init(CLzmaDec *p);
@@ -127,11 +134,11 @@ LzmaDec_Allocate* can return:
SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_UNSUPPORTED - Unsupported properties
*/ */
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);
/* ---------- Dictionary Interface ---------- */ /* ---------- Dictionary Interface ---------- */
@@ -218,6 +225,8 @@ Returns:
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc); ELzmaStatus *status, ISzAllocPtr alloc);
EXTERN_C_END
#endif #endif

615
C/LzmaEnc.c Executable file → Normal file
View File

File diff suppressed because it is too large Load Diff

56
C/LzmaEnc.h Executable file → Normal file
View File

@@ -1,19 +1,21 @@
/* LzmaEnc.h -- LZMA Encoder /* LzmaEnc.h -- LZMA Encoder
2008-10-04 : Igor Pavlov : Public domain */ 2017-07-27 : Igor Pavlov : Public domain */
#ifndef __LZMAENC_H #ifndef __LZMA_ENC_H
#define __LZMAENC_H #define __LZMA_ENC_H
#include "Types.h" #include "7zTypes.h"
EXTERN_C_BEGIN
#define LZMA_PROPS_SIZE 5 #define LZMA_PROPS_SIZE 5
typedef struct _CLzmaEncProps typedef struct _CLzmaEncProps
{ {
int level; /* 0 <= level <= 9 */ int level; /* 0 <= level <= 9 */
UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
(1 << 12) <= dictSize <= (1 << 30) for 64-bit version (1 << 12) <= dictSize <= (3 << 29) for 64-bit version
default = (1 << 24) */ default = (1 << 24) */
int lc; /* 0 <= lc <= 8, default = 3 */ int lc; /* 0 <= lc <= 8, default = 3 */
int lp; /* 0 <= lp <= 4, default = 0 */ int lp; /* 0 <= lp <= 4, default = 0 */
int pb; /* 0 <= pb <= 4, default = 2 */ int pb; /* 0 <= pb <= 4, default = 2 */
@@ -21,9 +23,12 @@ typedef struct _CLzmaEncProps
int fb; /* 5 <= fb <= 273, default = 32 */ int fb; /* 5 <= fb <= 273, default = 32 */
int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
int numHashBytes; /* 2, 3 or 4, default = 4 */ int numHashBytes; /* 2, 3 or 4, default = 4 */
UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
int numThreads; /* 1 or 2, default = 2 */ int numThreads; /* 1 or 2, default = 2 */
UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1.
Encoder uses this value to reduce dictionary size */
} CLzmaEncProps; } CLzmaEncProps;
void LzmaEncProps_Init(CLzmaEncProps *p); void LzmaEncProps_Init(CLzmaEncProps *p);
@@ -33,40 +38,39 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
/* ---------- CLzmaEncHandle Interface ---------- */ /* ---------- CLzmaEncHandle Interface ---------- */
/* LzmaEnc_* functions can return the following exit codes: /* LzmaEnc* functions can return the following exit codes:
Returns: SRes:
SZ_OK - OK SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - Write callback error. SZ_ERROR_WRITE - ISeqOutStream write callback error
SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
*/ */
typedef void * CLzmaEncHandle; typedef void * CLzmaEncHandle;
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc);
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig);
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize);
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p);
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
/* ---------- One Call Interface ---------- */ /* ---------- 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, SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
EXTERN_C_END
#endif #endif

16
C/LzmaLib.c Executable file → Normal file
View File

@@ -1,18 +1,12 @@
/* LzmaLib.c -- LZMA library wrapper /* LzmaLib.c -- LZMA library wrapper
2008-08-05 2015-06-13 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#include "LzmaEnc.h"
#include "LzmaDec.h"
#include "Alloc.h" #include "Alloc.h"
#include "LzmaDec.h"
#include "LzmaEnc.h"
#include "LzmaLib.h" #include "LzmaLib.h"
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
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, unsigned char *outProps, size_t *outPropsSize,
int level, /* 0 <= level <= 9, default = 5 */ int level, /* 0 <= level <= 9, default = 5 */
unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */
@@ -38,7 +32,7 @@ MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned cha
} }
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen,
const unsigned char *props, size_t propsSize) const unsigned char *props, size_t propsSize)
{ {
ELzmaStatus status; ELzmaStatus status;

20
C/LzmaLib.h Executable file → Normal file
View File

@@ -1,20 +1,14 @@
/* LzmaLib.h -- LZMA library interface /* LzmaLib.h -- LZMA library interface
2008-08-05 2013-01-18 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __LZMALIB_H #ifndef __LZMA_LIB_H
#define __LZMALIB_H #define __LZMA_LIB_H
#include "Types.h" #include "7zTypes.h"
#ifdef __cplusplus EXTERN_C_BEGIN
#define MY_EXTERN_C extern "C"
#else
#define MY_EXTERN_C extern
#endif
#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL #define MY_STDAPI int MY_STD_CALL
#define LZMA_PROPS_SIZE 5 #define LZMA_PROPS_SIZE 5
@@ -132,4 +126,6 @@ Returns:
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
const unsigned char *props, size_t propsSize); const unsigned char *props, size_t propsSize);
EXTERN_C_END
#endif #endif

View File

@@ -1,45 +0,0 @@
/* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder
2008-08-05
Igor Pavlov
Public domain */
#ifndef __LZMA86DEC_H
#define __LZMA86DEC_H
#include "../Types.h"
/*
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);
#endif

View File

@@ -1,44 +0,0 @@
PROG = lzma
CXX = g++
LIB =
RM = rm -f
CFLAGS = -c -O2 -Wall
OBJS = \
LzmaUtil.o \
Alloc.o \
LzFind.o \
LzmaDec.o \
LzmaEnc.o \
7zFile.o \
7zStream.o \
all: $(PROG)
$(PROG): $(OBJS)
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)
LzmaUtil.o: LzmaUtil.c
$(CXX) $(CFLAGS) LzmaUtil.c
Alloc.o: ../Alloc.c
$(CXX) $(CFLAGS) ../Alloc.c
LzFind.o: ../LzFind.c
$(CXX) $(CFLAGS) ../LzFind.c
LzmaDec.o: ../LzmaDec.c
$(CXX) $(CFLAGS) ../LzmaDec.c
LzmaEnc.o: ../LzmaEnc.c
$(CXX) $(CFLAGS) ../LzmaEnc.c
7zFile.o: ../7zFile.c
$(CXX) $(CFLAGS) ../7zFile.c
7zStream.o: ../7zStream.c
$(CXX) $(CFLAGS) ../7zStream.c
clean:
-$(RM) $(PROG) $(OBJS)

601
C/MtCoder.c Normal file
View File

@@ -0,0 +1,601 @@
/* MtCoder.c -- Multi-thread Coder
2018-02-21 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "MtCoder.h"
#ifndef _7ZIP_ST
SRes MtProgressThunk_Progress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize)
{
CMtProgressThunk *thunk = CONTAINER_FROM_VTBL(pp, CMtProgressThunk, vt);
UInt64 inSize2 = 0;
UInt64 outSize2 = 0;
if (inSize != (UInt64)(Int64)-1)
{
inSize2 = inSize - thunk->inSize;
thunk->inSize = inSize;
}
if (outSize != (UInt64)(Int64)-1)
{
outSize2 = outSize - thunk->outSize;
thunk->outSize = outSize;
}
return MtProgress_ProgressAdd(thunk->mtProgress, inSize2, outSize2);
}
void MtProgressThunk_CreateVTable(CMtProgressThunk *p)
{
p->vt.Progress = MtProgressThunk_Progress;
}
#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
static WRes ArEvent_OptCreate_And_Reset(CEvent *p)
{
if (Event_IsCreated(p))
return Event_Reset(p);
return AutoResetEvent_CreateNotSignaled(p);
}
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp);
static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t)
{
WRes wres = ArEvent_OptCreate_And_Reset(&t->startEvent);
if (wres == 0)
{
t->stop = False;
if (!Thread_WasCreated(&t->thread))
wres = Thread_Create(&t->thread, ThreadFunc, t);
if (wres == 0)
wres = Event_Set(&t->startEvent);
}
if (wres == 0)
return SZ_OK;
return MY_SRes_HRESULT_FROM_WRes(wres);
}
static void MtCoderThread_Destruct(CMtCoderThread *t)
{
if (Thread_WasCreated(&t->thread))
{
t->stop = 1;
Event_Set(&t->startEvent);
Thread_Wait(&t->thread);
Thread_Close(&t->thread);
}
Event_Close(&t->startEvent);
if (t->inBuf)
{
ISzAlloc_Free(t->mtCoder->allocBig, t->inBuf);
t->inBuf = NULL;
}
}
static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
{
size_t size = *processedSize;
*processedSize = 0;
while (size != 0)
{
size_t cur = size;
SRes res = ISeqInStream_Read(stream, data, &cur);
*processedSize += cur;
data += cur;
size -= cur;
RINOK(res);
if (cur == 0)
return SZ_OK;
}
return SZ_OK;
}
/*
ThreadFunc2() returns:
SZ_OK - in all normal cases (even for stream error or memory allocation error)
SZ_ERROR_THREAD - in case of failure in system synch function
*/
static SRes ThreadFunc2(CMtCoderThread *t)
{
CMtCoder *mtc = t->mtCoder;
for (;;)
{
unsigned bi;
SRes res;
SRes res2;
Bool finished;
unsigned bufIndex;
size_t size;
const Byte *inData;
UInt64 readProcessed = 0;
RINOK_THREAD(Event_Wait(&mtc->readEvent))
/* after Event_Wait(&mtc->readEvent) we must call Event_Set(&mtc->readEvent) in any case to unlock another threads */
if (mtc->stopReading)
{
return Event_Set(&mtc->readEvent) == 0 ? SZ_OK : SZ_ERROR_THREAD;
}
res = MtProgress_GetError(&mtc->mtProgress);
size = 0;
inData = NULL;
finished = True;
if (res == SZ_OK)
{
size = mtc->blockSize;
if (mtc->inStream)
{
if (!t->inBuf)
{
t->inBuf = (Byte *)ISzAlloc_Alloc(mtc->allocBig, mtc->blockSize);
if (!t->inBuf)
res = SZ_ERROR_MEM;
}
if (res == SZ_OK)
{
res = FullRead(mtc->inStream, t->inBuf, &size);
readProcessed = mtc->readProcessed + size;
mtc->readProcessed = readProcessed;
}
if (res != SZ_OK)
{
mtc->readRes = res;
/* after reading error - we can stop encoding of previous blocks */
MtProgress_SetError(&mtc->mtProgress, res);
}
else
finished = (size != mtc->blockSize);
}
else
{
size_t rem;
readProcessed = mtc->readProcessed;
rem = mtc->inDataSize - (size_t)readProcessed;
if (size > rem)
size = rem;
inData = mtc->inData + (size_t)readProcessed;
readProcessed += size;
mtc->readProcessed = readProcessed;
finished = (mtc->inDataSize == (size_t)readProcessed);
}
}
/* we must get some block from blocksSemaphore before Event_Set(&mtc->readEvent) */
res2 = SZ_OK;
if (Semaphore_Wait(&mtc->blocksSemaphore) != 0)
{
res2 = SZ_ERROR_THREAD;
if (res == SZ_OK)
{
res = res2;
// MtProgress_SetError(&mtc->mtProgress, res);
}
}
bi = mtc->blockIndex;
if (++mtc->blockIndex >= mtc->numBlocksMax)
mtc->blockIndex = 0;
bufIndex = (unsigned)(int)-1;
if (res == SZ_OK)
res = MtProgress_GetError(&mtc->mtProgress);
if (res != SZ_OK)
finished = True;
if (!finished)
{
if (mtc->numStartedThreads < mtc->numStartedThreadsLimit
&& mtc->expectedDataSize != readProcessed)
{
res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]);
if (res == SZ_OK)
mtc->numStartedThreads++;
else
{
MtProgress_SetError(&mtc->mtProgress, res);
finished = True;
}
}
}
if (finished)
mtc->stopReading = True;
RINOK_THREAD(Event_Set(&mtc->readEvent))
if (res2 != SZ_OK)
return res2;
if (res == SZ_OK)
{
CriticalSection_Enter(&mtc->cs);
bufIndex = mtc->freeBlockHead;
mtc->freeBlockHead = mtc->freeBlockList[bufIndex];
CriticalSection_Leave(&mtc->cs);
res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex,
mtc->inStream ? t->inBuf : inData, size, finished);
// MtProgress_Reinit(&mtc->mtProgress, t->index);
if (res != SZ_OK)
MtProgress_SetError(&mtc->mtProgress, res);
}
{
CMtCoderBlock *block = &mtc->blocks[bi];
block->res = res;
block->bufIndex = bufIndex;
block->finished = finished;
}
#ifdef MTCODER__USE_WRITE_THREAD
RINOK_THREAD(Event_Set(&mtc->writeEvents[bi]))
#else
{
unsigned wi;
{
CriticalSection_Enter(&mtc->cs);
wi = mtc->writeIndex;
if (wi == bi)
mtc->writeIndex = (unsigned)(int)-1;
else
mtc->ReadyBlocks[bi] = True;
CriticalSection_Leave(&mtc->cs);
}
if (wi != bi)
{
if (res != SZ_OK || finished)
return 0;
continue;
}
if (mtc->writeRes != SZ_OK)
res = mtc->writeRes;
for (;;)
{
if (res == SZ_OK && bufIndex != (unsigned)(int)-1)
{
res = mtc->mtCallback->Write(mtc->mtCallbackObject, bufIndex);
if (res != SZ_OK)
{
mtc->writeRes = res;
MtProgress_SetError(&mtc->mtProgress, res);
}
}
if (++wi >= mtc->numBlocksMax)
wi = 0;
{
Bool isReady;
CriticalSection_Enter(&mtc->cs);
if (bufIndex != (unsigned)(int)-1)
{
mtc->freeBlockList[bufIndex] = mtc->freeBlockHead;
mtc->freeBlockHead = bufIndex;
}
isReady = mtc->ReadyBlocks[wi];
if (isReady)
mtc->ReadyBlocks[wi] = False;
else
mtc->writeIndex = wi;
CriticalSection_Leave(&mtc->cs);
RINOK_THREAD(Semaphore_Release1(&mtc->blocksSemaphore))
if (!isReady)
break;
}
{
CMtCoderBlock *block = &mtc->blocks[wi];
if (res == SZ_OK && block->res != SZ_OK)
res = block->res;
bufIndex = block->bufIndex;
finished = block->finished;
}
}
}
#endif
if (finished || res != SZ_OK)
return 0;
}
}
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
{
CMtCoderThread *t = (CMtCoderThread *)pp;
for (;;)
{
if (Event_Wait(&t->startEvent) != 0)
return SZ_ERROR_THREAD;
if (t->stop)
return 0;
{
SRes res = ThreadFunc2(t);
CMtCoder *mtc = t->mtCoder;
if (res != SZ_OK)
{
MtProgress_SetError(&mtc->mtProgress, res);
}
#ifndef MTCODER__USE_WRITE_THREAD
{
unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads);
if (numFinished == mtc->numStartedThreads)
if (Event_Set(&mtc->finishedEvent) != 0)
return SZ_ERROR_THREAD;
}
#endif
}
}
}
void MtCoder_Construct(CMtCoder *p)
{
unsigned i;
p->blockSize = 0;
p->numThreadsMax = 0;
p->expectedDataSize = (UInt64)(Int64)-1;
p->inStream = NULL;
p->inData = NULL;
p->inDataSize = 0;
p->progress = NULL;
p->allocBig = NULL;
p->mtCallback = NULL;
p->mtCallbackObject = NULL;
p->allocatedBufsSize = 0;
Event_Construct(&p->readEvent);
Semaphore_Construct(&p->blocksSemaphore);
for (i = 0; i < MTCODER__THREADS_MAX; i++)
{
CMtCoderThread *t = &p->threads[i];
t->mtCoder = p;
t->index = i;
t->inBuf = NULL;
t->stop = False;
Event_Construct(&t->startEvent);
Thread_Construct(&t->thread);
}
#ifdef MTCODER__USE_WRITE_THREAD
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
Event_Construct(&p->writeEvents[i]);
#else
Event_Construct(&p->finishedEvent);
#endif
CriticalSection_Init(&p->cs);
CriticalSection_Init(&p->mtProgress.cs);
}
static void MtCoder_Free(CMtCoder *p)
{
unsigned i;
/*
p->stopReading = True;
if (Event_IsCreated(&p->readEvent))
Event_Set(&p->readEvent);
*/
for (i = 0; i < MTCODER__THREADS_MAX; i++)
MtCoderThread_Destruct(&p->threads[i]);
Event_Close(&p->readEvent);
Semaphore_Close(&p->blocksSemaphore);
#ifdef MTCODER__USE_WRITE_THREAD
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
Event_Close(&p->writeEvents[i]);
#else
Event_Close(&p->finishedEvent);
#endif
}
void MtCoder_Destruct(CMtCoder *p)
{
MtCoder_Free(p);
CriticalSection_Delete(&p->cs);
CriticalSection_Delete(&p->mtProgress.cs);
}
SRes MtCoder_Code(CMtCoder *p)
{
unsigned numThreads = p->numThreadsMax;
unsigned numBlocksMax;
unsigned i;
SRes res = SZ_OK;
if (numThreads > MTCODER__THREADS_MAX)
numThreads = MTCODER__THREADS_MAX;
numBlocksMax = MTCODER__GET_NUM_BLOCKS_FROM_THREADS(numThreads);
if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++;
if (p->blockSize < ((UInt32)1 << 24)) numBlocksMax++;
if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++;
if (numBlocksMax > MTCODER__BLOCKS_MAX)
numBlocksMax = MTCODER__BLOCKS_MAX;
if (p->blockSize != p->allocatedBufsSize)
{
for (i = 0; i < MTCODER__THREADS_MAX; i++)
{
CMtCoderThread *t = &p->threads[i];
if (t->inBuf)
{
ISzAlloc_Free(p->allocBig, t->inBuf);
t->inBuf = NULL;
}
}
p->allocatedBufsSize = p->blockSize;
}
p->readRes = SZ_OK;
MtProgress_Init(&p->mtProgress, p->progress);
#ifdef MTCODER__USE_WRITE_THREAD
for (i = 0; i < numBlocksMax; i++)
{
RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->writeEvents[i]));
}
#else
RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->finishedEvent));
#endif
{
RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->readEvent));
if (Semaphore_IsCreated(&p->blocksSemaphore))
{
RINOK_THREAD(Semaphore_Close(&p->blocksSemaphore));
}
RINOK_THREAD(Semaphore_Create(&p->blocksSemaphore, numBlocksMax, numBlocksMax));
}
for (i = 0; i < MTCODER__BLOCKS_MAX - 1; i++)
p->freeBlockList[i] = i + 1;
p->freeBlockList[MTCODER__BLOCKS_MAX - 1] = (unsigned)(int)-1;
p->freeBlockHead = 0;
p->readProcessed = 0;
p->blockIndex = 0;
p->numBlocksMax = numBlocksMax;
p->stopReading = False;
#ifndef MTCODER__USE_WRITE_THREAD
p->writeIndex = 0;
p->writeRes = SZ_OK;
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
p->ReadyBlocks[i] = False;
p->numFinishedThreads = 0;
#endif
p->numStartedThreadsLimit = numThreads;
p->numStartedThreads = 0;
// for (i = 0; i < numThreads; i++)
{
CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++];
RINOK(MtCoderThread_CreateAndStart(nextThread));
}
RINOK_THREAD(Event_Set(&p->readEvent))
#ifdef MTCODER__USE_WRITE_THREAD
{
unsigned bi = 0;
for (;; bi++)
{
if (bi >= numBlocksMax)
bi = 0;
RINOK_THREAD(Event_Wait(&p->writeEvents[bi]))
{
const CMtCoderBlock *block = &p->blocks[bi];
unsigned bufIndex = block->bufIndex;
Bool finished = block->finished;
if (res == SZ_OK && block->res != SZ_OK)
res = block->res;
if (bufIndex != (unsigned)(int)-1)
{
if (res == SZ_OK)
{
res = p->mtCallback->Write(p->mtCallbackObject, bufIndex);
if (res != SZ_OK)
MtProgress_SetError(&p->mtProgress, res);
}
CriticalSection_Enter(&p->cs);
{
p->freeBlockList[bufIndex] = p->freeBlockHead;
p->freeBlockHead = bufIndex;
}
CriticalSection_Leave(&p->cs);
}
RINOK_THREAD(Semaphore_Release1(&p->blocksSemaphore))
if (finished)
break;
}
}
}
#else
{
WRes wres = Event_Wait(&p->finishedEvent);
res = MY_SRes_HRESULT_FROM_WRes(wres);
}
#endif
if (res == SZ_OK)
res = p->readRes;
if (res == SZ_OK)
res = p->mtProgress.res;
#ifndef MTCODER__USE_WRITE_THREAD
if (res == SZ_OK)
res = p->writeRes;
#endif
if (res != SZ_OK)
MtCoder_Free(p);
return res;
}
#endif

141
C/MtCoder.h Normal file
View File

@@ -0,0 +1,141 @@
/* MtCoder.h -- Multi-thread Coder
2018-02-21 : Igor Pavlov : Public domain */
#ifndef __MT_CODER_H
#define __MT_CODER_H
#include "MtDec.h"
EXTERN_C_BEGIN
/*
if ( defined MTCODER__USE_WRITE_THREAD) : main thread writes all data blocks to output stream
if (not defined MTCODER__USE_WRITE_THREAD) : any coder thread can write data blocks to output stream
*/
/* #define MTCODER__USE_WRITE_THREAD */
#ifndef _7ZIP_ST
#define MTCODER__GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1)
#define MTCODER__THREADS_MAX 64
#define MTCODER__BLOCKS_MAX (MTCODER__GET_NUM_BLOCKS_FROM_THREADS(MTCODER__THREADS_MAX) + 3)
#else
#define MTCODER__THREADS_MAX 1
#define MTCODER__BLOCKS_MAX 1
#endif
#ifndef _7ZIP_ST
typedef struct
{
ICompressProgress vt;
CMtProgress *mtProgress;
UInt64 inSize;
UInt64 outSize;
} CMtProgressThunk;
void MtProgressThunk_CreateVTable(CMtProgressThunk *p);
#define MtProgressThunk_Init(p) { (p)->inSize = 0; (p)->outSize = 0; }
struct _CMtCoder;
typedef struct
{
struct _CMtCoder *mtCoder;
unsigned index;
int stop;
Byte *inBuf;
CAutoResetEvent startEvent;
CThread thread;
} CMtCoderThread;
typedef struct
{
SRes (*Code)(void *p, unsigned coderIndex, unsigned outBufIndex,
const Byte *src, size_t srcSize, int finished);
SRes (*Write)(void *p, unsigned outBufIndex);
} IMtCoderCallback2;
typedef struct
{
SRes res;
unsigned bufIndex;
Bool finished;
} CMtCoderBlock;
typedef struct _CMtCoder
{
/* input variables */
size_t blockSize; /* size of input block */
unsigned numThreadsMax;
UInt64 expectedDataSize;
ISeqInStream *inStream;
const Byte *inData;
size_t inDataSize;
ICompressProgress *progress;
ISzAllocPtr allocBig;
IMtCoderCallback2 *mtCallback;
void *mtCallbackObject;
/* internal variables */
size_t allocatedBufsSize;
CAutoResetEvent readEvent;
CSemaphore blocksSemaphore;
Bool stopReading;
SRes readRes;
#ifdef MTCODER__USE_WRITE_THREAD
CAutoResetEvent writeEvents[MTCODER__BLOCKS_MAX];
#else
CAutoResetEvent finishedEvent;
SRes writeRes;
unsigned writeIndex;
Byte ReadyBlocks[MTCODER__BLOCKS_MAX];
LONG numFinishedThreads;
#endif
unsigned numStartedThreadsLimit;
unsigned numStartedThreads;
unsigned numBlocksMax;
unsigned blockIndex;
UInt64 readProcessed;
CCriticalSection cs;
unsigned freeBlockHead;
unsigned freeBlockList[MTCODER__BLOCKS_MAX];
CMtProgress mtProgress;
CMtCoderBlock blocks[MTCODER__BLOCKS_MAX];
CMtCoderThread threads[MTCODER__THREADS_MAX];
} CMtCoder;
void MtCoder_Construct(CMtCoder *p);
void MtCoder_Destruct(CMtCoder *p);
SRes MtCoder_Code(CMtCoder *p);
#endif
EXTERN_C_END
#endif

1137
C/MtDec.c Normal file
View File

File diff suppressed because it is too large Load Diff

201
C/MtDec.h Normal file
View File

@@ -0,0 +1,201 @@
/* MtDec.h -- Multi-thread Decoder
2018-03-02 : Igor Pavlov : Public domain */
#ifndef __MT_DEC_H
#define __MT_DEC_H
#include "7zTypes.h"
#ifndef _7ZIP_ST
#include "Threads.h"
#endif
EXTERN_C_BEGIN
#ifndef _7ZIP_ST
#ifndef _7ZIP_ST
#define MTDEC__THREADS_MAX 32
#else
#define MTDEC__THREADS_MAX 1
#endif
typedef struct
{
ICompressProgress *progress;
SRes res;
UInt64 totalInSize;
UInt64 totalOutSize;
CCriticalSection cs;
} CMtProgress;
void MtProgress_Init(CMtProgress *p, ICompressProgress *progress);
SRes MtProgress_Progress_ST(CMtProgress *p);
SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize);
SRes MtProgress_GetError(CMtProgress *p);
void MtProgress_SetError(CMtProgress *p, SRes res);
struct _CMtDec;
typedef struct
{
struct _CMtDec *mtDec;
unsigned index;
void *inBuf;
size_t inDataSize_Start; // size of input data in start block
UInt64 inDataSize; // total size of input data in all blocks
CThread thread;
CAutoResetEvent canRead;
CAutoResetEvent canWrite;
void *allocaPtr;
} CMtDecThread;
void MtDecThread_FreeInBufs(CMtDecThread *t);
typedef enum
{
MTDEC_PARSE_CONTINUE, // continue this block with more input data
MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread
MTDEC_PARSE_NEW, // new block
MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue)
} EMtDecParseState;
typedef struct
{
// in
int startCall;
const Byte *src;
size_t srcSize;
// in : (srcSize == 0) is allowed
// out : it's allowed to return less that actually was used ?
int srcFinished;
// out
EMtDecParseState state;
Bool canCreateNewThread;
UInt64 outPos; // check it (size_t)
} CMtDecCallbackInfo;
typedef struct
{
void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci);
// PreCode() and Code():
// (SRes_return_result != SZ_OK) means stop decoding, no need another blocks
SRes (*PreCode)(void *p, unsigned coderIndex);
SRes (*Code)(void *p, unsigned coderIndex,
const Byte *src, size_t srcSize, int srcFinished,
UInt64 *inCodePos, UInt64 *outCodePos, int *stop);
// stop - means stop another Code calls
/* Write() must be called, if Parse() was called
set (needWrite) if
{
&& (was not interrupted by progress)
&& (was not interrupted in previous block)
}
out:
if (*needContinue), decoder still need to continue decoding with new iteration,
even after MTDEC_PARSE_END
if (*canRecode), we didn't flush current block data, so we still can decode current block later.
*/
SRes (*Write)(void *p, unsigned coderIndex,
Bool needWriteToStream,
const Byte *src, size_t srcSize,
// int srcFinished,
Bool *needContinue,
Bool *canRecode);
} IMtDecCallback;
typedef struct _CMtDec
{
/* input variables */
size_t inBufSize; /* size of input block */
unsigned numThreadsMax;
// size_t inBlockMax;
unsigned numThreadsMax_2;
ISeqInStream *inStream;
// const Byte *inData;
// size_t inDataSize;
ICompressProgress *progress;
ISzAllocPtr alloc;
IMtDecCallback *mtCallback;
void *mtCallbackObject;
/* internal variables */
size_t allocatedBufsSize;
Bool exitThread;
WRes exitThreadWRes;
UInt64 blockIndex;
Bool isAllocError;
Bool overflow;
SRes threadingErrorSRes;
Bool needContinue;
// CAutoResetEvent finishedEvent;
SRes readRes;
SRes codeRes;
Bool wasInterrupted;
unsigned numStartedThreads_Limit;
unsigned numStartedThreads;
Byte *crossBlock;
size_t crossStart;
size_t crossEnd;
UInt64 readProcessed;
Bool readWasFinished;
UInt64 inProcessed;
unsigned filledThreadStart;
unsigned numFilledThreads;
#ifndef _7ZIP_ST
Bool needInterrupt;
UInt64 interruptIndex;
CMtProgress mtProgress;
CMtDecThread threads[MTDEC__THREADS_MAX];
#endif
} CMtDec;
void MtDec_Construct(CMtDec *p);
void MtDec_Destruct(CMtDec *p);
/*
MtDec_Code() returns:
SZ_OK - in most cases
MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function
*/
SRes MtDec_Code(CMtDec *p);
Byte *MtDec_GetCrossBuff(CMtDec *p);
int MtDec_PrepareRead(CMtDec *p);
const Byte *MtDec_Read(CMtDec *p, size_t *inLim);
#endif
EXTERN_C_END
#endif

85
C/Ppmd.h Normal file
View File

@@ -0,0 +1,85 @@
/* Ppmd.h -- PPMD codec common code
2017-04-03 : 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) \
{ size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \
p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }}
EXTERN_C_END
#endif

712
C/Ppmd7.c Normal file
View File

@@ -0,0 +1,712 @@
/* Ppmd7.c -- PPMdH codec
2017-04-03 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h"
#include <string.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[(size_t)(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, ISzAllocPtr alloc)
{
ISzAlloc_Free(alloc, p->Base);
p->Size = 0;
p->Base = 0;
}
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc)
{
if (!p->Base || p->Size != size)
{
size_t size2;
Ppmd7_Free(p, alloc);
size2 = 0
#ifndef PPMD_32BIT
+ UNIT_SIZE
#endif
;
p->AlignOffset =
#ifdef PPMD_32BIT
(4 - size) & 3;
#else
4 - (size & 3);
#endif
if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size + size2)) == 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((size_t)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[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] +
(nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
2 * (unsigned)(p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
4 * (unsigned)(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);
}

142
C/Ppmd7.h Normal file
View File

@@ -0,0 +1,142 @@
/* Ppmd7.h -- PPMdH compression codec
2017-04-03 : 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, ISzAllocPtr alloc);
void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr 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[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
(p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
2 * p->HB2Flag[(unsigned)Ppmd7Context_OneState(p->MinContext)->Symbol] + \
((p->RunLength >> 26) & 0x20)]
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
/* ---------- Decode ---------- */
typedef struct IPpmd7_RangeDec IPpmd7_RangeDec;
struct IPpmd7_RangeDec
{
UInt32 (*GetThreshold)(const IPpmd7_RangeDec *p, UInt32 total);
void (*Decode)(const IPpmd7_RangeDec *p, UInt32 start, UInt32 size);
UInt32 (*DecodeBit)(const IPpmd7_RangeDec *p, UInt32 size0);
};
typedef struct
{
IPpmd7_RangeDec vt;
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, const 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

191
C/Ppmd7Dec.c Normal file
View File

@@ -0,0 +1,191 @@
/* Ppmd7Dec.c -- PPMdH Decoder
2017-04-03 : 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 (IByteIn_Read(p->Stream) != 0)
return False;
for (i = 0; i < 4; i++)
p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
return (p->Code < 0xFFFFFFFF);
}
#define GET_Ppmd7z_RangeDec CPpmd7z_RangeDec *p = CONTAINER_FROM_VTBL(pp, CPpmd7z_RangeDec, vt);
static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total)
{
GET_Ppmd7z_RangeDec
return p->Code / (p->Range /= total);
}
static void Range_Normalize(CPpmd7z_RangeDec *p)
{
if (p->Range < kTopValue)
{
p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
p->Range <<= 8;
if (p->Range < kTopValue)
{
p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
p->Range <<= 8;
}
}
}
static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size)
{
GET_Ppmd7z_RangeDec
p->Code -= start * p->Range;
p->Range *= size;
Range_Normalize(p);
}
static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0)
{
GET_Ppmd7z_RangeDec
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->vt.GetThreshold = Range_GetThreshold;
p->vt.Decode = Range_Decode;
p->vt.DecodeBit = Range_DecodeBit;
}
#define MASK(sym) ((signed char *)charMask)[sym]
int Ppmd7_DecodeSymbol(CPpmd7 *p, const 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);
}
}

187
C/Ppmd7Enc.c Normal file
View File

@@ -0,0 +1,187 @@
/* Ppmd7Enc.c -- PPMdH Encoder
2017-04-03 : 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
{
IByteOut_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);
}
}

1123
C/Ppmd8.c Normal file
View File

File diff suppressed because it is too large Load Diff

137
C/Ppmd8.h Normal file
View File

@@ -0,0 +1,137 @@
/* Ppmd8.h -- PPMdI codec
2017-04-03 : Igor Pavlov : Public domain
This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
#ifndef __PPMD8_H
#define __PPMD8_H
#include "Ppmd.h"
EXTERN_C_BEGIN
#define PPMD8_MIN_ORDER 2
#define PPMD8_MAX_ORDER 16
struct CPpmd8_Context_;
typedef
#ifdef PPMD_32BIT
struct CPpmd8_Context_ *
#else
UInt32
#endif
CPpmd8_Context_Ref;
#pragma pack(push, 1)
typedef struct CPpmd8_Context_
{
Byte NumStats;
Byte Flags;
UInt16 SummFreq;
CPpmd_State_Ref Stats;
CPpmd8_Context_Ref Suffix;
} CPpmd8_Context;
#pragma pack(pop)
#define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
/* The BUG in Shkarin's code for FREEZE mode was fixed, but that fixed
code is not compatible with original code for some files compressed
in FREEZE mode. So we disable FREEZE mode support. */
enum
{
PPMD8_RESTORE_METHOD_RESTART,
PPMD8_RESTORE_METHOD_CUT_OFF
#ifdef PPMD8_FREEZE_SUPPORT
, PPMD8_RESTORE_METHOD_FREEZE
#endif
};
typedef struct
{
CPpmd8_Context *MinContext, *MaxContext;
CPpmd_State *FoundState;
unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder;
Int32 RunLength, InitRL; /* must be 32-bit at least */
UInt32 Size;
UInt32 GlueCount;
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
UInt32 AlignOffset;
unsigned RestoreMethod;
/* Range Coder */
UInt32 Range;
UInt32 Code;
UInt32 Low;
union
{
IByteIn *In;
IByteOut *Out;
} Stream;
Byte Indx2Units[PPMD_NUM_INDEXES];
Byte Units2Indx[128];
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
UInt32 Stamps[PPMD_NUM_INDEXES];
Byte NS2BSIndx[256], NS2Indx[260];
CPpmd_See DummySee, See[24][32];
UInt16 BinSumm[25][64];
} CPpmd8;
void Ppmd8_Construct(CPpmd8 *p);
Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAllocPtr alloc);
void Ppmd8_Free(CPpmd8 *p, ISzAllocPtr alloc);
void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod);
#define Ppmd8_WasAllocated(p) ((p)->Base != NULL)
/* ---------- Internal Functions ---------- */
extern const Byte PPMD8_kExpEscape[16];
#ifdef PPMD_32BIT
#define Ppmd8_GetPtr(p, ptr) (ptr)
#define Ppmd8_GetContext(p, ptr) (ptr)
#define Ppmd8_GetStats(p, ctx) ((ctx)->Stats)
#else
#define Ppmd8_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
#define Ppmd8_GetContext(p, offs) ((CPpmd8_Context *)Ppmd8_GetPtr((p), (offs)))
#define Ppmd8_GetStats(p, ctx) ((CPpmd_State *)Ppmd8_GetPtr((p), ((ctx)->Stats)))
#endif
void Ppmd8_Update1(CPpmd8 *p);
void Ppmd8_Update1_0(CPpmd8 *p);
void Ppmd8_Update2(CPpmd8 *p);
void Ppmd8_UpdateBin(CPpmd8 *p);
#define Ppmd8_GetBinSumm(p) \
&p->BinSumm[p->NS2Indx[(size_t)Ppmd8Context_OneState(p->MinContext)->Freq - 1]][ \
p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \
p->PrevSuccess + p->MinContext->Flags + ((p->RunLength >> 26) & 0x20)]
CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale);
/* ---------- Decode ---------- */
Bool Ppmd8_RangeDec_Init(CPpmd8 *p);
#define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
int Ppmd8_DecodeSymbol(CPpmd8 *p); /* returns: -1 as EndMarker, -2 as DataError */
/* ---------- Encode ---------- */
#define Ppmd8_RangeEnc_Init(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; }
void Ppmd8_RangeEnc_FlushData(CPpmd8 *p);
void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol); /* symbol = -1 means EndMarker */
EXTERN_C_END
#endif

157
C/Ppmd8Dec.c Normal file
View File

@@ -0,0 +1,157 @@
/* Ppmd8Dec.c -- PPMdI Decoder
2017-04-03 : Igor Pavlov : Public domain
This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
#include "Precomp.h"
#include "Ppmd8.h"
#define kTop (1 << 24)
#define kBot (1 << 15)
Bool Ppmd8_RangeDec_Init(CPpmd8 *p)
{
unsigned i;
p->Low = 0;
p->Range = 0xFFFFFFFF;
p->Code = 0;
for (i = 0; i < 4; i++)
p->Code = (p->Code << 8) | IByteIn_Read(p->Stream.In);
return (p->Code < 0xFFFFFFFF);
}
static UInt32 RangeDec_GetThreshold(CPpmd8 *p, UInt32 total)
{
return p->Code / (p->Range /= total);
}
static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size)
{
start *= p->Range;
p->Low += start;
p->Code -= start;
p->Range *= size;
while ((p->Low ^ (p->Low + p->Range)) < kTop ||
(p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)))
{
p->Code = (p->Code << 8) | IByteIn_Read(p->Stream.In);
p->Range <<= 8;
p->Low <<= 8;
}
}
#define MASK(sym) ((signed char *)charMask)[sym]
int Ppmd8_DecodeSymbol(CPpmd8 *p)
{
size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 0)
{
CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);
unsigned i;
UInt32 count, hiCnt;
if ((count = RangeDec_GetThreshold(p, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
{
Byte symbol;
RangeDec_Decode(p, 0, s->Freq);
p->FoundState = s;
symbol = s->Symbol;
Ppmd8_Update1_0(p);
return symbol;
}
p->PrevSuccess = 0;
i = p->MinContext->NumStats;
do
{
if ((hiCnt += (++s)->Freq) > count)
{
Byte symbol;
RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
p->FoundState = s;
symbol = s->Symbol;
Ppmd8_Update1(p);
return symbol;
}
}
while (--i);
if (count >= p->MinContext->SummFreq)
return -2;
RangeDec_Decode(p, hiCnt, p->MinContext->SummFreq - hiCnt);
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
i = p->MinContext->NumStats;
do { MASK((--s)->Symbol) = 0; } while (--i);
}
else
{
UInt16 *prob = Ppmd8_GetBinSumm(p);
if (((p->Code / (p->Range >>= 14)) < *prob))
{
Byte symbol;
RangeDec_Decode(p, 0, *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
symbol = (p->FoundState = Ppmd8Context_OneState(p->MinContext))->Symbol;
Ppmd8_UpdateBin(p);
return symbol;
}
RangeDec_Decode(p, *prob, (1 << 14) - *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
p->InitEsc = PPMD8_kExpEscape[*prob >> 10];
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(Ppmd8Context_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 = Ppmd8_GetContext(p, p->MinContext->Suffix);
}
while (p->MinContext->NumStats == numMasked);
hiCnt = 0;
s = Ppmd8_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 = Ppmd8_MakeEscFreq(p, numMasked, &freqSum);
freqSum += hiCnt;
count = RangeDec_GetThreshold(p, freqSum);
if (count < hiCnt)
{
Byte symbol;
CPpmd_State **pps = ps;
for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
s = *pps;
RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
Ppmd_See_Update(see);
p->FoundState = s;
symbol = s->Symbol;
Ppmd8_Update2(p);
return symbol;
}
if (count >= freqSum)
return -2;
RangeDec_Decode(p, hiCnt, freqSum - hiCnt);
see->Summ = (UInt16)(see->Summ + freqSum);
do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
}
}

163
C/Ppmd8Enc.c Normal file
View File

@@ -0,0 +1,163 @@
/* Ppmd8Enc.c -- PPMdI Encoder
2017-04-03 : Igor Pavlov : Public domain
This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
#include "Precomp.h"
#include "Ppmd8.h"
#define kTop (1 << 24)
#define kBot (1 << 15)
void Ppmd8_RangeEnc_FlushData(CPpmd8 *p)
{
unsigned i;
for (i = 0; i < 4; i++, p->Low <<= 8 )
IByteOut_Write(p->Stream.Out, (Byte)(p->Low >> 24));
}
static void RangeEnc_Normalize(CPpmd8 *p)
{
while ((p->Low ^ (p->Low + p->Range)) < kTop ||
(p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)))
{
IByteOut_Write(p->Stream.Out, (Byte)(p->Low >> 24));
p->Range <<= 8;
p->Low <<= 8;
}
}
static void RangeEnc_Encode(CPpmd8 *p, UInt32 start, UInt32 size, UInt32 total)
{
p->Low += start * (p->Range /= total);
p->Range *= size;
RangeEnc_Normalize(p);
}
static void RangeEnc_EncodeBit_0(CPpmd8 *p, UInt32 size0)
{
p->Range >>= 14;
p->Range *= size0;
RangeEnc_Normalize(p);
}
static void RangeEnc_EncodeBit_1(CPpmd8 *p, UInt32 size0)
{
p->Low += size0 * (p->Range >>= 14);
p->Range *= ((1 << 14) - size0);
RangeEnc_Normalize(p);
}
#define MASK(sym) ((signed char *)charMask)[sym]
void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol)
{
size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 0)
{
CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);
UInt32 sum;
unsigned i;
if (s->Symbol == symbol)
{
RangeEnc_Encode(p, 0, s->Freq, p->MinContext->SummFreq);
p->FoundState = s;
Ppmd8_Update1_0(p);
return;
}
p->PrevSuccess = 0;
sum = s->Freq;
i = p->MinContext->NumStats;
do
{
if ((++s)->Symbol == symbol)
{
RangeEnc_Encode(p, sum, s->Freq, p->MinContext->SummFreq);
p->FoundState = s;
Ppmd8_Update1(p);
return;
}
sum += s->Freq;
}
while (--i);
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
i = p->MinContext->NumStats;
do { MASK((--s)->Symbol) = 0; } while (--i);
RangeEnc_Encode(p, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);
}
else
{
UInt16 *prob = Ppmd8_GetBinSumm(p);
CPpmd_State *s = Ppmd8Context_OneState(p->MinContext);
if (s->Symbol == symbol)
{
RangeEnc_EncodeBit_0(p, *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
p->FoundState = s;
Ppmd8_UpdateBin(p);
return;
}
else
{
RangeEnc_EncodeBit_1(p, *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
p->InitEsc = PPMD8_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 = Ppmd8_GetContext(p, p->MinContext->Suffix);
}
while (p->MinContext->NumStats == numMasked);
see = Ppmd8_MakeEscFreq(p, numMasked, &escFreq);
s = Ppmd8_GetStats(p, p->MinContext);
sum = 0;
i = p->MinContext->NumStats + 1;
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(p, low, s1->Freq, sum + escFreq);
Ppmd_See_Update(see);
p->FoundState = s1;
Ppmd8_Update2(p);
return;
}
sum += (s->Freq & (int)(MASK(cur)));
MASK(cur) = 0;
s++;
}
while (--i);
RangeEnc_Encode(p, sum, escFreq, sum + escFreq);
see->Summ = (UInt16)(see->Summ + sum + escFreq);
}
}

10
C/Precomp.h Normal file
View File

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

Some files were not shown because too many files have changed in this diff Show More