mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-17 04:11:51 -06:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1eddf527ca | ||
|
|
bec3b479dc | ||
|
|
66ac98bb02 | ||
|
|
c20d013055 | ||
|
|
9608215ad8 | ||
|
|
5de23c1deb | ||
|
|
e24f7fba53 | ||
|
|
7c8a265a15 | ||
|
|
a663a6deb7 | ||
|
|
6543c28020 | ||
|
|
f6444c3256 | ||
|
|
cba375916f | ||
|
|
54490d51d5 | ||
|
|
0713a3ab80 | ||
|
|
7e021179cd | ||
|
|
0dc16c691d | ||
|
|
f08f4dcc3c | ||
|
|
83f8ddcc5b | ||
|
|
35596517f2 | ||
|
|
de4f8c22fe | ||
|
|
b75af1bba6 | ||
|
|
c65230d858 | ||
|
|
2eb60a0598 | ||
|
|
044e4bb741 | ||
|
|
e279500d76 | ||
|
|
708873490e | ||
|
|
3dacb5eb8a | ||
|
|
76b173af78 | ||
|
|
993daef9cb | ||
|
|
db5eb6d638 | ||
|
|
1fbaf0aac5 | ||
|
|
2fed872194 | ||
|
|
c99f3ebdd6 | ||
|
|
829409452d | ||
|
|
8874e4fbc9 | ||
|
|
1dc92281fa | ||
|
|
3a524e5ba2 | ||
|
|
c1f1243a70 | ||
|
|
b717a4dbfe | ||
|
|
c10e6b16f6 | ||
|
|
173c07e166 | ||
|
|
3901bf0ab8 |
100
Asm/arm/7zCrcOpt.asm
Normal file
100
Asm/arm/7zCrcOpt.asm
Normal 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
|
||||||
@@ -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
|
|
||||||
105
Asm/x86/7zAsm.asm
Normal file
105
Asm/x86/7zAsm.asm
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
; 7zAsm.asm -- ASM macros
|
||||||
|
; 2012-12-30 : Igor Pavlov : Public domain
|
||||||
|
|
||||||
|
MY_ASM_START macro
|
||||||
|
ifdef x64
|
||||||
|
.code
|
||||||
|
else
|
||||||
|
.386
|
||||||
|
.model flat
|
||||||
|
_TEXT$00 SEGMENT PARA PUBLIC 'CODE'
|
||||||
|
endif
|
||||||
|
endm
|
||||||
|
|
||||||
|
MY_PROC macro name:req, numParams:req
|
||||||
|
align 16
|
||||||
|
proc_numParams = numParams
|
||||||
|
ifdef x64
|
||||||
|
proc_name equ name
|
||||||
|
else
|
||||||
|
proc_name equ @CatStr(@,name,@, %numParams * 4)
|
||||||
|
endif
|
||||||
|
proc_name PROC
|
||||||
|
endm
|
||||||
|
|
||||||
|
MY_ENDP macro
|
||||||
|
ifdef x64
|
||||||
|
ret
|
||||||
|
else
|
||||||
|
if proc_numParams LT 3
|
||||||
|
ret
|
||||||
|
else
|
||||||
|
ret (proc_numParams - 2) * 4
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
proc_name ENDP
|
||||||
|
endm
|
||||||
|
|
||||||
|
ifdef x64
|
||||||
|
REG_SIZE equ 8
|
||||||
|
REG_LOGAR_SIZE equ 3
|
||||||
|
else
|
||||||
|
REG_SIZE equ 4
|
||||||
|
REG_LOGAR_SIZE equ 2
|
||||||
|
endif
|
||||||
|
|
||||||
|
x0 equ EAX
|
||||||
|
x1 equ ECX
|
||||||
|
x2 equ EDX
|
||||||
|
x3 equ EBX
|
||||||
|
x4 equ ESP
|
||||||
|
x5 equ EBP
|
||||||
|
x6 equ ESI
|
||||||
|
x7 equ EDI
|
||||||
|
|
||||||
|
x0_L equ AL
|
||||||
|
x1_L equ CL
|
||||||
|
x2_L equ DL
|
||||||
|
x3_L equ BL
|
||||||
|
|
||||||
|
x0_H equ AH
|
||||||
|
x1_H equ CH
|
||||||
|
x2_H equ DH
|
||||||
|
x3_H equ BH
|
||||||
|
|
||||||
|
ifdef x64
|
||||||
|
r0 equ RAX
|
||||||
|
r1 equ RCX
|
||||||
|
r2 equ RDX
|
||||||
|
r3 equ RBX
|
||||||
|
r4 equ RSP
|
||||||
|
r5 equ RBP
|
||||||
|
r6 equ RSI
|
||||||
|
r7 equ RDI
|
||||||
|
x8 equ r8d
|
||||||
|
x9 equ r9d
|
||||||
|
x10 equ r10d
|
||||||
|
x11 equ r11d
|
||||||
|
x12 equ r12d
|
||||||
|
x13 equ r13d
|
||||||
|
x14 equ r14d
|
||||||
|
x15 equ r15d
|
||||||
|
else
|
||||||
|
r0 equ x0
|
||||||
|
r1 equ x1
|
||||||
|
r2 equ x2
|
||||||
|
r3 equ x3
|
||||||
|
r4 equ x4
|
||||||
|
r5 equ x5
|
||||||
|
r6 equ x6
|
||||||
|
r7 equ x7
|
||||||
|
endif
|
||||||
|
|
||||||
|
MY_PUSH_4_REGS macro
|
||||||
|
push r3
|
||||||
|
push r5
|
||||||
|
push r6
|
||||||
|
push r7
|
||||||
|
endm
|
||||||
|
|
||||||
|
MY_POP_4_REGS macro
|
||||||
|
pop r7
|
||||||
|
pop r6
|
||||||
|
pop r5
|
||||||
|
pop r3
|
||||||
|
endm
|
||||||
147
Asm/x86/7zCrcOpt.asm
Normal file
147
Asm/x86/7zCrcOpt.asm
Normal 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
|
||||||
@@ -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
237
Asm/x86/AesOpt.asm
Normal 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
|
||||||
205
Asm/x86/XzCrc64Opt.asm
Normal file
205
Asm/x86/XzCrc64Opt.asm
Normal 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
202
C/7z.h
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/* 7z.h -- 7z interface
|
||||||
|
2015-11-18 : 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,
|
||||||
|
ISzAlloc *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, ISzAlloc *alloc);
|
||||||
|
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
||||||
|
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if dest == NULL, the return value specifies the required size of the buffer,
|
||||||
|
in 16-bit characters, including the null-terminating character.
|
||||||
|
if dest != NULL, the return value specifies the number of 16-bit characters that
|
||||||
|
are written to the dest, including the null-terminating character. */
|
||||||
|
|
||||||
|
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||||
|
|
||||||
|
/*
|
||||||
|
size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex);
|
||||||
|
UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 */
|
||||||
|
ISzAlloc *allocMain,
|
||||||
|
ISzAlloc *allocTemp);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
SzArEx_Open Errors:
|
||||||
|
SZ_ERROR_NO_ARCHIVE
|
||||||
|
SZ_ERROR_ARCHIVE
|
||||||
|
SZ_ERROR_UNSUPPORTED
|
||||||
|
SZ_ERROR_MEM
|
||||||
|
SZ_ERROR_CRC
|
||||||
|
SZ_ERROR_INPUT_EOF
|
||||||
|
SZ_ERROR_FAIL
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
|
||||||
|
ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
||||||
24
C/Archive/7z/7zAlloc.c → C/7zAlloc.c
Executable file → Normal file
24
C/Archive/7z/7zAlloc.c → C/7zAlloc.c
Executable file → Normal file
@@ -1,6 +1,8 @@
|
|||||||
/* 7zAlloc.c */
|
/* 7zAlloc.c -- Allocation functions
|
||||||
|
2015-11-09 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "7zAlloc.h"
|
#include "7zAlloc.h"
|
||||||
|
|
||||||
/* #define _SZ_ALLOC_DEBUG */
|
/* #define _SZ_ALLOC_DEBUG */
|
||||||
@@ -11,24 +13,28 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
int g_allocCount = 0;
|
int g_allocCount = 0;
|
||||||
int g_allocCountTemp = 0;
|
int g_allocCountTemp = 0;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void *SzAlloc(size_t size)
|
void *SzAlloc(void *p, size_t size)
|
||||||
{
|
{
|
||||||
|
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 *address)
|
void SzFree(void *p, void *address)
|
||||||
{
|
{
|
||||||
|
UNUSED_VAR(p);
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
if (address != 0)
|
if (address != 0)
|
||||||
{
|
{
|
||||||
@@ -39,12 +45,13 @@ void SzFree(void *address)
|
|||||||
free(address);
|
free(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *SzAllocTemp(size_t size)
|
void *SzAllocTemp(void *p, size_t size)
|
||||||
{
|
{
|
||||||
|
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);
|
||||||
@@ -53,8 +60,9 @@ void *SzAllocTemp(size_t size)
|
|||||||
return malloc(size);
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SzFreeTemp(void *address)
|
void SzFreeTemp(void *p, void *address)
|
||||||
{
|
{
|
||||||
|
UNUSED_VAR(p);
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
if (address != 0)
|
if (address != 0)
|
||||||
{
|
{
|
||||||
23
C/7zAlloc.h
Normal file
23
C/7zAlloc.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/* 7zAlloc.h -- Allocation functions
|
||||||
|
2013-03-25 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_ALLOC_H
|
||||||
|
#define __7Z_ALLOC_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
1771
C/7zArcIn.c
Normal file
1771
C/7zArcIn.c
Normal file
File diff suppressed because it is too large
Load Diff
36
C/7zBuf.c
Normal file
36
C/7zBuf.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/* 7zBuf.c -- Byte Buffer
|
||||||
|
2013-01-21 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "7zBuf.h"
|
||||||
|
|
||||||
|
void Buf_Init(CBuf *p)
|
||||||
|
{
|
||||||
|
p->data = 0;
|
||||||
|
p->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
p->size = 0;
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
p->data = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
p->data = (Byte *)alloc->Alloc(alloc, size);
|
||||||
|
if (p->data != 0)
|
||||||
|
{
|
||||||
|
p->size = size;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buf_Free(CBuf *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
alloc->Free(alloc, p->data);
|
||||||
|
p->data = 0;
|
||||||
|
p->size = 0;
|
||||||
|
}
|
||||||
35
C/7zBuf.h
Normal file
35
C/7zBuf.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/* 7zBuf.h -- Byte Buffer
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_BUF_H
|
||||||
|
#define __7Z_BUF_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte *data;
|
||||||
|
size_t size;
|
||||||
|
} CBuf;
|
||||||
|
|
||||||
|
void Buf_Init(CBuf *p);
|
||||||
|
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
|
||||||
|
void Buf_Free(CBuf *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte *data;
|
||||||
|
size_t size;
|
||||||
|
size_t pos;
|
||||||
|
} CDynBuf;
|
||||||
|
|
||||||
|
void DynBuf_Construct(CDynBuf *p);
|
||||||
|
void DynBuf_SeekToBeg(CDynBuf *p);
|
||||||
|
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);
|
||||||
|
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
||||||
51
C/7zBuf2.c
Normal file
51
C/7zBuf2.c
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/* 7zBuf2.c -- Byte Buffer
|
||||||
|
2014-08-22 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "7zBuf.h"
|
||||||
|
|
||||||
|
void DynBuf_Construct(CDynBuf *p)
|
||||||
|
{
|
||||||
|
p->data = 0;
|
||||||
|
p->size = 0;
|
||||||
|
p->pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynBuf_SeekToBeg(CDynBuf *p)
|
||||||
|
{
|
||||||
|
p->pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
if (size > p->size - p->pos)
|
||||||
|
{
|
||||||
|
size_t newSize = p->pos + size;
|
||||||
|
Byte *data;
|
||||||
|
newSize += newSize / 4;
|
||||||
|
data = (Byte *)alloc->Alloc(alloc, newSize);
|
||||||
|
if (data == 0)
|
||||||
|
return 0;
|
||||||
|
p->size = newSize;
|
||||||
|
memcpy(data, p->data, p->pos);
|
||||||
|
alloc->Free(alloc, p->data);
|
||||||
|
p->data = data;
|
||||||
|
}
|
||||||
|
if (size != 0)
|
||||||
|
{
|
||||||
|
memcpy(p->data + p->pos, buf, size);
|
||||||
|
p->pos += size;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
alloc->Free(alloc, p->data);
|
||||||
|
p->data = 0;
|
||||||
|
p->size = 0;
|
||||||
|
p->pos = 0;
|
||||||
|
}
|
||||||
126
C/7zCrc.c
Executable file → Normal file
126
C/7zCrc.c
Executable file → Normal file
@@ -1,32 +1,128 @@
|
|||||||
/* 7zCrc.c */
|
/* 7zCrc.c -- CRC32 init
|
||||||
|
2015-03-10 : 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 & ~((r & 1) - 1));
|
||||||
g_CrcTable[i] = r;
|
g_CrcTable[i] = r;
|
||||||
}
|
}
|
||||||
}
|
for (; i < 256 * CRC_NUM_TABLES; i++)
|
||||||
|
{
|
||||||
|
UInt32 r = g_CrcTable[i - 256];
|
||||||
|
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
#if CRC_NUM_TABLES < 4
|
||||||
{
|
|
||||||
const Byte *p = (const Byte *)data;
|
g_CrcUpdate = CrcUpdateT1;
|
||||||
for (; size > 0 ; size--, p++)
|
|
||||||
v = CRC_UPDATE_BYTE(v, *p);
|
#else
|
||||||
return v;
|
|
||||||
}
|
#ifdef MY_CPU_LE
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
g_CrcUpdateT4 = CrcUpdateT4;
|
||||||
{
|
g_CrcUpdate = CrcUpdateT4;
|
||||||
return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF;
|
|
||||||
|
#if CRC_NUM_TABLES >= 8
|
||||||
|
g_CrcUpdateT8 = CrcUpdateT8;
|
||||||
|
|
||||||
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
if (!CPU_Is_InOrder())
|
||||||
|
g_CrcUpdate = CrcUpdateT8;
|
||||||
|
#endif
|
||||||
|
#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[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
|
||||||
}
|
}
|
||||||
|
|||||||
12
C/7zCrc.h
Executable file → Normal file
12
C/7zCrc.h
Executable file → Normal file
@@ -1,21 +1,25 @@
|
|||||||
/* 7zCrc.h */
|
/* 7zCrc.h -- CRC32 calculation
|
||||||
|
2013-01-18 : 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
115
C/7zCrcOpt.c
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/* 7zCrcOpt.c -- CRC32 calculation
|
||||||
|
2015-03-01 : 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
|
||||||
40
C/7zCrcT8.c
40
C/7zCrcT8.c
@@ -1,40 +0,0 @@
|
|||||||
/* 7zCrcT8.c */
|
|
||||||
|
|
||||||
#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
591
C/7zDec.c
Normal file
@@ -0,0 +1,591 @@
|
|||||||
|
/* 7zDec.c -- Decoding from 7z folder
|
||||||
|
2015-11-18 : 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 p;
|
||||||
|
const Byte *cur;
|
||||||
|
const Byte *end;
|
||||||
|
const Byte *begin;
|
||||||
|
UInt64 processed;
|
||||||
|
Bool extra;
|
||||||
|
SRes res;
|
||||||
|
ILookInStream *inStream;
|
||||||
|
} CByteInToLook;
|
||||||
|
|
||||||
|
static Byte ReadByte(void *pp)
|
||||||
|
{
|
||||||
|
CByteInToLook *p = (CByteInToLook *)pp;
|
||||||
|
if (p->cur != p->end)
|
||||||
|
return *p->cur++;
|
||||||
|
if (p->res == SZ_OK)
|
||||||
|
{
|
||||||
|
size_t size = p->cur - p->begin;
|
||||||
|
p->processed += size;
|
||||||
|
p->res = p->inStream->Skip(p->inStream, size);
|
||||||
|
size = (1 << 25);
|
||||||
|
p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
|
||||||
|
p->cur = p->begin;
|
||||||
|
p->end = p->begin + size;
|
||||||
|
if (size != 0)
|
||||||
|
return *p->cur++;;
|
||||||
|
}
|
||||||
|
p->extra = True;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
|
||||||
|
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||||
|
{
|
||||||
|
CPpmd7 ppmd;
|
||||||
|
CByteInToLook s;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
|
s.p.Read = ReadByte;
|
||||||
|
s.inStream = inStream;
|
||||||
|
s.begin = s.end = s.cur = NULL;
|
||||||
|
s.extra = False;
|
||||||
|
s.res = SZ_OK;
|
||||||
|
s.processed = 0;
|
||||||
|
|
||||||
|
if (propsSize != 5)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned order = props[0];
|
||||||
|
UInt32 memSize = GetUi32(props + 1);
|
||||||
|
if (order < PPMD7_MIN_ORDER ||
|
||||||
|
order > PPMD7_MAX_ORDER ||
|
||||||
|
memSize < PPMD7_MIN_MEM_SIZE ||
|
||||||
|
memSize > PPMD7_MAX_MEM_SIZE)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
Ppmd7_Construct(&ppmd);
|
||||||
|
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
Ppmd7_Init(&ppmd, order);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CPpmd7z_RangeDec rc;
|
||||||
|
Ppmd7z_RangeDec_CreateVTable(&rc);
|
||||||
|
rc.Stream = &s.p;
|
||||||
|
if (!Ppmd7z_RangeDec_Init(&rc))
|
||||||
|
res = SZ_ERROR_DATA;
|
||||||
|
else if (s.extra)
|
||||||
|
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
for (i = 0; i < outSize; i++)
|
||||||
|
{
|
||||||
|
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
|
||||||
|
if (s.extra || sym < 0)
|
||||||
|
break;
|
||||||
|
outBuffer[i] = (Byte)sym;
|
||||||
|
}
|
||||||
|
if (i != outSize)
|
||||||
|
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||||
|
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
|
||||||
|
res = SZ_ERROR_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ppmd7_Free(&ppmd, allocMain);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
|
||||||
|
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||||
|
{
|
||||||
|
CLzmaDec state;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
|
LzmaDec_Construct(&state);
|
||||||
|
RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain));
|
||||||
|
state.dic = outBuffer;
|
||||||
|
state.dicBufSize = outSize;
|
||||||
|
LzmaDec_Init(&state);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const void *inBuf = NULL;
|
||||||
|
size_t lookahead = (1 << 18);
|
||||||
|
if (lookahead > inSize)
|
||||||
|
lookahead = (size_t)inSize;
|
||||||
|
res = inStream->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 = inStream->Skip((void *)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, ISzAlloc *allocMain)
|
||||||
|
{
|
||||||
|
CLzma2Dec state;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
|
Lzma2Dec_Construct(&state);
|
||||||
|
if (propsSize != 1)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain));
|
||||||
|
state.decoder.dic = outBuffer;
|
||||||
|
state.decoder.dicBufSize = outSize;
|
||||||
|
Lzma2Dec_Init(&state);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const void *inBuf = NULL;
|
||||||
|
size_t lookahead = (1 << 18);
|
||||||
|
if (lookahead > inSize)
|
||||||
|
lookahead = (size_t)inSize;
|
||||||
|
res = inStream->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 = inStream->Skip((void *)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(inStream->Look(inStream, &inBuf, &curSize));
|
||||||
|
if (curSize == 0)
|
||||||
|
return SZ_ERROR_INPUT_EOF;
|
||||||
|
memcpy(outBuffer, inBuf, curSize);
|
||||||
|
outBuffer += curSize;
|
||||||
|
inSize -= curSize;
|
||||||
|
RINOK(inStream->Skip((void *)inStream, curSize));
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool IS_MAIN_METHOD(UInt32 m)
|
||||||
|
{
|
||||||
|
switch (m)
|
||||||
|
{
|
||||||
|
case k_Copy:
|
||||||
|
case k_LZMA:
|
||||||
|
#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, ISzAlloc *allocMain,
|
||||||
|
Byte *tempBuf[])
|
||||||
|
{
|
||||||
|
UInt32 ci;
|
||||||
|
SizeT tempSizes[3] = { 0, 0, 0};
|
||||||
|
SizeT tempSize3 = 0;
|
||||||
|
Byte *tempBuf3 = 0;
|
||||||
|
|
||||||
|
RINOK(CheckSupportedFolder(folder));
|
||||||
|
|
||||||
|
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||||
|
{
|
||||||
|
const CSzCoderInfo *coder = &folder->Coders[ci];
|
||||||
|
|
||||||
|
if (IS_MAIN_METHOD((UInt32)coder->MethodID))
|
||||||
|
{
|
||||||
|
UInt32 si = 0;
|
||||||
|
UInt64 offset;
|
||||||
|
UInt64 inSize;
|
||||||
|
Byte *outBufCur = outBuffer;
|
||||||
|
SizeT outSizeCur = outSize;
|
||||||
|
if (folder->NumCoders == 4)
|
||||||
|
{
|
||||||
|
UInt32 indices[] = { 3, 2, 0 };
|
||||||
|
UInt64 unpackSize = unpackSizes[ci];
|
||||||
|
si = indices[ci];
|
||||||
|
if (ci < 2)
|
||||||
|
{
|
||||||
|
Byte *temp;
|
||||||
|
outSizeCur = (SizeT)unpackSize;
|
||||||
|
if (outSizeCur != unpackSize)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
|
||||||
|
if (!temp && outSizeCur != 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
outBufCur = tempBuf[1 - ci] = temp;
|
||||||
|
tempSizes[1 - ci] = outSizeCur;
|
||||||
|
}
|
||||||
|
else if (ci == 2)
|
||||||
|
{
|
||||||
|
if (unpackSize > outSize) /* check it */
|
||||||
|
return SZ_ERROR_PARAM;
|
||||||
|
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
||||||
|
tempSize3 = outSizeCur = (SizeT)unpackSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
offset = packPositions[si];
|
||||||
|
inSize = packPositions[si + 1] - offset;
|
||||||
|
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||||
|
|
||||||
|
if (coder->MethodID == k_Copy)
|
||||||
|
{
|
||||||
|
if (inSize != outSizeCur) /* check it */
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
||||||
|
}
|
||||||
|
else if (coder->MethodID == k_LZMA)
|
||||||
|
{
|
||||||
|
RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||||
|
}
|
||||||
|
#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 *)IAlloc_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,
|
||||||
|
ISzAlloc *allocMain)
|
||||||
|
{
|
||||||
|
SRes res;
|
||||||
|
CSzFolder folder;
|
||||||
|
CSzData sd;
|
||||||
|
|
||||||
|
const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
|
||||||
|
sd.Data = data;
|
||||||
|
sd.Size = p->FoCodersOffsets[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++)
|
||||||
|
IAlloc_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
286
C/7zFile.c
Normal file
286
C/7zFile.c
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
/* 7zFile.c -- File IO
|
||||||
|
2009-11-24 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "7zFile.h"
|
||||||
|
|
||||||
|
#ifndef USE_WINDOWS_FILE
|
||||||
|
|
||||||
|
#ifndef UNDER_CE
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
ReadFile and WriteFile functions in Windows have BUG:
|
||||||
|
If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
|
||||||
|
from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
|
||||||
|
(Insufficient system resources exist to complete the requested service).
|
||||||
|
Probably in some version of Windows there are problems with other sizes:
|
||||||
|
for 32 MB (maybe also for 16 MB).
|
||||||
|
And message can be "Network connection was lost"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define kChunkSizeMax (1 << 22)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void File_Construct(CSzFile *p)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
p->handle = INVALID_HANDLE_VALUE;
|
||||||
|
#else
|
||||||
|
p->file = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
|
||||||
|
static WRes File_Open(CSzFile *p, const char *name, int writeMode)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
p->handle = CreateFileA(name,
|
||||||
|
writeMode ? GENERIC_WRITE : GENERIC_READ,
|
||||||
|
FILE_SHARE_READ, NULL,
|
||||||
|
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
|
||||||
|
#else
|
||||||
|
p->file = fopen(name, writeMode ? "wb+" : "rb");
|
||||||
|
return (p->file != 0) ? 0 :
|
||||||
|
#ifdef UNDER_CE
|
||||||
|
2; /* ENOENT */
|
||||||
|
#else
|
||||||
|
errno;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
|
||||||
|
WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)
|
||||||
|
{
|
||||||
|
p->handle = CreateFileW(name,
|
||||||
|
writeMode ? GENERIC_WRITE : GENERIC_READ,
|
||||||
|
FILE_SHARE_READ, NULL,
|
||||||
|
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
|
||||||
|
}
|
||||||
|
WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }
|
||||||
|
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WRes File_Close(CSzFile *p)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
if (p->handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
if (!CloseHandle(p->handle))
|
||||||
|
return GetLastError();
|
||||||
|
p->handle = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (p->file != NULL)
|
||||||
|
{
|
||||||
|
int res = fclose(p->file);
|
||||||
|
if (res != 0)
|
||||||
|
return res;
|
||||||
|
p->file = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes File_Read(CSzFile *p, void *data, size_t *size)
|
||||||
|
{
|
||||||
|
size_t originalSize = *size;
|
||||||
|
if (originalSize == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
|
||||||
|
*size = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
|
||||||
|
DWORD processed = 0;
|
||||||
|
BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);
|
||||||
|
data = (void *)((Byte *)data + processed);
|
||||||
|
originalSize -= processed;
|
||||||
|
*size += processed;
|
||||||
|
if (!res)
|
||||||
|
return GetLastError();
|
||||||
|
if (processed == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (originalSize > 0);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
*size = fread(data, 1, originalSize, p->file);
|
||||||
|
if (*size == originalSize)
|
||||||
|
return 0;
|
||||||
|
return ferror(p->file);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes File_Write(CSzFile *p, const void *data, size_t *size)
|
||||||
|
{
|
||||||
|
size_t originalSize = *size;
|
||||||
|
if (originalSize == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
|
||||||
|
*size = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
|
||||||
|
DWORD processed = 0;
|
||||||
|
BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);
|
||||||
|
data = (void *)((Byte *)data + processed);
|
||||||
|
originalSize -= processed;
|
||||||
|
*size += processed;
|
||||||
|
if (!res)
|
||||||
|
return GetLastError();
|
||||||
|
if (processed == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (originalSize > 0);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
*size = fwrite(data, 1, originalSize, p->file);
|
||||||
|
if (*size == originalSize)
|
||||||
|
return 0;
|
||||||
|
return ferror(p->file);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
|
||||||
|
LARGE_INTEGER value;
|
||||||
|
DWORD moveMethod;
|
||||||
|
value.LowPart = (DWORD)*pos;
|
||||||
|
value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */
|
||||||
|
switch (origin)
|
||||||
|
{
|
||||||
|
case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;
|
||||||
|
case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;
|
||||||
|
case SZ_SEEK_END: moveMethod = FILE_END; break;
|
||||||
|
default: return ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod);
|
||||||
|
if (value.LowPart == 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
WRes res = GetLastError();
|
||||||
|
if (res != NO_ERROR)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
*pos = ((Int64)value.HighPart << 32) | value.LowPart;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int moveMethod;
|
||||||
|
int res;
|
||||||
|
switch (origin)
|
||||||
|
{
|
||||||
|
case SZ_SEEK_SET: moveMethod = SEEK_SET; break;
|
||||||
|
case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;
|
||||||
|
case SZ_SEEK_END: moveMethod = SEEK_END; break;
|
||||||
|
default: return 1;
|
||||||
|
}
|
||||||
|
res = fseek(p->file, (long)*pos, moveMethod);
|
||||||
|
*pos = ftell(p->file);
|
||||||
|
return res;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes File_GetLength(CSzFile *p, UInt64 *length)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
|
||||||
|
DWORD sizeHigh;
|
||||||
|
DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
|
||||||
|
if (sizeLow == 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
DWORD res = GetLastError();
|
||||||
|
if (res != NO_ERROR)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
*length = (((UInt64)sizeHigh) << 32) + sizeLow;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
long pos = ftell(p->file);
|
||||||
|
int res = fseek(p->file, 0, SEEK_END);
|
||||||
|
*length = ftell(p->file);
|
||||||
|
fseek(p->file, pos, SEEK_SET);
|
||||||
|
return res;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- FileSeqInStream ---------- */
|
||||||
|
|
||||||
|
static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
CFileSeqInStream *p = (CFileSeqInStream *)pp;
|
||||||
|
return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
|
||||||
|
{
|
||||||
|
p->s.Read = FileSeqInStream_Read;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- FileInStream ---------- */
|
||||||
|
|
||||||
|
static SRes FileInStream_Read(void *pp, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
CFileInStream *p = (CFileInStream *)pp;
|
||||||
|
return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)
|
||||||
|
{
|
||||||
|
CFileInStream *p = (CFileInStream *)pp;
|
||||||
|
return File_Seek(&p->file, pos, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileInStream_CreateVTable(CFileInStream *p)
|
||||||
|
{
|
||||||
|
p->s.Read = FileInStream_Read;
|
||||||
|
p->s.Seek = FileInStream_Seek;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- FileOutStream ---------- */
|
||||||
|
|
||||||
|
static size_t FileOutStream_Write(void *pp, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
CFileOutStream *p = (CFileOutStream *)pp;
|
||||||
|
File_Write(&p->file, data, &size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileOutStream_CreateVTable(CFileOutStream *p)
|
||||||
|
{
|
||||||
|
p->s.Write = FileOutStream_Write;
|
||||||
|
}
|
||||||
83
C/7zFile.h
Normal file
83
C/7zFile.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/* 7zFile.h -- File IO
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_FILE_H
|
||||||
|
#define __7Z_FILE_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define USE_WINDOWS_FILE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
/* ---------- File ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
HANDLE handle;
|
||||||
|
#else
|
||||||
|
FILE *file;
|
||||||
|
#endif
|
||||||
|
} CSzFile;
|
||||||
|
|
||||||
|
void File_Construct(CSzFile *p);
|
||||||
|
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
|
||||||
|
WRes InFile_Open(CSzFile *p, const char *name);
|
||||||
|
WRes OutFile_Open(CSzFile *p, const char *name);
|
||||||
|
#endif
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
WRes InFile_OpenW(CSzFile *p, const WCHAR *name);
|
||||||
|
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);
|
||||||
|
#endif
|
||||||
|
WRes File_Close(CSzFile *p);
|
||||||
|
|
||||||
|
/* reads max(*size, remain file's size) bytes */
|
||||||
|
WRes File_Read(CSzFile *p, void *data, size_t *size);
|
||||||
|
|
||||||
|
/* writes *size bytes */
|
||||||
|
WRes File_Write(CSzFile *p, const void *data, size_t *size);
|
||||||
|
|
||||||
|
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin);
|
||||||
|
WRes File_GetLength(CSzFile *p, UInt64 *length);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- FileInStream ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream s;
|
||||||
|
CSzFile file;
|
||||||
|
} CFileSeqInStream;
|
||||||
|
|
||||||
|
void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeekInStream s;
|
||||||
|
CSzFile file;
|
||||||
|
} CFileInStream;
|
||||||
|
|
||||||
|
void FileInStream_CreateVTable(CFileInStream *p);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqOutStream s;
|
||||||
|
CSzFile file;
|
||||||
|
} CFileOutStream;
|
||||||
|
|
||||||
|
void FileOutStream_CreateVTable(CFileOutStream *p);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
||||||
171
C/7zStream.c
Normal file
171
C/7zStream.c
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
/* 7zStream.c -- 7z Stream functions
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
|
||||||
|
{
|
||||||
|
while (size != 0)
|
||||||
|
{
|
||||||
|
size_t processed = size;
|
||||||
|
RINOK(stream->Read(stream, buf, &processed));
|
||||||
|
if (processed == 0)
|
||||||
|
return errorType;
|
||||||
|
buf = (void *)((Byte *)buf + processed);
|
||||||
|
size -= processed;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
|
||||||
|
{
|
||||||
|
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)
|
||||||
|
{
|
||||||
|
size_t processed = 1;
|
||||||
|
RINOK(stream->Read(stream, buf, &processed));
|
||||||
|
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
|
||||||
|
{
|
||||||
|
Int64 t = offset;
|
||||||
|
return stream->Seek(stream, &t, SZ_SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
const void *lookBuf;
|
||||||
|
if (*size == 0)
|
||||||
|
return SZ_OK;
|
||||||
|
RINOK(stream->Look(stream, &lookBuf, size));
|
||||||
|
memcpy(buf, lookBuf, *size);
|
||||||
|
return stream->Skip(stream, *size);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)
|
||||||
|
{
|
||||||
|
while (size != 0)
|
||||||
|
{
|
||||||
|
size_t processed = size;
|
||||||
|
RINOK(stream->Read(stream, buf, &processed));
|
||||||
|
if (processed == 0)
|
||||||
|
return errorType;
|
||||||
|
buf = (void *)((Byte *)buf + processed);
|
||||||
|
size -= processed;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
|
||||||
|
{
|
||||||
|
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)
|
||||||
|
{
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
|
size_t size2 = p->size - p->pos;
|
||||||
|
if (size2 == 0 && *size > 0)
|
||||||
|
{
|
||||||
|
p->pos = 0;
|
||||||
|
size2 = LookToRead_BUF_SIZE;
|
||||||
|
res = p->realStream->Read(p->realStream, p->buf, &size2);
|
||||||
|
p->size = size2;
|
||||||
|
}
|
||||||
|
if (size2 < *size)
|
||||||
|
*size = size2;
|
||||||
|
*buf = p->buf + p->pos;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)
|
||||||
|
{
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
|
size_t size2 = p->size - p->pos;
|
||||||
|
if (size2 == 0 && *size > 0)
|
||||||
|
{
|
||||||
|
p->pos = 0;
|
||||||
|
if (*size > LookToRead_BUF_SIZE)
|
||||||
|
*size = LookToRead_BUF_SIZE;
|
||||||
|
res = p->realStream->Read(p->realStream, p->buf, size);
|
||||||
|
size2 = p->size = *size;
|
||||||
|
}
|
||||||
|
if (size2 < *size)
|
||||||
|
*size = size2;
|
||||||
|
*buf = p->buf + p->pos;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes LookToRead_Skip(void *pp, size_t offset)
|
||||||
|
{
|
||||||
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
|
p->pos += offset;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
|
size_t rem = p->size - p->pos;
|
||||||
|
if (rem == 0)
|
||||||
|
return p->realStream->Read(p->realStream, buf, size);
|
||||||
|
if (rem > *size)
|
||||||
|
rem = *size;
|
||||||
|
memcpy(buf, p->buf + p->pos, rem);
|
||||||
|
p->pos += rem;
|
||||||
|
*size = rem;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)
|
||||||
|
{
|
||||||
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
|
p->pos = p->size = 0;
|
||||||
|
return p->realStream->Seek(p->realStream, pos, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
|
||||||
|
{
|
||||||
|
p->s.Look = lookahead ?
|
||||||
|
LookToRead_Look_Lookahead :
|
||||||
|
LookToRead_Look_Exact;
|
||||||
|
p->s.Skip = LookToRead_Skip;
|
||||||
|
p->s.Read = LookToRead_Read;
|
||||||
|
p->s.Seek = LookToRead_Seek;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LookToRead_Init(CLookToRead *p)
|
||||||
|
{
|
||||||
|
p->pos = p->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
CSecToLook *p = (CSecToLook *)pp;
|
||||||
|
return LookInStream_LookRead(p->realStream, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecToLook_CreateVTable(CSecToLook *p)
|
||||||
|
{
|
||||||
|
p->s.Read = SecToLook_Read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
CSecToRead *p = (CSecToRead *)pp;
|
||||||
|
return p->realStream->Read(p->realStream, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecToRead_CreateVTable(CSecToRead *p)
|
||||||
|
{
|
||||||
|
p->s.Read = SecToRead_Read;
|
||||||
|
}
|
||||||
256
C/7zTypes.h
Normal file
256
C/7zTypes.h
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
/* 7zTypes.h -- Basic types
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_TYPES_H
|
||||||
|
#define __7Z_TYPES_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* #include <windows.h> */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef EXTERN_C_BEGIN
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define EXTERN_C_BEGIN extern "C" {
|
||||||
|
#define EXTERN_C_END }
|
||||||
|
#else
|
||||||
|
#define EXTERN_C_BEGIN
|
||||||
|
#define EXTERN_C_END
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define SZ_OK 0
|
||||||
|
|
||||||
|
#define SZ_ERROR_DATA 1
|
||||||
|
#define SZ_ERROR_MEM 2
|
||||||
|
#define SZ_ERROR_CRC 3
|
||||||
|
#define SZ_ERROR_UNSUPPORTED 4
|
||||||
|
#define SZ_ERROR_PARAM 5
|
||||||
|
#define SZ_ERROR_INPUT_EOF 6
|
||||||
|
#define SZ_ERROR_OUTPUT_EOF 7
|
||||||
|
#define SZ_ERROR_READ 8
|
||||||
|
#define SZ_ERROR_WRITE 9
|
||||||
|
#define SZ_ERROR_PROGRESS 10
|
||||||
|
#define SZ_ERROR_FAIL 11
|
||||||
|
#define SZ_ERROR_THREAD 12
|
||||||
|
|
||||||
|
#define SZ_ERROR_ARCHIVE 16
|
||||||
|
#define SZ_ERROR_NO_ARCHIVE 17
|
||||||
|
|
||||||
|
typedef int SRes;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* typedef DWORD WRes; */
|
||||||
|
typedef unsigned WRes;
|
||||||
|
#else
|
||||||
|
typedef int WRes;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RINOK
|
||||||
|
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned char Byte;
|
||||||
|
typedef short Int16;
|
||||||
|
typedef unsigned short UInt16;
|
||||||
|
|
||||||
|
#ifdef _LZMA_UINT32_IS_ULONG
|
||||||
|
typedef long Int32;
|
||||||
|
typedef unsigned long UInt32;
|
||||||
|
#else
|
||||||
|
typedef int Int32;
|
||||||
|
typedef unsigned int UInt32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _SZ_NO_INT_64
|
||||||
|
|
||||||
|
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
||||||
|
NOTES: Some code will work incorrectly in that case! */
|
||||||
|
|
||||||
|
typedef long Int64;
|
||||||
|
typedef unsigned long UInt64;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||||
|
typedef __int64 Int64;
|
||||||
|
typedef unsigned __int64 UInt64;
|
||||||
|
#define UINT64_CONST(n) n
|
||||||
|
#else
|
||||||
|
typedef long long int Int64;
|
||||||
|
typedef unsigned long long int UInt64;
|
||||||
|
#define UINT64_CONST(n) n ## ULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
||||||
|
typedef UInt32 SizeT;
|
||||||
|
#else
|
||||||
|
typedef size_t SizeT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef int Bool;
|
||||||
|
#define True 1
|
||||||
|
#define False 0
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define MY_STD_CALL __stdcall
|
||||||
|
#else
|
||||||
|
#define MY_STD_CALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1300
|
||||||
|
#define MY_NO_INLINE __declspec(noinline)
|
||||||
|
#else
|
||||||
|
#define MY_NO_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MY_CDECL __cdecl
|
||||||
|
#define MY_FAST_CALL __fastcall
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define MY_NO_INLINE
|
||||||
|
#define MY_CDECL
|
||||||
|
#define MY_FAST_CALL
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* The following interfaces use first parameter as pointer to structure */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
|
||||||
|
} IByteIn;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void (*Write)(void *p, Byte b);
|
||||||
|
} IByteOut;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||||
|
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||||
|
(output(*size) < input(*size)) is allowed */
|
||||||
|
} ISeqInStream;
|
||||||
|
|
||||||
|
/* it can return SZ_ERROR_INPUT_EOF */
|
||||||
|
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
|
||||||
|
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
||||||
|
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t (*Write)(void *p, const void *buf, size_t size);
|
||||||
|
/* Returns: result - the number of actually written bytes.
|
||||||
|
(result < size) means error */
|
||||||
|
} ISeqOutStream;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SZ_SEEK_SET = 0,
|
||||||
|
SZ_SEEK_CUR = 1,
|
||||||
|
SZ_SEEK_END = 2
|
||||||
|
} ESzSeek;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
||||||
|
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
||||||
|
} ISeekInStream;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SRes (*Look)(void *p, const void **buf, size_t *size);
|
||||||
|
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||||
|
(output(*size) > input(*size)) is not allowed
|
||||||
|
(output(*size) < input(*size)) is allowed */
|
||||||
|
SRes (*Skip)(void *p, size_t offset);
|
||||||
|
/* offset must be <= output(*size) of Look */
|
||||||
|
|
||||||
|
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||||
|
/* reads directly (without buffer). It's same as ISeqInStream::Read */
|
||||||
|
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
||||||
|
} ILookInStream;
|
||||||
|
|
||||||
|
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
|
||||||
|
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
|
||||||
|
|
||||||
|
/* reads via ILookInStream::Read */
|
||||||
|
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
||||||
|
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
|
||||||
|
|
||||||
|
#define LookToRead_BUF_SIZE (1 << 14)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ILookInStream s;
|
||||||
|
ISeekInStream *realStream;
|
||||||
|
size_t pos;
|
||||||
|
size_t size;
|
||||||
|
Byte buf[LookToRead_BUF_SIZE];
|
||||||
|
} CLookToRead;
|
||||||
|
|
||||||
|
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
|
||||||
|
void LookToRead_Init(CLookToRead *p);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream s;
|
||||||
|
ILookInStream *realStream;
|
||||||
|
} CSecToLook;
|
||||||
|
|
||||||
|
void SecToLook_CreateVTable(CSecToLook *p);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream s;
|
||||||
|
ILookInStream *realStream;
|
||||||
|
} CSecToRead;
|
||||||
|
|
||||||
|
void SecToRead_CreateVTable(CSecToRead *p);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
|
||||||
|
/* Returns: result. (result != SZ_OK) means break.
|
||||||
|
Value (UInt64)(Int64)-1 for size means unknown value. */
|
||||||
|
} ICompressProgress;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void *(*Alloc)(void *p, size_t size);
|
||||||
|
void (*Free)(void *p, void *address); /* address can be 0 */
|
||||||
|
} ISzAlloc;
|
||||||
|
|
||||||
|
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
|
||||||
|
#define IAlloc_Free(p, a) (p)->Free((p), a)
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#define CHAR_PATH_SEPARATOR '\\'
|
||||||
|
#define WCHAR_PATH_SEPARATOR L'\\'
|
||||||
|
#define STRING_PATH_SEPARATOR "\\"
|
||||||
|
#define WSTRING_PATH_SEPARATOR L"\\"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define CHAR_PATH_SEPARATOR '/'
|
||||||
|
#define WCHAR_PATH_SEPARATOR L'/'
|
||||||
|
#define STRING_PATH_SEPARATOR "/"
|
||||||
|
#define WSTRING_PATH_SEPARATOR L"/"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
||||||
19
C/7zVersion.h
Normal file
19
C/7zVersion.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#define MY_VER_MAJOR 16
|
||||||
|
#define MY_VER_MINOR 02
|
||||||
|
#define MY_VER_BUILD 0
|
||||||
|
#define MY_VERSION_NUMBERS "16.02"
|
||||||
|
#define MY_VERSION "16.02"
|
||||||
|
#define MY_DATE "2016-05-21"
|
||||||
|
#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-2016 Igor Pavlov"
|
||||||
|
|
||||||
|
#ifdef USE_COPYRIGHT_CR
|
||||||
|
#define MY_COPYRIGHT MY_COPYRIGHT_CR
|
||||||
|
#else
|
||||||
|
#define MY_COPYRIGHT MY_COPYRIGHT_PD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " : " MY_COPYRIGHT " : " MY_DATE
|
||||||
55
C/7zVersion.rc
Normal file
55
C/7zVersion.rc
Normal 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")
|
||||||
212
C/Crypto/Aes.c → C/Aes.c
Executable file → Normal file
212
C/Crypto/Aes.c → C/Aes.c
Executable file → Normal file
@@ -1,10 +1,13 @@
|
|||||||
/* Aes.h */
|
/* Aes.c -- AES encryption / decryption
|
||||||
|
2016-05-21 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
#include "Aes.h"
|
#include "Aes.h"
|
||||||
#include "../CpuArch.h"
|
#include "CpuArch.h"
|
||||||
|
|
||||||
UInt32 T[256 * 4];
|
static UInt32 T[256 * 4];
|
||||||
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,
|
||||||
@@ -22,10 +25,22 @@ 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};
|
||||||
|
|
||||||
UInt32 D[256 * 4];
|
void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
Byte InvS[256];
|
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);
|
||||||
|
|
||||||
Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
|
void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
|
||||||
|
AES_CODE_FUNC g_AesCbc_Encode;
|
||||||
|
AES_CODE_FUNC g_AesCbc_Decode;
|
||||||
|
AES_CODE_FUNC g_AesCtr_Code;
|
||||||
|
|
||||||
|
static UInt32 D[256 * 4];
|
||||||
|
static Byte InvS[256];
|
||||||
|
|
||||||
|
static 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)
|
||||||
|
|
||||||
@@ -36,17 +51,18 @@ Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x
|
|||||||
#define gb2(x) (((x) >> (16)) & 0xFF)
|
#define gb2(x) (((x) >> (16)) & 0xFF)
|
||||||
#define gb3(x) (((x) >> (24)) & 0xFF)
|
#define gb3(x) (((x) >> (24)) & 0xFF)
|
||||||
|
|
||||||
void MY_FAST_CALL 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);
|
T[ i] = Ui32(a2, a1, a1, a3);
|
||||||
T[0x100 + i] = Ui32(a3, a2, a1, a1);
|
T[0x100 + i] = Ui32(a3, a2, a1, a1);
|
||||||
T[0x200 + i] = Ui32(a1, a3, a2, a1);
|
T[0x200 + i] = Ui32(a1, a3, a2, a1);
|
||||||
@@ -67,87 +83,107 @@ void MY_FAST_CALL AesGenTables(void)
|
|||||||
D[0x300 + i] = Ui32(a9, aD, aB, aE);
|
D[0x300 + i] = Ui32(a9, aD, aB, aE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_AesCbc_Encode = AesCbc_Encode;
|
||||||
|
g_AesCbc_Decode = AesCbc_Decode;
|
||||||
|
g_AesCtr_Code = AesCtr_Code;
|
||||||
|
|
||||||
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
if (CPU_Is_Aes_Supported())
|
||||||
|
{
|
||||||
|
g_AesCbc_Encode = AesCbc_Encode_Intel;
|
||||||
|
g_AesCbc_Decode = AesCbc_Decode_Intel;
|
||||||
|
g_AesCtr_Code = AesCtr_Code_Intel;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])]
|
#define HT(i, x, s) (T + (x << 8))[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) \
|
#define HT16(m, s, p) \
|
||||||
HT4(m, 2, s, p); \
|
|
||||||
HT4(m, 0, s, p); \
|
HT4(m, 0, s, p); \
|
||||||
HT4(m, 3, s, p); \
|
|
||||||
HT4(m, 1, 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 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) (D + (x << 8))[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 MY_FAST_CALL AesSetKeyEncode(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;
|
for (i = 0; i < keySize; i++, key += 4)
|
||||||
w = p->rkey;
|
w[i] = GetUi32(key);
|
||||||
|
|
||||||
for (i = 0; i < keySize; i++, key += 4)
|
for (; i < wSize; i++)
|
||||||
w[i] = Ui32(key[0], key[1], key[2], key[3]);
|
|
||||||
|
|
||||||
for (; i < wSize; i++)
|
|
||||||
{
|
{
|
||||||
UInt32 t = w[i - 1];
|
UInt32 t = w[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)]);
|
||||||
else if (keySize > 6 && rem == 4)
|
else if (keySize > 6 && rem == 4)
|
||||||
t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]);
|
t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]);
|
||||||
w[i] = w[i - keySize] ^ t;
|
w[i] = w[i - keySize] ^ t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MY_FAST_CALL AesSetKeyDecode(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);
|
||||||
AesSetKeyEncode(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)]] ^
|
D[ (unsigned)Sbox[gb0(r)]] ^
|
||||||
D[0x100 + Sbox[gb1(r)]] ^
|
D[0x100 + (unsigned)Sbox[gb1(r)]] ^
|
||||||
D[0x200 + Sbox[gb2(r)]] ^
|
D[0x200 + (unsigned)Sbox[gb2(r)]] ^
|
||||||
D[0x300 + Sbox[gb3(r)]];
|
D[0x300 + (unsigned)Sbox[gb3(r)]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MY_FAST_CALL AesEncode32(const UInt32 *src, UInt32 *dest, 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];
|
||||||
@@ -165,11 +201,12 @@ void MY_FAST_CALL AesEncode32(const UInt32 *src, UInt32 *dest, const UInt32 *w,
|
|||||||
FT4(0); FT4(1); FT4(2); FT4(3);
|
FT4(0); FT4(1); FT4(2); FT4(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MY_FAST_CALL AesDecode32(const UInt32 *src, UInt32 *dest, 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];
|
||||||
@@ -185,75 +222,74 @@ void MY_FAST_CALL AesDecode32(const UInt32 *src, UInt32 *dest, const UInt32 *w,
|
|||||||
FD4(0); FD4(1); FD4(2); FD4(3);
|
FD4(0); FD4(1); FD4(2); FD4(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LITTLE_ENDIAN_UNALIGN
|
void AesCbc_Init(UInt32 *p, const Byte *iv)
|
||||||
#define GetUi32(p) (*(const UInt32 *)(p))
|
|
||||||
#define SetUi32(p, d) *(UInt32 *)(p) = d;
|
|
||||||
#else
|
|
||||||
#define GetUi32(p) ((p)[0] | ((UInt32)(p)[1] << 8) | ((UInt32)(p)[2] << 16) | ((UInt32)(p)[3] << 24))
|
|
||||||
#define SetUi32(p, d) { UInt32 x = (d); (p)[0] = (Byte)x; (p)[1] = (Byte)(x >> 8); \
|
|
||||||
(p)[2] = (Byte)(x >> 16); (p)[3] = (Byte)(x >> 24); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void MY_FAST_CALL AesCbcInit(CAesCbc *cbc, const Byte *iv)
|
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
cbc->prev[i] = GetUi32(iv + i * 4);
|
p[i] = GetUi32(iv + i * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL AesCbcEncode(CAesCbc *cbc, Byte *data, UInt32 size)
|
void MY_FAST_CALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
{
|
{
|
||||||
UInt32 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)
|
|
||||||
{
|
{
|
||||||
cbc->prev[0] ^= GetUi32(data);
|
p[0] ^= GetUi32(data);
|
||||||
cbc->prev[1] ^= GetUi32(data + 4);
|
p[1] ^= GetUi32(data + 4);
|
||||||
cbc->prev[2] ^= GetUi32(data + 8);
|
p[2] ^= GetUi32(data + 8);
|
||||||
cbc->prev[3] ^= GetUi32(data + 12);
|
p[3] ^= GetUi32(data + 12);
|
||||||
|
|
||||||
AesEncode32(cbc->prev, cbc->prev, cbc->aes.rkey, cbc->aes.numRounds2);
|
Aes_Encode(p + 4, p, p);
|
||||||
|
|
||||||
SetUi32(data, cbc->prev[0]);
|
SetUi32(data, p[0]);
|
||||||
SetUi32(data + 4, cbc->prev[1]);
|
SetUi32(data + 4, p[1]);
|
||||||
SetUi32(data + 8, cbc->prev[2]);
|
SetUi32(data + 8, p[2]);
|
||||||
SetUi32(data + 12, cbc->prev[3]);
|
SetUi32(data + 12, p[3]);
|
||||||
}
|
}
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL AesCbcDecode(CAesCbc *cbc, Byte *data, UInt32 size)
|
void MY_FAST_CALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
{
|
{
|
||||||
UInt32 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);
|
||||||
|
|
||||||
|
Aes_Decode(p + 4, out, in);
|
||||||
|
|
||||||
|
SetUi32(data, p[0] ^ out[0]);
|
||||||
|
SetUi32(data + 4, p[1] ^ out[1]);
|
||||||
|
SetUi32(data + 8, p[2] ^ out[2]);
|
||||||
|
SetUi32(data + 12, p[3] ^ out[3]);
|
||||||
|
|
||||||
AesDecode32(in, out, cbc->aes.rkey, cbc->aes.numRounds2);
|
p[0] = in[0];
|
||||||
|
p[1] = in[1];
|
||||||
SetUi32(data, cbc->prev[0] ^ out[0]);
|
p[2] = in[2];
|
||||||
SetUi32(data + 4, cbc->prev[1] ^ out[1]);
|
p[3] = in[3];
|
||||||
SetUi32(data + 8, cbc->prev[2] ^ out[2]);
|
}
|
||||||
SetUi32(data + 12, cbc->prev[3] ^ out[3]);
|
}
|
||||||
|
|
||||||
cbc->prev[0] = in[0];
|
void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
cbc->prev[1] = in[1];
|
{
|
||||||
cbc->prev[2] = in[2];
|
for (; numBlocks != 0; numBlocks--)
|
||||||
cbc->prev[3] = in[3];
|
{
|
||||||
|
UInt32 temp[4];
|
||||||
|
Byte buf[16];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (++p[0] == 0)
|
||||||
|
p[1]++;
|
||||||
|
|
||||||
|
Aes_Encode(p + 4, temp, p);
|
||||||
|
|
||||||
|
SetUi32(buf, temp[0]);
|
||||||
|
SetUi32(buf + 4, temp[1]);
|
||||||
|
SetUi32(buf + 8, temp[2]);
|
||||||
|
SetUi32(buf + 12, temp[3]);
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
*data++ ^= buf[i];
|
||||||
}
|
}
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
38
C/Aes.h
Normal file
38
C/Aes.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/* Aes.h -- AES encryption / decryption
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __AES_H
|
||||||
|
#define __AES_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define AES_BLOCK_SIZE 16
|
||||||
|
|
||||||
|
/* Call AesGenTables one time before other AES functions */
|
||||||
|
void AesGenTables(void);
|
||||||
|
|
||||||
|
/* UInt32 pointers must be 16-byte aligned */
|
||||||
|
|
||||||
|
/* 16-byte (4 * 32-bit words) blocks: 1 (IV) + 1 (keyMode) + 15 (AES-256 roundKeys) */
|
||||||
|
#define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4)
|
||||||
|
|
||||||
|
/* aes - 16-byte aligned pointer to keyMode+roundKeys sequence */
|
||||||
|
/* keySize = 16 or 24 or 32 (bytes) */
|
||||||
|
typedef void (MY_FAST_CALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize);
|
||||||
|
void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *aes, const Byte *key, unsigned keySize);
|
||||||
|
void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *aes, const Byte *key, unsigned keySize);
|
||||||
|
|
||||||
|
/* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */
|
||||||
|
void AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */
|
||||||
|
/* data - 16-byte aligned pointer to data */
|
||||||
|
/* numBlocks - the number of 16-byte blocks in data array */
|
||||||
|
typedef void (MY_FAST_CALL *AES_CODE_FUNC)(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
extern AES_CODE_FUNC g_AesCbc_Encode;
|
||||||
|
extern AES_CODE_FUNC g_AesCbc_Decode;
|
||||||
|
extern AES_CODE_FUNC g_AesCtr_Code;
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
||||||
184
C/AesOpt.c
Normal file
184
C/AesOpt.c
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
/* AesOpt.c -- Intel's AES
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
#if _MSC_VER >= 1500
|
||||||
|
#define USE_INTEL_AES
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_INTEL_AES
|
||||||
|
|
||||||
|
#include <wmmintrin.h>
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Encode_Intel(__m128i *p, __m128i *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
__m128i m = *p;
|
||||||
|
for (; numBlocks != 0; numBlocks--, data++)
|
||||||
|
{
|
||||||
|
UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;
|
||||||
|
const __m128i *w = p + 3;
|
||||||
|
m = _mm_xor_si128(m, *data);
|
||||||
|
m = _mm_xor_si128(m, p[2]);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m = _mm_aesenc_si128(m, w[0]);
|
||||||
|
m = _mm_aesenc_si128(m, w[1]);
|
||||||
|
w += 2;
|
||||||
|
}
|
||||||
|
while (--numRounds2 != 0);
|
||||||
|
m = _mm_aesenc_si128(m, w[0]);
|
||||||
|
m = _mm_aesenclast_si128(m, w[1]);
|
||||||
|
*data = m;
|
||||||
|
}
|
||||||
|
*p = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NUM_WAYS 3
|
||||||
|
|
||||||
|
#define AES_OP_W(op, n) { \
|
||||||
|
const __m128i t = w[n]; \
|
||||||
|
m0 = op(m0, t); \
|
||||||
|
m1 = op(m1, t); \
|
||||||
|
m2 = op(m2, t); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define AES_DEC(n) AES_OP_W(_mm_aesdec_si128, n)
|
||||||
|
#define AES_DEC_LAST(n) AES_OP_W(_mm_aesdeclast_si128, n)
|
||||||
|
#define AES_ENC(n) AES_OP_W(_mm_aesenc_si128, n)
|
||||||
|
#define AES_ENC_LAST(n) AES_OP_W(_mm_aesenclast_si128, n)
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Decode_Intel(__m128i *p, __m128i *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
__m128i iv = *p;
|
||||||
|
for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)
|
||||||
|
{
|
||||||
|
UInt32 numRounds2 = *(const UInt32 *)(p + 1);
|
||||||
|
const __m128i *w = p + numRounds2 * 2;
|
||||||
|
__m128i m0, m1, m2;
|
||||||
|
{
|
||||||
|
const __m128i t = w[2];
|
||||||
|
m0 = _mm_xor_si128(t, data[0]);
|
||||||
|
m1 = _mm_xor_si128(t, data[1]);
|
||||||
|
m2 = _mm_xor_si128(t, data[2]);
|
||||||
|
}
|
||||||
|
numRounds2--;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
AES_DEC(1)
|
||||||
|
AES_DEC(0)
|
||||||
|
w -= 2;
|
||||||
|
}
|
||||||
|
while (--numRounds2 != 0);
|
||||||
|
AES_DEC(1)
|
||||||
|
AES_DEC_LAST(0)
|
||||||
|
|
||||||
|
{
|
||||||
|
__m128i t;
|
||||||
|
t = _mm_xor_si128(m0, iv); iv = data[0]; data[0] = t;
|
||||||
|
t = _mm_xor_si128(m1, iv); iv = data[1]; data[1] = t;
|
||||||
|
t = _mm_xor_si128(m2, iv); iv = data[2]; data[2] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (; numBlocks != 0; numBlocks--, data++)
|
||||||
|
{
|
||||||
|
UInt32 numRounds2 = *(const UInt32 *)(p + 1);
|
||||||
|
const __m128i *w = p + numRounds2 * 2;
|
||||||
|
__m128i m = _mm_xor_si128(w[2], *data);
|
||||||
|
numRounds2--;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m = _mm_aesdec_si128(m, w[1]);
|
||||||
|
m = _mm_aesdec_si128(m, w[0]);
|
||||||
|
w -= 2;
|
||||||
|
}
|
||||||
|
while (--numRounds2 != 0);
|
||||||
|
m = _mm_aesdec_si128(m, w[1]);
|
||||||
|
m = _mm_aesdeclast_si128(m, w[0]);
|
||||||
|
|
||||||
|
m = _mm_xor_si128(m, iv);
|
||||||
|
iv = *data;
|
||||||
|
*data = m;
|
||||||
|
}
|
||||||
|
*p = iv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCtr_Code_Intel(__m128i *p, __m128i *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
__m128i ctr = *p;
|
||||||
|
__m128i one;
|
||||||
|
one.m128i_u64[0] = 1;
|
||||||
|
one.m128i_u64[1] = 0;
|
||||||
|
for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)
|
||||||
|
{
|
||||||
|
UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;
|
||||||
|
const __m128i *w = p;
|
||||||
|
__m128i m0, m1, m2;
|
||||||
|
{
|
||||||
|
const __m128i t = w[2];
|
||||||
|
ctr = _mm_add_epi64(ctr, one); m0 = _mm_xor_si128(ctr, t);
|
||||||
|
ctr = _mm_add_epi64(ctr, one); m1 = _mm_xor_si128(ctr, t);
|
||||||
|
ctr = _mm_add_epi64(ctr, one); m2 = _mm_xor_si128(ctr, t);
|
||||||
|
}
|
||||||
|
w += 3;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
AES_ENC(0)
|
||||||
|
AES_ENC(1)
|
||||||
|
w += 2;
|
||||||
|
}
|
||||||
|
while (--numRounds2 != 0);
|
||||||
|
AES_ENC(0)
|
||||||
|
AES_ENC_LAST(1)
|
||||||
|
data[0] = _mm_xor_si128(data[0], m0);
|
||||||
|
data[1] = _mm_xor_si128(data[1], m1);
|
||||||
|
data[2] = _mm_xor_si128(data[2], m2);
|
||||||
|
}
|
||||||
|
for (; numBlocks != 0; numBlocks--, data++)
|
||||||
|
{
|
||||||
|
UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;
|
||||||
|
const __m128i *w = p;
|
||||||
|
__m128i m;
|
||||||
|
ctr = _mm_add_epi64(ctr, one);
|
||||||
|
m = _mm_xor_si128(ctr, p[2]);
|
||||||
|
w += 3;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m = _mm_aesenc_si128(m, w[0]);
|
||||||
|
m = _mm_aesenc_si128(m, w[1]);
|
||||||
|
w += 2;
|
||||||
|
}
|
||||||
|
while (--numRounds2 != 0);
|
||||||
|
m = _mm_aesenc_si128(m, w[0]);
|
||||||
|
m = _mm_aesenclast_si128(m, w[1]);
|
||||||
|
*data = _mm_xor_si128(*data, m);
|
||||||
|
}
|
||||||
|
*p = ctr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
AesCbc_Encode(p, data, numBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
AesCbc_Decode(p, data, numBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
AesCtr_Code(p, data, numBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
27
C/Alloc.c
Executable file → Normal file
27
C/Alloc.c
Executable file → Normal file
@@ -1,4 +1,7 @@
|
|||||||
/* Alloc.c */
|
/* Alloc.c -- Memory allocation functions
|
||||||
|
2015-02-21 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@@ -22,16 +25,21 @@ void *MyAlloc(size_t size)
|
|||||||
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++);
|
{
|
||||||
#endif
|
void *p = malloc(size);
|
||||||
|
fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
#else
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyFree(void *address)
|
void MyFree(void *address)
|
||||||
{
|
{
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
if (address != 0)
|
if (address != 0)
|
||||||
fprintf(stderr, "\nFree; count = %10d", --g_allocCount);
|
fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address);
|
||||||
#endif
|
#endif
|
||||||
free(address);
|
free(address);
|
||||||
}
|
}
|
||||||
@@ -95,7 +103,7 @@ void *BigAlloc(size_t size)
|
|||||||
#ifdef _7ZIP_LARGE_PAGES
|
#ifdef _7ZIP_LARGE_PAGES
|
||||||
if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))
|
if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))
|
||||||
{
|
{
|
||||||
void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
|
void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
|
||||||
MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
|
MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
return res;
|
return res;
|
||||||
@@ -117,3 +125,12 @@ void BigFree(void *address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static void *SzAlloc(void *p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
|
||||||
|
static void SzFree(void *p, void *address) { UNUSED_VAR(p); MyFree(address); }
|
||||||
|
ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||||
|
|
||||||
|
static void *SzBigAlloc(void *p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); }
|
||||||
|
static void SzBigFree(void *p, void *address) { UNUSED_VAR(p); BigFree(address); }
|
||||||
|
ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||||
|
|||||||
12
C/Alloc.h
Executable file → Normal file
12
C/Alloc.h
Executable file → Normal file
@@ -1,9 +1,12 @@
|
|||||||
/* Alloc.h */
|
/* Alloc.h -- Memory allocation functions
|
||||||
|
2015-02-21 : 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);
|
||||||
@@ -26,4 +29,9 @@ void BigFree(void *address);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern ISzAlloc g_Alloc;
|
||||||
|
extern ISzAlloc g_BigAlloc;
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
/* 7zAlloc.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_ALLOC_H
|
|
||||||
#define __7Z_ALLOC_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
typedef struct _ISzAlloc
|
|
||||||
{
|
|
||||||
void *(*Alloc)(size_t size);
|
|
||||||
void (*Free)(void *address); /* address can be 0 */
|
|
||||||
} ISzAlloc;
|
|
||||||
|
|
||||||
void *SzAlloc(size_t size);
|
|
||||||
void SzFree(void *address);
|
|
||||||
|
|
||||||
void *SzAllocTemp(size_t size);
|
|
||||||
void SzFreeTemp(void *address);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/* 7zBuffer.c */
|
|
||||||
|
|
||||||
#include "7zBuffer.h"
|
|
||||||
#include "7zAlloc.h"
|
|
||||||
|
|
||||||
void SzByteBufferInit(CSzByteBuffer *buffer)
|
|
||||||
{
|
|
||||||
buffer->Capacity = 0;
|
|
||||||
buffer->Items = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size))
|
|
||||||
{
|
|
||||||
buffer->Capacity = newCapacity;
|
|
||||||
if (newCapacity == 0)
|
|
||||||
{
|
|
||||||
buffer->Items = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
buffer->Items = (Byte *)allocFunc(newCapacity);
|
|
||||||
return (buffer->Items != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *))
|
|
||||||
{
|
|
||||||
freeFunc(buffer->Items);
|
|
||||||
buffer->Items = 0;
|
|
||||||
buffer->Capacity = 0;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/* 7zBuffer.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_BUFFER_H
|
|
||||||
#define __7Z_BUFFER_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "../../Types.h"
|
|
||||||
|
|
||||||
typedef struct _CSzByteBuffer
|
|
||||||
{
|
|
||||||
size_t Capacity;
|
|
||||||
Byte *Items;
|
|
||||||
}CSzByteBuffer;
|
|
||||||
|
|
||||||
void SzByteBufferInit(CSzByteBuffer *buffer);
|
|
||||||
int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size));
|
|
||||||
void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *));
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,341 +0,0 @@
|
|||||||
/* 7zDecode.c */
|
|
||||||
|
|
||||||
#include <memory.h>
|
|
||||||
|
|
||||||
#include "7zDecode.h"
|
|
||||||
#ifdef _SZ_ONE_DIRECTORY
|
|
||||||
#include "LzmaDecode.h"
|
|
||||||
#else
|
|
||||||
#include "../../Compress/Lzma/LzmaDecode.h"
|
|
||||||
#include "../../Compress/Branch/BranchX86.h"
|
|
||||||
#include "../../Compress/Branch/BranchX86_2.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define k_Copy 0
|
|
||||||
#define k_LZMA 0x30101
|
|
||||||
#define k_BCJ 0x03030103
|
|
||||||
#define k_BCJ2 0x0303011B
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
|
|
||||||
typedef struct _CLzmaInCallbackImp
|
|
||||||
{
|
|
||||||
ILzmaInCallback InCallback;
|
|
||||||
ISzInStream *InStream;
|
|
||||||
CFileSize Size;
|
|
||||||
} CLzmaInCallbackImp;
|
|
||||||
|
|
||||||
int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size)
|
|
||||||
{
|
|
||||||
CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
|
|
||||||
size_t processedSize;
|
|
||||||
SZ_RESULT res;
|
|
||||||
size_t curSize = (1 << 20);
|
|
||||||
if (curSize > cb->Size)
|
|
||||||
curSize = (size_t)cb->Size;
|
|
||||||
*size = 0;
|
|
||||||
res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, curSize, &processedSize);
|
|
||||||
*size = (SizeT)processedSize;
|
|
||||||
if (processedSize > curSize)
|
|
||||||
return (int)SZE_FAIL;
|
|
||||||
cb->Size -= processedSize;
|
|
||||||
if (res == SZ_OK)
|
|
||||||
return 0;
|
|
||||||
return (int)res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SZ_RESULT SzDecodeLzma(CCoderInfo *coder, CFileSize inSize,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ISzInStream *inStream,
|
|
||||||
#else
|
|
||||||
const Byte *inBuffer,
|
|
||||||
#endif
|
|
||||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
CLzmaInCallbackImp lzmaCallback;
|
|
||||||
#else
|
|
||||||
SizeT inProcessed;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
|
|
||||||
int result;
|
|
||||||
SizeT outSizeProcessedLoc;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
lzmaCallback.Size = inSize;
|
|
||||||
lzmaCallback.InStream = inStream;
|
|
||||||
lzmaCallback.InCallback.Read = LzmaReadImp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items,
|
|
||||||
(unsigned)coder->Properties.Capacity) != LZMA_RESULT_OK)
|
|
||||||
return SZE_FAIL;
|
|
||||||
|
|
||||||
state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
|
|
||||||
if (state.Probs == 0)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (state.Properties.DictionarySize == 0)
|
|
||||||
state.Dictionary = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
|
|
||||||
if (state.Dictionary == 0)
|
|
||||||
{
|
|
||||||
allocMain->Free(state.Probs);
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LzmaDecoderInit(&state);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
result = LzmaDecode(&state,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
&lzmaCallback.InCallback,
|
|
||||||
#else
|
|
||||||
inBuffer, (SizeT)inSize, &inProcessed,
|
|
||||||
#endif
|
|
||||||
outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
|
|
||||||
allocMain->Free(state.Probs);
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
allocMain->Free(state.Dictionary);
|
|
||||||
#endif
|
|
||||||
if (result == LZMA_RESULT_DATA_ERROR)
|
|
||||||
return SZE_DATA_ERROR;
|
|
||||||
if (result != LZMA_RESULT_OK)
|
|
||||||
return SZE_FAIL;
|
|
||||||
return (outSizeProcessedLoc == outSize) ? SZ_OK : SZE_DATA_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
SZ_RESULT SzDecodeCopy(CFileSize inSize, ISzInStream *inStream, Byte *outBuffer)
|
|
||||||
{
|
|
||||||
while (inSize > 0)
|
|
||||||
{
|
|
||||||
void *inBuffer;
|
|
||||||
size_t processedSize, curSize = (1 << 18);
|
|
||||||
if (curSize > inSize)
|
|
||||||
curSize = (size_t)(inSize);
|
|
||||||
RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, curSize, &processedSize));
|
|
||||||
if (processedSize == 0)
|
|
||||||
return SZE_DATA_ERROR;
|
|
||||||
if (processedSize > curSize)
|
|
||||||
return SZE_FAIL;
|
|
||||||
memcpy(outBuffer, inBuffer, processedSize);
|
|
||||||
outBuffer += processedSize;
|
|
||||||
inSize -= processedSize;
|
|
||||||
}
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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)
|
|
||||||
|
|
||||||
SZ_RESULT CheckSupportedFolder(const CFolder *f)
|
|
||||||
{
|
|
||||||
if (f->NumCoders < 1 || f->NumCoders > 4)
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
if (IS_UNSUPPORTED_CODER(f->Coders[0]))
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
if (f->NumCoders == 1)
|
|
||||||
{
|
|
||||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
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 SZE_NOTIMPL;
|
|
||||||
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 SZE_NOTIMPL;
|
|
||||||
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 SZE_NOTIMPL;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFileSize GetSum(const CFileSize *values, UInt32 index)
|
|
||||||
{
|
|
||||||
CFileSize sum = 0;
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < index; i++)
|
|
||||||
sum += values[i];
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ISzInStream *inStream, CFileSize startPos,
|
|
||||||
#else
|
|
||||||
const Byte *inBuffer,
|
|
||||||
#endif
|
|
||||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain,
|
|
||||||
Byte *tempBuf[])
|
|
||||||
{
|
|
||||||
UInt32 ci;
|
|
||||||
size_t tempSizes[3] = { 0, 0, 0};
|
|
||||||
size_t tempSize3 = 0;
|
|
||||||
Byte *tempBuf3 = 0;
|
|
||||||
|
|
||||||
RINOK(CheckSupportedFolder(folder));
|
|
||||||
|
|
||||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
|
||||||
{
|
|
||||||
CCoderInfo *coder = &folder->Coders[ci];
|
|
||||||
|
|
||||||
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
|
|
||||||
{
|
|
||||||
UInt32 si = 0;
|
|
||||||
CFileSize offset;
|
|
||||||
CFileSize inSize;
|
|
||||||
Byte *outBufCur = outBuffer;
|
|
||||||
size_t outSizeCur = outSize;
|
|
||||||
if (folder->NumCoders == 4)
|
|
||||||
{
|
|
||||||
UInt32 indices[] = { 3, 2, 0 };
|
|
||||||
CFileSize unpackSize = folder->UnPackSizes[ci];
|
|
||||||
si = indices[ci];
|
|
||||||
if (ci < 2)
|
|
||||||
{
|
|
||||||
Byte *temp;
|
|
||||||
outSizeCur = (size_t)unpackSize;
|
|
||||||
if (outSizeCur != unpackSize)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
temp = (Byte *)allocMain->Alloc(outSizeCur);
|
|
||||||
if (temp == 0 && outSizeCur != 0)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
outBufCur = tempBuf[1 - ci] = temp;
|
|
||||||
tempSizes[1 - ci] = outSizeCur;
|
|
||||||
}
|
|
||||||
else if (ci == 2)
|
|
||||||
{
|
|
||||||
if (unpackSize > outSize)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
|
||||||
tempSize3 = outSizeCur = (size_t)unpackSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
}
|
|
||||||
offset = GetSum(packSizes, si);
|
|
||||||
inSize = packSizes[si];
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
RINOK(inStream->Seek(inStream, startPos + offset));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (coder->MethodID == k_Copy)
|
|
||||||
{
|
|
||||||
if (inSize != outSizeCur)
|
|
||||||
return SZE_DATA_ERROR;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
|
||||||
#else
|
|
||||||
memcpy(outBufCur, inBuffer + (size_t)offset, (size_t)inSize);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SZ_RESULT res = SzDecodeLzma(coder, inSize,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
inStream,
|
|
||||||
#else
|
|
||||||
inBuffer + (size_t)offset,
|
|
||||||
#endif
|
|
||||||
outBufCur, outSizeCur, allocMain);
|
|
||||||
RINOK(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (coder->MethodID == k_BCJ)
|
|
||||||
{
|
|
||||||
UInt32 state;
|
|
||||||
if (ci != 1)
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
x86_Convert_Init(state);
|
|
||||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
|
||||||
}
|
|
||||||
else if (coder->MethodID == k_BCJ2)
|
|
||||||
{
|
|
||||||
CFileSize offset = GetSum(packSizes, 1);
|
|
||||||
CFileSize s3Size = packSizes[1];
|
|
||||||
SZ_RESULT res;
|
|
||||||
if (ci != 3)
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
RINOK(inStream->Seek(inStream, startPos + offset));
|
|
||||||
tempSizes[2] = (size_t)s3Size;
|
|
||||||
if (tempSizes[2] != s3Size)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
tempBuf[2] = (Byte *)allocMain->Alloc(tempSizes[2]);
|
|
||||||
if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
|
||||||
RINOK(res)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
res = x86_2_Decode(
|
|
||||||
tempBuf3, tempSize3,
|
|
||||||
tempBuf[0], tempSizes[0],
|
|
||||||
tempBuf[1], tempSizes[1],
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
tempBuf[2], tempSizes[2],
|
|
||||||
#else
|
|
||||||
inBuffer + (size_t)offset, (size_t)s3Size,
|
|
||||||
#endif
|
|
||||||
outBuffer, outSize);
|
|
||||||
RINOK(res)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
}
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ISzInStream *inStream, CFileSize startPos,
|
|
||||||
#else
|
|
||||||
const Byte *inBuffer,
|
|
||||||
#endif
|
|
||||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
|
||||||
{
|
|
||||||
Byte *tempBuf[3] = { 0, 0, 0};
|
|
||||||
int i;
|
|
||||||
SZ_RESULT res = SzDecode2(packSizes, folder,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
inStream, startPos,
|
|
||||||
#else
|
|
||||||
inBuffer,
|
|
||||||
#endif
|
|
||||||
outBuffer, outSize, allocMain, tempBuf);
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
allocMain->Free(tempBuf[i]);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
/* 7zDecode.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_DECODE_H
|
|
||||||
#define __7Z_DECODE_H
|
|
||||||
|
|
||||||
#include "7zItem.h"
|
|
||||||
#include "7zAlloc.h"
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
#include "7zIn.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ISzInStream *stream, CFileSize startPos,
|
|
||||||
#else
|
|
||||||
const Byte *inBuffer,
|
|
||||||
#endif
|
|
||||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
/* 7zExtract.c */
|
|
||||||
|
|
||||||
#include "7zExtract.h"
|
|
||||||
#include "7zDecode.h"
|
|
||||||
#include "../../7zCrc.h"
|
|
||||||
|
|
||||||
SZ_RESULT SzExtract(
|
|
||||||
ISzInStream *inStream,
|
|
||||||
CArchiveDatabaseEx *db,
|
|
||||||
UInt32 fileIndex,
|
|
||||||
UInt32 *blockIndex,
|
|
||||||
Byte **outBuffer,
|
|
||||||
size_t *outBufferSize,
|
|
||||||
size_t *offset,
|
|
||||||
size_t *outSizeProcessed,
|
|
||||||
ISzAlloc *allocMain,
|
|
||||||
ISzAlloc *allocTemp)
|
|
||||||
{
|
|
||||||
UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
|
|
||||||
SZ_RESULT res = SZ_OK;
|
|
||||||
*offset = 0;
|
|
||||||
*outSizeProcessed = 0;
|
|
||||||
if (folderIndex == (UInt32)-1)
|
|
||||||
{
|
|
||||||
allocMain->Free(*outBuffer);
|
|
||||||
*blockIndex = folderIndex;
|
|
||||||
*outBuffer = 0;
|
|
||||||
*outBufferSize = 0;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*outBuffer == 0 || *blockIndex != folderIndex)
|
|
||||||
{
|
|
||||||
CFolder *folder = db->Database.Folders + folderIndex;
|
|
||||||
CFileSize unPackSizeSpec = SzFolderGetUnPackSize(folder);
|
|
||||||
size_t unPackSize = (size_t)unPackSizeSpec;
|
|
||||||
CFileSize startOffset = SzArDbGetFolderStreamPos(db, folderIndex, 0);
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
Byte *inBuffer = 0;
|
|
||||||
size_t processedSize;
|
|
||||||
CFileSize packSizeSpec;
|
|
||||||
size_t packSize;
|
|
||||||
RINOK(SzArDbGetFolderFullPackSize(db, folderIndex, &packSizeSpec));
|
|
||||||
packSize = (size_t)packSizeSpec;
|
|
||||||
if (packSize != packSizeSpec)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
#endif
|
|
||||||
if (unPackSize != unPackSizeSpec)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
*blockIndex = folderIndex;
|
|
||||||
allocMain->Free(*outBuffer);
|
|
||||||
*outBuffer = 0;
|
|
||||||
|
|
||||||
RINOK(inStream->Seek(inStream, startOffset));
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
if (packSize != 0)
|
|
||||||
{
|
|
||||||
inBuffer = (Byte *)allocTemp->Alloc(packSize);
|
|
||||||
if (inBuffer == 0)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
res = inStream->Read(inStream, inBuffer, packSize, &processedSize);
|
|
||||||
if (res == SZ_OK && processedSize != packSize)
|
|
||||||
res = SZE_FAIL;
|
|
||||||
#endif
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
*outBufferSize = unPackSize;
|
|
||||||
if (unPackSize != 0)
|
|
||||||
{
|
|
||||||
*outBuffer = (Byte *)allocMain->Alloc(unPackSize);
|
|
||||||
if (*outBuffer == 0)
|
|
||||||
res = SZE_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
res = SzDecode(db->Database.PackSizes +
|
|
||||||
db->FolderStartPackStreamIndex[folderIndex], folder,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
inStream, startOffset,
|
|
||||||
#else
|
|
||||||
inBuffer,
|
|
||||||
#endif
|
|
||||||
*outBuffer, unPackSize, allocTemp);
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
if (folder->UnPackCRCDefined)
|
|
||||||
{
|
|
||||||
if (CrcCalc(*outBuffer, unPackSize) != folder->UnPackCRC)
|
|
||||||
res = SZE_CRC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
allocTemp->Free(inBuffer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
CFileItem *fileItem = db->Database.Files + fileIndex;
|
|
||||||
*offset = 0;
|
|
||||||
for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
|
|
||||||
*offset += (UInt32)db->Database.Files[i].Size;
|
|
||||||
*outSizeProcessed = (size_t)fileItem->Size;
|
|
||||||
if (*offset + *outSizeProcessed > *outBufferSize)
|
|
||||||
return SZE_FAIL;
|
|
||||||
{
|
|
||||||
if (fileItem->IsFileCRCDefined)
|
|
||||||
{
|
|
||||||
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
|
|
||||||
res = SZE_CRC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/* 7zExtract.h */
|
|
||||||
|
|
||||||
#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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
SZ_RESULT SzExtract(
|
|
||||||
ISzInStream *inStream,
|
|
||||||
CArchiveDatabaseEx *db,
|
|
||||||
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
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
/* 7zHeader.c */
|
|
||||||
|
|
||||||
#include "7zHeader.h"
|
|
||||||
|
|
||||||
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
/* 7zHeader.h */
|
|
||||||
|
|
||||||
#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,
|
|
||||||
k7zIdCreationTime,
|
|
||||||
k7zIdLastAccessTime,
|
|
||||||
k7zIdLastWriteTime,
|
|
||||||
k7zIdWinAttributes,
|
|
||||||
k7zIdComment,
|
|
||||||
|
|
||||||
k7zIdEncodedHeader,
|
|
||||||
|
|
||||||
k7zIdStartPos
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
1314
C/Archive/7z/7zIn.c
1314
C/Archive/7z/7zIn.c
File diff suppressed because it is too large
Load Diff
@@ -1,55 +0,0 @@
|
|||||||
/* 7zIn.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_IN_H
|
|
||||||
#define __7Z_IN_H
|
|
||||||
|
|
||||||
#include "7zHeader.h"
|
|
||||||
#include "7zItem.h"
|
|
||||||
#include "7zAlloc.h"
|
|
||||||
|
|
||||||
typedef struct _CInArchiveInfo
|
|
||||||
{
|
|
||||||
CFileSize StartPositionAfterHeader;
|
|
||||||
CFileSize DataStartPosition;
|
|
||||||
}CInArchiveInfo;
|
|
||||||
|
|
||||||
typedef struct _CArchiveDatabaseEx
|
|
||||||
{
|
|
||||||
CArchiveDatabase Database;
|
|
||||||
CInArchiveInfo ArchiveInfo;
|
|
||||||
UInt32 *FolderStartPackStreamIndex;
|
|
||||||
CFileSize *PackStreamStartPositions;
|
|
||||||
UInt32 *FolderStartFileIndex;
|
|
||||||
UInt32 *FileIndexToFolderIndexMap;
|
|
||||||
}CArchiveDatabaseEx;
|
|
||||||
|
|
||||||
void SzArDbExInit(CArchiveDatabaseEx *db);
|
|
||||||
void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *));
|
|
||||||
CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder);
|
|
||||||
int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize);
|
|
||||||
|
|
||||||
typedef struct _ISzInStream
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
SZ_RESULT (*Read)(
|
|
||||||
void *object, /* pointer to ISzInStream itself */
|
|
||||||
void **buffer, /* out: pointer to buffer with data */
|
|
||||||
size_t maxRequiredSize, /* max required size to read */
|
|
||||||
size_t *processedSize); /* real processed size.
|
|
||||||
processedSize can be less than maxRequiredSize.
|
|
||||||
If processedSize == 0, then there are no more
|
|
||||||
bytes in stream. */
|
|
||||||
#else
|
|
||||||
SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize);
|
|
||||||
#endif
|
|
||||||
SZ_RESULT (*Seek)(void *object, CFileSize pos);
|
|
||||||
} ISzInStream;
|
|
||||||
|
|
||||||
|
|
||||||
int SzArchiveOpen(
|
|
||||||
ISzInStream *inStream,
|
|
||||||
CArchiveDatabaseEx *db,
|
|
||||||
ISzAlloc *allocMain,
|
|
||||||
ISzAlloc *allocTemp);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
/* 7zItem.c */
|
|
||||||
|
|
||||||
#include "7zItem.h"
|
|
||||||
#include "7zAlloc.h"
|
|
||||||
|
|
||||||
void SzCoderInfoInit(CCoderInfo *coder)
|
|
||||||
{
|
|
||||||
SzByteBufferInit(&coder->Properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p))
|
|
||||||
{
|
|
||||||
SzByteBufferFree(&coder->Properties, freeFunc);
|
|
||||||
SzCoderInfoInit(coder);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzFolderInit(CFolder *folder)
|
|
||||||
{
|
|
||||||
folder->NumCoders = 0;
|
|
||||||
folder->Coders = 0;
|
|
||||||
folder->NumBindPairs = 0;
|
|
||||||
folder->BindPairs = 0;
|
|
||||||
folder->NumPackStreams = 0;
|
|
||||||
folder->PackStreams = 0;
|
|
||||||
folder->UnPackSizes = 0;
|
|
||||||
folder->UnPackCRCDefined = 0;
|
|
||||||
folder->UnPackCRC = 0;
|
|
||||||
folder->NumUnPackStreams = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p))
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < folder->NumCoders; i++)
|
|
||||||
SzCoderInfoFree(&folder->Coders[i], freeFunc);
|
|
||||||
freeFunc(folder->Coders);
|
|
||||||
freeFunc(folder->BindPairs);
|
|
||||||
freeFunc(folder->PackStreams);
|
|
||||||
freeFunc(folder->UnPackSizes);
|
|
||||||
SzFolderInit(folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 SzFolderGetNumOutStreams(CFolder *folder)
|
|
||||||
{
|
|
||||||
UInt32 result = 0;
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < folder->NumCoders; i++)
|
|
||||||
result += folder->Coders[i].NumOutStreams;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for(i = 0; i < folder->NumBindPairs; i++)
|
|
||||||
if (folder->BindPairs[i].InIndex == inStreamIndex)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for(i = 0; i < folder->NumBindPairs; i++)
|
|
||||||
if (folder->BindPairs[i].OutIndex == outStreamIndex)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFileSize SzFolderGetUnPackSize(CFolder *folder)
|
|
||||||
{
|
|
||||||
int i = (int)SzFolderGetNumOutStreams(folder);
|
|
||||||
if (i == 0)
|
|
||||||
return 0;
|
|
||||||
for (i--; i >= 0; i--)
|
|
||||||
if (SzFolderFindBindPairForOutStream(folder, i) < 0)
|
|
||||||
return folder->UnPackSizes[i];
|
|
||||||
/* throw 1; */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
int FindPackStreamArrayIndex(int inStreamIndex) const
|
|
||||||
{
|
|
||||||
for(int i = 0; i < PackStreams.Size(); i++)
|
|
||||||
if (PackStreams[i] == inStreamIndex)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void SzFileInit(CFileItem *fileItem)
|
|
||||||
{
|
|
||||||
fileItem->IsFileCRCDefined = 0;
|
|
||||||
fileItem->HasStream = 1;
|
|
||||||
fileItem->IsDirectory = 0;
|
|
||||||
fileItem->IsAnti = 0;
|
|
||||||
fileItem->IsLastWriteTimeDefined = 0;
|
|
||||||
fileItem->Name = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p))
|
|
||||||
{
|
|
||||||
freeFunc(fileItem->Name);
|
|
||||||
SzFileInit(fileItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzArchiveDatabaseInit(CArchiveDatabase *db)
|
|
||||||
{
|
|
||||||
db->NumPackStreams = 0;
|
|
||||||
db->PackSizes = 0;
|
|
||||||
db->PackCRCsDefined = 0;
|
|
||||||
db->PackCRCs = 0;
|
|
||||||
db->NumFolders = 0;
|
|
||||||
db->Folders = 0;
|
|
||||||
db->NumFiles = 0;
|
|
||||||
db->Files = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *))
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < db->NumFolders; i++)
|
|
||||||
SzFolderFree(&db->Folders[i], freeFunc);
|
|
||||||
for (i = 0; i < db->NumFiles; i++)
|
|
||||||
SzFileFree(&db->Files[i], freeFunc);
|
|
||||||
freeFunc(db->PackSizes);
|
|
||||||
freeFunc(db->PackCRCsDefined);
|
|
||||||
freeFunc(db->PackCRCs);
|
|
||||||
freeFunc(db->Folders);
|
|
||||||
freeFunc(db->Files);
|
|
||||||
SzArchiveDatabaseInit(db);
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/* 7zItem.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_ITEM_H
|
|
||||||
#define __7Z_ITEM_H
|
|
||||||
|
|
||||||
#include "7zMethodID.h"
|
|
||||||
#include "7zHeader.h"
|
|
||||||
#include "7zBuffer.h"
|
|
||||||
|
|
||||||
typedef struct _CCoderInfo
|
|
||||||
{
|
|
||||||
UInt32 NumInStreams;
|
|
||||||
UInt32 NumOutStreams;
|
|
||||||
CMethodID MethodID;
|
|
||||||
CSzByteBuffer Properties;
|
|
||||||
}CCoderInfo;
|
|
||||||
|
|
||||||
void SzCoderInfoInit(CCoderInfo *coder);
|
|
||||||
void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p));
|
|
||||||
|
|
||||||
typedef struct _CBindPair
|
|
||||||
{
|
|
||||||
UInt32 InIndex;
|
|
||||||
UInt32 OutIndex;
|
|
||||||
}CBindPair;
|
|
||||||
|
|
||||||
typedef struct _CFolder
|
|
||||||
{
|
|
||||||
UInt32 NumCoders;
|
|
||||||
CCoderInfo *Coders;
|
|
||||||
UInt32 NumBindPairs;
|
|
||||||
CBindPair *BindPairs;
|
|
||||||
UInt32 NumPackStreams;
|
|
||||||
UInt32 *PackStreams;
|
|
||||||
CFileSize *UnPackSizes;
|
|
||||||
int UnPackCRCDefined;
|
|
||||||
UInt32 UnPackCRC;
|
|
||||||
|
|
||||||
UInt32 NumUnPackStreams;
|
|
||||||
}CFolder;
|
|
||||||
|
|
||||||
void SzFolderInit(CFolder *folder);
|
|
||||||
CFileSize SzFolderGetUnPackSize(CFolder *folder);
|
|
||||||
int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex);
|
|
||||||
UInt32 SzFolderGetNumOutStreams(CFolder *folder);
|
|
||||||
CFileSize SzFolderGetUnPackSize(CFolder *folder);
|
|
||||||
|
|
||||||
typedef struct _CArchiveFileTime
|
|
||||||
{
|
|
||||||
UInt32 Low;
|
|
||||||
UInt32 High;
|
|
||||||
} CArchiveFileTime;
|
|
||||||
|
|
||||||
typedef struct _CFileItem
|
|
||||||
{
|
|
||||||
CArchiveFileTime LastWriteTime;
|
|
||||||
/*
|
|
||||||
CFileSize StartPos;
|
|
||||||
UInt32 Attributes;
|
|
||||||
*/
|
|
||||||
CFileSize Size;
|
|
||||||
UInt32 FileCRC;
|
|
||||||
char *Name;
|
|
||||||
|
|
||||||
Byte IsFileCRCDefined;
|
|
||||||
Byte HasStream;
|
|
||||||
Byte IsDirectory;
|
|
||||||
Byte IsAnti;
|
|
||||||
Byte IsLastWriteTimeDefined;
|
|
||||||
/*
|
|
||||||
int AreAttributesDefined;
|
|
||||||
int IsLastWriteTimeDefined;
|
|
||||||
int IsStartPosDefined;
|
|
||||||
*/
|
|
||||||
}CFileItem;
|
|
||||||
|
|
||||||
void SzFileInit(CFileItem *fileItem);
|
|
||||||
|
|
||||||
typedef struct _CArchiveDatabase
|
|
||||||
{
|
|
||||||
UInt32 NumPackStreams;
|
|
||||||
CFileSize *PackSizes;
|
|
||||||
Byte *PackCRCsDefined;
|
|
||||||
UInt32 *PackCRCs;
|
|
||||||
UInt32 NumFolders;
|
|
||||||
CFolder *Folders;
|
|
||||||
UInt32 NumFiles;
|
|
||||||
CFileItem *Files;
|
|
||||||
}CArchiveDatabase;
|
|
||||||
|
|
||||||
void SzArchiveDatabaseInit(CArchiveDatabase *db);
|
|
||||||
void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *));
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,428 +0,0 @@
|
|||||||
/*
|
|
||||||
7zMain.c
|
|
||||||
Test application for 7z Decoder
|
|
||||||
LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define USE_WINDOWS_FUNCTIONS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "7zIn.h"
|
|
||||||
#include "7zExtract.h"
|
|
||||||
|
|
||||||
#include "../../7zCrc.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
typedef HANDLE MY_FILE_HANDLE;
|
|
||||||
#else
|
|
||||||
typedef FILE *MY_FILE_HANDLE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ConvertNumberToString(CFileSize value, char *s)
|
|
||||||
{
|
|
||||||
char temp[32];
|
|
||||||
int pos = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
temp[pos++] = (char)('0' + (int)(value % 10));
|
|
||||||
value /= 10;
|
|
||||||
}
|
|
||||||
while (value != 0);
|
|
||||||
do
|
|
||||||
*s++ = temp[--pos];
|
|
||||||
while(pos > 0);
|
|
||||||
*s = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PERIOD_4 (4 * 365 + 1)
|
|
||||||
#define PERIOD_100 (PERIOD_4 * 25 - 1)
|
|
||||||
#define PERIOD_400 (PERIOD_100 * 4 + 1)
|
|
||||||
|
|
||||||
void ConvertFileTimeToString(CArchiveFileTime *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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
/*
|
|
||||||
ReadFile and WriteFile functions in Windows have BUG:
|
|
||||||
If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
|
|
||||||
from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
|
|
||||||
(Insufficient system resources exist to complete the requested service).
|
|
||||||
*/
|
|
||||||
#define kChunkSizeMax (1 << 24)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t MyReadFile(MY_FILE_HANDLE file, void *data, size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
{
|
|
||||||
size_t processedSize = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
|
|
||||||
DWORD processedLoc = 0;
|
|
||||||
BOOL res = ReadFile(file, data, curSize, &processedLoc, NULL);
|
|
||||||
data = (void *)((unsigned char *)data + processedLoc);
|
|
||||||
size -= processedLoc;
|
|
||||||
processedSize += processedLoc;
|
|
||||||
if (!res || processedLoc == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (size > 0);
|
|
||||||
return processedSize;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return fread(data, 1, size, file);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t MyWriteFile(MY_FILE_HANDLE file, void *data, size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
{
|
|
||||||
size_t processedSize = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
|
|
||||||
DWORD processedLoc = 0;
|
|
||||||
BOOL res = WriteFile(file, data, curSize, &processedLoc, NULL);
|
|
||||||
data = (void *)((unsigned char *)data + processedLoc);
|
|
||||||
size -= processedLoc;
|
|
||||||
processedSize += processedLoc;
|
|
||||||
if (!res)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (size > 0);
|
|
||||||
return processedSize;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return fwrite(data, 1, size, file);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int MyCloseFile(MY_FILE_HANDLE file)
|
|
||||||
{
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
return (CloseHandle(file) != FALSE) ? 0 : 1;
|
|
||||||
#else
|
|
||||||
return fclose(file);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct _CFileInStream
|
|
||||||
{
|
|
||||||
ISzInStream InStream;
|
|
||||||
MY_FILE_HANDLE File;
|
|
||||||
} CFileInStream;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
|
|
||||||
#define kBufferSize (1 << 12)
|
|
||||||
Byte g_Buffer[kBufferSize];
|
|
||||||
|
|
||||||
SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize)
|
|
||||||
{
|
|
||||||
CFileInStream *s = (CFileInStream *)object;
|
|
||||||
size_t processedSizeLoc;
|
|
||||||
if (maxRequiredSize > kBufferSize)
|
|
||||||
maxRequiredSize = kBufferSize;
|
|
||||||
processedSizeLoc = MyReadFile(s->File, g_Buffer, maxRequiredSize);
|
|
||||||
*buffer = g_Buffer;
|
|
||||||
if (processedSize != 0)
|
|
||||||
*processedSize = processedSizeLoc;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize)
|
|
||||||
{
|
|
||||||
CFileInStream *s = (CFileInStream *)object;
|
|
||||||
size_t processedSizeLoc = MyReadFile(s->File, buffer, size);
|
|
||||||
if (processedSize != 0)
|
|
||||||
*processedSize = processedSizeLoc;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
|
|
||||||
{
|
|
||||||
CFileInStream *s = (CFileInStream *)object;
|
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
{
|
|
||||||
LARGE_INTEGER value;
|
|
||||||
value.LowPart = (DWORD)pos;
|
|
||||||
value.HighPart = (LONG)((UInt64)pos >> 32);
|
|
||||||
#ifdef _SZ_FILE_SIZE_32
|
|
||||||
/* VC 6.0 has bug with >> 32 shifts. */
|
|
||||||
value.HighPart = 0;
|
|
||||||
#endif
|
|
||||||
value.LowPart = SetFilePointer(s->File, value.LowPart, &value.HighPart, FILE_BEGIN);
|
|
||||||
if (value.LowPart == 0xFFFFFFFF)
|
|
||||||
if(GetLastError() != NO_ERROR)
|
|
||||||
return SZE_FAIL;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int res = fseek(s->File, (long)pos, SEEK_SET);
|
|
||||||
if (res == 0)
|
|
||||||
return SZ_OK;
|
|
||||||
return SZE_FAIL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrintError(char *sz)
|
|
||||||
{
|
|
||||||
printf("\nERROR: %s\n", sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int numargs, char *args[])
|
|
||||||
{
|
|
||||||
CFileInStream archiveStream;
|
|
||||||
CArchiveDatabaseEx db;
|
|
||||||
SZ_RESULT res;
|
|
||||||
ISzAlloc allocImp;
|
|
||||||
ISzAlloc allocTempImp;
|
|
||||||
|
|
||||||
printf("\n7z ANSI-C Decoder 4.48 Copyright (c) 1999-2007 Igor Pavlov 2007-06-21\n");
|
|
||||||
if (numargs == 1)
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"\nUsage: 7zDec <command> <archive_name>\n\n"
|
|
||||||
"<Commands>\n"
|
|
||||||
" e: Extract files from archive\n"
|
|
||||||
" l: List contents of archive\n"
|
|
||||||
" t: Test integrity of archive\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (numargs < 3)
|
|
||||||
{
|
|
||||||
PrintError("incorrect command");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
archiveStream.File =
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
CreateFile(args[2], GENERIC_READ, FILE_SHARE_READ,
|
|
||||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (archiveStream.File == INVALID_HANDLE_VALUE)
|
|
||||||
#else
|
|
||||||
archiveStream.File = fopen(args[2], "rb");
|
|
||||||
if (archiveStream.File == 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
PrintError("can not open input file");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
archiveStream.InStream.Read = SzFileReadImp;
|
|
||||||
archiveStream.InStream.Seek = SzFileSeekImp;
|
|
||||||
|
|
||||||
allocImp.Alloc = SzAlloc;
|
|
||||||
allocImp.Free = SzFree;
|
|
||||||
|
|
||||||
allocTempImp.Alloc = SzAllocTemp;
|
|
||||||
allocTempImp.Free = SzFreeTemp;
|
|
||||||
|
|
||||||
CrcGenerateTable();
|
|
||||||
|
|
||||||
SzArDbExInit(&db);
|
|
||||||
res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
char *command = args[1];
|
|
||||||
int listCommand = 0;
|
|
||||||
int testCommand = 0;
|
|
||||||
int extractCommand = 0;
|
|
||||||
if (strcmp(command, "l") == 0)
|
|
||||||
listCommand = 1;
|
|
||||||
if (strcmp(command, "t") == 0)
|
|
||||||
testCommand = 1;
|
|
||||||
else if (strcmp(command, "e") == 0)
|
|
||||||
extractCommand = 1;
|
|
||||||
|
|
||||||
if (listCommand)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < db.Database.NumFiles; i++)
|
|
||||||
{
|
|
||||||
CFileItem *f = db.Database.Files + i;
|
|
||||||
char s[32], t[32];
|
|
||||||
ConvertNumberToString(f->Size, s);
|
|
||||||
if (f->IsLastWriteTimeDefined)
|
|
||||||
ConvertFileTimeToString(&f->LastWriteTime, t);
|
|
||||||
else
|
|
||||||
strcpy(t, " ");
|
|
||||||
|
|
||||||
printf("%10s %s %s\n", s, t, f->Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (testCommand || extractCommand)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
|
|
||||||
/*
|
|
||||||
if you need cache, use these 3 variables.
|
|
||||||
if you use external function, you can make these variable as static.
|
|
||||||
*/
|
|
||||||
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
|
|
||||||
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
|
|
||||||
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
for (i = 0; i < db.Database.NumFiles; i++)
|
|
||||||
{
|
|
||||||
size_t offset;
|
|
||||||
size_t outSizeProcessed;
|
|
||||||
CFileItem *f = db.Database.Files + i;
|
|
||||||
if (f->IsDirectory)
|
|
||||||
printf("Directory ");
|
|
||||||
else
|
|
||||||
printf(testCommand ?
|
|
||||||
"Testing ":
|
|
||||||
"Extracting");
|
|
||||||
printf(" %s", f->Name);
|
|
||||||
if (f->IsDirectory)
|
|
||||||
{
|
|
||||||
printf("\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
res = SzExtract(&archiveStream.InStream, &db, i,
|
|
||||||
&blockIndex, &outBuffer, &outBufferSize,
|
|
||||||
&offset, &outSizeProcessed,
|
|
||||||
&allocImp, &allocTempImp);
|
|
||||||
if (res != SZ_OK)
|
|
||||||
break;
|
|
||||||
if (!testCommand)
|
|
||||||
{
|
|
||||||
MY_FILE_HANDLE outputHandle;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
outputHandle =
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ,
|
|
||||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (outputHandle == INVALID_HANDLE_VALUE)
|
|
||||||
#else
|
|
||||||
fopen(fileName, "wb+");
|
|
||||||
if (outputHandle == 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
PrintError("can not open output file");
|
|
||||||
res = SZE_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
processedSize = MyWriteFile(outputHandle, outBuffer + offset, outSizeProcessed);
|
|
||||||
if (processedSize != outSizeProcessed)
|
|
||||||
{
|
|
||||||
PrintError("can not write output file");
|
|
||||||
res = SZE_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (MyCloseFile(outputHandle))
|
|
||||||
{
|
|
||||||
PrintError("can not close output file");
|
|
||||||
res = SZE_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
allocImp.Free(outBuffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PrintError("incorrect command");
|
|
||||||
res = SZE_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SzArDbExFree(&db, allocImp.Free);
|
|
||||||
|
|
||||||
MyCloseFile(archiveStream.File);
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
printf("\nEverything is Ok\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (res == (SZ_RESULT)SZE_NOTIMPL)
|
|
||||||
PrintError("decoder doesn't support this archive");
|
|
||||||
else if (res == (SZ_RESULT)SZE_OUTOFMEMORY)
|
|
||||||
PrintError("can not allocate memory");
|
|
||||||
else if (res == (SZ_RESULT)SZE_CRC_ERROR)
|
|
||||||
PrintError("CRC error");
|
|
||||||
else
|
|
||||||
printf("\nERROR #%d\n", res);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* 7zMethodID.c */
|
|
||||||
|
|
||||||
#include "7zMethodID.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
int AreMethodsEqual(CMethodID *a1, CMethodID *a2)
|
|
||||||
{
|
|
||||||
return (*a1 == *a2) ? 1 : 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* 7zMethodID.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_METHOD_ID_H
|
|
||||||
#define __7Z_METHOD_ID_H
|
|
||||||
|
|
||||||
#include "../../Types.h"
|
|
||||||
|
|
||||||
typedef UInt64 CMethodID;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
PROG = 7zDec.exe
|
|
||||||
|
|
||||||
!IFDEF CPU
|
|
||||||
LIBS = $(LIBS) bufferoverflowU.lib
|
|
||||||
CFLAGS = $(CFLAGS) -GS- -Zc:forScope -WX -GS- -Gy -W4
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
!IFNDEF O
|
|
||||||
!IFDEF CPU
|
|
||||||
O=$(CPU)
|
|
||||||
!ELSE
|
|
||||||
O=O
|
|
||||||
!ENDIF
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -D_LZMA_IN_CB
|
|
||||||
CFLAGS_O1 = $(CFLAGS) -O1
|
|
||||||
CFLAGS_O2 = $(CFLAGS) -O2
|
|
||||||
|
|
||||||
LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF
|
|
||||||
|
|
||||||
PROGPATH = $O\$(PROG)
|
|
||||||
|
|
||||||
COMPL_O1 = $(CPP) $(CFLAGS_O1) $**
|
|
||||||
COMPL_O2 = $(CPP) $(CFLAGS_O2) $**
|
|
||||||
COMPL = $(CPP) $(CFLAGS_O1) $**
|
|
||||||
|
|
||||||
C_OBJS = \
|
|
||||||
$O\7zCrc.obj \
|
|
||||||
|
|
||||||
|
|
||||||
7Z_OBJS = \
|
|
||||||
$O\7zAlloc.obj \
|
|
||||||
$O\7zBuffer.obj \
|
|
||||||
$O\7zDecode.obj \
|
|
||||||
$O\7zExtract.obj \
|
|
||||||
$O\7zHeader.obj \
|
|
||||||
$O\7zIn.obj \
|
|
||||||
$O\7zItem.obj \
|
|
||||||
$O\7zMain.obj \
|
|
||||||
$O\7zMethodID.obj \
|
|
||||||
|
|
||||||
OBJS = \
|
|
||||||
$(7Z_OBJS) \
|
|
||||||
$O\LzmaDecode.obj \
|
|
||||||
$O\BranchX86.obj \
|
|
||||||
$O\BranchX86_2.obj \
|
|
||||||
$(C_OBJS) \
|
|
||||||
|
|
||||||
all: $(PROGPATH)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch
|
|
||||||
|
|
||||||
$O:
|
|
||||||
if not exist "$O" mkdir "$O"
|
|
||||||
|
|
||||||
$(PROGPATH): $O $(OBJS)
|
|
||||||
link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)
|
|
||||||
|
|
||||||
|
|
||||||
$(7Z_OBJS): $(*B).c
|
|
||||||
$(COMPL)
|
|
||||||
$O\LzmaDecode.obj: ../../Compress/Lzma/$(*B).c
|
|
||||||
$(COMPL_O2)
|
|
||||||
|
|
||||||
$O\BranchX86.obj: ../../Compress/Branch/$(*B).c
|
|
||||||
$(COMPL_O2)
|
|
||||||
|
|
||||||
$O\BranchX86_2.obj: ../../Compress/Branch/$(*B).c
|
|
||||||
$(COMPL_O2)
|
|
||||||
|
|
||||||
$(C_OBJS): ../../$(*B).c
|
|
||||||
$(COMPL_O2)
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
PROG = 7zDec
|
|
||||||
CXX = g++
|
|
||||||
LIB =
|
|
||||||
RM = rm -f
|
|
||||||
CFLAGS = -c -O2 -Wall -D_LZMA_IN_CB
|
|
||||||
|
|
||||||
OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o BranchX86.o BranchX86_2.o
|
|
||||||
|
|
||||||
all: $(PROG)
|
|
||||||
|
|
||||||
$(PROG): $(OBJS)
|
|
||||||
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
|
|
||||||
|
|
||||||
7zAlloc.o: 7zAlloc.c
|
|
||||||
$(CXX) $(CFLAGS) 7zAlloc.c
|
|
||||||
|
|
||||||
7zBuffer.o: 7zBuffer.c
|
|
||||||
$(CXX) $(CFLAGS) 7zBuffer.c
|
|
||||||
|
|
||||||
7zCrc.o: ../../7zCrc.c
|
|
||||||
$(CXX) $(CFLAGS) ../../7zCrc.c
|
|
||||||
|
|
||||||
7zDecode.o: 7zDecode.c
|
|
||||||
$(CXX) $(CFLAGS) 7zDecode.c
|
|
||||||
|
|
||||||
7zExtract.o: 7zExtract.c
|
|
||||||
$(CXX) $(CFLAGS) 7zExtract.c
|
|
||||||
|
|
||||||
7zHeader.o: 7zHeader.c
|
|
||||||
$(CXX) $(CFLAGS) 7zHeader.c
|
|
||||||
|
|
||||||
7zIn.o: 7zIn.c
|
|
||||||
$(CXX) $(CFLAGS) 7zIn.c
|
|
||||||
|
|
||||||
7zItem.o: 7zItem.c
|
|
||||||
$(CXX) $(CFLAGS) 7zItem.c
|
|
||||||
|
|
||||||
7zMain.o: 7zMain.c
|
|
||||||
$(CXX) $(CFLAGS) 7zMain.c
|
|
||||||
|
|
||||||
7zMethodID.o: 7zMethodID.c
|
|
||||||
$(CXX) $(CFLAGS) 7zMethodID.c
|
|
||||||
|
|
||||||
LzmaDecode.o: ../../Compress/Lzma/LzmaDecode.c
|
|
||||||
$(CXX) $(CFLAGS) ../../Compress/Lzma/LzmaDecode.c
|
|
||||||
|
|
||||||
BranchX86.o: ../../Compress/Branch/BranchX86.c
|
|
||||||
$(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86.c
|
|
||||||
|
|
||||||
BranchX86_2.o: ../../Compress/Branch/BranchX86_2.c
|
|
||||||
$(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86_2.c
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-$(RM) $(PROG) $(OBJS)
|
|
||||||
|
|
||||||
256
C/Bcj2.c
Normal file
256
C/Bcj2.c
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
|
||||||
|
2015-08-01 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.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
|
||||||
|
|
||||||
|
#define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)
|
||||||
|
#define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
|
||||||
|
#define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));
|
||||||
|
|
||||||
|
void Bcj2Dec_Init(CBcj2Dec *p)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
p->state = BCJ2_DEC_STATE_OK;
|
||||||
|
p->ip = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
|
||||||
|
{
|
||||||
|
p->state = BCJ2_STREAM_RC;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||||
|
}
|
||||||
|
|
||||||
|
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[p->state++ - BCJ2_DEC_STATE_ORIG_0];
|
||||||
|
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 (;;)
|
||||||
|
{
|
||||||
|
if (BCJ2_IS_32BIT_STREAM(p->state))
|
||||||
|
p->state = BCJ2_DEC_STATE_OK;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p->range < kTopValue)
|
||||||
|
{
|
||||||
|
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
|
||||||
|
{
|
||||||
|
p->state = BCJ2_STREAM_RC;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
p->range <<= 8;
|
||||||
|
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
|
||||||
|
const Byte *srcLim;
|
||||||
|
Byte *dest;
|
||||||
|
SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetUi32(dest, val);
|
||||||
|
p->temp[3] = (Byte)(val >> 24);
|
||||||
|
p->dest = dest + 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
146
C/Bcj2.h
Normal file
146
C/Bcj2.h
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
/* Bcj2.h -- BCJ2 Converter for x86 code
|
||||||
|
2014-11-10 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __BCJ2_H
|
||||||
|
#define __BCJ2_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)
|
||||||
|
|
||||||
|
/*
|
||||||
|
CBcj2Dec / CBcj2Enc
|
||||||
|
bufs sizes:
|
||||||
|
BUF_SIZE(n) = lims[n] - bufs[n]
|
||||||
|
bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4:
|
||||||
|
(BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0
|
||||||
|
(BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
CBcj2Dec:
|
||||||
|
dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions:
|
||||||
|
bufs[BCJ2_STREAM_MAIN] >= dest &&
|
||||||
|
bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv +
|
||||||
|
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
|
||||||
312
C/Bcj2Enc.c
Normal file
312
C/Bcj2Enc.c
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
/* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code)
|
||||||
|
2014-11-10 : 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[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
48
C/Blake2.h
Normal 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
244
C/Blake2s.c
Normal 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);
|
||||||
|
}
|
||||||
135
C/Bra.c
Normal file
135
C/Bra.c
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
/* Bra.c -- Converters for RISC code
|
||||||
|
2010-04-16 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Bra.h"
|
||||||
|
|
||||||
|
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
if (size < 4)
|
||||||
|
return 0;
|
||||||
|
size -= 4;
|
||||||
|
ip += 8;
|
||||||
|
for (i = 0; i <= size; i += 4)
|
||||||
|
{
|
||||||
|
if (data[i + 3] == 0xEB)
|
||||||
|
{
|
||||||
|
UInt32 dest;
|
||||||
|
UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]);
|
||||||
|
src <<= 2;
|
||||||
|
if (encoding)
|
||||||
|
dest = ip + (UInt32)i + src;
|
||||||
|
else
|
||||||
|
dest = src - (ip + (UInt32)i);
|
||||||
|
dest >>= 2;
|
||||||
|
data[i + 2] = (Byte)(dest >> 16);
|
||||||
|
data[i + 1] = (Byte)(dest >> 8);
|
||||||
|
data[i + 0] = (Byte)dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
if (size < 4)
|
||||||
|
return 0;
|
||||||
|
size -= 4;
|
||||||
|
ip += 4;
|
||||||
|
for (i = 0; i <= size; i += 2)
|
||||||
|
{
|
||||||
|
if ((data[i + 1] & 0xF8) == 0xF0 &&
|
||||||
|
(data[i + 3] & 0xF8) == 0xF8)
|
||||||
|
{
|
||||||
|
UInt32 dest;
|
||||||
|
UInt32 src =
|
||||||
|
(((UInt32)data[i + 1] & 0x7) << 19) |
|
||||||
|
((UInt32)data[i + 0] << 11) |
|
||||||
|
(((UInt32)data[i + 3] & 0x7) << 8) |
|
||||||
|
(data[i + 2]);
|
||||||
|
|
||||||
|
src <<= 1;
|
||||||
|
if (encoding)
|
||||||
|
dest = ip + (UInt32)i + src;
|
||||||
|
else
|
||||||
|
dest = src - (ip + (UInt32)i);
|
||||||
|
dest >>= 1;
|
||||||
|
|
||||||
|
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
|
||||||
|
data[i + 0] = (Byte)(dest >> 11);
|
||||||
|
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
|
||||||
|
data[i + 2] = (Byte)dest;
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
if (size < 4)
|
||||||
|
return 0;
|
||||||
|
size -= 4;
|
||||||
|
for (i = 0; i <= size; i += 4)
|
||||||
|
{
|
||||||
|
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
|
||||||
|
{
|
||||||
|
UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) |
|
||||||
|
((UInt32)data[i + 1] << 16) |
|
||||||
|
((UInt32)data[i + 2] << 8) |
|
||||||
|
((UInt32)data[i + 3] & (~3));
|
||||||
|
|
||||||
|
UInt32 dest;
|
||||||
|
if (encoding)
|
||||||
|
dest = ip + (UInt32)i + src;
|
||||||
|
else
|
||||||
|
dest = src - (ip + (UInt32)i);
|
||||||
|
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
|
||||||
|
data[i + 1] = (Byte)(dest >> 16);
|
||||||
|
data[i + 2] = (Byte)(dest >> 8);
|
||||||
|
data[i + 3] &= 0x3;
|
||||||
|
data[i + 3] |= dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
|
{
|
||||||
|
UInt32 i;
|
||||||
|
if (size < 4)
|
||||||
|
return 0;
|
||||||
|
size -= 4;
|
||||||
|
for (i = 0; i <= size; i += 4)
|
||||||
|
{
|
||||||
|
if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
|
||||||
|
(data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
|
||||||
|
{
|
||||||
|
UInt32 src =
|
||||||
|
((UInt32)data[i + 0] << 24) |
|
||||||
|
((UInt32)data[i + 1] << 16) |
|
||||||
|
((UInt32)data[i + 2] << 8) |
|
||||||
|
((UInt32)data[i + 3]);
|
||||||
|
UInt32 dest;
|
||||||
|
|
||||||
|
src <<= 2;
|
||||||
|
if (encoding)
|
||||||
|
dest = ip + i + src;
|
||||||
|
else
|
||||||
|
dest = src - (ip + i);
|
||||||
|
dest >>= 2;
|
||||||
|
|
||||||
|
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
|
||||||
|
|
||||||
|
data[i + 0] = (Byte)(dest >> 24);
|
||||||
|
data[i + 1] = (Byte)(dest >> 16);
|
||||||
|
data[i + 2] = (Byte)(dest >> 8);
|
||||||
|
data[i + 3] = (Byte)dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
64
C/Bra.h
Normal file
64
C/Bra.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* Bra.h -- Branch converters for executables
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __BRA_H
|
||||||
|
#define __BRA_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
/*
|
||||||
|
These functions convert relative addresses to absolute addresses
|
||||||
|
in CALL instructions to increase the compression ratio.
|
||||||
|
|
||||||
|
In:
|
||||||
|
data - data buffer
|
||||||
|
size - size of data
|
||||||
|
ip - current virtual Instruction Pinter (IP) value
|
||||||
|
state - state variable for x86 converter
|
||||||
|
encoding - 0 (for decoding), 1 (for encoding)
|
||||||
|
|
||||||
|
Out:
|
||||||
|
state - state variable for x86 converter
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The number of processed bytes. If you call these functions with multiple calls,
|
||||||
|
you must start next call with first byte after block of processed bytes.
|
||||||
|
|
||||||
|
Type Endian Alignment LookAhead
|
||||||
|
|
||||||
|
x86 little 1 4
|
||||||
|
ARMT little 2 2
|
||||||
|
ARM little 4 0
|
||||||
|
PPC big 4 0
|
||||||
|
SPARC big 4 0
|
||||||
|
IA64 little 16 0
|
||||||
|
|
||||||
|
size must be >= Alignment + LookAhead, if it's not last block.
|
||||||
|
If (size < Alignment + LookAhead), converter returns 0.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
UInt32 ip = 0;
|
||||||
|
for ()
|
||||||
|
{
|
||||||
|
; size must be >= Alignment + LookAhead, if it's not last block
|
||||||
|
SizeT processed = Convert(data, size, ip, 1);
|
||||||
|
data += processed;
|
||||||
|
size -= processed;
|
||||||
|
ip += processed;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define x86_Convert_Init(state) { state = 0; }
|
||||||
|
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);
|
||||||
|
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
|
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
|
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
|
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
|
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
||||||
82
C/Bra86.c
Normal file
82
C/Bra86.c
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/* Bra86.c -- Converter for x86 code (BCJ)
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Bra.h"
|
||||||
|
|
||||||
|
#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)
|
||||||
|
|
||||||
|
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
|
||||||
|
{
|
||||||
|
SizeT pos = 0;
|
||||||
|
UInt32 mask = *state & 7;
|
||||||
|
if (size < 5)
|
||||||
|
return 0;
|
||||||
|
size -= 4;
|
||||||
|
ip += 5;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Byte *p = data + pos;
|
||||||
|
const Byte *limit = data + size;
|
||||||
|
for (; p < limit; p++)
|
||||||
|
if ((*p & 0xFE) == 0xE8)
|
||||||
|
break;
|
||||||
|
|
||||||
|
{
|
||||||
|
SizeT d = (SizeT)(p - data - pos);
|
||||||
|
pos = (SizeT)(p - data);
|
||||||
|
if (p >= limit)
|
||||||
|
{
|
||||||
|
*state = (d > 2 ? 0 : mask >> (unsigned)d);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
if (d > 2)
|
||||||
|
mask = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask >>= (unsigned)d;
|
||||||
|
if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1])))
|
||||||
|
{
|
||||||
|
mask = (mask >> 1) | 4;
|
||||||
|
pos++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test86MSByte(p[4]))
|
||||||
|
{
|
||||||
|
UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
||||||
|
UInt32 cur = ip + (UInt32)pos;
|
||||||
|
pos += 5;
|
||||||
|
if (encoding)
|
||||||
|
v += cur;
|
||||||
|
else
|
||||||
|
v -= cur;
|
||||||
|
if (mask != 0)
|
||||||
|
{
|
||||||
|
unsigned sh = (mask & 6) << 2;
|
||||||
|
if (Test86MSByte((Byte)(v >> sh)))
|
||||||
|
{
|
||||||
|
v ^= (((UInt32)0x100 << sh) - 1);
|
||||||
|
if (encoding)
|
||||||
|
v += cur;
|
||||||
|
else
|
||||||
|
v -= cur;
|
||||||
|
}
|
||||||
|
mask = 0;
|
||||||
|
}
|
||||||
|
p[1] = (Byte)v;
|
||||||
|
p[2] = (Byte)(v >> 8);
|
||||||
|
p[3] = (Byte)(v >> 16);
|
||||||
|
p[4] = (Byte)(0 - ((v >> 24) & 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask = (mask >> 1) | 4;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
C/Compress/Branch/BranchIA64.c → C/BraIA64.c
Executable file → Normal file
33
C/Compress/Branch/BranchIA64.c → C/BraIA64.c
Executable file → Normal file
@@ -1,19 +1,25 @@
|
|||||||
/* BranchIA64.c */
|
/* BraIA64.c -- Converter for IA-64 code
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "BranchIA64.h"
|
#include "Precomp.h"
|
||||||
|
|
||||||
const Byte kBranchTable[32] =
|
#include "Bra.h"
|
||||||
{
|
|
||||||
|
static const Byte kBranchTable[32] =
|
||||||
|
{
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
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, 6, 6, 0, 0, 7, 7,
|
||||||
4, 4, 0, 0, 4, 4, 0, 0
|
4, 4, 0, 0, 4, 4, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
{
|
{
|
||||||
UInt32 i;
|
SizeT i;
|
||||||
for (i = 0; i + 16 <= size; i += 16)
|
if (size < 16)
|
||||||
|
return 0;
|
||||||
|
size -= 16;
|
||||||
|
for (i = 0; i <= size; i += 16)
|
||||||
{
|
{
|
||||||
UInt32 instrTemplate = data[i] & 0x1F;
|
UInt32 instrTemplate = data[i] & 0x1F;
|
||||||
UInt32 mask = kBranchTable[instrTemplate];
|
UInt32 mask = kBranchTable[instrTemplate];
|
||||||
@@ -30,13 +36,10 @@ UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
|||||||
bitRes = bitPos & 0x7;
|
bitRes = bitPos & 0x7;
|
||||||
instruction = 0;
|
instruction = 0;
|
||||||
for (j = 0; j < 6; j++)
|
for (j = 0; j < 6; j++)
|
||||||
instruction += (UInt64)(data[i + j + bytePos]) << (8 * j);
|
instruction += (UInt64)data[i + j + bytePos] << (8 * j);
|
||||||
|
|
||||||
instNorm = instruction >> bitRes;
|
instNorm = instruction >> bitRes;
|
||||||
if (((instNorm >> 37) & 0xF) == 0x5
|
if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0)
|
||||||
&& ((instNorm >> 9) & 0x7) == 0
|
|
||||||
/* && (instNorm & 0x3F)== 0 */
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);
|
UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);
|
||||||
UInt32 dest;
|
UInt32 dest;
|
||||||
@@ -45,9 +48,9 @@ UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
|||||||
src <<= 4;
|
src <<= 4;
|
||||||
|
|
||||||
if (encoding)
|
if (encoding)
|
||||||
dest = nowPos + i + src;
|
dest = ip + (UInt32)i + src;
|
||||||
else
|
else
|
||||||
dest = src - (nowPos + i);
|
dest = src - (ip + (UInt32)i);
|
||||||
|
|
||||||
dest >>= 4;
|
dest >>= 4;
|
||||||
|
|
||||||
177
CPP/7zip/Compress/BWT/BlockSort.cpp → C/BwtSort.c
Executable file → Normal file
177
CPP/7zip/Compress/BWT/BlockSort.cpp → C/BwtSort.c
Executable file → Normal file
@@ -1,56 +1,46 @@
|
|||||||
// BlockSort.cpp
|
/* BwtSort.c -- BWT block sorting
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "StdAfx.h"
|
#include "Precomp.h"
|
||||||
|
|
||||||
#include "BlockSort.h"
|
#include "BwtSort.h"
|
||||||
|
#include "Sort.h"
|
||||||
|
|
||||||
extern "C"
|
/* #define BLOCK_SORT_USE_HEAP_SORT */
|
||||||
{
|
|
||||||
#include "../../../../C/Sort.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
// use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M
|
#define NO_INLINE MY_FAST_CALL
|
||||||
// #define BLOCK_SORT_USE_HEAP_SORT
|
|
||||||
|
|
||||||
#if _MSC_VER >= 1300
|
/* Don't change it !!! */
|
||||||
#define NO_INLINE __declspec(noinline) __fastcall
|
#define kNumHashBytes 2
|
||||||
#else
|
#define kNumHashValues (1 << (kNumHashBytes * 8))
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define NO_INLINE __fastcall
|
|
||||||
#else
|
|
||||||
#define NO_INLINE
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Don't change it !!
|
/* kNumRefBitsMax must be < (kNumHashBytes * 8) = 16 */
|
||||||
static const int kNumHashBytes = 2;
|
#define kNumRefBitsMax 12
|
||||||
static const UInt32 kNumHashValues = 1 << (kNumHashBytes * 8);
|
|
||||||
|
|
||||||
static const int kNumRefBitsMax = 12; // must be < (kNumHashBytes * 8) = 16
|
|
||||||
|
|
||||||
#define BS_TEMP_SIZE kNumHashValues
|
#define BS_TEMP_SIZE kNumHashValues
|
||||||
|
|
||||||
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
|
|
||||||
static const int kNumFlagsBits = 5; // 32 Flags in UInt32 word
|
/* 32 Flags in UInt32 word */
|
||||||
static const UInt32 kNumFlagsInWord = (1 << kNumFlagsBits);
|
#define kNumFlagsBits 5
|
||||||
static const UInt32 kFlagsMask = kNumFlagsInWord - 1;
|
#define kNumFlagsInWord (1 << kNumFlagsBits)
|
||||||
static const UInt32 kAllFlags = 0xFFFFFFFF;
|
#define kFlagsMask (kNumFlagsInWord - 1)
|
||||||
|
#define kAllFlags 0xFFFFFFFF
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
const int kNumBitsMax = 20;
|
#define kNumBitsMax 20
|
||||||
const UInt32 kIndexMask = (1 << kNumBitsMax) - 1;
|
#define kIndexMask ((1 << kNumBitsMax) - 1)
|
||||||
const int kNumExtraBits = 32 - kNumBitsMax;
|
#define kNumExtraBits (32 - kNumBitsMax)
|
||||||
const int kNumExtra0Bits = kNumExtraBits - 2;
|
#define kNumExtra0Bits (kNumExtraBits - 2)
|
||||||
const UInt32 kNumExtra0Mask = (1 << kNumExtra0Bits) - 1;
|
#define kNumExtra0Mask ((1 << kNumExtra0Bits) - 1)
|
||||||
|
|
||||||
#define SetFinishedGroupSize(p, size) \
|
#define SetFinishedGroupSize(p, size) \
|
||||||
{ *(p) |= ((((size) - 1) & kNumExtra0Mask) << kNumBitsMax); \
|
{ *(p) |= ((((size) - 1) & kNumExtra0Mask) << kNumBitsMax); \
|
||||||
if ((size) > (1 << kNumExtra0Bits)) { \
|
if ((size) > (1 << kNumExtra0Bits)) { \
|
||||||
*(p) |= 0x40000000; *((p) + 1) |= ((((size) - 1)>> kNumExtra0Bits) << kNumBitsMax); } } \
|
*(p) |= 0x40000000; *((p) + 1) |= ((((size) - 1)>> kNumExtra0Bits) << kNumBitsMax); } } \
|
||||||
|
|
||||||
inline void SetGroupSize(UInt32 *p, UInt32 size)
|
static void SetGroupSize(UInt32 *p, UInt32 size)
|
||||||
{
|
{
|
||||||
if (--size == 0)
|
if (--size == 0)
|
||||||
return;
|
return;
|
||||||
@@ -64,9 +54,11 @@ inline void SetGroupSize(UInt32 *p, UInt32 size)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// SortGroup - is recursive Range-Sort function with HeapSort optimization for small blocks
|
/*
|
||||||
// "range" is not real range. It's only for optimization.
|
SortGroup - is recursive Range-Sort function with HeapSort optimization for small blocks
|
||||||
// returns: 1 - if there are groups, 0 - no more groups
|
"range" is not real range. It's only for optimization.
|
||||||
|
returns: 1 - if there are groups, 0 - no more groups
|
||||||
|
*/
|
||||||
|
|
||||||
UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 groupSize, int NumRefBits, UInt32 *Indices
|
UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 groupSize, int NumRefBits, UInt32 *Indices
|
||||||
#ifndef BLOCK_SORT_USE_HEAP_SORT
|
#ifndef BLOCK_SORT_USE_HEAP_SORT
|
||||||
@@ -75,6 +67,7 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
UInt32 *ind2 = Indices + groupOffset;
|
UInt32 *ind2 = Indices + groupOffset;
|
||||||
|
UInt32 *Groups;
|
||||||
if (groupSize <= 1)
|
if (groupSize <= 1)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -84,8 +77,8 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
*/
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
UInt32 *Groups = Indices + BlockSize + BS_TEMP_SIZE;
|
Groups = Indices + BlockSize + BS_TEMP_SIZE;
|
||||||
if (groupSize <= ((UInt32)1 << NumRefBits)
|
if (groupSize <= ((UInt32)1 << NumRefBits)
|
||||||
#ifndef BLOCK_SORT_USE_HEAP_SORT
|
#ifndef BLOCK_SORT_USE_HEAP_SORT
|
||||||
&& groupSize <= range
|
&& groupSize <= range
|
||||||
#endif
|
#endif
|
||||||
@@ -93,6 +86,7 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
{
|
{
|
||||||
UInt32 *temp = Indices + BlockSize;
|
UInt32 *temp = Indices + BlockSize;
|
||||||
UInt32 j;
|
UInt32 j;
|
||||||
|
UInt32 mask, thereAreGroups, group, cg;
|
||||||
{
|
{
|
||||||
UInt32 gPrev;
|
UInt32 gPrev;
|
||||||
UInt32 gRes = 0;
|
UInt32 gRes = 0;
|
||||||
@@ -106,8 +100,9 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
for (j = 1; j < groupSize; j++)
|
for (j = 1; j < groupSize; j++)
|
||||||
{
|
{
|
||||||
UInt32 sp = ind2[j] + NumSortedBytes;
|
UInt32 sp = ind2[j] + NumSortedBytes;
|
||||||
|
UInt32 g;
|
||||||
if (sp >= BlockSize) sp -= BlockSize;
|
if (sp >= BlockSize) sp -= BlockSize;
|
||||||
UInt32 g = Groups[sp];
|
g = Groups[sp];
|
||||||
temp[j] = (g << NumRefBits) | j;
|
temp[j] = (g << NumRefBits) | j;
|
||||||
gRes |= (gPrev ^ g);
|
gRes |= (gPrev ^ g);
|
||||||
}
|
}
|
||||||
@@ -121,13 +116,14 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
}
|
}
|
||||||
|
|
||||||
HeapSort(temp, groupSize);
|
HeapSort(temp, groupSize);
|
||||||
const UInt32 mask = ((1 << NumRefBits) - 1);
|
mask = ((1 << NumRefBits) - 1);
|
||||||
UInt32 thereAreGroups = 0;
|
thereAreGroups = 0;
|
||||||
|
|
||||||
UInt32 group = groupOffset;
|
group = groupOffset;
|
||||||
UInt32 cg = (temp[0] >> NumRefBits);
|
cg = (temp[0] >> NumRefBits);
|
||||||
temp[0] = ind2[temp[0] & mask];
|
temp[0] = ind2[temp[0] & mask];
|
||||||
|
|
||||||
|
{
|
||||||
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
UInt32 *Flags = Groups + BlockSize;
|
UInt32 *Flags = Groups + BlockSize;
|
||||||
#else
|
#else
|
||||||
@@ -145,8 +141,10 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
group = groupOffset + j;
|
group = groupOffset + j;
|
||||||
|
|
||||||
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
|
{
|
||||||
UInt32 t = group - 1;
|
UInt32 t = group - 1;
|
||||||
Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
|
Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
SetGroupSize(temp + prevGroupStart, j - prevGroupStart);
|
SetGroupSize(temp + prevGroupStart, j - prevGroupStart);
|
||||||
prevGroupStart = j;
|
prevGroupStart = j;
|
||||||
@@ -154,25 +152,28 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
thereAreGroups = 1;
|
thereAreGroups = 1;
|
||||||
|
{
|
||||||
UInt32 ind = ind2[val & mask];
|
UInt32 ind = ind2[val & mask];
|
||||||
temp[j] = ind;
|
temp[j] = ind;
|
||||||
Groups[ind] = group;
|
Groups[ind] = group;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
SetGroupSize(temp + prevGroupStart, j - prevGroupStart);
|
SetGroupSize(temp + prevGroupStart, j - prevGroupStart);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
for (j = 0; j < groupSize; j++)
|
for (j = 0; j < groupSize; j++)
|
||||||
ind2[j] = temp[j];
|
ind2[j] = temp[j];
|
||||||
return thereAreGroups;
|
return thereAreGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that all strings are in one group (cannot sort)
|
/* Check that all strings are in one group (cannot sort) */
|
||||||
{
|
{
|
||||||
|
UInt32 group, j;
|
||||||
UInt32 sp = ind2[0] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
|
UInt32 sp = ind2[0] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
|
||||||
UInt32 group = Groups[sp];
|
group = Groups[sp];
|
||||||
UInt32 j;
|
|
||||||
for (j = 1; j < groupSize; j++)
|
for (j = 1; j < groupSize; j++)
|
||||||
{
|
{
|
||||||
sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
|
sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
|
||||||
@@ -189,12 +190,13 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BLOCK_SORT_USE_HEAP_SORT
|
#ifndef BLOCK_SORT_USE_HEAP_SORT
|
||||||
//--------------------------------------
|
{
|
||||||
// Range Sort
|
/* ---------- Range Sort ---------- */
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
UInt32 mid;
|
UInt32 mid;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
UInt32 j;
|
||||||
if (range <= 1)
|
if (range <= 1)
|
||||||
{
|
{
|
||||||
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
@@ -203,7 +205,7 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
mid = left + ((range + 1) >> 1);
|
mid = left + ((range + 1) >> 1);
|
||||||
UInt32 j = groupSize;
|
j = groupSize;
|
||||||
i = 0;
|
i = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -223,7 +225,7 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(++i < j);
|
while (++i < j);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
range = range - (mid - left);
|
range = range - (mid - left);
|
||||||
@@ -231,7 +233,7 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
}
|
}
|
||||||
else if (i == groupSize)
|
else if (i == groupSize)
|
||||||
range = (mid - left);
|
range = (mid - left);
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,16 +245,22 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (UInt32 j = i; j < groupSize; j++)
|
{
|
||||||
Groups[ind2[j]] = groupOffset + i;
|
UInt32 j;
|
||||||
|
for (j = i; j < groupSize; j++)
|
||||||
|
Groups[ind2[j]] = groupOffset + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
UInt32 res = SortGroup(BlockSize, NumSortedBytes, groupOffset, i, NumRefBits, Indices, left, mid - left);
|
UInt32 res = SortGroup(BlockSize, NumSortedBytes, groupOffset, i, NumRefBits, Indices, left, mid - left);
|
||||||
return res | SortGroup(BlockSize, NumSortedBytes, groupOffset + i, groupSize - i, NumRefBits, Indices, mid, range - (mid - left));
|
return res | SortGroup(BlockSize, NumSortedBytes, groupOffset + i, groupSize - i, NumRefBits, Indices, mid, range - (mid - left));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
//--------------------------------------
|
/* ---------- Heap Sort ---------- */
|
||||||
// Heap Sort
|
|
||||||
|
|
||||||
{
|
{
|
||||||
UInt32 j;
|
UInt32 j;
|
||||||
@@ -264,7 +272,8 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
|
|
||||||
HeapSortRef(ind2, Groups, groupSize);
|
HeapSortRef(ind2, Groups, groupSize);
|
||||||
|
|
||||||
// Write Flags
|
/* Write Flags */
|
||||||
|
{
|
||||||
UInt32 sp = ind2[0];
|
UInt32 sp = ind2[0];
|
||||||
UInt32 group = Groups[sp];
|
UInt32 group = Groups[sp];
|
||||||
|
|
||||||
@@ -281,8 +290,10 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
{
|
{
|
||||||
group = Groups[sp];
|
group = Groups[sp];
|
||||||
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
|
{
|
||||||
UInt32 t = groupOffset + j - 1;
|
UInt32 t = groupOffset + j - 1;
|
||||||
Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
|
Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);
|
SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);
|
||||||
prevGroupStart = j;
|
prevGroupStart = j;
|
||||||
@@ -293,9 +304,10 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);
|
SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
// Write new Groups values and Check that there are groups
|
{
|
||||||
UInt32 thereAreGroups = 0;
|
/* Write new Groups values and Check that there are groups */
|
||||||
|
UInt32 thereAreGroups = 0;
|
||||||
for (j = 0; j < groupSize; j++)
|
for (j = 0; j < groupSize; j++)
|
||||||
{
|
{
|
||||||
UInt32 group = groupOffset + j;
|
UInt32 group = groupOffset + j;
|
||||||
@@ -317,6 +329,7 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
thereAreGroups = 1;
|
thereAreGroups = 1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
UInt32 *Flags = Groups + BlockSize;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
UInt32 sp = ind2[j]; if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes;
|
UInt32 sp = ind2[j]; if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes;
|
||||||
@@ -330,26 +343,31 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return thereAreGroups;
|
return thereAreGroups;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// conditions: blockSize > 0
|
/* conditions: blockSize > 0 */
|
||||||
UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
||||||
{
|
{
|
||||||
UInt32 *counters = Indices + blockSize;
|
UInt32 *counters = Indices + blockSize;
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
|
UInt32 *Groups;
|
||||||
|
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
|
UInt32 *Flags;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Radix-Sort for 2 bytes
|
/* Radix-Sort for 2 bytes */
|
||||||
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[i + 1]]++;
|
||||||
counters[((UInt32)data[i] << 8) | data[0]]++;
|
counters[((UInt32)data[i] << 8) | data[0]]++;
|
||||||
|
|
||||||
UInt32 *Groups = counters + BS_TEMP_SIZE;
|
Groups = counters + BS_TEMP_SIZE;
|
||||||
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
UInt32 *Flags = Groups + blockSize;
|
Flags = Groups + blockSize;
|
||||||
{
|
{
|
||||||
UInt32 numWords = (blockSize + kFlagsMask) >> kNumFlagsBits;
|
UInt32 numWords = (blockSize + kFlagsMask) >> kNumFlagsBits;
|
||||||
for (i = 0; i < numWords; i++)
|
for (i = 0; i < numWords; i++)
|
||||||
@@ -382,6 +400,7 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
|||||||
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
|
||||||
|
{
|
||||||
UInt32 prev = 0;
|
UInt32 prev = 0;
|
||||||
for (i = 0; i < kNumHashValues; i++)
|
for (i = 0; i < kNumHashValues; i++)
|
||||||
{
|
{
|
||||||
@@ -391,16 +410,19 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
|||||||
SetGroupSize(Indices + prev, prevGroupSize);
|
SetGroupSize(Indices + prev, prevGroupSize);
|
||||||
prev = counters[i];
|
prev = counters[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
int NumRefBits;
|
int NumRefBits;
|
||||||
|
UInt32 NumSortedBytes;
|
||||||
for (NumRefBits = 0; ((blockSize - 1) >> NumRefBits) != 0; NumRefBits++);
|
for (NumRefBits = 0; ((blockSize - 1) >> NumRefBits) != 0; NumRefBits++);
|
||||||
NumRefBits = 32 - NumRefBits;
|
NumRefBits = 32 - NumRefBits;
|
||||||
if (NumRefBits > kNumRefBitsMax)
|
if (NumRefBits > kNumRefBitsMax)
|
||||||
NumRefBits = kNumRefBitsMax;
|
NumRefBits = kNumRefBitsMax;
|
||||||
|
|
||||||
for (UInt32 NumSortedBytes = kNumHashBytes; ; NumSortedBytes <<= 1)
|
for (NumSortedBytes = kNumHashBytes; ; NumSortedBytes <<= 1)
|
||||||
{
|
{
|
||||||
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
UInt32 finishedGroupSize = 0;
|
UInt32 finishedGroupSize = 0;
|
||||||
@@ -408,6 +430,7 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
|||||||
UInt32 newLimit = 0;
|
UInt32 newLimit = 0;
|
||||||
for (i = 0; i < blockSize;)
|
for (i = 0; i < blockSize;)
|
||||||
{
|
{
|
||||||
|
UInt32 groupSize;
|
||||||
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
|
|
||||||
if ((Flags[i >> kNumFlagsBits] & (1 << (i & kFlagsMask))) == 0)
|
if ((Flags[i >> kNumFlagsBits] & (1 << (i & kFlagsMask))) == 0)
|
||||||
@@ -415,17 +438,17 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
|||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
UInt32 groupSize;
|
for (groupSize = 1;
|
||||||
for(groupSize = 1;
|
(Flags[(i + groupSize) >> kNumFlagsBits] & (1 << ((i + groupSize) & kFlagsMask))) != 0;
|
||||||
(Flags[(i + groupSize) >> kNumFlagsBits] & (1 << ((i + groupSize) & kFlagsMask))) != 0;
|
|
||||||
groupSize++);
|
groupSize++);
|
||||||
|
|
||||||
groupSize++;
|
groupSize++;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
UInt32 groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax);
|
groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax);
|
||||||
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[i + 1] >> kNumBitsMax) << kNumExtra0Bits);
|
||||||
@@ -438,28 +461,34 @@ 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[i - finishedGroupSize + 1] &= kIndexMask;
|
||||||
|
{
|
||||||
UInt32 newGroupSize = groupSize + finishedGroupSize;
|
UInt32 newGroupSize = groupSize + finishedGroupSize;
|
||||||
SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize);
|
SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize);
|
||||||
finishedGroupSize = newGroupSize;
|
finishedGroupSize = newGroupSize;
|
||||||
|
}
|
||||||
i += groupSize;
|
i += groupSize;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
finishedGroupSize = 0;
|
finishedGroupSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (NumSortedBytes >= blockSize)
|
if (NumSortedBytes >= blockSize)
|
||||||
for (UInt32 j = 0; j < groupSize; j++)
|
{
|
||||||
|
UInt32 j;
|
||||||
|
for (j = 0; j < groupSize; j++)
|
||||||
{
|
{
|
||||||
UInt32 t = (i + j);
|
UInt32 t = (i + j);
|
||||||
// Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
|
/* Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); */
|
||||||
Groups[Indices[t]] = t;
|
Groups[Indices[t]] = t;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (SortGroup(blockSize, NumSortedBytes, i, groupSize, NumRefBits, Indices
|
if (SortGroup(blockSize, NumSortedBytes, i, groupSize, NumRefBits, Indices
|
||||||
#ifndef BLOCK_SORT_USE_HEAP_SORT
|
#ifndef BLOCK_SORT_USE_HEAP_SORT
|
||||||
, 0, blockSize
|
, 0, blockSize
|
||||||
#endif
|
#endif
|
||||||
) != 0)
|
) != 0)
|
||||||
newLimit = i + groupSize;
|
newLimit = i + groupSize;
|
||||||
i += groupSize;
|
i += groupSize;
|
||||||
@@ -467,6 +496,7 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
|||||||
if (newLimit == 0)
|
if (newLimit == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
for (i = 0; i < blockSize;)
|
for (i = 0; i < blockSize;)
|
||||||
{
|
{
|
||||||
@@ -483,4 +513,3 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
|||||||
#endif
|
#endif
|
||||||
return Groups[0];
|
return Groups[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
17
CPP/7zip/Compress/BWT/BlockSort.h → C/BwtSort.h
Executable file → Normal file
17
CPP/7zip/Compress/BWT/BlockSort.h → C/BwtSort.h
Executable file → Normal file
@@ -1,12 +1,15 @@
|
|||||||
// BlockSort.h
|
/* BwtSort.h -- BWT block sorting
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __BLOCKSORT_H
|
#ifndef __BWT_SORT_H
|
||||||
#define __BLOCKSORT_H
|
#define __BWT_SORT_H
|
||||||
|
|
||||||
#include "Common/Types.h"
|
#include "7zTypes.h"
|
||||||
|
|
||||||
// use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M
|
EXTERN_C_BEGIN
|
||||||
// #define BLOCK_SORT_EXTERNAL_FLAGS
|
|
||||||
|
/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */
|
||||||
|
/* #define BLOCK_SORT_EXTERNAL_FLAGS */
|
||||||
|
|
||||||
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
||||||
#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) ((((blockSize) + 31) >> 5))
|
#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) ((((blockSize) + 31) >> 5))
|
||||||
@@ -18,4 +21,6 @@
|
|||||||
|
|
||||||
UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize);
|
UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
32
C/Compiler.h
Normal file
32
C/Compiler.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/* Compiler.h
|
||||||
|
2015-08-02 : 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 : 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
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
/* BranchARM.c */
|
|
||||||
|
|
||||||
#include "BranchARM.h"
|
|
||||||
|
|
||||||
UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i + 4 <= size; i += 4)
|
|
||||||
{
|
|
||||||
if (data[i + 3] == 0xEB)
|
|
||||||
{
|
|
||||||
UInt32 dest;
|
|
||||||
UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]);
|
|
||||||
src <<= 2;
|
|
||||||
if (encoding)
|
|
||||||
dest = nowPos + i + 8 + src;
|
|
||||||
else
|
|
||||||
dest = src - (nowPos + i + 8);
|
|
||||||
dest >>= 2;
|
|
||||||
data[i + 2] = (Byte)(dest >> 16);
|
|
||||||
data[i + 1] = (Byte)(dest >> 8);
|
|
||||||
data[i + 0] = (Byte)dest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* BranchARM.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCH_ARM_H
|
|
||||||
#define __BRANCH_ARM_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/* BranchARMThumb.c */
|
|
||||||
|
|
||||||
#include "BranchARMThumb.h"
|
|
||||||
|
|
||||||
UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i + 4 <= size; i += 2)
|
|
||||||
{
|
|
||||||
if ((data[i + 1] & 0xF8) == 0xF0 &&
|
|
||||||
(data[i + 3] & 0xF8) == 0xF8)
|
|
||||||
{
|
|
||||||
UInt32 dest;
|
|
||||||
UInt32 src =
|
|
||||||
((data[i + 1] & 0x7) << 19) |
|
|
||||||
(data[i + 0] << 11) |
|
|
||||||
((data[i + 3] & 0x7) << 8) |
|
|
||||||
(data[i + 2]);
|
|
||||||
|
|
||||||
src <<= 1;
|
|
||||||
if (encoding)
|
|
||||||
dest = nowPos + i + 4 + src;
|
|
||||||
else
|
|
||||||
dest = src - (nowPos + i + 4);
|
|
||||||
dest >>= 1;
|
|
||||||
|
|
||||||
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
|
|
||||||
data[i + 0] = (Byte)(dest >> 11);
|
|
||||||
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
|
|
||||||
data[i + 2] = (Byte)dest;
|
|
||||||
i += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* BranchARMThumb.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCH_ARM_THUMB_H
|
|
||||||
#define __BRANCH_ARM_THUMB_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* BranchIA64.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCH_IA64_H
|
|
||||||
#define __BRANCH_IA64_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/* BranchPPC.c */
|
|
||||||
|
|
||||||
#include "BranchPPC.h"
|
|
||||||
|
|
||||||
UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i + 4 <= size; i += 4)
|
|
||||||
{
|
|
||||||
/* PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) */
|
|
||||||
if ((data[i] >> 2) == 0x12 &&
|
|
||||||
(
|
|
||||||
(data[i + 3] & 3) == 1
|
|
||||||
/* || (data[i+3] & 3) == 3 */
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UInt32 src = ((data[i + 0] & 3) << 24) |
|
|
||||||
(data[i + 1] << 16) |
|
|
||||||
(data[i + 2] << 8) |
|
|
||||||
(data[i + 3] & (~3));
|
|
||||||
|
|
||||||
UInt32 dest;
|
|
||||||
if (encoding)
|
|
||||||
dest = nowPos + i + src;
|
|
||||||
else
|
|
||||||
dest = src - (nowPos + i);
|
|
||||||
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
|
|
||||||
data[i + 1] = (Byte)(dest >> 16);
|
|
||||||
data[i + 2] = (Byte)(dest >> 8);
|
|
||||||
data[i + 3] &= 0x3;
|
|
||||||
data[i + 3] |= dest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* BranchPPC.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCH_PPC_H
|
|
||||||
#define __BRANCH_PPC_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/* BranchSPARC.c */
|
|
||||||
|
|
||||||
#include "BranchSPARC.h"
|
|
||||||
|
|
||||||
UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i + 4 <= size; i += 4)
|
|
||||||
{
|
|
||||||
if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 ||
|
|
||||||
data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)
|
|
||||||
{
|
|
||||||
UInt32 src =
|
|
||||||
((UInt32)data[i + 0] << 24) |
|
|
||||||
((UInt32)data[i + 1] << 16) |
|
|
||||||
((UInt32)data[i + 2] << 8) |
|
|
||||||
((UInt32)data[i + 3]);
|
|
||||||
UInt32 dest;
|
|
||||||
|
|
||||||
src <<= 2;
|
|
||||||
if (encoding)
|
|
||||||
dest = nowPos + i + src;
|
|
||||||
else
|
|
||||||
dest = src - (nowPos + i);
|
|
||||||
dest >>= 2;
|
|
||||||
|
|
||||||
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
|
|
||||||
|
|
||||||
data[i + 0] = (Byte)(dest >> 24);
|
|
||||||
data[i + 1] = (Byte)(dest >> 16);
|
|
||||||
data[i + 2] = (Byte)(dest >> 8);
|
|
||||||
data[i + 3] = (Byte)dest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* BranchSPARC.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCH_SPARC_H
|
|
||||||
#define __BRANCH_SPARC_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/* BranchTypes.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCHTYPES_H
|
|
||||||
#define __BRANCHTYPES_H
|
|
||||||
|
|
||||||
#ifndef _7ZIP_BYTE_DEFINED
|
|
||||||
#define _7ZIP_BYTE_DEFINED
|
|
||||||
typedef unsigned char Byte;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _7ZIP_UINT16_DEFINED
|
|
||||||
#define _7ZIP_UINT16_DEFINED
|
|
||||||
typedef unsigned short UInt16;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _7ZIP_UINT32_DEFINED
|
|
||||||
#define _7ZIP_UINT32_DEFINED
|
|
||||||
#ifdef _LZMA_UINT32_IS_ULONG
|
|
||||||
typedef unsigned long UInt32;
|
|
||||||
#else
|
|
||||||
typedef unsigned int UInt32;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _7ZIP_UINT64_DEFINED
|
|
||||||
#define _7ZIP_UINT64_DEFINED
|
|
||||||
#ifdef _SZ_NO_INT_64
|
|
||||||
typedef unsigned long UInt64;
|
|
||||||
#else
|
|
||||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
|
||||||
typedef unsigned __int64 UInt64;
|
|
||||||
#else
|
|
||||||
typedef unsigned long long int UInt64;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* #define _LZMA_NO_SYSTEM_SIZE_T */
|
|
||||||
/* You can use it, if you don't want <stddef.h> */
|
|
||||||
|
|
||||||
#ifndef _7ZIP_SIZET_DEFINED
|
|
||||||
#define _7ZIP_SIZET_DEFINED
|
|
||||||
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
|
||||||
typedef UInt32 SizeT;
|
|
||||||
#else
|
|
||||||
#include <stddef.h>
|
|
||||||
typedef size_t SizeT;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
/* BranchX86.c */
|
|
||||||
|
|
||||||
#include "BranchX86.h"
|
|
||||||
|
|
||||||
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
|
|
||||||
|
|
||||||
const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
|
|
||||||
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
|
|
||||||
|
|
||||||
SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *prevMaskMix, int encoding)
|
|
||||||
{
|
|
||||||
SizeT bufferPos = 0, prevPosT;
|
|
||||||
UInt32 prevMask = *prevMaskMix & 0x7;
|
|
||||||
if (endPos < 5)
|
|
||||||
return 0;
|
|
||||||
nowPos += 5;
|
|
||||||
prevPosT = (SizeT)0 - 1;
|
|
||||||
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
Byte *p = buffer + bufferPos;
|
|
||||||
Byte *limit = buffer + endPos - 4;
|
|
||||||
for (; p < limit; p++)
|
|
||||||
if ((*p & 0xFE) == 0xE8)
|
|
||||||
break;
|
|
||||||
bufferPos = (SizeT)(p - buffer);
|
|
||||||
if (p >= limit)
|
|
||||||
break;
|
|
||||||
prevPosT = bufferPos - prevPosT;
|
|
||||||
if (prevPosT > 3)
|
|
||||||
prevMask = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
|
|
||||||
if (prevMask != 0)
|
|
||||||
{
|
|
||||||
Byte b = p[4 - kMaskToBitNumber[prevMask]];
|
|
||||||
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
|
|
||||||
{
|
|
||||||
prevPosT = bufferPos;
|
|
||||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
|
||||||
bufferPos++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prevPosT = bufferPos;
|
|
||||||
|
|
||||||
if (Test86MSByte(p[4]))
|
|
||||||
{
|
|
||||||
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
|
||||||
UInt32 dest;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
Byte b;
|
|
||||||
int index;
|
|
||||||
if (encoding)
|
|
||||||
dest = (nowPos + (UInt32)bufferPos) + src;
|
|
||||||
else
|
|
||||||
dest = src - (nowPos + (UInt32)bufferPos);
|
|
||||||
if (prevMask == 0)
|
|
||||||
break;
|
|
||||||
index = kMaskToBitNumber[prevMask] * 8;
|
|
||||||
b = (Byte)(dest >> (24 - index));
|
|
||||||
if (!Test86MSByte(b))
|
|
||||||
break;
|
|
||||||
src = dest ^ ((1 << (32 - index)) - 1);
|
|
||||||
}
|
|
||||||
p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
|
|
||||||
p[3] = (Byte)(dest >> 16);
|
|
||||||
p[2] = (Byte)(dest >> 8);
|
|
||||||
p[1] = (Byte)dest;
|
|
||||||
bufferPos += 5;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
|
||||||
bufferPos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prevPosT = bufferPos - prevPosT;
|
|
||||||
*prevMaskMix = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
|
||||||
return bufferPos;
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
/* BranchX86.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCHX86_H
|
|
||||||
#define __BRANCHX86_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
#define x86_Convert_Init(state) { state = 0; }
|
|
||||||
|
|
||||||
SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *state, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
// BranchX86_2.c
|
|
||||||
|
|
||||||
#include "BranchX86_2.h"
|
|
||||||
|
|
||||||
#include "../../Alloc.h"
|
|
||||||
|
|
||||||
#ifdef _LZMA_PROB32
|
|
||||||
#define CProb UInt32
|
|
||||||
#else
|
|
||||||
#define CProb UInt16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
|
|
||||||
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
|
|
||||||
|
|
||||||
#define kNumTopBits 24
|
|
||||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
|
||||||
|
|
||||||
#define kNumBitModelTotalBits 11
|
|
||||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
|
||||||
#define kNumMoveBits 5
|
|
||||||
|
|
||||||
#define RC_READ_BYTE (*Buffer++)
|
|
||||||
|
|
||||||
#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
|
|
||||||
{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
|
|
||||||
|
|
||||||
#define RC_TEST { if (Buffer == BufferLim) return BCJ2_RESULT_DATA_ERROR; }
|
|
||||||
|
|
||||||
#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
|
|
||||||
|
|
||||||
#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
|
|
||||||
|
|
||||||
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
|
|
||||||
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
|
|
||||||
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
|
|
||||||
// #define UpdateBit0(p) Range = bound; *(p) = (CProb)(*(p) + ((kBitModelTotal - *(p)) >> kNumMoveBits));
|
|
||||||
// #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) = (CProb)(*(p) - (*(p) >> kNumMoveBits));
|
|
||||||
|
|
||||||
int x86_2_Decode(
|
|
||||||
const Byte *buf0, SizeT size0,
|
|
||||||
const Byte *buf1, SizeT size1,
|
|
||||||
const Byte *buf2, SizeT size2,
|
|
||||||
const Byte *buf3, SizeT size3,
|
|
||||||
Byte *outBuf, SizeT outSize)
|
|
||||||
{
|
|
||||||
CProb p[256 + 2];
|
|
||||||
SizeT inPos = 0, outPos = 0;
|
|
||||||
|
|
||||||
const Byte *Buffer, *BufferLim;
|
|
||||||
UInt32 Range, Code;
|
|
||||||
Byte prevByte = 0;
|
|
||||||
|
|
||||||
unsigned int i;
|
|
||||||
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
RC_INIT(buf3, size3);
|
|
||||||
|
|
||||||
if (outSize == 0)
|
|
||||||
return BCJ2_RESULT_OK;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
Byte b;
|
|
||||||
CProb *prob;
|
|
||||||
UInt32 bound;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob)
|
|
||||||
prevByte = b;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UInt32 dest;
|
|
||||||
const Byte *v;
|
|
||||||
UpdateBit1(prob)
|
|
||||||
if (b == 0xE8)
|
|
||||||
{
|
|
||||||
v = buf1;
|
|
||||||
if (size1 < 4)
|
|
||||||
return BCJ2_RESULT_DATA_ERROR;
|
|
||||||
buf1 += 4;
|
|
||||||
size1 -= 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v = buf2;
|
|
||||||
if (size2 < 4)
|
|
||||||
return BCJ2_RESULT_DATA_ERROR;
|
|
||||||
buf2 += 4;
|
|
||||||
size2 -= 4;
|
|
||||||
}
|
|
||||||
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
|
|
||||||
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
|
|
||||||
outBuf[outPos++] = (Byte)dest;
|
|
||||||
if (outPos == outSize)
|
|
||||||
break;
|
|
||||||
outBuf[outPos++] = (Byte)(dest >> 8);
|
|
||||||
if (outPos == outSize)
|
|
||||||
break;
|
|
||||||
outBuf[outPos++] = (Byte)(dest >> 16);
|
|
||||||
if (outPos == outSize)
|
|
||||||
break;
|
|
||||||
outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (outPos == outSize) ? BCJ2_RESULT_OK : BCJ2_RESULT_DATA_ERROR;
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
// BranchX86_2.h
|
|
||||||
|
|
||||||
#ifndef __BRANCHX86_2_H
|
|
||||||
#define __BRANCHX86_2_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
#define BCJ2_RESULT_OK 0
|
|
||||||
#define BCJ2_RESULT_DATA_ERROR 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
Conditions:
|
|
||||||
outSize <= FullOutputSize,
|
|
||||||
where FullOutputSize is full size of output stream of x86_2 filter.
|
|
||||||
|
|
||||||
If buf0 overlaps outBuf, there are two required conditions:
|
|
||||||
1) (buf0 >= outBuf)
|
|
||||||
2) (buf0 + size0 >= outBuf + FullOutputSize).
|
|
||||||
*/
|
|
||||||
|
|
||||||
int x86_2_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);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
/* LzHash.h */
|
|
||||||
|
|
||||||
#ifndef __C_LZHASH_H
|
|
||||||
#define __C_LZHASH_H
|
|
||||||
|
|
||||||
#define kHash2Size (1 << 10)
|
|
||||||
#define kHash3Size (1 << 16)
|
|
||||||
#define kHash4Size (1 << 20)
|
|
||||||
|
|
||||||
#define kFix3HashSize (kHash2Size)
|
|
||||||
#define kFix4HashSize (kHash2Size + kHash3Size)
|
|
||||||
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
|
||||||
|
|
||||||
#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
|
|
||||||
|
|
||||||
#define HASH3_CALC { \
|
|
||||||
UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
|
|
||||||
hash2Value = temp & (kHash2Size - 1); \
|
|
||||||
hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
|
||||||
|
|
||||||
#define HASH4_CALC { \
|
|
||||||
UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
|
|
||||||
hash2Value = temp & (kHash2Size - 1); \
|
|
||||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
|
||||||
hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & p->hashMask; }
|
|
||||||
|
|
||||||
#define HASH5_CALC { \
|
|
||||||
UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
|
|
||||||
hash2Value = temp & (kHash2Size - 1); \
|
|
||||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
|
||||||
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)); \
|
|
||||||
hashValue = (hash4Value ^ (g_CrcTable[cur[4]] << 3)) & p->hashMask; \
|
|
||||||
hash4Value &= (kHash4Size - 1); }
|
|
||||||
|
|
||||||
/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ g_CrcTable[cur[2]]) & 0xFFFF; */
|
|
||||||
#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ g_CrcTable[cur[1]]) & 0xFFFF;
|
|
||||||
|
|
||||||
|
|
||||||
#define MT_HASH2_CALC \
|
|
||||||
hash2Value = (g_CrcTable[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
|
||||||
|
|
||||||
#define MT_HASH3_CALC { \
|
|
||||||
UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
|
|
||||||
hash2Value = temp & (kHash2Size - 1); \
|
|
||||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
|
||||||
|
|
||||||
#define MT_HASH4_CALC { \
|
|
||||||
UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
|
|
||||||
hash2Value = temp & (kHash2Size - 1); \
|
|
||||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
|
||||||
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & (kHash4Size - 1); }
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,584 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaDecode.c
|
|
||||||
LZMA Decoder (optimized for Speed version)
|
|
||||||
|
|
||||||
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
|
|
||||||
http://www.7-zip.org/
|
|
||||||
|
|
||||||
LZMA SDK is licensed under two licenses:
|
|
||||||
1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
2) Common Public License (CPL)
|
|
||||||
It means that you can select one of these two licenses and
|
|
||||||
follow rules of that license.
|
|
||||||
|
|
||||||
SPECIAL EXCEPTION:
|
|
||||||
Igor Pavlov, as the author of this Code, expressly permits you to
|
|
||||||
statically or dynamically link your Code (or bind by name) to the
|
|
||||||
interfaces of this file without subjecting your linked Code to the
|
|
||||||
terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LzmaDecode.h"
|
|
||||||
|
|
||||||
#define kNumTopBits 24
|
|
||||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
|
||||||
|
|
||||||
#define kNumBitModelTotalBits 11
|
|
||||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
|
||||||
#define kNumMoveBits 5
|
|
||||||
|
|
||||||
#define RC_READ_BYTE (*Buffer++)
|
|
||||||
|
|
||||||
#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
|
|
||||||
{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
|
|
||||||
#define RC_TEST { if (Buffer == BufferLim) \
|
|
||||||
{ SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
|
|
||||||
BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
|
|
||||||
|
|
||||||
#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
|
|
||||||
|
|
||||||
#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
|
|
||||||
|
|
||||||
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
|
|
||||||
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
|
|
||||||
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
|
|
||||||
|
|
||||||
#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
|
|
||||||
{ UpdateBit0(p); mi <<= 1; A0; } else \
|
|
||||||
{ UpdateBit1(p); mi = (mi + mi) + 1; A1; }
|
|
||||||
|
|
||||||
#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
|
|
||||||
|
|
||||||
#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
|
|
||||||
{ int i = numLevels; res = 1; \
|
|
||||||
do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
|
|
||||||
res -= (1 << numLevels); }
|
|
||||||
|
|
||||||
|
|
||||||
#define kNumPosBitsMax 4
|
|
||||||
#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
|
||||||
|
|
||||||
#define kLenNumLowBits 3
|
|
||||||
#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
|
||||||
#define kLenNumMidBits 3
|
|
||||||
#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
|
||||||
#define kLenNumHighBits 8
|
|
||||||
#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
|
||||||
|
|
||||||
#define LenChoice 0
|
|
||||||
#define LenChoice2 (LenChoice + 1)
|
|
||||||
#define LenLow (LenChoice2 + 1)
|
|
||||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
|
||||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
|
||||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
|
||||||
|
|
||||||
|
|
||||||
#define kNumStates 12
|
|
||||||
#define kNumLitStates 7
|
|
||||||
|
|
||||||
#define kStartPosModelIndex 4
|
|
||||||
#define kEndPosModelIndex 14
|
|
||||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
|
||||||
|
|
||||||
#define kNumPosSlotBits 6
|
|
||||||
#define kNumLenToPosStates 4
|
|
||||||
|
|
||||||
#define kNumAlignBits 4
|
|
||||||
#define kAlignTableSize (1 << kNumAlignBits)
|
|
||||||
|
|
||||||
#define kMatchMinLen 2
|
|
||||||
|
|
||||||
#define IsMatch 0
|
|
||||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define IsRepG0 (IsRep + kNumStates)
|
|
||||||
#define IsRepG1 (IsRepG0 + kNumStates)
|
|
||||||
#define IsRepG2 (IsRepG1 + kNumStates)
|
|
||||||
#define IsRep0Long (IsRepG2 + kNumStates)
|
|
||||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
|
||||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
|
||||||
#define LenCoder (Align + kAlignTableSize)
|
|
||||||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
|
||||||
#define Literal (RepLenCoder + kNumLenProbs)
|
|
||||||
|
|
||||||
#if Literal != LZMA_BASE_SIZE
|
|
||||||
StopCompilingDueBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
|
|
||||||
{
|
|
||||||
unsigned char prop0;
|
|
||||||
if (size < LZMA_PROPERTIES_SIZE)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
prop0 = propsData[0];
|
|
||||||
if (prop0 >= (9 * 5 * 5))
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
{
|
|
||||||
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
|
|
||||||
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
|
|
||||||
propsRes->lc = prop0;
|
|
||||||
/*
|
|
||||||
unsigned char remainder = (unsigned char)(prop0 / 9);
|
|
||||||
propsRes->lc = prop0 % 9;
|
|
||||||
propsRes->pb = remainder / 5;
|
|
||||||
propsRes->lp = remainder % 5;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
propsRes->DictionarySize = 0;
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
|
|
||||||
if (propsRes->DictionarySize == 0)
|
|
||||||
propsRes->DictionarySize = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define kLzmaStreamWasFinishedId (-1)
|
|
||||||
|
|
||||||
int LzmaDecode(CLzmaDecoderState *vs,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ILzmaInCallback *InCallback,
|
|
||||||
#else
|
|
||||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
|
|
||||||
#endif
|
|
||||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
|
|
||||||
{
|
|
||||||
CProb *p = vs->Probs;
|
|
||||||
SizeT nowPos = 0;
|
|
||||||
Byte previousByte = 0;
|
|
||||||
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
|
|
||||||
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
|
|
||||||
int lc = vs->Properties.lc;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
|
|
||||||
UInt32 Range = vs->Range;
|
|
||||||
UInt32 Code = vs->Code;
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
const Byte *Buffer = vs->Buffer;
|
|
||||||
const Byte *BufferLim = vs->BufferLim;
|
|
||||||
#else
|
|
||||||
const Byte *Buffer = inStream;
|
|
||||||
const Byte *BufferLim = inStream + inSize;
|
|
||||||
#endif
|
|
||||||
int state = vs->State;
|
|
||||||
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
|
|
||||||
int len = vs->RemainLen;
|
|
||||||
UInt32 globalPos = vs->GlobalPos;
|
|
||||||
UInt32 distanceLimit = vs->DistanceLimit;
|
|
||||||
|
|
||||||
Byte *dictionary = vs->Dictionary;
|
|
||||||
UInt32 dictionarySize = vs->Properties.DictionarySize;
|
|
||||||
UInt32 dictionaryPos = vs->DictionaryPos;
|
|
||||||
|
|
||||||
Byte tempDictionary[4];
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
*inSizeProcessed = 0;
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = 0;
|
|
||||||
if (len == kLzmaStreamWasFinishedId)
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
|
|
||||||
if (dictionarySize == 0)
|
|
||||||
{
|
|
||||||
dictionary = tempDictionary;
|
|
||||||
dictionarySize = 1;
|
|
||||||
tempDictionary[0] = vs->TempDictionary[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == kLzmaNeedInitId)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < numProbs; i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
rep0 = rep1 = rep2 = rep3 = 1;
|
|
||||||
state = 0;
|
|
||||||
globalPos = 0;
|
|
||||||
distanceLimit = 0;
|
|
||||||
dictionaryPos = 0;
|
|
||||||
dictionary[dictionarySize - 1] = 0;
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
RC_INIT;
|
|
||||||
#else
|
|
||||||
RC_INIT(inStream, inSize);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize)
|
|
||||||
{
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
if (dictionaryPos == 0)
|
|
||||||
previousByte = dictionary[dictionarySize - 1];
|
|
||||||
else
|
|
||||||
previousByte = dictionary[dictionaryPos - 1];
|
|
||||||
|
|
||||||
#else /* if !_LZMA_OUT_READ */
|
|
||||||
|
|
||||||
int state = 0;
|
|
||||||
UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
|
|
||||||
int len = 0;
|
|
||||||
const Byte *Buffer;
|
|
||||||
const Byte *BufferLim;
|
|
||||||
UInt32 Range;
|
|
||||||
UInt32 Code;
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
*inSizeProcessed = 0;
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = 0;
|
|
||||||
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
|
|
||||||
for (i = 0; i < numProbs; i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
RC_INIT;
|
|
||||||
#else
|
|
||||||
RC_INIT(inStream, inSize);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _LZMA_OUT_READ */
|
|
||||||
|
|
||||||
while(nowPos < outSize)
|
|
||||||
{
|
|
||||||
CProb *prob;
|
|
||||||
UInt32 bound;
|
|
||||||
int posState = (int)(
|
|
||||||
(nowPos
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
+ globalPos
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
& posStateMask);
|
|
||||||
|
|
||||||
prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
int symbol = 1;
|
|
||||||
UpdateBit0(prob)
|
|
||||||
prob = p + Literal + (LZMA_LIT_SIZE *
|
|
||||||
(((
|
|
||||||
(nowPos
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
+ globalPos
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
& literalPosMask) << lc) + (previousByte >> (8 - lc))));
|
|
||||||
|
|
||||||
if (state >= kNumLitStates)
|
|
||||||
{
|
|
||||||
int matchByte;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
matchByte = dictionary[pos];
|
|
||||||
#else
|
|
||||||
matchByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
do
|
|
||||||
{
|
|
||||||
int bit;
|
|
||||||
CProb *probLit;
|
|
||||||
matchByte <<= 1;
|
|
||||||
bit = (matchByte & 0x100);
|
|
||||||
probLit = prob + 0x100 + bit + symbol;
|
|
||||||
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
}
|
|
||||||
while (symbol < 0x100)
|
|
||||||
{
|
|
||||||
CProb *probLit = prob + symbol;
|
|
||||||
RC_GET_BIT(probLit, symbol)
|
|
||||||
}
|
|
||||||
previousByte = (Byte)symbol;
|
|
||||||
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#endif
|
|
||||||
if (state < 4) state = 0;
|
|
||||||
else if (state < 10) state -= 3;
|
|
||||||
else state -= 6;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRep + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
rep3 = rep2;
|
|
||||||
rep2 = rep1;
|
|
||||||
rep1 = rep0;
|
|
||||||
state = state < kNumLitStates ? 0 : 3;
|
|
||||||
prob = p + LenCoder;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG0 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos;
|
|
||||||
#endif
|
|
||||||
UpdateBit0(prob);
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit == 0)
|
|
||||||
#else
|
|
||||||
if (nowPos == 0)
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
|
|
||||||
state = state < kNumLitStates ? 9 : 11;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#else
|
|
||||||
previousByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UInt32 distance;
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG1 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
distance = rep1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG2 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
distance = rep2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
distance = rep3;
|
|
||||||
rep3 = rep2;
|
|
||||||
}
|
|
||||||
rep2 = rep1;
|
|
||||||
}
|
|
||||||
rep1 = rep0;
|
|
||||||
rep0 = distance;
|
|
||||||
}
|
|
||||||
state = state < kNumLitStates ? 8 : 11;
|
|
||||||
prob = p + RepLenCoder;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
int numBits, offset;
|
|
||||||
CProb *probLen = prob + LenChoice;
|
|
||||||
IfBit0(probLen)
|
|
||||||
{
|
|
||||||
UpdateBit0(probLen);
|
|
||||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
|
||||||
offset = 0;
|
|
||||||
numBits = kLenNumLowBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(probLen);
|
|
||||||
probLen = prob + LenChoice2;
|
|
||||||
IfBit0(probLen)
|
|
||||||
{
|
|
||||||
UpdateBit0(probLen);
|
|
||||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
|
||||||
offset = kLenNumLowSymbols;
|
|
||||||
numBits = kLenNumMidBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(probLen);
|
|
||||||
probLen = prob + LenHigh;
|
|
||||||
offset = kLenNumLowSymbols + kLenNumMidSymbols;
|
|
||||||
numBits = kLenNumHighBits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RangeDecoderBitTreeDecode(probLen, numBits, len);
|
|
||||||
len += offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state < 4)
|
|
||||||
{
|
|
||||||
int posSlot;
|
|
||||||
state += kNumLitStates;
|
|
||||||
prob = p + PosSlot +
|
|
||||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
|
|
||||||
kNumPosSlotBits);
|
|
||||||
RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
|
|
||||||
if (posSlot >= kStartPosModelIndex)
|
|
||||||
{
|
|
||||||
int numDirectBits = ((posSlot >> 1) - 1);
|
|
||||||
rep0 = (2 | ((UInt32)posSlot & 1));
|
|
||||||
if (posSlot < kEndPosModelIndex)
|
|
||||||
{
|
|
||||||
rep0 <<= numDirectBits;
|
|
||||||
prob = p + SpecPos + rep0 - posSlot - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numDirectBits -= kNumAlignBits;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
RC_NORMALIZE
|
|
||||||
Range >>= 1;
|
|
||||||
rep0 <<= 1;
|
|
||||||
if (Code >= Range)
|
|
||||||
{
|
|
||||||
Code -= Range;
|
|
||||||
rep0 |= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (--numDirectBits != 0);
|
|
||||||
prob = p + Align;
|
|
||||||
rep0 <<= kNumAlignBits;
|
|
||||||
numDirectBits = kNumAlignBits;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
int i = 1;
|
|
||||||
int mi = 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
CProb *prob3 = prob + mi;
|
|
||||||
RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
|
|
||||||
i <<= 1;
|
|
||||||
}
|
|
||||||
while(--numDirectBits != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rep0 = posSlot;
|
|
||||||
if (++rep0 == (UInt32)(0))
|
|
||||||
{
|
|
||||||
/* it's for stream version */
|
|
||||||
len = kLzmaStreamWasFinishedId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len += kMatchMinLen;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (rep0 > distanceLimit)
|
|
||||||
#else
|
|
||||||
if (rep0 > nowPos)
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (dictionarySize - distanceLimit > (UInt32)len)
|
|
||||||
distanceLimit += len;
|
|
||||||
else
|
|
||||||
distanceLimit = dictionarySize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#else
|
|
||||||
previousByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
len--;
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RC_NORMALIZE;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
vs->Range = Range;
|
|
||||||
vs->Code = Code;
|
|
||||||
vs->DictionaryPos = dictionaryPos;
|
|
||||||
vs->GlobalPos = globalPos + (UInt32)nowPos;
|
|
||||||
vs->DistanceLimit = distanceLimit;
|
|
||||||
vs->Reps[0] = rep0;
|
|
||||||
vs->Reps[1] = rep1;
|
|
||||||
vs->Reps[2] = rep2;
|
|
||||||
vs->Reps[3] = rep3;
|
|
||||||
vs->State = state;
|
|
||||||
vs->RemainLen = len;
|
|
||||||
vs->TempDictionary[0] = tempDictionary[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
vs->Buffer = Buffer;
|
|
||||||
vs->BufferLim = BufferLim;
|
|
||||||
#else
|
|
||||||
*inSizeProcessed = (SizeT)(Buffer - inStream);
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = nowPos;
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaDecode.h
|
|
||||||
LZMA Decoder interface
|
|
||||||
|
|
||||||
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
|
|
||||||
http://www.7-zip.org/
|
|
||||||
|
|
||||||
LZMA SDK is licensed under two licenses:
|
|
||||||
1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
2) Common Public License (CPL)
|
|
||||||
It means that you can select one of these two licenses and
|
|
||||||
follow rules of that license.
|
|
||||||
|
|
||||||
SPECIAL EXCEPTION:
|
|
||||||
Igor Pavlov, as the author of this code, expressly permits you to
|
|
||||||
statically or dynamically link your code (or bind by name) to the
|
|
||||||
interfaces of this file without subjecting your linked code to the
|
|
||||||
terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __LZMADECODE_H
|
|
||||||
#define __LZMADECODE_H
|
|
||||||
|
|
||||||
#include "LzmaTypes.h"
|
|
||||||
|
|
||||||
/* #define _LZMA_IN_CB */
|
|
||||||
/* Use callback for input data */
|
|
||||||
|
|
||||||
/* #define _LZMA_OUT_READ */
|
|
||||||
/* Use read function for output data */
|
|
||||||
|
|
||||||
/* #define _LZMA_PROB32 */
|
|
||||||
/* It can increase speed on some 32-bit CPUs,
|
|
||||||
but memory usage will be doubled in that case */
|
|
||||||
|
|
||||||
/* #define _LZMA_LOC_OPT */
|
|
||||||
/* Enable local speed optimizations inside code */
|
|
||||||
|
|
||||||
#ifdef _LZMA_PROB32
|
|
||||||
#define CProb UInt32
|
|
||||||
#else
|
|
||||||
#define CProb UInt16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LZMA_RESULT_OK 0
|
|
||||||
#define LZMA_RESULT_DATA_ERROR 1
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
typedef struct _ILzmaInCallback
|
|
||||||
{
|
|
||||||
int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
|
|
||||||
} ILzmaInCallback;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LZMA_BASE_SIZE 1846
|
|
||||||
#define LZMA_LIT_SIZE 768
|
|
||||||
|
|
||||||
#define LZMA_PROPERTIES_SIZE 5
|
|
||||||
|
|
||||||
typedef struct _CLzmaProperties
|
|
||||||
{
|
|
||||||
int lc;
|
|
||||||
int lp;
|
|
||||||
int pb;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 DictionarySize;
|
|
||||||
#endif
|
|
||||||
}CLzmaProperties;
|
|
||||||
|
|
||||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
|
|
||||||
|
|
||||||
#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
|
|
||||||
|
|
||||||
#define kLzmaNeedInitId (-2)
|
|
||||||
|
|
||||||
typedef struct _CLzmaDecoderState
|
|
||||||
{
|
|
||||||
CLzmaProperties Properties;
|
|
||||||
CProb *Probs;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
const unsigned char *Buffer;
|
|
||||||
const unsigned char *BufferLim;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
unsigned char *Dictionary;
|
|
||||||
UInt32 Range;
|
|
||||||
UInt32 Code;
|
|
||||||
UInt32 DictionaryPos;
|
|
||||||
UInt32 GlobalPos;
|
|
||||||
UInt32 DistanceLimit;
|
|
||||||
UInt32 Reps[4];
|
|
||||||
int State;
|
|
||||||
int RemainLen;
|
|
||||||
unsigned char TempDictionary[4];
|
|
||||||
#endif
|
|
||||||
} CLzmaDecoderState;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int LzmaDecode(CLzmaDecoderState *vs,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ILzmaInCallback *inCallback,
|
|
||||||
#else
|
|
||||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
|
|
||||||
#endif
|
|
||||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,712 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaDecodeSize.c
|
|
||||||
LZMA Decoder (optimized for Size version)
|
|
||||||
|
|
||||||
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
|
|
||||||
http://www.7-zip.org/
|
|
||||||
|
|
||||||
LZMA SDK is licensed under two licenses:
|
|
||||||
1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
2) Common Public License (CPL)
|
|
||||||
It means that you can select one of these two licenses and
|
|
||||||
follow rules of that license.
|
|
||||||
|
|
||||||
SPECIAL EXCEPTION:
|
|
||||||
Igor Pavlov, as the author of this code, expressly permits you to
|
|
||||||
statically or dynamically link your code (or bind by name) to the
|
|
||||||
interfaces of this file without subjecting your linked code to the
|
|
||||||
terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LzmaDecode.h"
|
|
||||||
|
|
||||||
#define kNumTopBits 24
|
|
||||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
|
||||||
|
|
||||||
#define kNumBitModelTotalBits 11
|
|
||||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
|
||||||
#define kNumMoveBits 5
|
|
||||||
|
|
||||||
typedef struct _CRangeDecoder
|
|
||||||
{
|
|
||||||
const Byte *Buffer;
|
|
||||||
const Byte *BufferLim;
|
|
||||||
UInt32 Range;
|
|
||||||
UInt32 Code;
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ILzmaInCallback *InCallback;
|
|
||||||
int Result;
|
|
||||||
#endif
|
|
||||||
int ExtraBytes;
|
|
||||||
} CRangeDecoder;
|
|
||||||
|
|
||||||
Byte RangeDecoderReadByte(CRangeDecoder *rd)
|
|
||||||
{
|
|
||||||
if (rd->Buffer == rd->BufferLim)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
SizeT size;
|
|
||||||
rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
|
|
||||||
rd->BufferLim = rd->Buffer + size;
|
|
||||||
if (size == 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
rd->ExtraBytes = 1;
|
|
||||||
return 0xFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (*rd->Buffer++);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #define ReadByte (*rd->Buffer++) */
|
|
||||||
#define ReadByte (RangeDecoderReadByte(rd))
|
|
||||||
|
|
||||||
void RangeDecoderInit(CRangeDecoder *rd
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
, const Byte *stream, SizeT bufferSize
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
rd->Buffer = rd->BufferLim = 0;
|
|
||||||
#else
|
|
||||||
rd->Buffer = stream;
|
|
||||||
rd->BufferLim = stream + bufferSize;
|
|
||||||
#endif
|
|
||||||
rd->ExtraBytes = 0;
|
|
||||||
rd->Code = 0;
|
|
||||||
rd->Range = (0xFFFFFFFF);
|
|
||||||
for(i = 0; i < 5; i++)
|
|
||||||
rd->Code = (rd->Code << 8) | ReadByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
|
|
||||||
#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
|
|
||||||
#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
|
|
||||||
|
|
||||||
UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
|
|
||||||
{
|
|
||||||
RC_INIT_VAR
|
|
||||||
UInt32 result = 0;
|
|
||||||
int i;
|
|
||||||
for (i = numTotalBits; i != 0; i--)
|
|
||||||
{
|
|
||||||
/* UInt32 t; */
|
|
||||||
range >>= 1;
|
|
||||||
|
|
||||||
result <<= 1;
|
|
||||||
if (code >= range)
|
|
||||||
{
|
|
||||||
code -= range;
|
|
||||||
result |= 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
t = (code - range) >> 31;
|
|
||||||
t &= 1;
|
|
||||||
code -= range & (t - 1);
|
|
||||||
result = (result + result) | (1 - t);
|
|
||||||
*/
|
|
||||||
RC_NORMALIZE
|
|
||||||
}
|
|
||||||
RC_FLUSH_VAR
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
|
|
||||||
{
|
|
||||||
UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
|
|
||||||
if (rd->Code < bound)
|
|
||||||
{
|
|
||||||
rd->Range = bound;
|
|
||||||
*prob += (kBitModelTotal - *prob) >> kNumMoveBits;
|
|
||||||
if (rd->Range < kTopValue)
|
|
||||||
{
|
|
||||||
rd->Code = (rd->Code << 8) | ReadByte;
|
|
||||||
rd->Range <<= 8;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rd->Range -= bound;
|
|
||||||
rd->Code -= bound;
|
|
||||||
*prob -= (*prob) >> kNumMoveBits;
|
|
||||||
if (rd->Range < kTopValue)
|
|
||||||
{
|
|
||||||
rd->Code = (rd->Code << 8) | ReadByte;
|
|
||||||
rd->Range <<= 8;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RC_GET_BIT2(prob, mi, A0, A1) \
|
|
||||||
UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
|
|
||||||
if (code < bound) \
|
|
||||||
{ A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
|
|
||||||
else \
|
|
||||||
{ A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
|
|
||||||
RC_NORMALIZE
|
|
||||||
|
|
||||||
#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
|
|
||||||
|
|
||||||
int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
|
|
||||||
{
|
|
||||||
int mi = 1;
|
|
||||||
int i;
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_INIT_VAR
|
|
||||||
#endif
|
|
||||||
for(i = numLevels; i != 0; i--)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
CProb *prob = probs + mi;
|
|
||||||
RC_GET_BIT(prob, mi)
|
|
||||||
#else
|
|
||||||
mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_FLUSH_VAR
|
|
||||||
#endif
|
|
||||||
return mi - (1 << numLevels);
|
|
||||||
}
|
|
||||||
|
|
||||||
int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
|
|
||||||
{
|
|
||||||
int mi = 1;
|
|
||||||
int i;
|
|
||||||
int symbol = 0;
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_INIT_VAR
|
|
||||||
#endif
|
|
||||||
for(i = 0; i < numLevels; i++)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
CProb *prob = probs + mi;
|
|
||||||
RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
|
|
||||||
#else
|
|
||||||
int bit = RangeDecoderBitDecode(probs + mi, rd);
|
|
||||||
mi = mi + mi + bit;
|
|
||||||
symbol |= (bit << i);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_FLUSH_VAR
|
|
||||||
#endif
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
|
|
||||||
{
|
|
||||||
int symbol = 1;
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_INIT_VAR
|
|
||||||
#endif
|
|
||||||
do
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
CProb *prob = probs + symbol;
|
|
||||||
RC_GET_BIT(prob, symbol)
|
|
||||||
#else
|
|
||||||
symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_FLUSH_VAR
|
|
||||||
#endif
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
|
|
||||||
{
|
|
||||||
int symbol = 1;
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_INIT_VAR
|
|
||||||
#endif
|
|
||||||
do
|
|
||||||
{
|
|
||||||
int bit;
|
|
||||||
int matchBit = (matchByte >> 7) & 1;
|
|
||||||
matchByte <<= 1;
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
{
|
|
||||||
CProb *prob = probs + 0x100 + (matchBit << 8) + symbol;
|
|
||||||
RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd);
|
|
||||||
symbol = (symbol << 1) | bit;
|
|
||||||
#endif
|
|
||||||
if (matchBit != bit)
|
|
||||||
{
|
|
||||||
while (symbol < 0x100)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
CProb *prob = probs + symbol;
|
|
||||||
RC_GET_BIT(prob, symbol)
|
|
||||||
#else
|
|
||||||
symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_FLUSH_VAR
|
|
||||||
#endif
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define kNumPosBitsMax 4
|
|
||||||
#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
|
||||||
|
|
||||||
#define kLenNumLowBits 3
|
|
||||||
#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
|
||||||
#define kLenNumMidBits 3
|
|
||||||
#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
|
||||||
#define kLenNumHighBits 8
|
|
||||||
#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
|
||||||
|
|
||||||
#define LenChoice 0
|
|
||||||
#define LenChoice2 (LenChoice + 1)
|
|
||||||
#define LenLow (LenChoice2 + 1)
|
|
||||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
|
||||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
|
||||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
|
||||||
|
|
||||||
int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
|
|
||||||
{
|
|
||||||
if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
|
|
||||||
return RangeDecoderBitTreeDecode(p + LenLow +
|
|
||||||
(posState << kLenNumLowBits), kLenNumLowBits, rd);
|
|
||||||
if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
|
|
||||||
return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
|
|
||||||
(posState << kLenNumMidBits), kLenNumMidBits, rd);
|
|
||||||
return kLenNumLowSymbols + kLenNumMidSymbols +
|
|
||||||
RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define kNumStates 12
|
|
||||||
#define kNumLitStates 7
|
|
||||||
|
|
||||||
#define kStartPosModelIndex 4
|
|
||||||
#define kEndPosModelIndex 14
|
|
||||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
|
||||||
|
|
||||||
#define kNumPosSlotBits 6
|
|
||||||
#define kNumLenToPosStates 4
|
|
||||||
|
|
||||||
#define kNumAlignBits 4
|
|
||||||
#define kAlignTableSize (1 << kNumAlignBits)
|
|
||||||
|
|
||||||
#define kMatchMinLen 2
|
|
||||||
|
|
||||||
#define IsMatch 0
|
|
||||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define IsRepG0 (IsRep + kNumStates)
|
|
||||||
#define IsRepG1 (IsRepG0 + kNumStates)
|
|
||||||
#define IsRepG2 (IsRepG1 + kNumStates)
|
|
||||||
#define IsRep0Long (IsRepG2 + kNumStates)
|
|
||||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
|
||||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
|
||||||
#define LenCoder (Align + kAlignTableSize)
|
|
||||||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
|
||||||
#define Literal (RepLenCoder + kNumLenProbs)
|
|
||||||
|
|
||||||
#if Literal != LZMA_BASE_SIZE
|
|
||||||
StopCompilingDueBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
|
|
||||||
{
|
|
||||||
unsigned char prop0;
|
|
||||||
if (size < LZMA_PROPERTIES_SIZE)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
prop0 = propsData[0];
|
|
||||||
if (prop0 >= (9 * 5 * 5))
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
{
|
|
||||||
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
|
|
||||||
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
|
|
||||||
propsRes->lc = prop0;
|
|
||||||
/*
|
|
||||||
unsigned char remainder = (unsigned char)(prop0 / 9);
|
|
||||||
propsRes->lc = prop0 % 9;
|
|
||||||
propsRes->pb = remainder / 5;
|
|
||||||
propsRes->lp = remainder % 5;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
propsRes->DictionarySize = 0;
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
|
|
||||||
if (propsRes->DictionarySize == 0)
|
|
||||||
propsRes->DictionarySize = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define kLzmaStreamWasFinishedId (-1)
|
|
||||||
|
|
||||||
int LzmaDecode(CLzmaDecoderState *vs,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ILzmaInCallback *InCallback,
|
|
||||||
#else
|
|
||||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
|
|
||||||
#endif
|
|
||||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
|
|
||||||
{
|
|
||||||
CProb *p = vs->Probs;
|
|
||||||
SizeT nowPos = 0;
|
|
||||||
Byte previousByte = 0;
|
|
||||||
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
|
|
||||||
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
|
|
||||||
int lc = vs->Properties.lc;
|
|
||||||
CRangeDecoder rd;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
|
|
||||||
int state = vs->State;
|
|
||||||
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
|
|
||||||
int len = vs->RemainLen;
|
|
||||||
UInt32 globalPos = vs->GlobalPos;
|
|
||||||
UInt32 distanceLimit = vs->DistanceLimit;
|
|
||||||
|
|
||||||
Byte *dictionary = vs->Dictionary;
|
|
||||||
UInt32 dictionarySize = vs->Properties.DictionarySize;
|
|
||||||
UInt32 dictionaryPos = vs->DictionaryPos;
|
|
||||||
|
|
||||||
Byte tempDictionary[4];
|
|
||||||
|
|
||||||
rd.Range = vs->Range;
|
|
||||||
rd.Code = vs->Code;
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
rd.InCallback = InCallback;
|
|
||||||
rd.Buffer = vs->Buffer;
|
|
||||||
rd.BufferLim = vs->BufferLim;
|
|
||||||
#else
|
|
||||||
rd.Buffer = inStream;
|
|
||||||
rd.BufferLim = inStream + inSize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
*inSizeProcessed = 0;
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = 0;
|
|
||||||
if (len == kLzmaStreamWasFinishedId)
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
|
|
||||||
if (dictionarySize == 0)
|
|
||||||
{
|
|
||||||
dictionary = tempDictionary;
|
|
||||||
dictionarySize = 1;
|
|
||||||
tempDictionary[0] = vs->TempDictionary[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == kLzmaNeedInitId)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < numProbs; i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
rep0 = rep1 = rep2 = rep3 = 1;
|
|
||||||
state = 0;
|
|
||||||
globalPos = 0;
|
|
||||||
distanceLimit = 0;
|
|
||||||
dictionaryPos = 0;
|
|
||||||
dictionary[dictionarySize - 1] = 0;
|
|
||||||
RangeDecoderInit(&rd
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
, inStream, inSize
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
if (rd.Result != LZMA_RESULT_OK)
|
|
||||||
return rd.Result;
|
|
||||||
#endif
|
|
||||||
if (rd.ExtraBytes != 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
}
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize)
|
|
||||||
{
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
if (dictionaryPos == 0)
|
|
||||||
previousByte = dictionary[dictionarySize - 1];
|
|
||||||
else
|
|
||||||
previousByte = dictionary[dictionaryPos - 1];
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
rd.Result = LZMA_RESULT_OK;
|
|
||||||
#endif
|
|
||||||
rd.ExtraBytes = 0;
|
|
||||||
|
|
||||||
#else /* if !_LZMA_OUT_READ */
|
|
||||||
|
|
||||||
int state = 0;
|
|
||||||
UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
|
|
||||||
int len = 0;
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
*inSizeProcessed = 0;
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = 0;
|
|
||||||
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
|
|
||||||
for (i = 0; i < numProbs; i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
rd.InCallback = InCallback;
|
|
||||||
#endif
|
|
||||||
RangeDecoderInit(&rd
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
, inStream, inSize
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
if (rd.Result != LZMA_RESULT_OK)
|
|
||||||
return rd.Result;
|
|
||||||
#endif
|
|
||||||
if (rd.ExtraBytes != 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
|
|
||||||
#endif /* _LZMA_OUT_READ */
|
|
||||||
|
|
||||||
|
|
||||||
while(nowPos < outSize)
|
|
||||||
{
|
|
||||||
int posState = (int)(
|
|
||||||
(nowPos
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
+ globalPos
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
& posStateMask);
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
if (rd.Result != LZMA_RESULT_OK)
|
|
||||||
return rd.Result;
|
|
||||||
#endif
|
|
||||||
if (rd.ExtraBytes != 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
|
|
||||||
{
|
|
||||||
CProb *probs = p + Literal + (LZMA_LIT_SIZE *
|
|
||||||
(((
|
|
||||||
(nowPos
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
+ globalPos
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
& literalPosMask) << lc) + (previousByte >> (8 - lc))));
|
|
||||||
|
|
||||||
if (state >= kNumLitStates)
|
|
||||||
{
|
|
||||||
Byte matchByte;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
matchByte = dictionary[pos];
|
|
||||||
#else
|
|
||||||
matchByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
previousByte = LzmaLiteralDecode(probs, &rd);
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#endif
|
|
||||||
if (state < 4) state = 0;
|
|
||||||
else if (state < 10) state -= 3;
|
|
||||||
else state -= 6;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
|
|
||||||
{
|
|
||||||
if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
|
|
||||||
{
|
|
||||||
if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit == 0)
|
|
||||||
#else
|
|
||||||
if (nowPos == 0)
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
|
|
||||||
state = state < 7 ? 9 : 11;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#else
|
|
||||||
previousByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
#endif
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UInt32 distance;
|
|
||||||
if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
|
|
||||||
distance = rep1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
|
|
||||||
distance = rep2;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
distance = rep3;
|
|
||||||
rep3 = rep2;
|
|
||||||
}
|
|
||||||
rep2 = rep1;
|
|
||||||
}
|
|
||||||
rep1 = rep0;
|
|
||||||
rep0 = distance;
|
|
||||||
}
|
|
||||||
len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
|
|
||||||
state = state < 7 ? 8 : 11;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int posSlot;
|
|
||||||
rep3 = rep2;
|
|
||||||
rep2 = rep1;
|
|
||||||
rep1 = rep0;
|
|
||||||
state = state < 7 ? 7 : 10;
|
|
||||||
len = LzmaLenDecode(p + LenCoder, &rd, posState);
|
|
||||||
posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
|
|
||||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
|
|
||||||
kNumPosSlotBits), kNumPosSlotBits, &rd);
|
|
||||||
if (posSlot >= kStartPosModelIndex)
|
|
||||||
{
|
|
||||||
int numDirectBits = ((posSlot >> 1) - 1);
|
|
||||||
rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
|
|
||||||
if (posSlot < kEndPosModelIndex)
|
|
||||||
{
|
|
||||||
rep0 += RangeDecoderReverseBitTreeDecode(
|
|
||||||
p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rep0 += RangeDecoderDecodeDirectBits(&rd,
|
|
||||||
numDirectBits - kNumAlignBits) << kNumAlignBits;
|
|
||||||
rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rep0 = posSlot;
|
|
||||||
if (++rep0 == (UInt32)(0))
|
|
||||||
{
|
|
||||||
/* it's for stream version */
|
|
||||||
len = kLzmaStreamWasFinishedId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len += kMatchMinLen;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (rep0 > distanceLimit)
|
|
||||||
#else
|
|
||||||
if (rep0 > nowPos)
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (dictionarySize - distanceLimit > (UInt32)len)
|
|
||||||
distanceLimit += len;
|
|
||||||
else
|
|
||||||
distanceLimit = dictionarySize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#else
|
|
||||||
previousByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
len--;
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
vs->Range = rd.Range;
|
|
||||||
vs->Code = rd.Code;
|
|
||||||
vs->DictionaryPos = dictionaryPos;
|
|
||||||
vs->GlobalPos = globalPos + (UInt32)nowPos;
|
|
||||||
vs->DistanceLimit = distanceLimit;
|
|
||||||
vs->Reps[0] = rep0;
|
|
||||||
vs->Reps[1] = rep1;
|
|
||||||
vs->Reps[2] = rep2;
|
|
||||||
vs->Reps[3] = rep3;
|
|
||||||
vs->State = state;
|
|
||||||
vs->RemainLen = len;
|
|
||||||
vs->TempDictionary[0] = tempDictionary[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
vs->Buffer = rd.Buffer;
|
|
||||||
vs->BufferLim = rd.BufferLim;
|
|
||||||
#else
|
|
||||||
*inSizeProcessed = (SizeT)(rd.Buffer - inStream);
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = nowPos;
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
@@ -1,521 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaStateDecode.c
|
|
||||||
LZMA Decoder (State version)
|
|
||||||
|
|
||||||
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
|
|
||||||
http://www.7-zip.org/
|
|
||||||
|
|
||||||
LZMA SDK is licensed under two licenses:
|
|
||||||
1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
2) Common Public License (CPL)
|
|
||||||
It means that you can select one of these two licenses and
|
|
||||||
follow rules of that license.
|
|
||||||
|
|
||||||
SPECIAL EXCEPTION:
|
|
||||||
Igor Pavlov, as the author of this Code, expressly permits you to
|
|
||||||
statically or dynamically link your Code (or bind by name) to the
|
|
||||||
interfaces of this file without subjecting your linked Code to the
|
|
||||||
terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LzmaStateDecode.h"
|
|
||||||
|
|
||||||
#define kNumTopBits 24
|
|
||||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
|
||||||
|
|
||||||
#define kNumBitModelTotalBits 11
|
|
||||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
|
||||||
#define kNumMoveBits 5
|
|
||||||
|
|
||||||
#define RC_READ_BYTE (*Buffer++)
|
|
||||||
|
|
||||||
#define RC_INIT Code = 0; Range = 0xFFFFFFFF; \
|
|
||||||
{ int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }}
|
|
||||||
|
|
||||||
#define RC_NORMALIZE if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
|
|
||||||
|
|
||||||
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
|
|
||||||
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
|
|
||||||
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
|
|
||||||
|
|
||||||
#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
|
|
||||||
{ UpdateBit0(p); mi <<= 1; A0; } else \
|
|
||||||
{ UpdateBit1(p); mi = (mi + mi) + 1; A1; }
|
|
||||||
|
|
||||||
#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
|
|
||||||
|
|
||||||
#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
|
|
||||||
{ int i = numLevels; res = 1; \
|
|
||||||
do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
|
|
||||||
res -= (1 << numLevels); }
|
|
||||||
|
|
||||||
|
|
||||||
#define kNumPosBitsMax 4
|
|
||||||
#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
|
||||||
|
|
||||||
#define kLenNumLowBits 3
|
|
||||||
#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
|
||||||
#define kLenNumMidBits 3
|
|
||||||
#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
|
||||||
#define kLenNumHighBits 8
|
|
||||||
#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
|
||||||
|
|
||||||
#define LenChoice 0
|
|
||||||
#define LenChoice2 (LenChoice + 1)
|
|
||||||
#define LenLow (LenChoice2 + 1)
|
|
||||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
|
||||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
|
||||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
|
||||||
|
|
||||||
|
|
||||||
#define kNumStates 12
|
|
||||||
#define kNumLitStates 7
|
|
||||||
|
|
||||||
#define kStartPosModelIndex 4
|
|
||||||
#define kEndPosModelIndex 14
|
|
||||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
|
||||||
|
|
||||||
#define kNumPosSlotBits 6
|
|
||||||
#define kNumLenToPosStates 4
|
|
||||||
|
|
||||||
#define kNumAlignBits 4
|
|
||||||
#define kAlignTableSize (1 << kNumAlignBits)
|
|
||||||
|
|
||||||
#define kMatchMinLen 2
|
|
||||||
|
|
||||||
#define IsMatch 0
|
|
||||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define IsRepG0 (IsRep + kNumStates)
|
|
||||||
#define IsRepG1 (IsRepG0 + kNumStates)
|
|
||||||
#define IsRepG2 (IsRepG1 + kNumStates)
|
|
||||||
#define IsRep0Long (IsRepG2 + kNumStates)
|
|
||||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
|
||||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
|
||||||
#define LenCoder (Align + kAlignTableSize)
|
|
||||||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
|
||||||
#define Literal (RepLenCoder + kNumLenProbs)
|
|
||||||
|
|
||||||
#if Literal != LZMA_BASE_SIZE
|
|
||||||
StopCompilingDueBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* kRequiredInBufferSize = number of required input bytes for worst case:
|
|
||||||
longest match with longest distance.
|
|
||||||
kLzmaInBufferSize must be larger than kRequiredInBufferSize
|
|
||||||
23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8)
|
|
||||||
|
|
||||||
#define kLzmaStreamWasFinishedId (-1)
|
|
||||||
|
|
||||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
|
|
||||||
{
|
|
||||||
unsigned char prop0;
|
|
||||||
if (size < LZMA_PROPERTIES_SIZE)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
prop0 = propsData[0];
|
|
||||||
if (prop0 >= (9 * 5 * 5))
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
{
|
|
||||||
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
|
|
||||||
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
|
|
||||||
propsRes->lc = prop0;
|
|
||||||
/*
|
|
||||||
unsigned char remainder = (unsigned char)(prop0 / 9);
|
|
||||||
propsRes->lc = prop0 % 9;
|
|
||||||
propsRes->pb = remainder / 5;
|
|
||||||
propsRes->lp = remainder % 5;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
propsRes->DictionarySize = 0;
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
|
|
||||||
if (propsRes->DictionarySize == 0)
|
|
||||||
propsRes->DictionarySize = 1;
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int LzmaDecode(
|
|
||||||
CLzmaDecoderState *vs,
|
|
||||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
|
|
||||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
|
|
||||||
int finishDecoding)
|
|
||||||
{
|
|
||||||
UInt32 Range = vs->Range;
|
|
||||||
UInt32 Code = vs->Code;
|
|
||||||
|
|
||||||
unsigned char *Buffer = vs->Buffer;
|
|
||||||
int BufferSize = vs->BufferSize; /* don't change it to unsigned int */
|
|
||||||
CProb *p = vs->Probs;
|
|
||||||
|
|
||||||
int state = vs->State;
|
|
||||||
unsigned char previousByte;
|
|
||||||
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
|
|
||||||
SizeT nowPos = 0;
|
|
||||||
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
|
|
||||||
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
|
|
||||||
int lc = vs->Properties.lc;
|
|
||||||
int len = vs->RemainLen;
|
|
||||||
UInt32 globalPos = vs->GlobalPos;
|
|
||||||
UInt32 distanceLimit = vs->DistanceLimit;
|
|
||||||
|
|
||||||
unsigned char *dictionary = vs->Dictionary;
|
|
||||||
UInt32 dictionarySize = vs->Properties.DictionarySize;
|
|
||||||
UInt32 dictionaryPos = vs->DictionaryPos;
|
|
||||||
|
|
||||||
unsigned char tempDictionary[4];
|
|
||||||
|
|
||||||
(*inSizeProcessed) = 0;
|
|
||||||
(*outSizeProcessed) = 0;
|
|
||||||
if (len == kLzmaStreamWasFinishedId)
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
|
|
||||||
if (dictionarySize == 0)
|
|
||||||
{
|
|
||||||
dictionary = tempDictionary;
|
|
||||||
dictionarySize = 1;
|
|
||||||
tempDictionary[0] = vs->TempDictionary[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == kLzmaNeedInitId)
|
|
||||||
{
|
|
||||||
while (inSize > 0 && BufferSize < kLzmaInBufferSize)
|
|
||||||
{
|
|
||||||
Buffer[BufferSize++] = *inStream++;
|
|
||||||
(*inSizeProcessed)++;
|
|
||||||
inSize--;
|
|
||||||
}
|
|
||||||
if (BufferSize < 5)
|
|
||||||
{
|
|
||||||
vs->BufferSize = BufferSize;
|
|
||||||
return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < numProbs; i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
rep0 = rep1 = rep2 = rep3 = 1;
|
|
||||||
state = 0;
|
|
||||||
globalPos = 0;
|
|
||||||
distanceLimit = 0;
|
|
||||||
dictionaryPos = 0;
|
|
||||||
dictionary[dictionarySize - 1] = 0;
|
|
||||||
RC_INIT;
|
|
||||||
}
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize)
|
|
||||||
{
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
if (dictionaryPos == 0)
|
|
||||||
previousByte = dictionary[dictionarySize - 1];
|
|
||||||
else
|
|
||||||
previousByte = dictionary[dictionaryPos - 1];
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
int bufferPos = (int)(Buffer - vs->Buffer);
|
|
||||||
if (BufferSize - bufferPos < kRequiredInBufferSize)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
BufferSize -= bufferPos;
|
|
||||||
if (BufferSize < 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
for (i = 0; i < BufferSize; i++)
|
|
||||||
vs->Buffer[i] = Buffer[i];
|
|
||||||
Buffer = vs->Buffer;
|
|
||||||
while (inSize > 0 && BufferSize < kLzmaInBufferSize)
|
|
||||||
{
|
|
||||||
Buffer[BufferSize++] = *inStream++;
|
|
||||||
(*inSizeProcessed)++;
|
|
||||||
inSize--;
|
|
||||||
}
|
|
||||||
if (BufferSize < kRequiredInBufferSize && !finishDecoding)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (nowPos >= outSize)
|
|
||||||
break;
|
|
||||||
{
|
|
||||||
CProb *prob;
|
|
||||||
UInt32 bound;
|
|
||||||
int posState = (int)((nowPos + globalPos) & posStateMask);
|
|
||||||
|
|
||||||
prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
int symbol = 1;
|
|
||||||
UpdateBit0(prob)
|
|
||||||
prob = p + Literal + (LZMA_LIT_SIZE *
|
|
||||||
((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc))));
|
|
||||||
|
|
||||||
if (state >= kNumLitStates)
|
|
||||||
{
|
|
||||||
int matchByte;
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
matchByte = dictionary[pos];
|
|
||||||
do
|
|
||||||
{
|
|
||||||
int bit;
|
|
||||||
CProb *probLit;
|
|
||||||
matchByte <<= 1;
|
|
||||||
bit = (matchByte & 0x100);
|
|
||||||
probLit = prob + 0x100 + bit + symbol;
|
|
||||||
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
}
|
|
||||||
while (symbol < 0x100)
|
|
||||||
{
|
|
||||||
CProb *probLit = prob + symbol;
|
|
||||||
RC_GET_BIT(probLit, symbol)
|
|
||||||
}
|
|
||||||
previousByte = (unsigned char)symbol;
|
|
||||||
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
if (state < 4) state = 0;
|
|
||||||
else if (state < 10) state -= 3;
|
|
||||||
else state -= 6;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRep + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
rep3 = rep2;
|
|
||||||
rep2 = rep1;
|
|
||||||
rep1 = rep0;
|
|
||||||
state = state < kNumLitStates ? 0 : 3;
|
|
||||||
prob = p + LenCoder;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG0 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UInt32 pos;
|
|
||||||
UpdateBit0(prob);
|
|
||||||
if (distanceLimit == 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
state = state < kNumLitStates ? 9 : 11;
|
|
||||||
pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UInt32 distance;
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG1 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
distance = rep1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG2 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
distance = rep2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
distance = rep3;
|
|
||||||
rep3 = rep2;
|
|
||||||
}
|
|
||||||
rep2 = rep1;
|
|
||||||
}
|
|
||||||
rep1 = rep0;
|
|
||||||
rep0 = distance;
|
|
||||||
}
|
|
||||||
state = state < kNumLitStates ? 8 : 11;
|
|
||||||
prob = p + RepLenCoder;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
int numBits, offset;
|
|
||||||
CProb *probLen = prob + LenChoice;
|
|
||||||
IfBit0(probLen)
|
|
||||||
{
|
|
||||||
UpdateBit0(probLen);
|
|
||||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
|
||||||
offset = 0;
|
|
||||||
numBits = kLenNumLowBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(probLen);
|
|
||||||
probLen = prob + LenChoice2;
|
|
||||||
IfBit0(probLen)
|
|
||||||
{
|
|
||||||
UpdateBit0(probLen);
|
|
||||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
|
||||||
offset = kLenNumLowSymbols;
|
|
||||||
numBits = kLenNumMidBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(probLen);
|
|
||||||
probLen = prob + LenHigh;
|
|
||||||
offset = kLenNumLowSymbols + kLenNumMidSymbols;
|
|
||||||
numBits = kLenNumHighBits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RangeDecoderBitTreeDecode(probLen, numBits, len);
|
|
||||||
len += offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state < 4)
|
|
||||||
{
|
|
||||||
int posSlot;
|
|
||||||
state += kNumLitStates;
|
|
||||||
prob = p + PosSlot +
|
|
||||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
|
|
||||||
kNumPosSlotBits);
|
|
||||||
RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
|
|
||||||
if (posSlot >= kStartPosModelIndex)
|
|
||||||
{
|
|
||||||
int numDirectBits = ((posSlot >> 1) - 1);
|
|
||||||
rep0 = (2 | ((UInt32)posSlot & 1));
|
|
||||||
if (posSlot < kEndPosModelIndex)
|
|
||||||
{
|
|
||||||
rep0 <<= numDirectBits;
|
|
||||||
prob = p + SpecPos + rep0 - posSlot - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numDirectBits -= kNumAlignBits;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
RC_NORMALIZE
|
|
||||||
Range >>= 1;
|
|
||||||
rep0 <<= 1;
|
|
||||||
if (Code >= Range)
|
|
||||||
{
|
|
||||||
Code -= Range;
|
|
||||||
rep0 |= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (--numDirectBits != 0);
|
|
||||||
prob = p + Align;
|
|
||||||
rep0 <<= kNumAlignBits;
|
|
||||||
numDirectBits = kNumAlignBits;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
int i = 1;
|
|
||||||
int mi = 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
CProb *prob3 = prob + mi;
|
|
||||||
RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
|
|
||||||
i <<= 1;
|
|
||||||
}
|
|
||||||
while(--numDirectBits != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rep0 = posSlot;
|
|
||||||
if (++rep0 == (UInt32)(0))
|
|
||||||
{
|
|
||||||
/* it's for stream version */
|
|
||||||
len = kLzmaStreamWasFinishedId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len += kMatchMinLen;
|
|
||||||
if (rep0 > distanceLimit)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
if (dictionarySize - distanceLimit > (UInt32)len)
|
|
||||||
distanceLimit += len;
|
|
||||||
else
|
|
||||||
distanceLimit = dictionarySize;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
len--;
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RC_NORMALIZE;
|
|
||||||
|
|
||||||
BufferSize -= (int)(Buffer - vs->Buffer);
|
|
||||||
if (BufferSize < 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < BufferSize; i++)
|
|
||||||
vs->Buffer[i] = Buffer[i];
|
|
||||||
}
|
|
||||||
vs->BufferSize = BufferSize;
|
|
||||||
vs->Range = Range;
|
|
||||||
vs->Code = Code;
|
|
||||||
vs->DictionaryPos = dictionaryPos;
|
|
||||||
vs->GlobalPos = (UInt32)(globalPos + nowPos);
|
|
||||||
vs->DistanceLimit = distanceLimit;
|
|
||||||
vs->Reps[0] = rep0;
|
|
||||||
vs->Reps[1] = rep1;
|
|
||||||
vs->Reps[2] = rep2;
|
|
||||||
vs->Reps[3] = rep3;
|
|
||||||
vs->State = state;
|
|
||||||
vs->RemainLen = len;
|
|
||||||
vs->TempDictionary[0] = tempDictionary[0];
|
|
||||||
|
|
||||||
(*outSizeProcessed) = nowPos;
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaStateDecode.h
|
|
||||||
LZMA Decoder interface (State version)
|
|
||||||
|
|
||||||
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
|
|
||||||
http://www.7-zip.org/
|
|
||||||
|
|
||||||
LZMA SDK is licensed under two licenses:
|
|
||||||
1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
2) Common Public License (CPL)
|
|
||||||
It means that you can select one of these two licenses and
|
|
||||||
follow rules of that license.
|
|
||||||
|
|
||||||
SPECIAL EXCEPTION:
|
|
||||||
Igor Pavlov, as the author of this code, expressly permits you to
|
|
||||||
statically or dynamically link your code (or bind by name) to the
|
|
||||||
interfaces of this file without subjecting your linked code to the
|
|
||||||
terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __LZMASTATEDECODE_H
|
|
||||||
#define __LZMASTATEDECODE_H
|
|
||||||
|
|
||||||
#include "LzmaTypes.h"
|
|
||||||
|
|
||||||
/* #define _LZMA_PROB32 */
|
|
||||||
/* It can increase speed on some 32-bit CPUs,
|
|
||||||
but memory usage will be doubled in that case */
|
|
||||||
|
|
||||||
#ifdef _LZMA_PROB32
|
|
||||||
#define CProb UInt32
|
|
||||||
#else
|
|
||||||
#define CProb UInt16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LZMA_RESULT_OK 0
|
|
||||||
#define LZMA_RESULT_DATA_ERROR 1
|
|
||||||
|
|
||||||
#define LZMA_BASE_SIZE 1846
|
|
||||||
#define LZMA_LIT_SIZE 768
|
|
||||||
|
|
||||||
#define LZMA_PROPERTIES_SIZE 5
|
|
||||||
|
|
||||||
typedef struct _CLzmaProperties
|
|
||||||
{
|
|
||||||
int lc;
|
|
||||||
int lp;
|
|
||||||
int pb;
|
|
||||||
UInt32 DictionarySize;
|
|
||||||
}CLzmaProperties;
|
|
||||||
|
|
||||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
|
|
||||||
|
|
||||||
#define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp)))
|
|
||||||
|
|
||||||
#define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */
|
|
||||||
|
|
||||||
#define kLzmaNeedInitId (-2)
|
|
||||||
|
|
||||||
typedef struct _CLzmaDecoderState
|
|
||||||
{
|
|
||||||
CLzmaProperties Properties;
|
|
||||||
CProb *Probs;
|
|
||||||
unsigned char *Dictionary;
|
|
||||||
|
|
||||||
unsigned char Buffer[kLzmaInBufferSize];
|
|
||||||
int BufferSize;
|
|
||||||
|
|
||||||
UInt32 Range;
|
|
||||||
UInt32 Code;
|
|
||||||
UInt32 DictionaryPos;
|
|
||||||
UInt32 GlobalPos;
|
|
||||||
UInt32 DistanceLimit;
|
|
||||||
UInt32 Reps[4];
|
|
||||||
int State;
|
|
||||||
int RemainLen; /* -2: decoder needs internal initialization
|
|
||||||
-1: stream was finished,
|
|
||||||
0: ok
|
|
||||||
> 0: need to write RemainLen bytes as match Reps[0],
|
|
||||||
*/
|
|
||||||
unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */
|
|
||||||
} CLzmaDecoderState;
|
|
||||||
|
|
||||||
#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; }
|
|
||||||
|
|
||||||
/* LzmaDecode: decoding from input stream to output stream.
|
|
||||||
If finishDecoding != 0, then there are no more bytes in input stream
|
|
||||||
after inStream[inSize - 1]. */
|
|
||||||
|
|
||||||
int LzmaDecode(CLzmaDecoderState *vs,
|
|
||||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
|
|
||||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
|
|
||||||
int finishDecoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaStateTest.c
|
|
||||||
Test application for LZMA Decoder (State version)
|
|
||||||
|
|
||||||
This file written and distributed to public domain by Igor Pavlov.
|
|
||||||
This file is part of LZMA SDK 4.26 (2005-08-02)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "LzmaStateDecode.h"
|
|
||||||
|
|
||||||
const char *kCantReadMessage = "Can not read input file";
|
|
||||||
const char *kCantWriteMessage = "Can not write output file";
|
|
||||||
const char *kCantAllocateMessage = "Can not allocate memory";
|
|
||||||
|
|
||||||
#define kInBufferSize (1 << 15)
|
|
||||||
#define kOutBufferSize (1 << 15)
|
|
||||||
|
|
||||||
unsigned char g_InBuffer[kInBufferSize];
|
|
||||||
unsigned char g_OutBuffer[kOutBufferSize];
|
|
||||||
|
|
||||||
size_t MyReadFile(FILE *file, void *data, size_t size)
|
|
||||||
{ return fread(data, 1, size, file); }
|
|
||||||
|
|
||||||
int MyReadFileAndCheck(FILE *file, void *data, size_t size)
|
|
||||||
{ return (MyReadFile(file, data, size) == size); }
|
|
||||||
|
|
||||||
int PrintError(char *buffer, const char *message)
|
|
||||||
{
|
|
||||||
sprintf(buffer + strlen(buffer), "\nError: ");
|
|
||||||
sprintf(buffer + strlen(buffer), message);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main3(FILE *inFile, FILE *outFile, char *rs)
|
|
||||||
{
|
|
||||||
/* We use two 32-bit integers to construct 64-bit integer for file size.
|
|
||||||
You can remove outSizeHigh, if you don't need >= 4GB supporting,
|
|
||||||
or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
|
|
||||||
UInt32 outSize = 0;
|
|
||||||
UInt32 outSizeHigh = 0;
|
|
||||||
|
|
||||||
int waitEOS = 1;
|
|
||||||
/* waitEOS = 1, if there is no uncompressed size in headers,
|
|
||||||
so decoder will wait EOS (End of Stream Marker) in compressed stream */
|
|
||||||
|
|
||||||
int i;
|
|
||||||
int res = 0;
|
|
||||||
CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */
|
|
||||||
unsigned char properties[LZMA_PROPERTIES_SIZE];
|
|
||||||
SizeT inAvail = 0;
|
|
||||||
unsigned char *inBuffer = 0;
|
|
||||||
|
|
||||||
if (sizeof(UInt32) < 4)
|
|
||||||
return PrintError(rs, "LZMA decoder needs correct UInt32");
|
|
||||||
|
|
||||||
/* Read LZMA properties for compressed stream */
|
|
||||||
|
|
||||||
if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
|
|
||||||
return PrintError(rs, kCantReadMessage);
|
|
||||||
|
|
||||||
/* Read uncompressed size */
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
unsigned char b;
|
|
||||||
if (!MyReadFileAndCheck(inFile, &b, 1))
|
|
||||||
return PrintError(rs, kCantReadMessage);
|
|
||||||
if (b != 0xFF)
|
|
||||||
waitEOS = 0;
|
|
||||||
if (i < 4)
|
|
||||||
outSize += (UInt32)(b) << (i * 8);
|
|
||||||
else
|
|
||||||
outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode LZMA properties and allocate memory */
|
|
||||||
|
|
||||||
if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
|
|
||||||
return PrintError(rs, "Incorrect stream properties");
|
|
||||||
state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
|
|
||||||
if (state.Probs == 0)
|
|
||||||
return PrintError(rs, kCantAllocateMessage);
|
|
||||||
|
|
||||||
if (state.Properties.DictionarySize == 0)
|
|
||||||
state.Dictionary = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
|
|
||||||
if (state.Dictionary == 0)
|
|
||||||
{
|
|
||||||
free(state.Probs);
|
|
||||||
return PrintError(rs, kCantAllocateMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decompress */
|
|
||||||
|
|
||||||
LzmaDecoderInit(&state);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
SizeT inProcessed, outProcessed;
|
|
||||||
int finishDecoding;
|
|
||||||
UInt32 outAvail = kOutBufferSize;
|
|
||||||
if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
|
|
||||||
outAvail = outSize;
|
|
||||||
if (inAvail == 0)
|
|
||||||
{
|
|
||||||
inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize);
|
|
||||||
inBuffer = g_InBuffer;
|
|
||||||
}
|
|
||||||
finishDecoding = (inAvail == 0);
|
|
||||||
res = LzmaDecode(&state,
|
|
||||||
inBuffer, inAvail, &inProcessed,
|
|
||||||
g_OutBuffer, outAvail, &outProcessed,
|
|
||||||
finishDecoding);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
inAvail -= inProcessed;
|
|
||||||
inBuffer += inProcessed;
|
|
||||||
|
|
||||||
if (outFile != 0)
|
|
||||||
if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed)
|
|
||||||
{
|
|
||||||
PrintError(rs, kCantWriteMessage);
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outSize < outProcessed)
|
|
||||||
outSizeHigh--;
|
|
||||||
outSize -= (UInt32)outProcessed;
|
|
||||||
outSize &= 0xFFFFFFFF;
|
|
||||||
|
|
||||||
if (outProcessed == 0 && finishDecoding)
|
|
||||||
{
|
|
||||||
if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
|
|
||||||
|
|
||||||
free(state.Dictionary);
|
|
||||||
free(state.Probs);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main2(int numArgs, const char *args[], char *rs)
|
|
||||||
{
|
|
||||||
FILE *inFile = 0;
|
|
||||||
FILE *outFile = 0;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n");
|
|
||||||
if (numArgs < 2 || numArgs > 3)
|
|
||||||
{
|
|
||||||
sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inFile = fopen(args[1], "rb");
|
|
||||||
if (inFile == 0)
|
|
||||||
return PrintError(rs, "Can not open input file");
|
|
||||||
|
|
||||||
if (numArgs > 2)
|
|
||||||
{
|
|
||||||
outFile = fopen(args[2], "wb+");
|
|
||||||
if (outFile == 0)
|
|
||||||
return PrintError(rs, "Can not open output file");
|
|
||||||
}
|
|
||||||
|
|
||||||
res = main3(inFile, outFile, rs);
|
|
||||||
|
|
||||||
if (outFile != 0)
|
|
||||||
fclose(outFile);
|
|
||||||
fclose(inFile);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int numArgs, const char *args[])
|
|
||||||
{
|
|
||||||
char rs[800] = { 0 };
|
|
||||||
int res = main2(numArgs, args, rs);
|
|
||||||
printf(rs);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
@@ -1,342 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaTest.c
|
|
||||||
Test application for LZMA Decoder
|
|
||||||
|
|
||||||
This file written and distributed to public domain by Igor Pavlov.
|
|
||||||
This file is part of LZMA SDK 4.26 (2005-08-05)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "LzmaDecode.h"
|
|
||||||
|
|
||||||
const char *kCantReadMessage = "Can not read input file";
|
|
||||||
const char *kCantWriteMessage = "Can not write output file";
|
|
||||||
const char *kCantAllocateMessage = "Can not allocate memory";
|
|
||||||
|
|
||||||
size_t MyReadFile(FILE *file, void *data, size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
return fread(data, 1, size, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
int MyReadFileAndCheck(FILE *file, void *data, size_t size)
|
|
||||||
{ return (MyReadFile(file, data, size) == size);}
|
|
||||||
|
|
||||||
size_t MyWriteFile(FILE *file, const void *data, size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
return fwrite(data, 1, size, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
int MyWriteFileAndCheck(FILE *file, const void *data, size_t size)
|
|
||||||
{ return (MyWriteFile(file, data, size) == size); }
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
#define kInBufferSize (1 << 15)
|
|
||||||
typedef struct _CBuffer
|
|
||||||
{
|
|
||||||
ILzmaInCallback InCallback;
|
|
||||||
FILE *File;
|
|
||||||
unsigned char Buffer[kInBufferSize];
|
|
||||||
} CBuffer;
|
|
||||||
|
|
||||||
int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size)
|
|
||||||
{
|
|
||||||
CBuffer *b = (CBuffer *)object;
|
|
||||||
*buffer = b->Buffer;
|
|
||||||
*size = (SizeT)MyReadFile(b->File, b->Buffer, kInBufferSize);
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
CBuffer g_InBuffer;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
#define kOutBufferSize (1 << 15)
|
|
||||||
unsigned char g_OutBuffer[kOutBufferSize];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int PrintError(char *buffer, const char *message)
|
|
||||||
{
|
|
||||||
sprintf(buffer + strlen(buffer), "\nError: ");
|
|
||||||
sprintf(buffer + strlen(buffer), message);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main3(FILE *inFile, FILE *outFile, char *rs)
|
|
||||||
{
|
|
||||||
/* We use two 32-bit integers to construct 64-bit integer for file size.
|
|
||||||
You can remove outSizeHigh, if you don't need >= 4GB supporting,
|
|
||||||
or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
|
|
||||||
UInt32 outSize = 0;
|
|
||||||
UInt32 outSizeHigh = 0;
|
|
||||||
#ifndef _LZMA_OUT_READ
|
|
||||||
SizeT outSizeFull;
|
|
||||||
unsigned char *outStream;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int waitEOS = 1;
|
|
||||||
/* waitEOS = 1, if there is no uncompressed size in headers,
|
|
||||||
so decoder will wait EOS (End of Stream Marker) in compressed stream */
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
SizeT compressedSize;
|
|
||||||
unsigned char *inStream;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
|
|
||||||
unsigned char properties[LZMA_PROPERTIES_SIZE];
|
|
||||||
|
|
||||||
int res;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
g_InBuffer.File = inFile;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (sizeof(UInt32) < 4)
|
|
||||||
return PrintError(rs, "LZMA decoder needs correct UInt32");
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
{
|
|
||||||
long length;
|
|
||||||
fseek(inFile, 0, SEEK_END);
|
|
||||||
length = ftell(inFile);
|
|
||||||
fseek(inFile, 0, SEEK_SET);
|
|
||||||
if ((long)(SizeT)length != length)
|
|
||||||
return PrintError(rs, "Too big compressed stream");
|
|
||||||
compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read LZMA properties for compressed stream */
|
|
||||||
|
|
||||||
if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
|
|
||||||
return PrintError(rs, kCantReadMessage);
|
|
||||||
|
|
||||||
/* Read uncompressed size */
|
|
||||||
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
unsigned char b;
|
|
||||||
if (!MyReadFileAndCheck(inFile, &b, 1))
|
|
||||||
return PrintError(rs, kCantReadMessage);
|
|
||||||
if (b != 0xFF)
|
|
||||||
waitEOS = 0;
|
|
||||||
if (i < 4)
|
|
||||||
outSize += (UInt32)(b) << (i * 8);
|
|
||||||
else
|
|
||||||
outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef _LZMA_OUT_READ
|
|
||||||
if (waitEOS)
|
|
||||||
return PrintError(rs, "Stream with EOS marker is not supported");
|
|
||||||
outSizeFull = (SizeT)outSize;
|
|
||||||
if (sizeof(SizeT) >= 8)
|
|
||||||
outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
|
|
||||||
else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize)
|
|
||||||
return PrintError(rs, "Too big uncompressed stream");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode LZMA properties and allocate memory */
|
|
||||||
|
|
||||||
if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
|
|
||||||
return PrintError(rs, "Incorrect stream properties");
|
|
||||||
state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (state.Properties.DictionarySize == 0)
|
|
||||||
state.Dictionary = 0;
|
|
||||||
else
|
|
||||||
state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
|
|
||||||
#else
|
|
||||||
if (outSizeFull == 0)
|
|
||||||
outStream = 0;
|
|
||||||
else
|
|
||||||
outStream = (unsigned char *)malloc(outSizeFull);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
if (compressedSize == 0)
|
|
||||||
inStream = 0;
|
|
||||||
else
|
|
||||||
inStream = (unsigned char *)malloc(compressedSize);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (state.Probs == 0
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
|| (state.Dictionary == 0 && state.Properties.DictionarySize != 0)
|
|
||||||
#else
|
|
||||||
|| (outStream == 0 && outSizeFull != 0)
|
|
||||||
#endif
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
|| (inStream == 0 && compressedSize != 0)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
free(state.Probs);
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
free(state.Dictionary);
|
|
||||||
#else
|
|
||||||
free(outStream);
|
|
||||||
#endif
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
free(inStream);
|
|
||||||
#endif
|
|
||||||
return PrintError(rs, kCantAllocateMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decompress */
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
g_InBuffer.InCallback.Read = LzmaReadCompressed;
|
|
||||||
#else
|
|
||||||
if (!MyReadFileAndCheck(inFile, inStream, compressedSize))
|
|
||||||
return PrintError(rs, kCantReadMessage);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
{
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
SizeT inAvail = compressedSize;
|
|
||||||
const unsigned char *inBuffer = inStream;
|
|
||||||
#endif
|
|
||||||
LzmaDecoderInit(&state);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
SizeT inProcessed;
|
|
||||||
#endif
|
|
||||||
SizeT outProcessed;
|
|
||||||
SizeT outAvail = kOutBufferSize;
|
|
||||||
if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
|
|
||||||
outAvail = (SizeT)outSize;
|
|
||||||
res = LzmaDecode(&state,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
&g_InBuffer.InCallback,
|
|
||||||
#else
|
|
||||||
inBuffer, inAvail, &inProcessed,
|
|
||||||
#endif
|
|
||||||
g_OutBuffer, outAvail, &outProcessed);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
inAvail -= inProcessed;
|
|
||||||
inBuffer += inProcessed;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (outFile != 0)
|
|
||||||
if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed))
|
|
||||||
{
|
|
||||||
PrintError(rs, kCantWriteMessage);
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outSize < outProcessed)
|
|
||||||
outSizeHigh--;
|
|
||||||
outSize -= (UInt32)outProcessed;
|
|
||||||
outSize &= 0xFFFFFFFF;
|
|
||||||
|
|
||||||
if (outProcessed == 0)
|
|
||||||
{
|
|
||||||
if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
SizeT inProcessed;
|
|
||||||
#endif
|
|
||||||
SizeT outProcessed;
|
|
||||||
res = LzmaDecode(&state,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
&g_InBuffer.InCallback,
|
|
||||||
#else
|
|
||||||
inStream, compressedSize, &inProcessed,
|
|
||||||
#endif
|
|
||||||
outStream, outSizeFull, &outProcessed);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
|
|
||||||
res = 1;
|
|
||||||
}
|
|
||||||
else if (outFile != 0)
|
|
||||||
{
|
|
||||||
if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed))
|
|
||||||
{
|
|
||||||
PrintError(rs, kCantWriteMessage);
|
|
||||||
res = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
free(state.Probs);
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
free(state.Dictionary);
|
|
||||||
#else
|
|
||||||
free(outStream);
|
|
||||||
#endif
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
free(inStream);
|
|
||||||
#endif
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main2(int numArgs, const char *args[], char *rs)
|
|
||||||
{
|
|
||||||
FILE *inFile = 0;
|
|
||||||
FILE *outFile = 0;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n");
|
|
||||||
if (numArgs < 2 || numArgs > 3)
|
|
||||||
{
|
|
||||||
sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inFile = fopen(args[1], "rb");
|
|
||||||
if (inFile == 0)
|
|
||||||
return PrintError(rs, "Can not open input file");
|
|
||||||
|
|
||||||
if (numArgs > 2)
|
|
||||||
{
|
|
||||||
outFile = fopen(args[2], "wb+");
|
|
||||||
if (outFile == 0)
|
|
||||||
return PrintError(rs, "Can not open output file");
|
|
||||||
}
|
|
||||||
|
|
||||||
res = main3(inFile, outFile, rs);
|
|
||||||
|
|
||||||
if (outFile != 0)
|
|
||||||
fclose(outFile);
|
|
||||||
fclose(inFile);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int numArgs, const char *args[])
|
|
||||||
{
|
|
||||||
char rs[800] = { 0 };
|
|
||||||
int res = main2(numArgs, args, rs);
|
|
||||||
printf(rs);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaTypes.h
|
|
||||||
|
|
||||||
Types for LZMA Decoder
|
|
||||||
|
|
||||||
This file written and distributed to public domain by Igor Pavlov.
|
|
||||||
This file is part of LZMA SDK 4.40 (2006-05-01)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __LZMATYPES_H
|
|
||||||
#define __LZMATYPES_H
|
|
||||||
|
|
||||||
#ifndef _7ZIP_BYTE_DEFINED
|
|
||||||
#define _7ZIP_BYTE_DEFINED
|
|
||||||
typedef unsigned char Byte;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _7ZIP_UINT16_DEFINED
|
|
||||||
#define _7ZIP_UINT16_DEFINED
|
|
||||||
typedef unsigned short UInt16;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _7ZIP_UINT32_DEFINED
|
|
||||||
#define _7ZIP_UINT32_DEFINED
|
|
||||||
#ifdef _LZMA_UINT32_IS_ULONG
|
|
||||||
typedef unsigned long UInt32;
|
|
||||||
#else
|
|
||||||
typedef unsigned int UInt32;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* #define _LZMA_NO_SYSTEM_SIZE_T */
|
|
||||||
/* You can use it, if you don't want <stddef.h> */
|
|
||||||
|
|
||||||
#ifndef _7ZIP_SIZET_DEFINED
|
|
||||||
#define _7ZIP_SIZET_DEFINED
|
|
||||||
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
|
||||||
typedef UInt32 SizeT;
|
|
||||||
#else
|
|
||||||
#include <stddef.h>
|
|
||||||
typedef size_t SizeT;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
200
C/CpuArch.c
Normal file
200
C/CpuArch.c
Normal 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
|
||||||
226
C/CpuArch.h
Executable file → Normal file
226
C/CpuArch.h
Executable file → Normal file
@@ -1,18 +1,222 @@
|
|||||||
/* CpuArch.h */
|
/* CpuArch.h -- CPU specific code
|
||||||
|
2015-12-01: Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __CPUARCH_H
|
#ifndef __CPU_ARCH_H
|
||||||
#define __CPUARCH_H
|
#define __CPU_ARCH_H
|
||||||
|
|
||||||
/*
|
#include "7zTypes.h"
|
||||||
LITTLE_ENDIAN_UNALIGN means:
|
|
||||||
1) CPU is LITTLE_ENDIAN
|
EXTERN_C_BEGIN
|
||||||
2) it's allowed to make unaligned memory accesses
|
|
||||||
if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know
|
/*
|
||||||
about these properties of platform.
|
MY_CPU_LE means that CPU is LITTLE ENDIAN.
|
||||||
|
MY_CPU_BE means that CPU is BIG ENDIAN.
|
||||||
|
If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS 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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_AMD64) \
|
||||||
|
|| defined(_M_IA64) \
|
||||||
|
|| defined(__AARCH64EL__) \
|
||||||
|
|| defined(__AARCH64EB__)
|
||||||
|
#define MY_CPU_64BIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_M_IX86) || defined(__i386__)
|
||||||
|
#define MY_CPU_X86
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
|
||||||
|
#define MY_CPU_X86_OR_AMD64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_X86) \
|
||||||
|
|| defined(_M_ARM) \
|
||||||
|
|| defined(__ARMEL__) \
|
||||||
|
|| defined(__THUMBEL__) \
|
||||||
|
|| defined(__ARMEB__) \
|
||||||
|
|| defined(__THUMBEB__)
|
||||||
|
#define MY_CPU_32BIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(_M_ARM)
|
||||||
|
#define MY_CPU_ARM_LE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(_M_IA64)
|
||||||
|
#define MY_CPU_IA64_LE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||||
|
|| defined(MY_CPU_ARM_LE) \
|
||||||
|
|| defined(MY_CPU_IA64_LE) \
|
||||||
|
|| defined(__LITTLE_ENDIAN__) \
|
||||||
|
|| defined(__ARMEL__) \
|
||||||
|
|| defined(__THUMBEL__) \
|
||||||
|
|| defined(__AARCH64EL__) \
|
||||||
|
|| defined(__MIPSEL__) \
|
||||||
|
|| defined(__MIPSEL) \
|
||||||
|
|| defined(_MIPSEL) \
|
||||||
|
|| (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)
|
||||||
|
Stop_Compiling_Bad_Endian
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MY_CPU_LE
|
||||||
|
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||||
|
/* || defined(__AARCH64EL__) */
|
||||||
|
#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
|
||||||
|
|
||||||
|
#define GetUi16(p) ( (UInt16) ( \
|
||||||
|
((const Byte *)(p))[0] | \
|
||||||
|
((UInt16)((const Byte *)(p))[1] << 8) ))
|
||||||
|
|
||||||
|
#define GetUi32(p) ( \
|
||||||
|
((const Byte *)(p))[0] | \
|
||||||
|
((UInt32)((const Byte *)(p))[1] << 8) | \
|
||||||
|
((UInt32)((const Byte *)(p))[2] << 16) | \
|
||||||
|
((UInt32)((const Byte *)(p))[3] << 24))
|
||||||
|
|
||||||
|
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||||
|
|
||||||
|
#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||||
|
_ppp_[0] = (Byte)_vvv_; \
|
||||||
|
_ppp_[1] = (Byte)(_vvv_ >> 8); }
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
#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_ulong)
|
||||||
|
#pragma intrinsic(_byteswap_uint64)
|
||||||
|
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
|
||||||
|
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
|
||||||
|
|
||||||
|
#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))
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#define GetBe32(p) ( \
|
||||||
|
((UInt32)((const Byte *)(p))[0] << 24) | \
|
||||||
|
((UInt32)((const Byte *)(p))[1] << 16) | \
|
||||||
|
((UInt32)((const Byte *)(p))[2] << 8) | \
|
||||||
|
((const Byte *)(p))[3] )
|
||||||
|
|
||||||
|
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||||
|
|
||||||
|
#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||||
|
_ppp_[0] = (Byte)(_vvv_ >> 24); \
|
||||||
|
_ppp_[1] = (Byte)(_vvv_ >> 16); \
|
||||||
|
_ppp_[2] = (Byte)(_vvv_ >> 8); \
|
||||||
|
_ppp_[3] = (Byte)_vvv_; }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define GetBe16(p) ( (UInt16) ( \
|
||||||
|
((UInt16)((const Byte *)(p))[0] << 8) | \
|
||||||
|
((const Byte *)(p))[1] ))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt32 maxFunc;
|
||||||
|
UInt32 vendor[3];
|
||||||
|
UInt32 ver;
|
||||||
|
UInt32 b;
|
||||||
|
UInt32 c;
|
||||||
|
UInt32 d;
|
||||||
|
} Cx86cpuid;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CPU_FIRM_INTEL,
|
||||||
|
CPU_FIRM_AMD,
|
||||||
|
CPU_FIRM_VIA
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
/* Aes.h */
|
|
||||||
|
|
||||||
#ifndef __AES_H
|
|
||||||
#define __AES_H
|
|
||||||
|
|
||||||
#include "../Types.h"
|
|
||||||
|
|
||||||
#define AES_BLOCK_SIZE 16
|
|
||||||
|
|
||||||
typedef struct _CAes
|
|
||||||
{
|
|
||||||
unsigned numRounds2; /* = numRounds / 2 */
|
|
||||||
UInt32 rkey[(14 + 1) * 4];
|
|
||||||
} CAes;
|
|
||||||
|
|
||||||
/* Call AesGenTables one time before other AES functions */
|
|
||||||
void MY_FAST_CALL AesGenTables(void);
|
|
||||||
|
|
||||||
/* keySize = 16 or 24 or 32 */
|
|
||||||
void MY_FAST_CALL AesSetKeyEncode(CAes *p, const Byte *key, unsigned keySize);
|
|
||||||
void MY_FAST_CALL AesSetKeyDecode(CAes *p, const Byte *key, unsigned keySize);
|
|
||||||
|
|
||||||
/*
|
|
||||||
AesEncode32 and AesDecode32 functions work with little-endian words.
|
|
||||||
src and dest can contain same address
|
|
||||||
*/
|
|
||||||
void MY_FAST_CALL AesEncode32(const UInt32 *src, UInt32 *dest, const UInt32 *w, unsigned numRounds2);
|
|
||||||
void MY_FAST_CALL AesDecode32(const UInt32 *src, UInt32 *dest, const UInt32 *w, unsigned numRounds2);
|
|
||||||
|
|
||||||
typedef struct _CAesCbc
|
|
||||||
{
|
|
||||||
UInt32 prev[4];
|
|
||||||
CAes aes;
|
|
||||||
} CAesCbc;
|
|
||||||
|
|
||||||
void MY_FAST_CALL AesCbcInit(CAesCbc *cbc, const Byte *iv); /* iv size is AES_BLOCK_SIZE */
|
|
||||||
UInt32 MY_FAST_CALL AesCbcDecode(CAesCbc *cbc, Byte *data, UInt32 size);
|
|
||||||
UInt32 MY_FAST_CALL AesCbcEncode(CAesCbc *cbc, Byte *data, UInt32 size);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
64
C/Delta.c
Normal file
64
C/Delta.c
Normal 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
19
C/Delta.h
Normal 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
|
||||||
52
C/Compress/Huffman/HuffmanEncode.c → C/HuffEnc.c
Executable file → Normal file
52
C/Compress/Huffman/HuffmanEncode.c → C/HuffEnc.c
Executable file → Normal file
@@ -1,7 +1,10 @@
|
|||||||
/* Compress/HuffmanEncode.c */
|
/* HuffEnc.c -- functions for Huffman encoding
|
||||||
|
2016-05-16 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "HuffmanEncode.h"
|
#include "Precomp.h"
|
||||||
#include "../../Sort.h"
|
|
||||||
|
#include "HuffEnc.h"
|
||||||
|
#include "Sort.h"
|
||||||
|
|
||||||
#define kMaxLen 16
|
#define kMaxLen 16
|
||||||
#define NUM_BITS 10
|
#define NUM_BITS 10
|
||||||
@@ -9,7 +12,6 @@
|
|||||||
|
|
||||||
#define NUM_COUNTERS 64
|
#define NUM_COUNTERS 64
|
||||||
|
|
||||||
/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M */
|
|
||||||
#define HUFFMAN_SPEED_OPT
|
#define HUFFMAN_SPEED_OPT
|
||||||
|
|
||||||
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen)
|
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen)
|
||||||
@@ -22,22 +24,22 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
|
|||||||
#ifdef HUFFMAN_SPEED_OPT
|
#ifdef HUFFMAN_SPEED_OPT
|
||||||
|
|
||||||
UInt32 counters[NUM_COUNTERS];
|
UInt32 counters[NUM_COUNTERS];
|
||||||
for (i = 0; i < NUM_COUNTERS; i++)
|
for (i = 0; i < NUM_COUNTERS; i++)
|
||||||
counters[i] = 0;
|
counters[i] = 0;
|
||||||
for (i = 0; i < numSymbols; i++)
|
for (i = 0; i < numSymbols; i++)
|
||||||
{
|
{
|
||||||
UInt32 freq = freqs[i];
|
UInt32 freq = freqs[i];
|
||||||
counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++;
|
counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i < NUM_COUNTERS; i++)
|
for (i = 1; i < NUM_COUNTERS; i++)
|
||||||
{
|
{
|
||||||
UInt32 temp = counters[i];
|
UInt32 temp = counters[i];
|
||||||
counters[i] = num;
|
counters[i] = num;
|
||||||
num += temp;
|
num += temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < numSymbols; i++)
|
for (i = 0; i < numSymbols; i++)
|
||||||
{
|
{
|
||||||
UInt32 freq = freqs[i];
|
UInt32 freq = freqs[i];
|
||||||
if (freq == 0)
|
if (freq == 0)
|
||||||
@@ -50,7 +52,7 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
for (i = 0; i < numSymbols; i++)
|
for (i = 0; i < numSymbols; i++)
|
||||||
{
|
{
|
||||||
UInt32 freq = freqs[i];
|
UInt32 freq = freqs[i];
|
||||||
if (freq == 0)
|
if (freq == 0)
|
||||||
@@ -63,13 +65,13 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = p[0] & MASK;
|
maxCode = (unsigned)p[0] & MASK;
|
||||||
if (maxCode == 0)
|
if (maxCode == 0)
|
||||||
maxCode++;
|
maxCode++;
|
||||||
}
|
}
|
||||||
@@ -83,7 +85,7 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
|
|||||||
UInt32 b, e, i;
|
UInt32 b, e, i;
|
||||||
|
|
||||||
i = b = e = 0;
|
i = b = e = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
UInt32 n, m, freq;
|
UInt32 n, m, freq;
|
||||||
n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
|
n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
|
||||||
@@ -94,21 +96,21 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
|
|||||||
p[m] = (p[m] & MASK) | (e << NUM_BITS);
|
p[m] = (p[m] & MASK) | (e << NUM_BITS);
|
||||||
p[e] = (p[e] & MASK) | freq;
|
p[e] = (p[e] & MASK) | freq;
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
while (num - e > 1);
|
while (num - e > 1);
|
||||||
|
|
||||||
{
|
{
|
||||||
UInt32 lenCounters[kMaxLen + 1];
|
UInt32 lenCounters[kMaxLen + 1];
|
||||||
for (i = 0; i <= kMaxLen; i++)
|
for (i = 0; i <= kMaxLen; i++)
|
||||||
lenCounters[i] = 0;
|
lenCounters[i] = 0;
|
||||||
|
|
||||||
p[--e] &= MASK;
|
p[--e] &= MASK;
|
||||||
lenCounters[1] = 2;
|
lenCounters[1] = 2;
|
||||||
while (e > 0)
|
while (e > 0)
|
||||||
{
|
{
|
||||||
UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1;
|
UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1;
|
||||||
p[e] = (p[e] & MASK) | (len << NUM_BITS);
|
p[e] = (p[e] & MASK) | (len << NUM_BITS);
|
||||||
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[len + 1] += 2;
|
||||||
@@ -117,10 +119,10 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
|
|||||||
{
|
{
|
||||||
UInt32 len;
|
UInt32 len;
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,15 +132,15 @@ 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[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]]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
13
C/Compress/Huffman/HuffmanEncode.h → C/HuffEnc.h
Executable file → Normal file
13
C/Compress/Huffman/HuffmanEncode.h → C/HuffEnc.h
Executable file → Normal file
@@ -1,9 +1,12 @@
|
|||||||
/* Compress/HuffmanEncode.h */
|
/* HuffEnc.h -- Huffman encoding
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __COMPRESS_HUFFMANENCODE_H
|
#ifndef __HUFF_ENC_H
|
||||||
#define __COMPRESS_HUFFMANENCODE_H
|
#define __HUFF_ENC_H
|
||||||
|
|
||||||
#include "../../Types.h"
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Conditions:
|
Conditions:
|
||||||
@@ -15,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
|
||||||
19
C/IStream.h
19
C/IStream.h
@@ -1,19 +0,0 @@
|
|||||||
/* IStream.h */
|
|
||||||
|
|
||||||
#ifndef __C_ISTREAM_H
|
|
||||||
#define __C_ISTREAM_H
|
|
||||||
|
|
||||||
#include "Types.h"
|
|
||||||
|
|
||||||
typedef struct _ISeqInStream
|
|
||||||
{
|
|
||||||
HRes (*Read)(void *object, void *data, UInt32 size, UInt32 *processedSize);
|
|
||||||
} ISeqInStream;
|
|
||||||
|
|
||||||
typedef struct _ISzAlloc
|
|
||||||
{
|
|
||||||
void *(*Alloc)(size_t size);
|
|
||||||
void (*Free)(void *address); /* address can be 0 */
|
|
||||||
} ISzAlloc;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
646
C/Compress/Lz/MatchFinder.c → C/LzFind.c
Executable file → Normal file
646
C/Compress/Lz/MatchFinder.c → C/LzFind.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
53
C/Compress/Lz/MatchFinder.h → C/LzFind.h
Executable file → Normal file
53
C/Compress/Lz/MatchFinder.h → C/LzFind.h
Executable file → Normal file
@@ -1,9 +1,12 @@
|
|||||||
/* MatchFinder.h */
|
/* LzFind.h -- Match finder for LZ algorithms
|
||||||
|
2015-10-15 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __MATCHFINDER_H
|
#ifndef __LZ_FIND_H
|
||||||
#define __MATCHFINDER_H
|
#define __LZ_FIND_H
|
||||||
|
|
||||||
#include "../../IStream.h"
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
typedef UInt32 CLzRef;
|
typedef UInt32 CLzRef;
|
||||||
|
|
||||||
@@ -18,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;
|
||||||
@@ -26,30 +34,30 @@ 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;
|
||||||
|
UInt32 crc[256];
|
||||||
HRes result;
|
size_t numRefs;
|
||||||
} 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);
|
||||||
@@ -61,25 +69,24 @@ void MatchFinder_Construct(CMatchFinder *p);
|
|||||||
historySize <= 3 GB
|
historySize <= 3 GB
|
||||||
keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
|
keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
|
||||||
*/
|
*/
|
||||||
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);
|
ISzAlloc *alloc);
|
||||||
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
|
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *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,
|
||||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||||
UInt32 *distances, UInt32 maxLen);
|
UInt32 *distances, UInt32 maxLen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Conditions:
|
Conditions:
|
||||||
Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
|
Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
|
||||||
Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
|
Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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);
|
||||||
@@ -88,7 +95,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;
|
||||||
@@ -97,10 +103,15 @@ typedef struct _IMatchFinder
|
|||||||
|
|
||||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
||||||
|
|
||||||
|
void MatchFinder_Init_2(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
|
||||||
387
C/Compress/Lz/MatchFinderMt.c → C/LzFindMt.c
Executable file → Normal file
387
C/Compress/Lz/MatchFinderMt.c → C/LzFindMt.c
Executable file → Normal file
@@ -1,23 +1,13 @@
|
|||||||
/* MatchFinderMt.c */
|
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
|
||||||
|
2015-10-15 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifdef _WIN32
|
#include "Precomp.h"
|
||||||
#define USE_ALLOCA
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_ALLOCA
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <malloc.h>
|
|
||||||
#else
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../../7zCrc.h"
|
|
||||||
#include "LzHash.h"
|
#include "LzHash.h"
|
||||||
|
|
||||||
#include "MatchFinderMt.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;
|
||||||
@@ -30,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)
|
||||||
{
|
{
|
||||||
@@ -58,8 +48,8 @@ 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)
|
||||||
return;
|
return;
|
||||||
@@ -81,7 +71,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))
|
||||||
{
|
{
|
||||||
@@ -107,54 +97,57 @@ void MtSync_Destruct(CMtSync *p)
|
|||||||
p->wasCreated = False;
|
p->wasCreated = False;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRes MtSync_Create2(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
|
#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
|
||||||
|
|
||||||
|
static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)
|
||||||
{
|
{
|
||||||
if (p->wasCreated)
|
if (p->wasCreated)
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
|
|
||||||
RINOK(CriticalSection_Init(&p->cs));
|
RINOK_THREAD(CriticalSection_Init(&p->cs));
|
||||||
p->csWasInitialized = True;
|
p->csWasInitialized = True;
|
||||||
|
|
||||||
RINOK(AutoResetEvent_CreateNotSignaled(&p->canStart));
|
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart));
|
||||||
RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
|
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
|
||||||
RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
|
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
|
||||||
|
|
||||||
RINOK(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
|
RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
|
||||||
RINOK(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
|
RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
|
||||||
|
|
||||||
p->needStart = True;
|
p->needStart = True;
|
||||||
|
|
||||||
RINOK(Thread_Create(&p->thread, startAddress, obj));
|
RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj));
|
||||||
p->wasCreated = True;
|
p->wasCreated = True;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRes MtSync_Create(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
|
static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)
|
||||||
{
|
{
|
||||||
HRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
|
SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
|
||||||
if (res != SZ_OK)
|
if (res != SZ_OK)
|
||||||
MtSync_Destruct(p);
|
MtSync_Destruct(p);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MtSync_Init(CMtSync *p) { p->needStart = True; }
|
void MtSync_Init(CMtSync *p) { p->needStart = True; }
|
||||||
|
|
||||||
#define kMtMaxValForNormalize 0xFFFFFFFF
|
#define kMtMaxValForNormalize 0xFFFFFFFF
|
||||||
|
|
||||||
#define DEF_GetHeads(name, v) \
|
#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) { \
|
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
|
||||||
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++; } }
|
||||||
|
|
||||||
DEF_GetHeads(2, (p[0] | ((UInt32)p[1] << 8)) & hashMask)
|
#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
|
||||||
DEF_GetHeads(3, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
|
|
||||||
DEF_GetHeads(4, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5)) & hashMask)
|
|
||||||
DEF_GetHeads(4b, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
|
|
||||||
DEF_GetHeads(5, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5) ^ (g_CrcTable[p[4]] << 3)) & hashMask)
|
|
||||||
|
|
||||||
void HashThreadFunc(CMatchFinderMt *mt)
|
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(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
|
||||||
|
DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
|
||||||
|
/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
|
||||||
|
|
||||||
|
static void HashThreadFunc(CMatchFinderMt *mt)
|
||||||
{
|
{
|
||||||
CMtSync *p = &mt->hashSync;
|
CMtSync *p = &mt->hashSync;
|
||||||
for (;;)
|
for (;;)
|
||||||
@@ -180,12 +173,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);
|
||||||
@@ -199,7 +192,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;
|
||||||
@@ -211,7 +204,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
|
|||||||
num = num - mf->numHashBytes + 1;
|
num = num - mf->numHashBytes + 1;
|
||||||
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);
|
mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);
|
||||||
heads[0] += num;
|
heads[0] += num;
|
||||||
}
|
}
|
||||||
mf->pos += num;
|
mf->pos += num;
|
||||||
@@ -224,7 +217,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;
|
||||||
@@ -238,16 +231,10 @@ void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
|
|||||||
|
|
||||||
#ifdef MFMT_GM_INLINE
|
#ifdef MFMT_GM_INLINE
|
||||||
|
|
||||||
#if _MSC_VER >= 1300
|
#define NO_INLINE MY_FAST_CALL
|
||||||
#define NO_INLINE __declspec(noinline) __fastcall
|
|
||||||
#else
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define NO_INLINE __fastcall
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *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)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
@@ -275,7 +262,7 @@ Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CL
|
|||||||
if (pb[len] == cur[len])
|
if (pb[len] == cur[len])
|
||||||
{
|
{
|
||||||
if (++len != lenLimit && pb[len] == cur[len])
|
if (++len != lenLimit && pb[len] == cur[len])
|
||||||
while(++len != lenLimit)
|
while (++len != lenLimit)
|
||||||
if (pb[len] != cur[len])
|
if (pb[len] != cur[len])
|
||||||
break;
|
break;
|
||||||
if (maxLen < len)
|
if (maxLen < len)
|
||||||
@@ -323,12 +310,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)
|
||||||
@@ -337,9 +326,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;
|
||||||
@@ -356,13 +347,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++;
|
||||||
@@ -372,8 +364,8 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
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;
|
||||||
@@ -389,10 +381,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)
|
||||||
@@ -406,7 +399,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,15 +438,15 @@ 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, ISzAlloc *alloc)
|
||||||
{
|
{
|
||||||
alloc->Free(p->hashBuf);
|
alloc->Free(alloc, p->hashBuf);
|
||||||
p->hashBuf = 0;
|
p->hashBuf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
|
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
|
||||||
@@ -466,34 +459,36 @@ 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 StdCall 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 StdCall BtThreadFunc2(void *p)
|
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)
|
||||||
{
|
{
|
||||||
#ifdef USE_ALLOCA
|
Byte allocaDummy[0x180];
|
||||||
alloca(0x180);
|
unsigned i = 0;
|
||||||
#endif
|
for (i = 0; i < 16; i++)
|
||||||
BtThreadFunc((CMatchFinderMt *)p);
|
allocaDummy[i] = (Byte)0;
|
||||||
return 0;
|
if (allocaDummy[0] == 0)
|
||||||
|
BtThreadFunc((CMatchFinderMt *)p);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRes 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, ISzAlloc *alloc)
|
||||||
{
|
{
|
||||||
CMatchFinder *mf = p->MatchFinder;
|
CMatchFinder *mf = p->MatchFinder;
|
||||||
p->historySize = historySize;
|
p->historySize = historySize;
|
||||||
if (kMtBtBlockSize <= matchMaxLen * 4)
|
if (kMtBtBlockSize <= matchMaxLen * 4)
|
||||||
return E_INVALIDARG;
|
return SZ_ERROR_PARAM;
|
||||||
if (p->hashBuf == 0)
|
if (!p->hashBuf)
|
||||||
{
|
{
|
||||||
p->hashBuf = (UInt32 *)alloc->Alloc((kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
|
p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
|
||||||
if (p->hashBuf == 0)
|
if (!p->hashBuf)
|
||||||
return SZE_OUTOFMEMORY;
|
return SZ_ERROR_MEM;
|
||||||
p->btBuf = p->hashBuf + kHashBufferSize;
|
p->btBuf = p->hashBuf + kHashBufferSize;
|
||||||
}
|
}
|
||||||
keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
|
keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
|
||||||
keepAddBufferAfter += kMtHashBlockSize;
|
keepAddBufferAfter += kMtHashBlockSize;
|
||||||
if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
|
if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
|
||||||
return SZE_OUTOFMEMORY;
|
return SZ_ERROR_MEM;
|
||||||
|
|
||||||
RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));
|
RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));
|
||||||
RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));
|
RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));
|
||||||
@@ -502,17 +497,21 @@ HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
|
|||||||
|
|
||||||
/* Call it after ReleaseStream / SetStream */
|
/* Call it after ReleaseStream / SetStream */
|
||||||
void MatchFinderMt_Init(CMatchFinderMt *p)
|
void MatchFinderMt_Init(CMatchFinderMt *p)
|
||||||
{
|
{
|
||||||
CMatchFinder *mf = p->MatchFinder;
|
CMatchFinder *mf = p->MatchFinder;
|
||||||
p->btBufPos = p->btBufPosLimit = 0;
|
p->btBufPos = p->btBufPosLimit = 0;
|
||||||
p->hashBufPos = p->hashBufPosLimit = 0;
|
p->hashBufPos = p->hashBufPosLimit = 0;
|
||||||
MatchFinder_Init(mf);
|
|
||||||
p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
|
/* Init without data reading. We don't want to read data in this thread */
|
||||||
|
MatchFinder_Init_2(mf, False);
|
||||||
|
|
||||||
|
p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf);
|
||||||
p->btNumAvailBytes = 0;
|
p->btNumAvailBytes = 0;
|
||||||
p->lzPos = p->historySize + 1;
|
p->lzPos = p->historySize + 1;
|
||||||
|
|
||||||
p->hash = mf->hash;
|
p->hash = mf->hash;
|
||||||
p->fixedHashSize = mf->fixedHashSize;
|
p->fixedHashSize = mf->fixedHashSize;
|
||||||
|
p->crc = mf->crc;
|
||||||
|
|
||||||
p->son = mf->son;
|
p->son = mf->son;
|
||||||
p->matchMaxLen = mf->matchMaxLen;
|
p->matchMaxLen = mf->matchMaxLen;
|
||||||
@@ -526,18 +525,18 @@ void MatchFinderMt_Init(CMatchFinderMt *p)
|
|||||||
|
|
||||||
/* ReleaseStream is required to finish multithreading */
|
/* ReleaseStream is required to finish multithreading */
|
||||||
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
|
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
|
||||||
{
|
{
|
||||||
MtSync_StopWriting(&p->btSync);
|
MtSync_StopWriting(&p->btSync);
|
||||||
/* 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);
|
||||||
@@ -545,111 +544,108 @@ void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
|
|||||||
p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;
|
p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;
|
||||||
p->btBufPosLimit += p->btBuf[p->btBufPos++];
|
p->btBufPosLimit += p->btBuf[p->btBufPos++];
|
||||||
p->btNumAvailBytes = p->btBuf[p->btBufPos++];
|
p->btNumAvailBytes = p->btBuf[p->btBufPos++];
|
||||||
if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)
|
if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)
|
||||||
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 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
|
||||||
{
|
{
|
||||||
UInt32 hash2Value, curMatch2;
|
UInt32 h2, 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])
|
||||||
{
|
{
|
||||||
*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])
|
|
||||||
{
|
|
||||||
distances[1] = lzPos - curMatch2 - 1;
|
|
||||||
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
|
|
||||||
{
|
|
||||||
distances[0] = 3;
|
|
||||||
return distances + 2;
|
|
||||||
}
|
|
||||||
distances[0] = 2;
|
|
||||||
distances += 2;
|
|
||||||
}
|
|
||||||
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
|
||||||
{
|
|
||||||
*distances++ = 3;
|
|
||||||
*distances++ = lzPos - curMatch3 - 1;
|
|
||||||
}
|
|
||||||
return distances;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
|
||||||
{
|
|
||||||
UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
|
|
||||||
UInt32 *hash = p->hash;
|
|
||||||
const Byte *cur = p->pointerToCurPos;
|
|
||||||
UInt32 lzPos = p->lzPos;
|
|
||||||
MT_HASH4_CALC
|
|
||||||
|
|
||||||
curMatch2 = hash[ hash2Value];
|
|
||||||
curMatch3 = hash[kFix3HashSize + hash3Value];
|
|
||||||
curMatch4 = hash[kFix4HashSize + hash4Value];
|
|
||||||
|
|
||||||
hash[ hash2Value] =
|
|
||||||
hash[kFix3HashSize + hash3Value] =
|
|
||||||
hash[kFix4HashSize + hash4Value] =
|
|
||||||
lzPos;
|
|
||||||
|
|
||||||
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
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] = 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])
|
||||||
|
{
|
||||||
|
*distances++ = 3;
|
||||||
|
*distances++ = lzPos - curMatch3 - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return distances;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||||
|
{
|
||||||
|
UInt32 h2, h3, h4, curMatch2, curMatch3, curMatch4;
|
||||||
|
UInt32 *hash = p->hash;
|
||||||
|
const Byte *cur = p->pointerToCurPos;
|
||||||
|
UInt32 lzPos = p->lzPos;
|
||||||
|
MT_HASH4_CALC
|
||||||
|
|
||||||
|
curMatch2 = hash[ h2];
|
||||||
|
curMatch3 = hash[kFix3HashSize + h3];
|
||||||
|
curMatch4 = hash[kFix4HashSize + h4];
|
||||||
|
|
||||||
|
hash[ h2] = lzPos;
|
||||||
|
hash[kFix3HashSize + h3] = lzPos;
|
||||||
|
hash[kFix4HashSize + h4] = lzPos;
|
||||||
|
|
||||||
|
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||||
|
{
|
||||||
|
distances[1] = lzPos - curMatch2 - 1;
|
||||||
|
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
|
||||||
|
{
|
||||||
|
distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
|
||||||
|
return distances + 2;
|
||||||
|
}
|
||||||
|
distances[0] = 2;
|
||||||
|
distances += 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
||||||
{
|
{
|
||||||
distances[1] = lzPos - curMatch3 - 1;
|
distances[1] = lzPos - curMatch3 - 1;
|
||||||
@@ -671,14 +667,15 @@ 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++;
|
||||||
p->btBufPos += 1 + len;
|
p->btBufPos += 1 + len;
|
||||||
@@ -695,15 +692,16 @@ UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||||||
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++;
|
||||||
p->btBufPos += 1 + len;
|
p->btBufPos += 1 + len;
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
{
|
{
|
||||||
if (p->btNumAvailBytes-- >= 4)
|
/* change for bt5 ! */
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -712,70 +710,70 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||||||
UInt32 *distances2;
|
UInt32 *distances2;
|
||||||
p->btNumAvailBytes--;
|
p->btNumAvailBytes--;
|
||||||
distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
|
distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
*distances2++ = *btBuf++;
|
*distances2++ = *btBuf++;
|
||||||
*distances2++ = *btBuf++;
|
*distances2++ = *btBuf++;
|
||||||
}
|
}
|
||||||
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;
|
||||||
@@ -791,7 +789,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;
|
||||||
22
C/Compress/Lz/MatchFinderMt.h → C/LzFindMt.h
Executable file → Normal file
22
C/Compress/Lz/MatchFinderMt.h → C/LzFindMt.h
Executable file → Normal file
@@ -1,10 +1,13 @@
|
|||||||
/* MatchFinderMt.h */
|
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
|
||||||
|
2015-05-03 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __MATCHFINDERMT_H
|
#ifndef __LZ_FIND_MT_H
|
||||||
#define __MATCHFINDERMT_H
|
#define __LZ_FIND_MT_H
|
||||||
|
|
||||||
#include "../../Threads.h"
|
#include "LzFind.h"
|
||||||
#include "MatchFinder.h"
|
#include "Threads.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
#define kMtHashBlockSize (1 << 13)
|
#define kMtHashBlockSize (1 << 13)
|
||||||
#define kMtHashNumBlocks (1 << 3)
|
#define kMtHashNumBlocks (1 << 3)
|
||||||
@@ -39,7 +42,7 @@ typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distance
|
|||||||
#define kMtCacheLineDummy 128
|
#define kMtCacheLineDummy 128
|
||||||
|
|
||||||
typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
|
typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
|
||||||
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads);
|
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);
|
||||||
|
|
||||||
typedef struct _CMatchFinderMt
|
typedef struct _CMatchFinderMt
|
||||||
{
|
{
|
||||||
@@ -54,6 +57,7 @@ typedef struct _CMatchFinderMt
|
|||||||
UInt32 *hash;
|
UInt32 *hash;
|
||||||
UInt32 fixedHashSize;
|
UInt32 fixedHashSize;
|
||||||
UInt32 historySize;
|
UInt32 historySize;
|
||||||
|
const UInt32 *crc;
|
||||||
|
|
||||||
Mf_Mix_Matches MixMatchesFunc;
|
Mf_Mix_Matches MixMatchesFunc;
|
||||||
|
|
||||||
@@ -71,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;
|
||||||
@@ -87,9 +91,11 @@ typedef struct _CMatchFinderMt
|
|||||||
|
|
||||||
void MatchFinderMt_Construct(CMatchFinderMt *p);
|
void MatchFinderMt_Construct(CMatchFinderMt *p);
|
||||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);
|
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);
|
||||||
HRes 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, ISzAlloc *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
|
||||||
57
C/LzHash.h
Normal file
57
C/LzHash.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/* LzHash.h -- HASH functions for LZ algorithms
|
||||||
|
2015-04-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZ_HASH_H
|
||||||
|
#define __LZ_HASH_H
|
||||||
|
|
||||||
|
#define kHash2Size (1 << 10)
|
||||||
|
#define kHash3Size (1 << 16)
|
||||||
|
#define kHash4Size (1 << 20)
|
||||||
|
|
||||||
|
#define kFix3HashSize (kHash2Size)
|
||||||
|
#define kFix4HashSize (kHash2Size + kHash3Size)
|
||||||
|
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
||||||
|
|
||||||
|
#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);
|
||||||
|
|
||||||
|
#define HASH3_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
h2 = temp & (kHash2Size - 1); \
|
||||||
|
hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
||||||
|
|
||||||
|
#define HASH4_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
h2 = temp & (kHash2Size - 1); \
|
||||||
|
temp ^= ((UInt32)cur[2] << 8); \
|
||||||
|
h3 = temp & (kHash3Size - 1); \
|
||||||
|
hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
|
||||||
|
|
||||||
|
#define HASH5_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
h2 = temp & (kHash2Size - 1); \
|
||||||
|
temp ^= ((UInt32)cur[2] << 8); \
|
||||||
|
h3 = temp & (kHash3Size - 1); \
|
||||||
|
temp ^= (p->crc[cur[3]] << 5); \
|
||||||
|
h4 = temp & (kHash4Size - 1); \
|
||||||
|
hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }
|
||||||
|
|
||||||
|
/* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
|
||||||
|
#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||||
|
|
||||||
|
|
||||||
|
#define MT_HASH2_CALC \
|
||||||
|
h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
||||||
|
|
||||||
|
#define MT_HASH3_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
h2 = temp & (kHash2Size - 1); \
|
||||||
|
h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
||||||
|
|
||||||
|
#define MT_HASH4_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
h2 = temp & (kHash2Size - 1); \
|
||||||
|
temp ^= ((UInt32)cur[2] << 8); \
|
||||||
|
h3 = temp & (kHash3Size - 1); \
|
||||||
|
h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
|
||||||
|
|
||||||
|
#endif
|
||||||
378
C/Lzma2Dec.c
Normal file
378
C/Lzma2Dec.c
Normal file
@@ -0,0 +1,378 @@
|
|||||||
|
/* Lzma2Dec.c -- LZMA2 Decoder
|
||||||
|
2015-11-09 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
/* #define SHOW_DEBUG_INFO */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#ifdef SHOW_DEBUG_INFO
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Lzma2Dec.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
00000000 - EOS
|
||||||
|
00000001 U U - Uncompressed Reset Dic
|
||||||
|
00000010 U U - Uncompressed No Reset
|
||||||
|
100uuuuu U U P P - LZMA no reset
|
||||||
|
101uuuuu U U P P - LZMA reset state
|
||||||
|
110uuuuu U U P P S - LZMA reset state + new prop
|
||||||
|
111uuuuu U U P P S - LZMA reset state + new prop + reset dic
|
||||||
|
|
||||||
|
u, U - Unpack Size
|
||||||
|
P - Pack Size
|
||||||
|
S - Props
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LZMA2_CONTROL_LZMA (1 << 7)
|
||||||
|
#define LZMA2_CONTROL_COPY_NO_RESET 2
|
||||||
|
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
||||||
|
#define LZMA2_CONTROL_EOF 0
|
||||||
|
|
||||||
|
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
|
||||||
|
|
||||||
|
#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
|
||||||
|
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
|
||||||
|
|
||||||
|
#define LZMA2_LCLP_MAX 4
|
||||||
|
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||||
|
|
||||||
|
#ifdef SHOW_DEBUG_INFO
|
||||||
|
#define PRF(x) x
|
||||||
|
#else
|
||||||
|
#define PRF(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
LZMA2_STATE_CONTROL,
|
||||||
|
LZMA2_STATE_UNPACK0,
|
||||||
|
LZMA2_STATE_UNPACK1,
|
||||||
|
LZMA2_STATE_PACK0,
|
||||||
|
LZMA2_STATE_PACK1,
|
||||||
|
LZMA2_STATE_PROP,
|
||||||
|
LZMA2_STATE_DATA,
|
||||||
|
LZMA2_STATE_DATA_CONT,
|
||||||
|
LZMA2_STATE_FINISHED,
|
||||||
|
LZMA2_STATE_ERROR
|
||||||
|
} ELzma2State;
|
||||||
|
|
||||||
|
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
|
||||||
|
{
|
||||||
|
UInt32 dicSize;
|
||||||
|
if (prop > 40)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
||||||
|
props[0] = (Byte)LZMA2_LCLP_MAX;
|
||||||
|
props[1] = (Byte)(dicSize);
|
||||||
|
props[2] = (Byte)(dicSize >> 8);
|
||||||
|
props[3] = (Byte)(dicSize >> 16);
|
||||||
|
props[4] = (Byte)(dicSize >> 24);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
|
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||||
|
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
|
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||||
|
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lzma2Dec_Init(CLzma2Dec *p)
|
||||||
|
{
|
||||||
|
p->state = LZMA2_STATE_CONTROL;
|
||||||
|
p->needInitDic = True;
|
||||||
|
p->needInitState = True;
|
||||||
|
p->needInitProp = True;
|
||||||
|
LzmaDec_Init(&p->decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||||
|
{
|
||||||
|
switch (p->state)
|
||||||
|
{
|
||||||
|
case LZMA2_STATE_CONTROL:
|
||||||
|
p->control = b;
|
||||||
|
PRF(printf("\n %4X ", (unsigned)p->decoder.dicPos));
|
||||||
|
PRF(printf(" %2X", (unsigned)b));
|
||||||
|
if (p->control == 0)
|
||||||
|
return LZMA2_STATE_FINISHED;
|
||||||
|
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||||
|
{
|
||||||
|
if ((p->control & 0x7F) > 2)
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
p->unpackSize = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
|
||||||
|
return LZMA2_STATE_UNPACK0;
|
||||||
|
|
||||||
|
case LZMA2_STATE_UNPACK0:
|
||||||
|
p->unpackSize |= (UInt32)b << 8;
|
||||||
|
return LZMA2_STATE_UNPACK1;
|
||||||
|
|
||||||
|
case LZMA2_STATE_UNPACK1:
|
||||||
|
p->unpackSize |= (UInt32)b;
|
||||||
|
p->unpackSize++;
|
||||||
|
PRF(printf(" %8u", (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++;
|
||||||
|
PRF(printf(" %8u", (unsigned)p->packSize));
|
||||||
|
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
|
||||||
|
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
|
||||||
|
|
||||||
|
case LZMA2_STATE_PROP:
|
||||||
|
{
|
||||||
|
unsigned lc, lp;
|
||||||
|
if (b >= (9 * 5 * 5))
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
lc = b % 9;
|
||||||
|
b /= 9;
|
||||||
|
p->decoder.prop.pb = b / 5;
|
||||||
|
lp = b % 5;
|
||||||
|
if (lc + lp > LZMA2_LCLP_MAX)
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
p->decoder.prop.lc = lc;
|
||||||
|
p->decoder.prop.lp = lp;
|
||||||
|
p->needInitProp = False;
|
||||||
|
return LZMA2_STATE_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
|
||||||
|
{
|
||||||
|
memcpy(p->dic + p->dicPos, src, size);
|
||||||
|
p->dicPos += size;
|
||||||
|
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
|
||||||
|
p->checkDicSize = p->prop.dicSize;
|
||||||
|
p->processedPos += (UInt32)size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||||
|
{
|
||||||
|
SizeT inSize = *srcLen;
|
||||||
|
*srcLen = 0;
|
||||||
|
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||||
|
|
||||||
|
while (p->state != LZMA2_STATE_FINISHED)
|
||||||
|
{
|
||||||
|
SizeT dicPos = p->decoder.dicPos;
|
||||||
|
|
||||||
|
if (p->state == LZMA2_STATE_ERROR)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
|
||||||
|
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
||||||
|
{
|
||||||
|
*status = LZMA_STATUS_NOT_FINISHED;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||||
|
{
|
||||||
|
if (*srcLen == inSize)
|
||||||
|
{
|
||||||
|
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
(*srcLen)++;
|
||||||
|
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||||
|
|
||||||
|
if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
|
||||||
|
{
|
||||||
|
p->state = LZMA2_STATE_ERROR;
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SizeT destSizeCur = dicLimit - dicPos;
|
||||||
|
SizeT srcSizeCur = inSize - *srcLen;
|
||||||
|
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
|
||||||
|
|
||||||
|
if (p->unpackSize <= destSizeCur)
|
||||||
|
{
|
||||||
|
destSizeCur = (SizeT)p->unpackSize;
|
||||||
|
curFinishMode = LZMA_FINISH_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||||
|
{
|
||||||
|
if (*srcLen == inSize)
|
||||||
|
{
|
||||||
|
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->state == LZMA2_STATE_DATA)
|
||||||
|
{
|
||||||
|
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
|
||||||
|
if (initDic)
|
||||||
|
p->needInitProp = p->needInitState = True;
|
||||||
|
else if (p->needInitDic)
|
||||||
|
{
|
||||||
|
p->state = LZMA2_STATE_ERROR;
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
}
|
||||||
|
p->needInitDic = False;
|
||||||
|
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcSizeCur > destSizeCur)
|
||||||
|
srcSizeCur = destSizeCur;
|
||||||
|
|
||||||
|
if (srcSizeCur == 0)
|
||||||
|
{
|
||||||
|
p->state = LZMA2_STATE_ERROR;
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
|
||||||
|
|
||||||
|
src += srcSizeCur;
|
||||||
|
*srcLen += srcSizeCur;
|
||||||
|
p->unpackSize -= (UInt32)srcSizeCur;
|
||||||
|
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SizeT outSizeProcessed;
|
||||||
|
SRes res;
|
||||||
|
|
||||||
|
if (p->state == LZMA2_STATE_DATA)
|
||||||
|
{
|
||||||
|
unsigned mode = LZMA2_GET_LZMA_MODE(p);
|
||||||
|
Bool initDic = (mode == 3);
|
||||||
|
Bool initState = (mode != 0);
|
||||||
|
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
|
||||||
|
{
|
||||||
|
p->state = LZMA2_STATE_ERROR;
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||||
|
p->needInitDic = False;
|
||||||
|
p->needInitState = False;
|
||||||
|
p->state = LZMA2_STATE_DATA_CONT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcSizeCur > p->packSize)
|
||||||
|
srcSizeCur = (SizeT)p->packSize;
|
||||||
|
|
||||||
|
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||||
|
|
||||||
|
src += srcSizeCur;
|
||||||
|
*srcLen += srcSizeCur;
|
||||||
|
p->packSize -= (UInt32)srcSizeCur;
|
||||||
|
|
||||||
|
outSizeProcessed = p->decoder.dicPos - dicPos;
|
||||||
|
p->unpackSize -= (UInt32)outSizeProcessed;
|
||||||
|
|
||||||
|
RINOK(res);
|
||||||
|
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (srcSizeCur == 0 && outSizeProcessed == 0)
|
||||||
|
{
|
||||||
|
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||||
|
|| p->unpackSize != 0
|
||||||
|
|| p->packSize != 0)
|
||||||
|
{
|
||||||
|
p->state = LZMA2_STATE_ERROR;
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
}
|
||||||
|
p->state = LZMA2_STATE_CONTROL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||||
|
*status = LZMA_STATUS_NOT_FINISHED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||||
|
{
|
||||||
|
SizeT outSize = *destLen, inSize = *srcLen;
|
||||||
|
*srcLen = *destLen = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
SizeT srcSizeCur = inSize, outSizeCur, dicPos;
|
||||||
|
ELzmaFinishMode curFinishMode;
|
||||||
|
SRes res;
|
||||||
|
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
||||||
|
p->decoder.dicPos = 0;
|
||||||
|
dicPos = p->decoder.dicPos;
|
||||||
|
if (outSize > p->decoder.dicBufSize - dicPos)
|
||||||
|
{
|
||||||
|
outSizeCur = p->decoder.dicBufSize;
|
||||||
|
curFinishMode = LZMA_FINISH_ANY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outSizeCur = dicPos + outSize;
|
||||||
|
curFinishMode = finishMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||||
|
src += srcSizeCur;
|
||||||
|
inSize -= srcSizeCur;
|
||||||
|
*srcLen += srcSizeCur;
|
||||||
|
outSizeCur = p->decoder.dicPos - dicPos;
|
||||||
|
memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
|
||||||
|
dest += outSizeCur;
|
||||||
|
outSize -= outSizeCur;
|
||||||
|
*destLen += outSizeCur;
|
||||||
|
if (res != 0)
|
||||||
|
return res;
|
||||||
|
if (outSizeCur == 0 || outSize == 0)
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
CLzma2Dec p;
|
||||||
|
SRes res;
|
||||||
|
SizeT outSize = *destLen, inSize = *srcLen;
|
||||||
|
*destLen = *srcLen = 0;
|
||||||
|
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||||
|
Lzma2Dec_Construct(&p);
|
||||||
|
RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
|
||||||
|
p.decoder.dic = dest;
|
||||||
|
p.decoder.dicBufSize = outSize;
|
||||||
|
Lzma2Dec_Init(&p);
|
||||||
|
*srcLen = inSize;
|
||||||
|
res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
|
||||||
|
*destLen = p.decoder.dicPos;
|
||||||
|
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||||
|
res = SZ_ERROR_INPUT_EOF;
|
||||||
|
Lzma2Dec_FreeProbs(&p, alloc);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
80
C/Lzma2Dec.h
Normal file
80
C/Lzma2Dec.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/* Lzma2Dec.h -- LZMA2 Decoder
|
||||||
|
2015-05-13 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA2_DEC_H
|
||||||
|
#define __LZMA2_DEC_H
|
||||||
|
|
||||||
|
#include "LzmaDec.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
/* ---------- State Interface ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CLzmaDec decoder;
|
||||||
|
UInt32 packSize;
|
||||||
|
UInt32 unpackSize;
|
||||||
|
unsigned state;
|
||||||
|
Byte control;
|
||||||
|
Bool needInitDic;
|
||||||
|
Bool needInitState;
|
||||||
|
Bool needInitProp;
|
||||||
|
} CLzma2Dec;
|
||||||
|
|
||||||
|
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
|
||||||
|
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
|
||||||
|
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
|
||||||
|
|
||||||
|
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
|
||||||
|
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
|
||||||
|
void Lzma2Dec_Init(CLzma2Dec *p);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
finishMode:
|
||||||
|
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
|
||||||
|
LZMA_FINISH_ANY - use smallest number of input bytes
|
||||||
|
LZMA_FINISH_END - read EndOfStream marker after decoding
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
SZ_OK
|
||||||
|
status:
|
||||||
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
|
LZMA_STATUS_NOT_FINISHED
|
||||||
|
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||||
|
SZ_ERROR_DATA - Data error
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
finishMode:
|
||||||
|
It has meaning only if the decoding reaches output limit (*destLen).
|
||||||
|
LZMA_FINISH_ANY - use smallest number of input bytes
|
||||||
|
LZMA_FINISH_END - read EndOfStream marker after decoding
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
SZ_OK
|
||||||
|
status:
|
||||||
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
|
LZMA_STATUS_NOT_FINISHED
|
||||||
|
SZ_ERROR_DATA - Data error
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||||
|
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
||||||
520
C/Lzma2Enc.c
Normal file
520
C/Lzma2Enc.c
Normal file
@@ -0,0 +1,520 @@
|
|||||||
|
/* Lzma2Enc.c -- LZMA2 Encoder
|
||||||
|
2015-10-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
/* #include <stdio.h> */
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* #define _7ZIP_ST */
|
||||||
|
|
||||||
|
#include "Lzma2Enc.h"
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
#include "MtCoder.h"
|
||||||
|
#else
|
||||||
|
#define NUM_MT_CODER_THREADS_MAX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LZMA2_CONTROL_LZMA (1 << 7)
|
||||||
|
#define LZMA2_CONTROL_COPY_NO_RESET 2
|
||||||
|
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
||||||
|
#define LZMA2_CONTROL_EOF 0
|
||||||
|
|
||||||
|
#define LZMA2_LCLP_MAX 4
|
||||||
|
|
||||||
|
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||||
|
|
||||||
|
#define LZMA2_PACK_SIZE_MAX (1 << 16)
|
||||||
|
#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX
|
||||||
|
#define LZMA2_UNPACK_SIZE_MAX (1 << 21)
|
||||||
|
#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX
|
||||||
|
|
||||||
|
#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16)
|
||||||
|
|
||||||
|
|
||||||
|
#define PRF(x) /* x */
|
||||||
|
|
||||||
|
/* ---------- CLzma2EncInt ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CLzmaEncHandle enc;
|
||||||
|
UInt64 srcPos;
|
||||||
|
Byte props;
|
||||||
|
Bool needInitState;
|
||||||
|
Bool needInitProp;
|
||||||
|
} CLzma2EncInt;
|
||||||
|
|
||||||
|
static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props)
|
||||||
|
{
|
||||||
|
Byte propsEncoded[LZMA_PROPS_SIZE];
|
||||||
|
SizeT propsSize = LZMA_PROPS_SIZE;
|
||||||
|
RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
|
||||||
|
RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
|
||||||
|
p->srcPos = 0;
|
||||||
|
p->props = propsEncoded[0];
|
||||||
|
p->needInitState = True;
|
||||||
|
p->needInitProp = True;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
|
||||||
|
ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
|
||||||
|
UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
|
||||||
|
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
|
||||||
|
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
|
||||||
|
void LzmaEnc_Finish(CLzmaEncHandle pp);
|
||||||
|
void LzmaEnc_SaveState(CLzmaEncHandle pp);
|
||||||
|
void LzmaEnc_RestoreState(CLzmaEncHandle pp);
|
||||||
|
|
||||||
|
|
||||||
|
static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
|
||||||
|
size_t *packSizeRes, ISeqOutStream *outStream)
|
||||||
|
{
|
||||||
|
size_t packSizeLimit = *packSizeRes;
|
||||||
|
size_t packSize = packSizeLimit;
|
||||||
|
UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
|
||||||
|
unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
|
||||||
|
Bool useCopyBlock;
|
||||||
|
SRes res;
|
||||||
|
|
||||||
|
*packSizeRes = 0;
|
||||||
|
if (packSize < lzHeaderSize)
|
||||||
|
return SZ_ERROR_OUTPUT_EOF;
|
||||||
|
packSize -= lzHeaderSize;
|
||||||
|
|
||||||
|
LzmaEnc_SaveState(p->enc);
|
||||||
|
res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,
|
||||||
|
outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);
|
||||||
|
|
||||||
|
PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize));
|
||||||
|
|
||||||
|
if (unpackSize == 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (res != SZ_ERROR_OUTPUT_EOF)
|
||||||
|
return res;
|
||||||
|
res = SZ_OK;
|
||||||
|
useCopyBlock = True;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useCopyBlock)
|
||||||
|
{
|
||||||
|
size_t destPos = 0;
|
||||||
|
PRF(printf("################# COPY "));
|
||||||
|
|
||||||
|
while (unpackSize > 0)
|
||||||
|
{
|
||||||
|
UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
|
||||||
|
if (packSizeLimit - destPos < u + 3)
|
||||||
|
return SZ_ERROR_OUTPUT_EOF;
|
||||||
|
outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);
|
||||||
|
outBuf[destPos++] = (Byte)((u - 1) >> 8);
|
||||||
|
outBuf[destPos++] = (Byte)(u - 1);
|
||||||
|
memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);
|
||||||
|
unpackSize -= u;
|
||||||
|
destPos += u;
|
||||||
|
p->srcPos += u;
|
||||||
|
|
||||||
|
if (outStream)
|
||||||
|
{
|
||||||
|
*packSizeRes += destPos;
|
||||||
|
if (outStream->Write(outStream, outBuf, destPos) != destPos)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
destPos = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*packSizeRes = destPos;
|
||||||
|
/* needInitState = True; */
|
||||||
|
}
|
||||||
|
|
||||||
|
LzmaEnc_RestoreState(p->enc);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t destPos = 0;
|
||||||
|
UInt32 u = unpackSize - 1;
|
||||||
|
UInt32 pm = (UInt32)(packSize - 1);
|
||||||
|
unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);
|
||||||
|
|
||||||
|
PRF(printf(" "));
|
||||||
|
|
||||||
|
outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));
|
||||||
|
outBuf[destPos++] = (Byte)(u >> 8);
|
||||||
|
outBuf[destPos++] = (Byte)u;
|
||||||
|
outBuf[destPos++] = (Byte)(pm >> 8);
|
||||||
|
outBuf[destPos++] = (Byte)pm;
|
||||||
|
|
||||||
|
if (p->needInitProp)
|
||||||
|
outBuf[destPos++] = p->props;
|
||||||
|
|
||||||
|
p->needInitProp = False;
|
||||||
|
p->needInitState = False;
|
||||||
|
destPos += packSize;
|
||||||
|
p->srcPos += unpackSize;
|
||||||
|
|
||||||
|
if (outStream)
|
||||||
|
if (outStream->Write(outStream, outBuf, destPos) != destPos)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
|
||||||
|
*packSizeRes = destPos;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Lzma2 Props ---------- */
|
||||||
|
|
||||||
|
void Lzma2EncProps_Init(CLzma2EncProps *p)
|
||||||
|
{
|
||||||
|
LzmaEncProps_Init(&p->lzmaProps);
|
||||||
|
p->numTotalThreads = -1;
|
||||||
|
p->numBlockThreads = -1;
|
||||||
|
p->blockSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
|
||||||
|
{
|
||||||
|
int t1, t1n, t2, t3;
|
||||||
|
{
|
||||||
|
CLzmaEncProps lzmaProps = p->lzmaProps;
|
||||||
|
LzmaEncProps_Normalize(&lzmaProps);
|
||||||
|
t1n = lzmaProps.numThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
t1 = p->lzmaProps.numThreads;
|
||||||
|
t2 = p->numBlockThreads;
|
||||||
|
t3 = p->numTotalThreads;
|
||||||
|
|
||||||
|
if (t2 > NUM_MT_CODER_THREADS_MAX)
|
||||||
|
t2 = NUM_MT_CODER_THREADS_MAX;
|
||||||
|
|
||||||
|
if (t3 <= 0)
|
||||||
|
{
|
||||||
|
if (t2 <= 0)
|
||||||
|
t2 = 1;
|
||||||
|
t3 = t1n * t2;
|
||||||
|
}
|
||||||
|
else if (t2 <= 0)
|
||||||
|
{
|
||||||
|
t2 = t3 / t1n;
|
||||||
|
if (t2 == 0)
|
||||||
|
{
|
||||||
|
t1 = 1;
|
||||||
|
t2 = t3;
|
||||||
|
}
|
||||||
|
if (t2 > NUM_MT_CODER_THREADS_MAX)
|
||||||
|
t2 = NUM_MT_CODER_THREADS_MAX;
|
||||||
|
}
|
||||||
|
else if (t1 <= 0)
|
||||||
|
{
|
||||||
|
t1 = t3 / t2;
|
||||||
|
if (t1 == 0)
|
||||||
|
t1 = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
t3 = t1n * t2;
|
||||||
|
|
||||||
|
p->lzmaProps.numThreads = t1;
|
||||||
|
|
||||||
|
LzmaEncProps_Normalize(&p->lzmaProps);
|
||||||
|
|
||||||
|
t1 = p->lzmaProps.numThreads;
|
||||||
|
|
||||||
|
if (p->blockSize == 0)
|
||||||
|
{
|
||||||
|
UInt32 dictSize = p->lzmaProps.dictSize;
|
||||||
|
UInt64 blockSize = (UInt64)dictSize << 2;
|
||||||
|
const UInt32 kMinSize = (UInt32)1 << 20;
|
||||||
|
const UInt32 kMaxSize = (UInt32)1 << 28;
|
||||||
|
if (blockSize < kMinSize) blockSize = kMinSize;
|
||||||
|
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
||||||
|
if (blockSize < dictSize) blockSize = dictSize;
|
||||||
|
p->blockSize = (size_t)blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t2 > 1 && p->lzmaProps.reduceSize != (UInt64)(Int64)-1)
|
||||||
|
{
|
||||||
|
UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1;
|
||||||
|
if (temp > p->lzmaProps.reduceSize)
|
||||||
|
{
|
||||||
|
UInt64 numBlocks = temp / p->blockSize;
|
||||||
|
if (numBlocks < (unsigned)t2)
|
||||||
|
{
|
||||||
|
t2 = (unsigned)numBlocks;
|
||||||
|
if (t2 == 0)
|
||||||
|
t2 = 1;
|
||||||
|
t3 = t1 * t2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p->numBlockThreads = t2;
|
||||||
|
p->numTotalThreads = t3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
|
||||||
|
{
|
||||||
|
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Lzma2 ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte propEncoded;
|
||||||
|
CLzma2EncProps props;
|
||||||
|
|
||||||
|
Byte *outBuf;
|
||||||
|
|
||||||
|
ISzAlloc *alloc;
|
||||||
|
ISzAlloc *allocBig;
|
||||||
|
|
||||||
|
CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX];
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
CMtCoder mtCoder;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} CLzma2Enc;
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Lzma2EncThread ---------- */
|
||||||
|
|
||||||
|
static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
|
||||||
|
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
|
||||||
|
{
|
||||||
|
UInt64 packTotal = 0;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
|
if (!mainEncoder->outBuf)
|
||||||
|
{
|
||||||
|
mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
|
||||||
|
if (!mainEncoder->outBuf)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
|
||||||
|
RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,
|
||||||
|
mainEncoder->alloc, mainEncoder->allocBig));
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
|
||||||
|
res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
packTotal += packSize;
|
||||||
|
res = Progress(progress, p->srcPos, packTotal);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
if (packSize == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LzmaEnc_Finish(p->enc);
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
Byte b = 0;
|
||||||
|
if (outStream->Write(outStream, &b, 1) != 1)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
IMtCoderCallback funcTable;
|
||||||
|
CLzma2Enc *lzma2Enc;
|
||||||
|
} CMtCallbackImp;
|
||||||
|
|
||||||
|
static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize,
|
||||||
|
const Byte *src, size_t srcSize, int finished)
|
||||||
|
{
|
||||||
|
CMtCallbackImp *imp = (CMtCallbackImp *)pp;
|
||||||
|
CLzma2Enc *mainEncoder = imp->lzma2Enc;
|
||||||
|
CLzma2EncInt *p = &mainEncoder->coders[index];
|
||||||
|
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
{
|
||||||
|
size_t destLim = *destSize;
|
||||||
|
*destSize = 0;
|
||||||
|
|
||||||
|
if (srcSize != 0)
|
||||||
|
{
|
||||||
|
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
|
||||||
|
|
||||||
|
RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE,
|
||||||
|
mainEncoder->alloc, mainEncoder->allocBig));
|
||||||
|
|
||||||
|
while (p->srcPos < srcSize)
|
||||||
|
{
|
||||||
|
size_t packSize = destLim - *destSize;
|
||||||
|
res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
*destSize += packSize;
|
||||||
|
|
||||||
|
if (packSize == 0)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_PROGRESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LzmaEnc_Finish(p->enc);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finished)
|
||||||
|
{
|
||||||
|
if (*destSize == destLim)
|
||||||
|
return SZ_ERROR_OUTPUT_EOF;
|
||||||
|
dest[(*destSize)++] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Lzma2Enc ---------- */
|
||||||
|
|
||||||
|
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));
|
||||||
|
if (!p)
|
||||||
|
return NULL;
|
||||||
|
Lzma2EncProps_Init(&p->props);
|
||||||
|
Lzma2EncProps_Normalize(&p->props);
|
||||||
|
p->outBuf = 0;
|
||||||
|
p->alloc = alloc;
|
||||||
|
p->allocBig = allocBig;
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
p->coders[i].enc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
MtCoder_Construct(&p->mtCoder);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lzma2Enc_Destroy(CLzma2EncHandle pp)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
{
|
||||||
|
CLzma2EncInt *t = &p->coders[i];
|
||||||
|
if (t->enc)
|
||||||
|
{
|
||||||
|
LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
|
||||||
|
t->enc = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
MtCoder_Destruct(&p->mtCoder);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IAlloc_Free(p->alloc, p->outBuf);
|
||||||
|
IAlloc_Free(p->alloc, pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
CLzmaEncProps lzmaProps = props->lzmaProps;
|
||||||
|
LzmaEncProps_Normalize(&lzmaProps);
|
||||||
|
if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
|
||||||
|
return SZ_ERROR_PARAM;
|
||||||
|
p->props = *props;
|
||||||
|
Lzma2EncProps_Normalize(&p->props);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
unsigned i;
|
||||||
|
UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
|
||||||
|
for (i = 0; i < 40; i++)
|
||||||
|
if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))
|
||||||
|
break;
|
||||||
|
return (Byte)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
|
||||||
|
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < p->props.numBlockThreads; i++)
|
||||||
|
{
|
||||||
|
CLzma2EncInt *t = &p->coders[(unsigned)i];
|
||||||
|
if (!t->enc)
|
||||||
|
{
|
||||||
|
t->enc = LzmaEnc_Create(p->alloc);
|
||||||
|
if (!t->enc)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
if (p->props.numBlockThreads > 1)
|
||||||
|
{
|
||||||
|
CMtCallbackImp mtCallback;
|
||||||
|
|
||||||
|
mtCallback.funcTable.Code = MtCallbackImp_Code;
|
||||||
|
mtCallback.lzma2Enc = p;
|
||||||
|
|
||||||
|
p->mtCoder.progress = progress;
|
||||||
|
p->mtCoder.inStream = inStream;
|
||||||
|
p->mtCoder.outStream = outStream;
|
||||||
|
p->mtCoder.alloc = p->alloc;
|
||||||
|
p->mtCoder.mtCallback = &mtCallback.funcTable;
|
||||||
|
|
||||||
|
p->mtCoder.blockSize = p->props.blockSize;
|
||||||
|
p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;
|
||||||
|
if (p->mtCoder.destBlockSize < p->props.blockSize)
|
||||||
|
{
|
||||||
|
p->mtCoder.destBlockSize = (size_t)0 - 1;
|
||||||
|
if (p->mtCoder.destBlockSize < p->props.blockSize)
|
||||||
|
return SZ_ERROR_FAIL;
|
||||||
|
}
|
||||||
|
p->mtCoder.numThreads = p->props.numBlockThreads;
|
||||||
|
|
||||||
|
return MtCoder_Code(&p->mtCoder);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
|
||||||
|
}
|
||||||
62
C/Lzma2Enc.h
Normal file
62
C/Lzma2Enc.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/* Lzma2Enc.h -- LZMA2 Encoder
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA2_ENC_H
|
||||||
|
#define __LZMA2_ENC_H
|
||||||
|
|
||||||
|
#include "LzmaEnc.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CLzmaEncProps lzmaProps;
|
||||||
|
size_t blockSize;
|
||||||
|
int numBlockThreads;
|
||||||
|
int numTotalThreads;
|
||||||
|
} CLzma2EncProps;
|
||||||
|
|
||||||
|
void Lzma2EncProps_Init(CLzma2EncProps *p);
|
||||||
|
void Lzma2EncProps_Normalize(CLzma2EncProps *p);
|
||||||
|
|
||||||
|
/* ---------- CLzmaEnc2Handle Interface ---------- */
|
||||||
|
|
||||||
|
/* Lzma2Enc_* functions can return the following exit codes:
|
||||||
|
Returns:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||||
|
SZ_ERROR_WRITE - Write callback error
|
||||||
|
SZ_ERROR_PROGRESS - some break from progress callback
|
||||||
|
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef void * CLzma2EncHandle;
|
||||||
|
|
||||||
|
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
void Lzma2Enc_Destroy(CLzma2EncHandle p);
|
||||||
|
SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
|
||||||
|
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
|
||||||
|
SRes Lzma2Enc_Encode(CLzma2EncHandle p,
|
||||||
|
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);
|
||||||
|
|
||||||
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
|
/* Lzma2Encode
|
||||||
|
Return code:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_PARAM - Incorrect paramater
|
||||||
|
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||||
|
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||||
|
const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark,
|
||||||
|
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
*/
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user