mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-17 06:11:50 -06:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e75ad3d355 | ||
|
|
ff14e3badb | ||
|
|
5c10d25476 | ||
|
|
5d7485c7d9 | ||
|
|
758c3790d3 | ||
|
|
50a695679a | ||
|
|
04d04adea5 | ||
|
|
cb75c2b5bf | ||
|
|
5b2a99c548 | ||
|
|
f623539c73 | ||
|
|
c287fb0519 | ||
|
|
9b07a1847f | ||
|
|
cc9036aad9 | ||
|
|
42fa923138 | ||
|
|
b82b3e5533 | ||
|
|
20e38032e6 | ||
|
|
18dc2b4161 | ||
|
|
801aad2d7c | ||
|
|
f19b649c73 | ||
|
|
e3dc4878fe | ||
|
|
866a06f5a0 | ||
|
|
da28077952 | ||
|
|
b5dc853b24 | ||
|
|
2efa10565a | ||
|
|
603abd5528 | ||
|
|
232ce79574 | ||
|
|
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 |
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
*.o
|
||||
out/
|
||||
7zAll/x64/
|
||||
*.pdb
|
||||
*.tlog
|
||||
*.obj
|
||||
*.user
|
||||
*.log
|
||||
*.pch
|
||||
*.idb
|
||||
x64/
|
||||
*.exe
|
||||
*.res
|
||||
*.dll
|
||||
*.lib
|
||||
*.exp
|
||||
*.sfx
|
||||
*.txt
|
||||
41
7zAll/7zAll.sln
Normal file
41
7zAll/7zAll.sln
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28010.2048
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "7zFM", "..\CPP\7zip\UI\FileManager\FM.vcxproj", "{2628FF64-E1E1-4CB7-B588-08DE7145B630}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "7zG", "..\CPP\7zip\UI\GUI\GUI.vcxproj", "{D4BC12CF-49F2-474D-BAF6-EAC069DB7D6C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
DebugU|Win32 = DebugU|Win32
|
||||
DebugU|x64 = DebugU|x64
|
||||
ReleaseU|Win32 = ReleaseU|Win32
|
||||
ReleaseU|x64 = ReleaseU|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2628FF64-E1E1-4CB7-B588-08DE7145B630}.DebugU|Win32.ActiveCfg = DebugU|Win32
|
||||
{2628FF64-E1E1-4CB7-B588-08DE7145B630}.DebugU|Win32.Build.0 = DebugU|Win32
|
||||
{2628FF64-E1E1-4CB7-B588-08DE7145B630}.DebugU|x64.ActiveCfg = DebugU|x64
|
||||
{2628FF64-E1E1-4CB7-B588-08DE7145B630}.DebugU|x64.Build.0 = DebugU|x64
|
||||
{2628FF64-E1E1-4CB7-B588-08DE7145B630}.ReleaseU|Win32.ActiveCfg = ReleaseU|Win32
|
||||
{2628FF64-E1E1-4CB7-B588-08DE7145B630}.ReleaseU|Win32.Build.0 = ReleaseU|Win32
|
||||
{2628FF64-E1E1-4CB7-B588-08DE7145B630}.ReleaseU|x64.ActiveCfg = ReleaseU|x64
|
||||
{2628FF64-E1E1-4CB7-B588-08DE7145B630}.ReleaseU|x64.Build.0 = ReleaseU|x64
|
||||
{D4BC12CF-49F2-474D-BAF6-EAC069DB7D6C}.DebugU|Win32.ActiveCfg = DebugU|Win32
|
||||
{D4BC12CF-49F2-474D-BAF6-EAC069DB7D6C}.DebugU|Win32.Build.0 = DebugU|Win32
|
||||
{D4BC12CF-49F2-474D-BAF6-EAC069DB7D6C}.DebugU|x64.ActiveCfg = DebugU|x64
|
||||
{D4BC12CF-49F2-474D-BAF6-EAC069DB7D6C}.DebugU|x64.Build.0 = DebugU|x64
|
||||
{D4BC12CF-49F2-474D-BAF6-EAC069DB7D6C}.ReleaseU|Win32.ActiveCfg = ReleaseU|Win32
|
||||
{D4BC12CF-49F2-474D-BAF6-EAC069DB7D6C}.ReleaseU|Win32.Build.0 = ReleaseU|Win32
|
||||
{D4BC12CF-49F2-474D-BAF6-EAC069DB7D6C}.ReleaseU|x64.ActiveCfg = ReleaseU|x64
|
||||
{D4BC12CF-49F2-474D-BAF6-EAC069DB7D6C}.ReleaseU|x64.Build.0 = ReleaseU|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {BF7D9E83-83E0-4B40-B356-AA6A664D563E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
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
|
||||
147
Asm/x86/7zAsm.asm
Normal file
147
Asm/x86/7zAsm.asm
Normal file
@@ -0,0 +1,147 @@
|
||||
; 7zAsm.asm -- ASM macros
|
||||
; 2018-02-03 : Igor Pavlov : Public domain
|
||||
|
||||
MY_ASM_START macro
|
||||
ifdef x64
|
||||
.code
|
||||
else
|
||||
.386
|
||||
.model flat
|
||||
_TEXT$00 SEGMENT PARA PUBLIC 'CODE'
|
||||
endif
|
||||
endm
|
||||
|
||||
MY_PROC macro name:req, numParams:req
|
||||
align 16
|
||||
proc_numParams = numParams
|
||||
ifdef x64
|
||||
proc_name equ name
|
||||
else
|
||||
proc_name equ @CatStr(@,name,@, %numParams * 4)
|
||||
endif
|
||||
proc_name PROC
|
||||
endm
|
||||
|
||||
MY_ENDP macro
|
||||
ifdef x64
|
||||
ret
|
||||
else
|
||||
if proc_numParams LT 3
|
||||
ret
|
||||
else
|
||||
ret (proc_numParams - 2) * 4
|
||||
endif
|
||||
endif
|
||||
proc_name ENDP
|
||||
endm
|
||||
|
||||
ifdef x64
|
||||
REG_SIZE equ 8
|
||||
REG_LOGAR_SIZE equ 3
|
||||
else
|
||||
REG_SIZE equ 4
|
||||
REG_LOGAR_SIZE equ 2
|
||||
endif
|
||||
|
||||
x0 equ EAX
|
||||
x1 equ ECX
|
||||
x2 equ EDX
|
||||
x3 equ EBX
|
||||
x4 equ ESP
|
||||
x5 equ EBP
|
||||
x6 equ ESI
|
||||
x7 equ EDI
|
||||
|
||||
x0_W equ AX
|
||||
x1_W equ CX
|
||||
x2_W equ DX
|
||||
x3_W equ BX
|
||||
|
||||
x5_W equ BP
|
||||
x6_W equ SI
|
||||
x7_W equ DI
|
||||
|
||||
x0_L equ AL
|
||||
x1_L equ CL
|
||||
x2_L equ DL
|
||||
x3_L equ BL
|
||||
|
||||
x0_H equ AH
|
||||
x1_H equ CH
|
||||
x2_H equ DH
|
||||
x3_H equ BH
|
||||
|
||||
ifdef x64
|
||||
x5_L equ BPL
|
||||
x6_L equ SIL
|
||||
x7_L equ DIL
|
||||
|
||||
r0 equ RAX
|
||||
r1 equ RCX
|
||||
r2 equ RDX
|
||||
r3 equ RBX
|
||||
r4 equ RSP
|
||||
r5 equ RBP
|
||||
r6 equ RSI
|
||||
r7 equ RDI
|
||||
x8 equ r8d
|
||||
x9 equ r9d
|
||||
x10 equ r10d
|
||||
x11 equ r11d
|
||||
x12 equ r12d
|
||||
x13 equ r13d
|
||||
x14 equ r14d
|
||||
x15 equ r15d
|
||||
else
|
||||
r0 equ x0
|
||||
r1 equ x1
|
||||
r2 equ x2
|
||||
r3 equ x3
|
||||
r4 equ x4
|
||||
r5 equ x5
|
||||
r6 equ x6
|
||||
r7 equ x7
|
||||
endif
|
||||
|
||||
MY_PUSH_4_REGS macro
|
||||
push r3
|
||||
push r5
|
||||
push r6
|
||||
push r7
|
||||
endm
|
||||
|
||||
MY_POP_4_REGS macro
|
||||
pop r7
|
||||
pop r6
|
||||
pop r5
|
||||
pop r3
|
||||
endm
|
||||
|
||||
|
||||
ifdef x64
|
||||
|
||||
; for WIN64-x64 ABI:
|
||||
|
||||
REG_PARAM_0 equ r1
|
||||
REG_PARAM_1 equ r2
|
||||
REG_PARAM_2 equ r8
|
||||
REG_PARAM_3 equ r9
|
||||
|
||||
MY_PUSH_PRESERVED_REGS macro
|
||||
MY_PUSH_4_REGS
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
endm
|
||||
|
||||
|
||||
MY_POP_PRESERVED_REGS macro
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
MY_POP_4_REGS
|
||||
endm
|
||||
|
||||
endif
|
||||
147
Asm/x86/7zCrcOpt.asm
Normal file
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
|
||||
1258
Asm/x86/LzmaDecOpt.asm
Normal file
1258
Asm/x86/LzmaDecOpt.asm
Normal file
File diff suppressed because it is too large
Load Diff
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
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_H
|
||||
#define __7Z_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define k7zStartHeaderSize 0x20
|
||||
#define k7zSignatureSize 6
|
||||
|
||||
extern const Byte k7zSignature[k7zSignatureSize];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const Byte *Data;
|
||||
size_t Size;
|
||||
} CSzData;
|
||||
|
||||
/* CSzCoderInfo & CSzFolder support only default methods */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t PropsOffset;
|
||||
UInt32 MethodID;
|
||||
Byte NumStreams;
|
||||
Byte PropsSize;
|
||||
} CSzCoderInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 InIndex;
|
||||
UInt32 OutIndex;
|
||||
} CSzBond;
|
||||
|
||||
#define SZ_NUM_CODERS_IN_FOLDER_MAX 4
|
||||
#define SZ_NUM_BONDS_IN_FOLDER_MAX 3
|
||||
#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 NumCoders;
|
||||
UInt32 NumBonds;
|
||||
UInt32 NumPackStreams;
|
||||
UInt32 UnpackStream;
|
||||
UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
|
||||
CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];
|
||||
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
|
||||
} CSzFolder;
|
||||
|
||||
|
||||
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 Low;
|
||||
UInt32 High;
|
||||
} CNtfsFileTime;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte *Defs; /* MSB 0 bit numbering */
|
||||
UInt32 *Vals;
|
||||
} CSzBitUi32s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte *Defs; /* MSB 0 bit numbering */
|
||||
// UInt64 *Vals;
|
||||
CNtfsFileTime *Vals;
|
||||
} CSzBitUi64s;
|
||||
|
||||
#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
|
||||
|
||||
#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 NumPackStreams;
|
||||
UInt32 NumFolders;
|
||||
|
||||
UInt64 *PackPositions; // NumPackStreams + 1
|
||||
CSzBitUi32s FolderCRCs; // NumFolders
|
||||
|
||||
size_t *FoCodersOffsets; // NumFolders + 1
|
||||
UInt32 *FoStartPackStreamIndex; // NumFolders + 1
|
||||
UInt32 *FoToCoderUnpackSizes; // NumFolders + 1
|
||||
Byte *FoToMainUnpackSizeIndex; // NumFolders
|
||||
UInt64 *CoderUnpackSizes; // for all coders in all folders
|
||||
|
||||
Byte *CodersData;
|
||||
} CSzAr;
|
||||
|
||||
UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);
|
||||
|
||||
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
|
||||
ILookInStream *stream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize,
|
||||
ISzAllocPtr allocMain);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzAr db;
|
||||
|
||||
UInt64 startPosAfterHeader;
|
||||
UInt64 dataPos;
|
||||
|
||||
UInt32 NumFiles;
|
||||
|
||||
UInt64 *UnpackPositions; // NumFiles + 1
|
||||
// Byte *IsEmptyFiles;
|
||||
Byte *IsDirs;
|
||||
CSzBitUi32s CRCs;
|
||||
|
||||
CSzBitUi32s Attribs;
|
||||
// CSzBitUi32s Parents;
|
||||
CSzBitUi64s MTime;
|
||||
CSzBitUi64s CTime;
|
||||
|
||||
UInt32 *FolderToFile; // NumFolders + 1
|
||||
UInt32 *FileToFolder; // NumFiles
|
||||
|
||||
size_t *FileNameOffsets; /* in 2-byte steps */
|
||||
Byte *FileNames; /* UTF-16-LE */
|
||||
} CSzArEx;
|
||||
|
||||
#define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i))
|
||||
|
||||
#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i])
|
||||
|
||||
void SzArEx_Init(CSzArEx *p);
|
||||
void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc);
|
||||
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
||||
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
||||
|
||||
/*
|
||||
if dest == NULL, the return value specifies the required size of the buffer,
|
||||
in 16-bit characters, including the null-terminating character.
|
||||
if dest != NULL, the return value specifies the number of 16-bit characters that
|
||||
are written to the dest, including the null-terminating character. */
|
||||
|
||||
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||
|
||||
/*
|
||||
size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex);
|
||||
UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
SzArEx_Extract extracts file from archive
|
||||
|
||||
*outBuffer must be 0 before first call for each new archive.
|
||||
|
||||
Extracting cache:
|
||||
If you need to decompress more than one file, you can send
|
||||
these values from previous call:
|
||||
*blockIndex,
|
||||
*outBuffer,
|
||||
*outBufferSize
|
||||
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
||||
it will increase decompression speed.
|
||||
|
||||
If you use external function, you can declare these 3 cache variables
|
||||
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
||||
|
||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||
*/
|
||||
|
||||
SRes SzArEx_Extract(
|
||||
const CSzArEx *db,
|
||||
ILookInStream *inStream,
|
||||
UInt32 fileIndex, /* index of file */
|
||||
UInt32 *blockIndex, /* index of solid block */
|
||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||
size_t *outBufferSize, /* buffer size for output buffer */
|
||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||
ISzAllocPtr allocMain,
|
||||
ISzAllocPtr allocTemp);
|
||||
|
||||
|
||||
/*
|
||||
SzArEx_Open Errors:
|
||||
SZ_ERROR_NO_ARCHIVE
|
||||
SZ_ERROR_ARCHIVE
|
||||
SZ_ERROR_UNSUPPORTED
|
||||
SZ_ERROR_MEM
|
||||
SZ_ERROR_CRC
|
||||
SZ_ERROR_INPUT_EOF
|
||||
SZ_ERROR_FAIL
|
||||
*/
|
||||
|
||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
|
||||
ISzAllocPtr allocMain, ISzAllocPtr allocTemp);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
25
C/Archive/7z/7zAlloc.c → C/7zAlloc.c
Executable file → Normal file
25
C/Archive/7z/7zAlloc.c → C/7zAlloc.c
Executable file → Normal file
@@ -1,7 +1,10 @@
|
||||
/* 7zAlloc.c -- Allocation functions
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "7zAlloc.h"
|
||||
|
||||
/* #define _SZ_ALLOC_DEBUG */
|
||||
@@ -19,21 +22,21 @@ int g_allocCountTemp = 0;
|
||||
|
||||
#endif
|
||||
|
||||
void *SzAlloc(void *p, size_t size)
|
||||
void *SzAlloc(ISzAllocPtr p, size_t size)
|
||||
{
|
||||
p = p;
|
||||
UNUSED_VAR(p);
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#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++;
|
||||
#endif
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void SzFree(void *p, void *address)
|
||||
void SzFree(ISzAllocPtr p, void *address)
|
||||
{
|
||||
p = p;
|
||||
UNUSED_VAR(p);
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
{
|
||||
@@ -44,13 +47,13 @@ void SzFree(void *p, void *address)
|
||||
free(address);
|
||||
}
|
||||
|
||||
void *SzAllocTemp(void *p, size_t size)
|
||||
void *SzAllocTemp(ISzAllocPtr p, size_t size)
|
||||
{
|
||||
p = p;
|
||||
UNUSED_VAR(p);
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#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++;
|
||||
#ifdef _WIN32
|
||||
return HeapAlloc(GetProcessHeap(), 0, size);
|
||||
@@ -59,9 +62,9 @@ void *SzAllocTemp(void *p, size_t size)
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void SzFreeTemp(void *p, void *address)
|
||||
void SzFreeTemp(ISzAllocPtr p, void *address)
|
||||
{
|
||||
p = p;
|
||||
UNUSED_VAR(p);
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
{
|
||||
19
C/7zAlloc.h
Normal file
19
C/7zAlloc.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* 7zAlloc.h -- Allocation functions
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_ALLOC_H
|
||||
#define __7Z_ALLOC_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
void *SzAlloc(ISzAllocPtr p, size_t size);
|
||||
void SzFree(ISzAllocPtr p, void *address);
|
||||
|
||||
void *SzAllocTemp(ISzAllocPtr p, size_t size);
|
||||
void SzFreeTemp(ISzAllocPtr p, void *address);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
1771
C/7zArcIn.c
Normal file
1771
C/7zArcIn.c
Normal file
File diff suppressed because it is too large
Load Diff
16
C/7zBuf.c
Executable file → Normal file
16
C/7zBuf.c
Executable file → Normal file
@@ -1,7 +1,7 @@
|
||||
/* 7zBuf.c -- Byte Buffer
|
||||
2008-03-28
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "7zBuf.h"
|
||||
|
||||
@@ -11,7 +11,7 @@ void Buf_Init(CBuf *p)
|
||||
p->size = 0;
|
||||
}
|
||||
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc)
|
||||
{
|
||||
p->size = 0;
|
||||
if (size == 0)
|
||||
@@ -19,8 +19,8 @@ int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
|
||||
p->data = 0;
|
||||
return 1;
|
||||
}
|
||||
p->data = (Byte *)alloc->Alloc(alloc, size);
|
||||
if (p->data != 0)
|
||||
p->data = (Byte *)ISzAlloc_Alloc(alloc, size);
|
||||
if (p->data)
|
||||
{
|
||||
p->size = size;
|
||||
return 1;
|
||||
@@ -28,9 +28,9 @@ int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Buf_Free(CBuf *p, ISzAlloc *alloc)
|
||||
void Buf_Free(CBuf *p, ISzAllocPtr alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->data);
|
||||
ISzAlloc_Free(alloc, p->data);
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
}
|
||||
|
||||
16
C/7zBuf.h
Executable file → Normal file
16
C/7zBuf.h
Executable file → Normal file
@@ -1,10 +1,12 @@
|
||||
/* 7zBuf.h -- Byte Buffer
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_BUF_H
|
||||
#define __7Z_BUF_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -13,8 +15,8 @@ typedef struct
|
||||
} CBuf;
|
||||
|
||||
void Buf_Init(CBuf *p);
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
|
||||
void Buf_Free(CBuf *p, ISzAlloc *alloc);
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc);
|
||||
void Buf_Free(CBuf *p, ISzAllocPtr alloc);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -25,7 +27,9 @@ typedef struct
|
||||
|
||||
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);
|
||||
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc);
|
||||
void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
27
C/7zBuf2.c
Executable file → Normal file
27
C/7zBuf2.c
Executable file → Normal file
@@ -1,7 +1,10 @@
|
||||
/* 7zBuf2.c -- Byte Buffer
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "7zBuf.h"
|
||||
|
||||
void DynBuf_Construct(CDynBuf *p)
|
||||
@@ -16,29 +19,33 @@ void DynBuf_SeekToBeg(CDynBuf *p)
|
||||
p->pos = 0;
|
||||
}
|
||||
|
||||
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc)
|
||||
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc)
|
||||
{
|
||||
if (size > p->size - p->pos)
|
||||
{
|
||||
size_t newSize = p->pos + size;
|
||||
Byte *data;
|
||||
newSize += newSize / 4;
|
||||
data = (Byte *)alloc->Alloc(alloc, newSize);
|
||||
if (data == 0)
|
||||
data = (Byte *)ISzAlloc_Alloc(alloc, newSize);
|
||||
if (!data)
|
||||
return 0;
|
||||
p->size = newSize;
|
||||
memcpy(data, p->data, p->pos);
|
||||
alloc->Free(alloc, p->data);
|
||||
if (p->pos != 0)
|
||||
memcpy(data, p->data, p->pos);
|
||||
ISzAlloc_Free(alloc, p->data);
|
||||
p->data = data;
|
||||
}
|
||||
memcpy(p->data + p->pos, buf, size);
|
||||
p->pos += size;
|
||||
if (size != 0)
|
||||
{
|
||||
memcpy(p->data + p->pos, buf, size);
|
||||
p->pos += size;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc)
|
||||
void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->data);
|
||||
ISzAlloc_Free(alloc, p->data);
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
p->pos = 0;
|
||||
|
||||
131
C/7zCrc.c
Executable file → Normal file
131
C/7zCrc.c
Executable file → Normal file
@@ -1,35 +1,128 @@
|
||||
/* 7zCrc.c -- CRC32 calculation
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
/* 7zCrc.c -- CRC32 init
|
||||
2017-06-06 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "7zCrc.h"
|
||||
#include "CpuArch.h"
|
||||
|
||||
#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;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
UInt32 r = i;
|
||||
int j;
|
||||
unsigned j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
|
||||
g_CrcTable[i] = r;
|
||||
}
|
||||
}
|
||||
for (i = 256; i < 256 * CRC_NUM_TABLES; i++)
|
||||
{
|
||||
UInt32 r = g_CrcTable[(size_t)i - 256];
|
||||
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 ; size--, p++)
|
||||
v = CRC_UPDATE_BYTE(v, *p);
|
||||
return v;
|
||||
}
|
||||
#if CRC_NUM_TABLES < 4
|
||||
|
||||
g_CrcUpdate = CrcUpdateT1;
|
||||
|
||||
#else
|
||||
|
||||
#ifdef MY_CPU_LE
|
||||
|
||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||
{
|
||||
return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF;
|
||||
g_CrcUpdateT4 = CrcUpdateT4;
|
||||
g_CrcUpdate = CrcUpdateT4;
|
||||
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT8;
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
if (!CPU_Is_InOrder())
|
||||
#endif
|
||||
g_CrcUpdate = CrcUpdateT8;
|
||||
#endif
|
||||
|
||||
#else
|
||||
{
|
||||
#ifndef MY_CPU_BE
|
||||
UInt32 k = 0x01020304;
|
||||
const Byte *p = (const Byte *)&k;
|
||||
if (p[0] == 4 && p[1] == 3)
|
||||
{
|
||||
g_CrcUpdateT4 = CrcUpdateT4;
|
||||
g_CrcUpdate = CrcUpdateT4;
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT8;
|
||||
g_CrcUpdate = CrcUpdateT8;
|
||||
#endif
|
||||
}
|
||||
else if (p[0] != 1 || p[1] != 2)
|
||||
g_CrcUpdate = CrcUpdateT1;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
|
||||
{
|
||||
UInt32 x = g_CrcTable[(size_t)i - 256];
|
||||
g_CrcTable[i] = CRC_UINT32_SWAP(x);
|
||||
}
|
||||
g_CrcUpdateT4 = CrcUpdateT1_BeT4;
|
||||
g_CrcUpdate = CrcUpdateT1_BeT4;
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT1_BeT8;
|
||||
g_CrcUpdate = CrcUpdateT1_BeT8;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
13
C/7zCrc.h
Executable file → Normal file
13
C/7zCrc.h
Executable file → Normal file
@@ -1,24 +1,25 @@
|
||||
/* 7zCrc.h -- CRC32 calculation
|
||||
2008-03-13
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_CRC_H
|
||||
#define __7Z_CRC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "7zTypes.h"
|
||||
|
||||
#include "Types.h"
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
extern UInt32 g_CrcTable[];
|
||||
|
||||
/* Call CrcGenerateTable one time before other CRC functions */
|
||||
void MY_FAST_CALL CrcGenerateTable(void);
|
||||
|
||||
#define CRC_INIT_VAL 0xFFFFFFFF
|
||||
#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF)
|
||||
#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
|
||||
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
|
||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
115
C/7zCrcOpt.c
Normal file
115
C/7zCrcOpt.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/* 7zCrcOpt.c -- CRC32 calculation
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
|
||||
#ifndef MY_CPU_BE
|
||||
|
||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
for (; size >= 4; size -= 4, p += 4)
|
||||
{
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
(table + 0x300)[((v ) & 0xFF)]
|
||||
^ (table + 0x200)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x100)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x000)[((v >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
for (; size >= 8; size -= 8, p += 8)
|
||||
{
|
||||
UInt32 d;
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
(table + 0x700)[((v ) & 0xFF)]
|
||||
^ (table + 0x600)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x500)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x400)[((v >> 24))];
|
||||
d = *((const UInt32 *)p + 1);
|
||||
v ^=
|
||||
(table + 0x300)[((d ) & 0xFF)]
|
||||
^ (table + 0x200)[((d >> 8) & 0xFF)]
|
||||
^ (table + 0x100)[((d >> 16) & 0xFF)]
|
||||
^ (table + 0x000)[((d >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MY_CPU_LE
|
||||
|
||||
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
|
||||
|
||||
#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
table += 0x100;
|
||||
v = CRC_UINT32_SWAP(v);
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
for (; size >= 4; size -= 4, p += 4)
|
||||
{
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
(table + 0x000)[((v ) & 0xFF)]
|
||||
^ (table + 0x100)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x200)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x300)[((v >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
return CRC_UINT32_SWAP(v);
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
table += 0x100;
|
||||
v = CRC_UINT32_SWAP(v);
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
for (; size >= 8; size -= 8, p += 8)
|
||||
{
|
||||
UInt32 d;
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
(table + 0x400)[((v ) & 0xFF)]
|
||||
^ (table + 0x500)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x600)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x700)[((v >> 24))];
|
||||
d = *((const UInt32 *)p + 1);
|
||||
v ^=
|
||||
(table + 0x000)[((d ) & 0xFF)]
|
||||
^ (table + 0x100)[((d >> 8) & 0xFF)]
|
||||
^ (table + 0x200)[((d >> 16) & 0xFF)]
|
||||
^ (table + 0x300)[((d >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
return CRC_UINT32_SWAP(v);
|
||||
}
|
||||
|
||||
#endif
|
||||
43
C/7zCrcT8.c
43
C/7zCrcT8.c
@@ -1,43 +0,0 @@
|
||||
/* 7zCrcT8.c -- CRC32 calculation with 8 tables
|
||||
2008-03-19
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#include "7zCrc.h"
|
||||
|
||||
#define kCrcPoly 0xEDB88320
|
||||
#define CRC_NUM_TABLES 8
|
||||
|
||||
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable()
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
UInt32 r = i;
|
||||
int j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
g_CrcTable[i] = r;
|
||||
}
|
||||
#if CRC_NUM_TABLES > 1
|
||||
for (; i < 256 * CRC_NUM_TABLES; i++)
|
||||
{
|
||||
UInt32 r = g_CrcTable[i - 256];
|
||||
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
||||
{
|
||||
return CrcUpdateT8(v, data, size, g_CrcTable);
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||
{
|
||||
return CrcUpdateT8(CRC_INIT_VAL, data, size, g_CrcTable) ^ 0xFFFFFFFF;
|
||||
}
|
||||
591
C/7zDec.c
Normal file
591
C/7zDec.c
Normal file
@@ -0,0 +1,591 @@
|
||||
/* 7zDec.c -- Decoding from 7z folder
|
||||
2018-07-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* #define _7ZIP_PPMD_SUPPPORT */
|
||||
|
||||
#include "7z.h"
|
||||
#include "7zCrc.h"
|
||||
|
||||
#include "Bcj2.h"
|
||||
#include "Bra.h"
|
||||
#include "CpuArch.h"
|
||||
#include "Delta.h"
|
||||
#include "LzmaDec.h"
|
||||
#include "Lzma2Dec.h"
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
#include "Ppmd7.h"
|
||||
#endif
|
||||
|
||||
#define k_Copy 0
|
||||
#define k_Delta 3
|
||||
#define k_LZMA2 0x21
|
||||
#define k_LZMA 0x30101
|
||||
#define k_BCJ 0x3030103
|
||||
#define k_BCJ2 0x303011B
|
||||
#define k_PPC 0x3030205
|
||||
#define k_IA64 0x3030401
|
||||
#define k_ARM 0x3030501
|
||||
#define k_ARMT 0x3030701
|
||||
#define k_SPARC 0x3030805
|
||||
|
||||
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
|
||||
#define k_PPMD 0x30401
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IByteIn vt;
|
||||
const Byte *cur;
|
||||
const Byte *end;
|
||||
const Byte *begin;
|
||||
UInt64 processed;
|
||||
BoolInt extra;
|
||||
SRes res;
|
||||
const ILookInStream *inStream;
|
||||
} CByteInToLook;
|
||||
|
||||
static Byte ReadByte(const IByteIn *pp)
|
||||
{
|
||||
CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt);
|
||||
if (p->cur != p->end)
|
||||
return *p->cur++;
|
||||
if (p->res == SZ_OK)
|
||||
{
|
||||
size_t size = p->cur - p->begin;
|
||||
p->processed += size;
|
||||
p->res = ILookInStream_Skip(p->inStream, size);
|
||||
size = (1 << 25);
|
||||
p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size);
|
||||
p->cur = p->begin;
|
||||
p->end = p->begin + size;
|
||||
if (size != 0)
|
||||
return *p->cur++;;
|
||||
}
|
||||
p->extra = True;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, const ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
|
||||
{
|
||||
CPpmd7 ppmd;
|
||||
CByteInToLook s;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
s.vt.Read = ReadByte;
|
||||
s.inStream = inStream;
|
||||
s.begin = s.end = s.cur = NULL;
|
||||
s.extra = False;
|
||||
s.res = SZ_OK;
|
||||
s.processed = 0;
|
||||
|
||||
if (propsSize != 5)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
{
|
||||
unsigned order = props[0];
|
||||
UInt32 memSize = GetUi32(props + 1);
|
||||
if (order < PPMD7_MIN_ORDER ||
|
||||
order > PPMD7_MAX_ORDER ||
|
||||
memSize < PPMD7_MIN_MEM_SIZE ||
|
||||
memSize > PPMD7_MAX_MEM_SIZE)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
Ppmd7_Construct(&ppmd);
|
||||
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
|
||||
return SZ_ERROR_MEM;
|
||||
Ppmd7_Init(&ppmd, order);
|
||||
}
|
||||
{
|
||||
CPpmd7z_RangeDec rc;
|
||||
Ppmd7z_RangeDec_CreateVTable(&rc);
|
||||
rc.Stream = &s.vt;
|
||||
if (!Ppmd7z_RangeDec_Init(&rc))
|
||||
res = SZ_ERROR_DATA;
|
||||
else if (s.extra)
|
||||
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||
else
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < outSize; i++)
|
||||
{
|
||||
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt);
|
||||
if (s.extra || sym < 0)
|
||||
break;
|
||||
outBuffer[i] = (Byte)sym;
|
||||
}
|
||||
if (i != outSize)
|
||||
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
|
||||
res = SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
Ppmd7_Free(&ppmd, allocMain);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
|
||||
{
|
||||
CLzmaDec state;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
LzmaDec_Construct(&state);
|
||||
RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain));
|
||||
state.dic = outBuffer;
|
||||
state.dicBufSize = outSize;
|
||||
LzmaDec_Init(&state);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const void *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = ILookInStream_Look(inStream, &inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
{
|
||||
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
|
||||
ELzmaStatus status;
|
||||
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
if (outSize != state.dicPos || inSize != 0)
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
break;
|
||||
|
||||
if (inProcessed == 0 && dicPos == state.dicPos)
|
||||
{
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
res = ILookInStream_Skip(inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LzmaDec_FreeProbs(&state, allocMain);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
|
||||
static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
|
||||
{
|
||||
CLzma2Dec state;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
Lzma2Dec_Construct(&state);
|
||||
if (propsSize != 1)
|
||||
return SZ_ERROR_DATA;
|
||||
RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain));
|
||||
state.decoder.dic = outBuffer;
|
||||
state.decoder.dicBufSize = outSize;
|
||||
Lzma2Dec_Init(&state);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const void *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = ILookInStream_Look(inStream, &inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
{
|
||||
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
|
||||
ELzmaStatus status;
|
||||
res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
if (outSize != state.decoder.dicPos || inSize != 0)
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
if (inProcessed == 0 && dicPos == state.decoder.dicPos)
|
||||
{
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
res = ILookInStream_Skip(inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Lzma2Dec_FreeProbs(&state, allocMain);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
|
||||
{
|
||||
while (inSize > 0)
|
||||
{
|
||||
const void *inBuf;
|
||||
size_t curSize = (1 << 18);
|
||||
if (curSize > inSize)
|
||||
curSize = (size_t)inSize;
|
||||
RINOK(ILookInStream_Look(inStream, &inBuf, &curSize));
|
||||
if (curSize == 0)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
memcpy(outBuffer, inBuf, curSize);
|
||||
outBuffer += curSize;
|
||||
inSize -= curSize;
|
||||
RINOK(ILookInStream_Skip(inStream, curSize));
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static BoolInt 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 BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c)
|
||||
{
|
||||
return
|
||||
c->NumStreams == 1
|
||||
/* && c->MethodID <= (UInt32)0xFFFFFFFF */
|
||||
&& IS_MAIN_METHOD((UInt32)c->MethodID);
|
||||
}
|
||||
|
||||
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4)
|
||||
|
||||
static SRes CheckSupportedFolder(const CSzFolder *f)
|
||||
{
|
||||
if (f->NumCoders < 1 || f->NumCoders > 4)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (!IS_SUPPORTED_CODER(&f->Coders[0]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (f->NumCoders == 1)
|
||||
{
|
||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _7Z_NO_METHODS_FILTERS
|
||||
|
||||
if (f->NumCoders == 2)
|
||||
{
|
||||
const CSzCoderInfo *c = &f->Coders[1];
|
||||
if (
|
||||
/* c->MethodID > (UInt32)0xFFFFFFFF || */
|
||||
c->NumStreams != 1
|
||||
|| f->NumPackStreams != 1
|
||||
|| f->PackStreams[0] != 0
|
||||
|| f->NumBonds != 1
|
||||
|| f->Bonds[0].InIndex != 1
|
||||
|| f->Bonds[0].OutIndex != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
switch ((UInt32)c->MethodID)
|
||||
{
|
||||
case k_Delta:
|
||||
case k_BCJ:
|
||||
case k_PPC:
|
||||
case k_IA64:
|
||||
case k_SPARC:
|
||||
case k_ARM:
|
||||
case k_ARMT:
|
||||
break;
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (f->NumCoders == 4)
|
||||
{
|
||||
if (!IS_SUPPORTED_CODER(&f->Coders[1])
|
||||
|| !IS_SUPPORTED_CODER(&f->Coders[2])
|
||||
|| !IS_BCJ2(&f->Coders[3]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (f->NumPackStreams != 4
|
||||
|| f->PackStreams[0] != 2
|
||||
|| f->PackStreams[1] != 6
|
||||
|| f->PackStreams[2] != 1
|
||||
|| f->PackStreams[3] != 0
|
||||
|| f->NumBonds != 3
|
||||
|| f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0
|
||||
|| f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1
|
||||
|| f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
|
||||
|
||||
static SRes SzFolder_Decode2(const CSzFolder *folder,
|
||||
const Byte *propsData,
|
||||
const UInt64 *unpackSizes,
|
||||
const UInt64 *packPositions,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain,
|
||||
Byte *tempBuf[])
|
||||
{
|
||||
UInt32 ci;
|
||||
SizeT tempSizes[3] = { 0, 0, 0};
|
||||
SizeT tempSize3 = 0;
|
||||
Byte *tempBuf3 = 0;
|
||||
|
||||
RINOK(CheckSupportedFolder(folder));
|
||||
|
||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||
{
|
||||
const CSzCoderInfo *coder = &folder->Coders[ci];
|
||||
|
||||
if (IS_MAIN_METHOD((UInt32)coder->MethodID))
|
||||
{
|
||||
UInt32 si = 0;
|
||||
UInt64 offset;
|
||||
UInt64 inSize;
|
||||
Byte *outBufCur = outBuffer;
|
||||
SizeT outSizeCur = outSize;
|
||||
if (folder->NumCoders == 4)
|
||||
{
|
||||
UInt32 indices[] = { 3, 2, 0 };
|
||||
UInt64 unpackSize = unpackSizes[ci];
|
||||
si = indices[ci];
|
||||
if (ci < 2)
|
||||
{
|
||||
Byte *temp;
|
||||
outSizeCur = (SizeT)unpackSize;
|
||||
if (outSizeCur != unpackSize)
|
||||
return SZ_ERROR_MEM;
|
||||
temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur);
|
||||
if (!temp && outSizeCur != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
outBufCur = tempBuf[1 - ci] = temp;
|
||||
tempSizes[1 - ci] = outSizeCur;
|
||||
}
|
||||
else if (ci == 2)
|
||||
{
|
||||
if (unpackSize > outSize) /* check it */
|
||||
return SZ_ERROR_PARAM;
|
||||
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
||||
tempSize3 = outSizeCur = (SizeT)unpackSize;
|
||||
}
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
offset = packPositions[si];
|
||||
inSize = packPositions[(size_t)si + 1] - offset;
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
|
||||
if (coder->MethodID == k_Copy)
|
||||
{
|
||||
if (inSize != outSizeCur) /* check it */
|
||||
return SZ_ERROR_DATA;
|
||||
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
||||
}
|
||||
else if (coder->MethodID == k_LZMA)
|
||||
{
|
||||
RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
else if (coder->MethodID == k_LZMA2)
|
||||
{
|
||||
RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
#endif
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
else if (coder->MethodID == k_PPMD)
|
||||
{
|
||||
RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ2)
|
||||
{
|
||||
UInt64 offset = packPositions[1];
|
||||
UInt64 s3Size = packPositions[2] - offset;
|
||||
|
||||
if (ci != 3)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
tempSizes[2] = (SizeT)s3Size;
|
||||
if (tempSizes[2] != s3Size)
|
||||
return SZ_ERROR_MEM;
|
||||
tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]);
|
||||
if (!tempBuf[2] && tempSizes[2] != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2]));
|
||||
|
||||
if ((tempSizes[0] & 3) != 0 ||
|
||||
(tempSizes[1] & 3) != 0 ||
|
||||
tempSize3 + tempSizes[0] + tempSizes[1] != outSize)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
{
|
||||
CBcj2Dec p;
|
||||
|
||||
p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3;
|
||||
p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0];
|
||||
p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1];
|
||||
p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2];
|
||||
|
||||
p.dest = outBuffer;
|
||||
p.destLim = outBuffer + outSize;
|
||||
|
||||
Bcj2Dec_Init(&p);
|
||||
RINOK(Bcj2Dec_Decode(&p));
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; i++)
|
||||
if (p.bufs[i] != p.lims[i])
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
if (!Bcj2Dec_IsFinished(&p))
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
if (p.dest != p.destLim
|
||||
|| p.state != BCJ2_STREAM_MAIN)
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef _7Z_NO_METHODS_FILTERS
|
||||
else if (ci == 1)
|
||||
{
|
||||
if (coder->MethodID == k_Delta)
|
||||
{
|
||||
if (coder->PropsSize != 1)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
{
|
||||
Byte state[DELTA_STATE_SIZE];
|
||||
Delta_Init(state);
|
||||
Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (coder->PropsSize != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
switch (coder->MethodID)
|
||||
{
|
||||
case k_BCJ:
|
||||
{
|
||||
UInt32 state;
|
||||
x86_Convert_Init(state);
|
||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||
break;
|
||||
}
|
||||
CASE_BRA_CONV(PPC)
|
||||
CASE_BRA_CONV(IA64)
|
||||
CASE_BRA_CONV(SPARC)
|
||||
CASE_BRA_CONV(ARM)
|
||||
CASE_BRA_CONV(ARMT)
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize,
|
||||
ISzAllocPtr allocMain)
|
||||
{
|
||||
SRes res;
|
||||
CSzFolder folder;
|
||||
CSzData sd;
|
||||
|
||||
const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
|
||||
sd.Data = data;
|
||||
sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex];
|
||||
|
||||
res = SzGetNextFolderItem(&folder, &sd);
|
||||
|
||||
if (res != SZ_OK)
|
||||
return res;
|
||||
|
||||
if (sd.Size != 0
|
||||
|| folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex]
|
||||
|| outSize != SzAr_GetFolderUnpackSize(p, folderIndex))
|
||||
return SZ_ERROR_FAIL;
|
||||
{
|
||||
unsigned i;
|
||||
Byte *tempBuf[3] = { 0, 0, 0};
|
||||
|
||||
res = SzFolder_Decode2(&folder, data,
|
||||
&p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]],
|
||||
p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
|
||||
inStream, startPos,
|
||||
outBuffer, (SizeT)outSize, allocMain, tempBuf);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
ISzAlloc_Free(allocMain, tempBuf[i]);
|
||||
|
||||
if (res == SZ_OK)
|
||||
if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))
|
||||
if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex])
|
||||
res = SZ_ERROR_CRC;
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
55
C/7zFile.c
Executable file → Normal file
55
C/7zFile.c
Executable file → Normal file
@@ -1,15 +1,17 @@
|
||||
/* 7zFile.c -- File IO
|
||||
2008-11-22 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "7zFile.h"
|
||||
|
||||
#ifndef USE_WINDOWS_FILE
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#include <errno.h>
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
#else
|
||||
|
||||
/*
|
||||
ReadFile and WriteFile functions in Windows have BUG:
|
||||
@@ -34,6 +36,7 @@ void File_Construct(CSzFile *p)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
|
||||
static WRes File_Open(CSzFile *p, const char *name, int writeMode)
|
||||
{
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
@@ -45,12 +48,32 @@ static WRes File_Open(CSzFile *p, const char *name, int writeMode)
|
||||
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
|
||||
#else
|
||||
p->file = fopen(name, writeMode ? "wb+" : "rb");
|
||||
return (p->file != 0) ? 0 : errno;
|
||||
return (p->file != 0) ? 0 :
|
||||
#ifdef UNDER_CE
|
||||
2; /* ENOENT */
|
||||
#else
|
||||
errno;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -215,49 +238,49 @@ WRes File_GetLength(CSzFile *p, UInt64 *length)
|
||||
|
||||
/* ---------- FileSeqInStream ---------- */
|
||||
|
||||
static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes FileSeqInStream_Read(const ISeqInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CFileSeqInStream *p = (CFileSeqInStream *)pp;
|
||||
CFileSeqInStream *p = CONTAINER_FROM_VTBL(pp, CFileSeqInStream, vt);
|
||||
return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
|
||||
}
|
||||
|
||||
void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
|
||||
{
|
||||
p->s.Read = FileSeqInStream_Read;
|
||||
p->vt.Read = FileSeqInStream_Read;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- FileInStream ---------- */
|
||||
|
||||
static SRes FileInStream_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes FileInStream_Read(const ISeekInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CFileInStream *p = (CFileInStream *)pp;
|
||||
CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
|
||||
return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
|
||||
}
|
||||
|
||||
static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)
|
||||
static SRes FileInStream_Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin)
|
||||
{
|
||||
CFileInStream *p = (CFileInStream *)pp;
|
||||
CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
|
||||
return File_Seek(&p->file, pos, origin);
|
||||
}
|
||||
|
||||
void FileInStream_CreateVTable(CFileInStream *p)
|
||||
{
|
||||
p->s.Read = FileInStream_Read;
|
||||
p->s.Seek = FileInStream_Seek;
|
||||
p->vt.Read = FileInStream_Read;
|
||||
p->vt.Seek = FileInStream_Seek;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- FileOutStream ---------- */
|
||||
|
||||
static size_t FileOutStream_Write(void *pp, const void *data, size_t size)
|
||||
static size_t FileOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size)
|
||||
{
|
||||
CFileOutStream *p = (CFileOutStream *)pp;
|
||||
CFileOutStream *p = CONTAINER_FROM_VTBL(pp, CFileOutStream, vt);
|
||||
File_Write(&p->file, data, &size);
|
||||
return size;
|
||||
}
|
||||
|
||||
void FileOutStream_CreateVTable(CFileOutStream *p)
|
||||
{
|
||||
p->s.Write = FileOutStream_Write;
|
||||
p->vt.Write = FileOutStream_Write;
|
||||
}
|
||||
|
||||
19
C/7zFile.h
Executable file → Normal file
19
C/7zFile.h
Executable file → Normal file
@@ -1,5 +1,5 @@
|
||||
/* 7zFile.h -- File IO
|
||||
2008-11-22 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_FILE_H
|
||||
#define __7Z_FILE_H
|
||||
@@ -14,8 +14,9 @@
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* ---------- File ---------- */
|
||||
|
||||
@@ -29,8 +30,14 @@ typedef struct
|
||||
} 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 */
|
||||
@@ -47,7 +54,7 @@ WRes File_GetLength(CSzFile *p, UInt64 *length);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream s;
|
||||
ISeqInStream vt;
|
||||
CSzFile file;
|
||||
} CFileSeqInStream;
|
||||
|
||||
@@ -56,7 +63,7 @@ void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeekInStream s;
|
||||
ISeekInStream vt;
|
||||
CSzFile file;
|
||||
} CFileInStream;
|
||||
|
||||
@@ -65,10 +72,12 @@ void FileInStream_CreateVTable(CFileInStream *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqOutStream s;
|
||||
ISeqOutStream vt;
|
||||
CSzFile file;
|
||||
} CFileOutStream;
|
||||
|
||||
void FileOutStream_CreateVTable(CFileOutStream *p);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
117
C/7zStream.c
Executable file → Normal file
117
C/7zStream.c
Executable file → Normal file
@@ -1,16 +1,18 @@
|
||||
/* 7zStream.c -- 7z Stream functions
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
RINOK(stream->Read(stream, buf, &processed));
|
||||
RINOK(ISeqInStream_Read(stream, buf, &processed));
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((Byte *)buf + processed);
|
||||
@@ -19,40 +21,42 @@ SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorT
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
|
||||
SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size)
|
||||
{
|
||||
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
}
|
||||
|
||||
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)
|
||||
SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf)
|
||||
{
|
||||
size_t processed = 1;
|
||||
RINOK(stream->Read(stream, buf, &processed));
|
||||
RINOK(ISeqInStream_Read(stream, buf, &processed));
|
||||
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
|
||||
}
|
||||
|
||||
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
|
||||
|
||||
|
||||
SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset)
|
||||
{
|
||||
Int64 t = offset;
|
||||
return stream->Seek(stream, &t, SZ_SEEK_SET);
|
||||
return ILookInStream_Seek(stream, &t, SZ_SEEK_SET);
|
||||
}
|
||||
|
||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
|
||||
SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size)
|
||||
{
|
||||
void *lookBuf;
|
||||
const void *lookBuf;
|
||||
if (*size == 0)
|
||||
return SZ_OK;
|
||||
RINOK(stream->Look(stream, &lookBuf, size));
|
||||
RINOK(ILookInStream_Look(stream, &lookBuf, size));
|
||||
memcpy(buf, lookBuf, *size);
|
||||
return stream->Skip(stream, *size);
|
||||
return ILookInStream_Skip(stream, *size);
|
||||
}
|
||||
|
||||
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
RINOK(stream->Read(stream, buf, &processed));
|
||||
RINOK(ILookInStream_Read(stream, buf, &processed));
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((Byte *)buf + processed);
|
||||
@@ -61,61 +65,67 @@ SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes erro
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
|
||||
SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size)
|
||||
{
|
||||
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
}
|
||||
|
||||
static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size)
|
||||
|
||||
|
||||
#define GET_LookToRead2 CLookToRead2 *p = CONTAINER_FROM_VTBL(pp, CLookToRead2, vt);
|
||||
|
||||
static SRes LookToRead2_Look_Lookahead(const ILookInStream *pp, const void **buf, size_t *size)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
GET_LookToRead2
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size > 0)
|
||||
if (size2 == 0 && *size != 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
size2 = LookToRead_BUF_SIZE;
|
||||
res = p->realStream->Read(p->realStream, p->buf, &size2);
|
||||
p->size = 0;
|
||||
size2 = p->bufSize;
|
||||
res = ISeekInStream_Read(p->realStream, p->buf, &size2);
|
||||
p->size = size2;
|
||||
}
|
||||
if (size2 < *size)
|
||||
if (*size > size2)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size)
|
||||
static SRes LookToRead2_Look_Exact(const ILookInStream *pp, const void **buf, size_t *size)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
GET_LookToRead2
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size > 0)
|
||||
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);
|
||||
p->size = 0;
|
||||
if (*size > p->bufSize)
|
||||
*size = p->bufSize;
|
||||
res = ISeekInStream_Read(p->realStream, p->buf, size);
|
||||
size2 = p->size = *size;
|
||||
}
|
||||
if (size2 < *size)
|
||||
if (*size > size2)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Skip(void *pp, size_t offset)
|
||||
static SRes LookToRead2_Skip(const ILookInStream *pp, size_t offset)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
GET_LookToRead2
|
||||
p->pos += offset;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes LookToRead2_Read(const ILookInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
GET_LookToRead2
|
||||
size_t rem = p->size - p->pos;
|
||||
if (rem == 0)
|
||||
return p->realStream->Read(p->realStream, buf, size);
|
||||
return ISeekInStream_Read(p->realStream, buf, size);
|
||||
if (rem > *size)
|
||||
rem = *size;
|
||||
memcpy(buf, p->buf + p->pos, rem);
|
||||
@@ -124,46 +134,43 @@ static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)
|
||||
static SRes LookToRead2_Seek(const ILookInStream *pp, Int64 *pos, ESzSeek origin)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
GET_LookToRead2
|
||||
p->pos = p->size = 0;
|
||||
return p->realStream->Seek(p->realStream, pos, origin);
|
||||
return ISeekInStream_Seek(p->realStream, pos, origin);
|
||||
}
|
||||
|
||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
|
||||
void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead)
|
||||
{
|
||||
p->s.Look = lookahead ?
|
||||
LookToRead_Look_Lookahead :
|
||||
LookToRead_Look_Exact;
|
||||
p->s.Skip = LookToRead_Skip;
|
||||
p->s.Read = LookToRead_Read;
|
||||
p->s.Seek = LookToRead_Seek;
|
||||
p->vt.Look = lookahead ?
|
||||
LookToRead2_Look_Lookahead :
|
||||
LookToRead2_Look_Exact;
|
||||
p->vt.Skip = LookToRead2_Skip;
|
||||
p->vt.Read = LookToRead2_Read;
|
||||
p->vt.Seek = LookToRead2_Seek;
|
||||
}
|
||||
|
||||
void LookToRead_Init(CLookToRead *p)
|
||||
{
|
||||
p->pos = p->size = 0;
|
||||
}
|
||||
|
||||
static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
|
||||
|
||||
static SRes SecToLook_Read(const ISeqInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CSecToLook *p = (CSecToLook *)pp;
|
||||
CSecToLook *p = CONTAINER_FROM_VTBL(pp, CSecToLook, vt);
|
||||
return LookInStream_LookRead(p->realStream, buf, size);
|
||||
}
|
||||
|
||||
void SecToLook_CreateVTable(CSecToLook *p)
|
||||
{
|
||||
p->s.Read = SecToLook_Read;
|
||||
p->vt.Read = SecToLook_Read;
|
||||
}
|
||||
|
||||
static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes SecToRead_Read(const ISeqInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CSecToRead *p = (CSecToRead *)pp;
|
||||
return p->realStream->Read(p->realStream, buf, size);
|
||||
CSecToRead *p = CONTAINER_FROM_VTBL(pp, CSecToRead, vt);
|
||||
return ILookInStream_Read(p->realStream, buf, size);
|
||||
}
|
||||
|
||||
void SecToRead_CreateVTable(CSecToRead *p)
|
||||
{
|
||||
p->s.Read = SecToRead_Read;
|
||||
p->vt.Read = SecToRead_Read;
|
||||
}
|
||||
|
||||
375
C/7zTypes.h
Normal file
375
C/7zTypes.h
Normal file
@@ -0,0 +1,375 @@
|
||||
/* 7zTypes.h -- Basic types
|
||||
2018-08-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_TYPES_H
|
||||
#define __7Z_TYPES_H
|
||||
|
||||
#ifdef _WIN32
|
||||
/* #include <windows.h> */
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef EXTERN_C_BEGIN
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN_C_BEGIN extern "C" {
|
||||
#define EXTERN_C_END }
|
||||
#else
|
||||
#define EXTERN_C_BEGIN
|
||||
#define EXTERN_C_END
|
||||
#endif
|
||||
#endif
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define SZ_OK 0
|
||||
|
||||
#define SZ_ERROR_DATA 1
|
||||
#define SZ_ERROR_MEM 2
|
||||
#define SZ_ERROR_CRC 3
|
||||
#define SZ_ERROR_UNSUPPORTED 4
|
||||
#define SZ_ERROR_PARAM 5
|
||||
#define SZ_ERROR_INPUT_EOF 6
|
||||
#define SZ_ERROR_OUTPUT_EOF 7
|
||||
#define SZ_ERROR_READ 8
|
||||
#define SZ_ERROR_WRITE 9
|
||||
#define SZ_ERROR_PROGRESS 10
|
||||
#define SZ_ERROR_FAIL 11
|
||||
#define SZ_ERROR_THREAD 12
|
||||
|
||||
#define SZ_ERROR_ARCHIVE 16
|
||||
#define SZ_ERROR_NO_ARCHIVE 17
|
||||
|
||||
typedef int SRes;
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* typedef DWORD WRes; */
|
||||
typedef unsigned WRes;
|
||||
#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)
|
||||
|
||||
#else
|
||||
|
||||
typedef int WRes;
|
||||
#define MY__FACILITY_WIN32 7
|
||||
#define MY__FACILITY__WRes MY__FACILITY_WIN32
|
||||
#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000)))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef RINOK
|
||||
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
|
||||
#endif
|
||||
|
||||
typedef unsigned char Byte;
|
||||
typedef short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
|
||||
#ifdef _LZMA_UINT32_IS_ULONG
|
||||
typedef long Int32;
|
||||
typedef unsigned long UInt32;
|
||||
#else
|
||||
typedef int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
#endif
|
||||
|
||||
#ifdef _SZ_NO_INT_64
|
||||
|
||||
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
||||
NOTES: Some code will work incorrectly in that case! */
|
||||
|
||||
typedef long Int64;
|
||||
typedef unsigned long UInt64;
|
||||
|
||||
#else
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
#define UINT64_CONST(n) n
|
||||
#else
|
||||
typedef long long int Int64;
|
||||
typedef unsigned long long int UInt64;
|
||||
#define UINT64_CONST(n) n ## ULL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
||||
typedef UInt32 SizeT;
|
||||
#else
|
||||
typedef size_t SizeT;
|
||||
#endif
|
||||
|
||||
typedef int BoolInt;
|
||||
/* typedef BoolInt Bool; */
|
||||
#define True 1
|
||||
#define False 0
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define MY_STD_CALL __stdcall
|
||||
#else
|
||||
#define MY_STD_CALL
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
#define MY_NO_INLINE __declspec(noinline)
|
||||
#else
|
||||
#define MY_NO_INLINE
|
||||
#endif
|
||||
|
||||
#define MY_FORCE_INLINE __forceinline
|
||||
|
||||
#define MY_CDECL __cdecl
|
||||
#define MY_FAST_CALL __fastcall
|
||||
|
||||
#else
|
||||
|
||||
#define MY_NO_INLINE
|
||||
#define MY_FORCE_INLINE
|
||||
#define MY_CDECL
|
||||
#define MY_FAST_CALL
|
||||
|
||||
/* inline keyword : for C++ / C99 */
|
||||
|
||||
/* GCC, clang: */
|
||||
/*
|
||||
#if defined (__GNUC__) && (__GNUC__ >= 4)
|
||||
#define MY_FORCE_INLINE __attribute__((always_inline))
|
||||
#define MY_NO_INLINE __attribute__((noinline))
|
||||
#endif
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* The following interfaces use first parameter as pointer to structure */
|
||||
|
||||
typedef struct IByteIn IByteIn;
|
||||
struct IByteIn
|
||||
{
|
||||
Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */
|
||||
};
|
||||
#define IByteIn_Read(p) (p)->Read(p)
|
||||
|
||||
|
||||
typedef struct IByteOut IByteOut;
|
||||
struct IByteOut
|
||||
{
|
||||
void (*Write)(const IByteOut *p, Byte b);
|
||||
};
|
||||
#define IByteOut_Write(p, b) (p)->Write(p, b)
|
||||
|
||||
|
||||
typedef struct ISeqInStream ISeqInStream;
|
||||
struct ISeqInStream
|
||||
{
|
||||
SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size);
|
||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||
(output(*size) < input(*size)) is allowed */
|
||||
};
|
||||
#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||
|
||||
/* it can return SZ_ERROR_INPUT_EOF */
|
||||
SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size);
|
||||
SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf);
|
||||
|
||||
|
||||
typedef struct ISeqOutStream ISeqOutStream;
|
||||
struct ISeqOutStream
|
||||
{
|
||||
size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size);
|
||||
/* Returns: result - the number of actually written bytes.
|
||||
(result < size) means error */
|
||||
};
|
||||
#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SZ_SEEK_SET = 0,
|
||||
SZ_SEEK_CUR = 1,
|
||||
SZ_SEEK_END = 2
|
||||
} ESzSeek;
|
||||
|
||||
|
||||
typedef struct ISeekInStream ISeekInStream;
|
||||
struct ISeekInStream
|
||||
{
|
||||
SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
||||
SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin);
|
||||
};
|
||||
#define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||
#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
|
||||
|
||||
|
||||
typedef struct ILookInStream ILookInStream;
|
||||
struct ILookInStream
|
||||
{
|
||||
SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size);
|
||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||
(output(*size) > input(*size)) is not allowed
|
||||
(output(*size) < input(*size)) is allowed */
|
||||
SRes (*Skip)(const ILookInStream *p, size_t offset);
|
||||
/* offset must be <= output(*size) of Look */
|
||||
|
||||
SRes (*Read)(const ILookInStream *p, void *buf, size_t *size);
|
||||
/* reads directly (without buffer). It's same as ISeqInStream::Read */
|
||||
SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin);
|
||||
};
|
||||
|
||||
#define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size)
|
||||
#define ILookInStream_Skip(p, offset) (p)->Skip(p, offset)
|
||||
#define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||
#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
|
||||
|
||||
|
||||
SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size);
|
||||
SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset);
|
||||
|
||||
/* reads via ILookInStream::Read */
|
||||
SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size);
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ILookInStream vt;
|
||||
const ISeekInStream *realStream;
|
||||
|
||||
size_t pos;
|
||||
size_t size; /* it's data size */
|
||||
|
||||
/* the following variables must be set outside */
|
||||
Byte *buf;
|
||||
size_t bufSize;
|
||||
} CLookToRead2;
|
||||
|
||||
void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead);
|
||||
|
||||
#define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; }
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream vt;
|
||||
const ILookInStream *realStream;
|
||||
} CSecToLook;
|
||||
|
||||
void SecToLook_CreateVTable(CSecToLook *p);
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream vt;
|
||||
const ILookInStream *realStream;
|
||||
} CSecToRead;
|
||||
|
||||
void SecToRead_CreateVTable(CSecToRead *p);
|
||||
|
||||
|
||||
typedef struct ICompressProgress ICompressProgress;
|
||||
|
||||
struct ICompressProgress
|
||||
{
|
||||
SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize);
|
||||
/* Returns: result. (result != SZ_OK) means break.
|
||||
Value (UInt64)(Int64)-1 for size means unknown value. */
|
||||
};
|
||||
#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)
|
||||
|
||||
|
||||
|
||||
typedef struct ISzAlloc ISzAlloc;
|
||||
typedef const ISzAlloc * ISzAllocPtr;
|
||||
|
||||
struct ISzAlloc
|
||||
{
|
||||
void *(*Alloc)(ISzAllocPtr p, size_t size);
|
||||
void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */
|
||||
};
|
||||
|
||||
#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size)
|
||||
#define ISzAlloc_Free(p, a) (p)->Free(p, a)
|
||||
|
||||
/* deprecated */
|
||||
#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size)
|
||||
#define IAlloc_Free(p, a) ISzAlloc_Free(p, a)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef MY_offsetof
|
||||
#ifdef offsetof
|
||||
#define MY_offsetof(type, m) offsetof(type, m)
|
||||
/*
|
||||
#define MY_offsetof(type, m) FIELD_OFFSET(type, m)
|
||||
*/
|
||||
#else
|
||||
#define MY_offsetof(type, m) ((size_t)&(((type *)0)->m))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef MY_container_of
|
||||
|
||||
/*
|
||||
#define MY_container_of(ptr, type, m) container_of(ptr, type, m)
|
||||
#define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m)
|
||||
#define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m)))
|
||||
#define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m))))
|
||||
*/
|
||||
|
||||
/*
|
||||
GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly"
|
||||
GCC 3.4.4 : classes with constructor
|
||||
GCC 4.8.1 : classes with non-public variable members"
|
||||
*/
|
||||
|
||||
#define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m)))
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr))
|
||||
|
||||
/*
|
||||
#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
|
||||
*/
|
||||
#define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m)
|
||||
|
||||
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
|
||||
/*
|
||||
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define CHAR_PATH_SEPARATOR '\\'
|
||||
#define WCHAR_PATH_SEPARATOR L'\\'
|
||||
#define STRING_PATH_SEPARATOR "\\"
|
||||
#define WSTRING_PATH_SEPARATOR L"\\"
|
||||
|
||||
#else
|
||||
|
||||
#define CHAR_PATH_SEPARATOR '/'
|
||||
#define WCHAR_PATH_SEPARATOR L'/'
|
||||
#define STRING_PATH_SEPARATOR "/"
|
||||
#define WSTRING_PATH_SEPARATOR L"/"
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
32
C/7zVersion.h
Executable file → Normal file
32
C/7zVersion.h
Executable file → Normal file
@@ -1,7 +1,27 @@
|
||||
#define MY_VER_MAJOR 4
|
||||
#define MY_VER_MINOR 63
|
||||
#define MY_VER_MAJOR 19
|
||||
#define MY_VER_MINOR 00
|
||||
#define MY_VER_BUILD 0
|
||||
#define MY_VERSION "4.63"
|
||||
#define MY_DATE "2008-12-31"
|
||||
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
|
||||
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE
|
||||
#define MY_VERSION_NUMBERS "19.00"
|
||||
#define MY_VERSION MY_VERSION_NUMBERS
|
||||
|
||||
#ifdef MY_CPU_NAME
|
||||
#define MY_VERSION_CPU MY_VERSION " (" MY_CPU_NAME ")"
|
||||
#else
|
||||
#define MY_VERSION_CPU MY_VERSION
|
||||
#endif
|
||||
|
||||
#define MY_DATE "2019-02-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-2018 Igor Pavlov"
|
||||
|
||||
#ifdef USE_COPYRIGHT_CR
|
||||
#define MY_COPYRIGHT MY_COPYRIGHT_CR
|
||||
#else
|
||||
#define MY_COPYRIGHT MY_COPYRIGHT_PD
|
||||
#endif
|
||||
|
||||
#define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE
|
||||
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE
|
||||
|
||||
55
C/7zVersion.rc
Normal file
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")
|
||||
238
C/Aes.c
Executable file → Normal file
238
C/Aes.c
Executable file → Normal file
@@ -1,13 +1,13 @@
|
||||
/* Aes.c -- AES encryption / decryption
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2017-01-24 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "Aes.h"
|
||||
#include "CpuArch.h"
|
||||
|
||||
static UInt32 T[256 * 4];
|
||||
static Byte Sbox[256] = {
|
||||
static const Byte Sbox[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
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,
|
||||
@@ -25,10 +25,22 @@ static Byte Sbox[256] = {
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
|
||||
|
||||
void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
|
||||
void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
|
||||
AES_CODE_FUNC g_AesCbc_Encode;
|
||||
AES_CODE_FUNC g_AesCbc_Decode;
|
||||
AES_CODE_FUNC g_AesCtr_Code;
|
||||
|
||||
static UInt32 D[256 * 4];
|
||||
static Byte InvS[256];
|
||||
|
||||
static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
|
||||
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)
|
||||
|
||||
@@ -37,23 +49,30 @@ static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0
|
||||
#define gb0(x) ( (x) & 0xFF)
|
||||
#define gb1(x) (((x) >> ( 8)) & 0xFF)
|
||||
#define gb2(x) (((x) >> (16)) & 0xFF)
|
||||
#define gb3(x) (((x) >> (24)) & 0xFF)
|
||||
#define gb3(x) (((x) >> (24)))
|
||||
|
||||
#define gb(n, x) gb ## n(x)
|
||||
|
||||
#define TT(x) (T + (x << 8))
|
||||
#define DD(x) (D + (x << 8))
|
||||
|
||||
|
||||
void AesGenTables(void)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < 256; i++)
|
||||
InvS[Sbox[i]] = (Byte)i;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
{
|
||||
UInt32 a1 = Sbox[i];
|
||||
UInt32 a2 = xtime(a1);
|
||||
UInt32 a3 = xtime(a1) ^ a1;
|
||||
T[ i] = Ui32(a2, a1, a1, a3);
|
||||
T[0x100 + i] = Ui32(a3, a2, a1, a1);
|
||||
T[0x200 + i] = Ui32(a1, a3, a2, a1);
|
||||
T[0x300 + i] = Ui32(a1, a1, a3, a2);
|
||||
UInt32 a3 = a2 ^ a1;
|
||||
TT(0)[i] = Ui32(a2, a1, a1, a3);
|
||||
TT(1)[i] = Ui32(a3, a2, a1, a1);
|
||||
TT(2)[i] = Ui32(a1, a3, a2, a1);
|
||||
TT(3)[i] = Ui32(a1, a1, a3, a2);
|
||||
}
|
||||
{
|
||||
UInt32 a1 = InvS[i];
|
||||
@@ -64,62 +83,77 @@ void AesGenTables(void)
|
||||
UInt32 aB = a8 ^ a2 ^ a1;
|
||||
UInt32 aD = a8 ^ a4 ^ a1;
|
||||
UInt32 aE = a8 ^ a4 ^ a2;
|
||||
D[ i] = Ui32(aE, a9, aD, aB);
|
||||
D[0x100 + i] = Ui32(aB, aE, a9, aD);
|
||||
D[0x200 + i] = Ui32(aD, aB, aE, a9);
|
||||
D[0x300 + i] = Ui32(a9, aD, aB, aE);
|
||||
DD(0)[i] = Ui32(aE, a9, aD, aB);
|
||||
DD(1)[i] = Ui32(aB, aE, a9, aD);
|
||||
DD(2)[i] = Ui32(aD, aB, aE, a9);
|
||||
DD(3)[i] = Ui32(a9, aD, aB, aE);
|
||||
}
|
||||
}
|
||||
|
||||
g_AesCbc_Encode = AesCbc_Encode;
|
||||
g_AesCbc_Decode = AesCbc_Decode;
|
||||
g_AesCtr_Code = AesCtr_Code;
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
if (CPU_Is_Aes_Supported())
|
||||
{
|
||||
g_AesCbc_Encode = AesCbc_Encode_Intel;
|
||||
g_AesCbc_Decode = AesCbc_Decode_Intel;
|
||||
g_AesCtr_Code = AesCtr_Code_Intel;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])]
|
||||
|
||||
#define HT(i, x, s) TT(x)[gb(x, s[(i + x) & 3])]
|
||||
|
||||
#define HT4(m, i, s, p) m[i] = \
|
||||
HT(i, 0, s) ^ \
|
||||
HT(i, 1, s) ^ \
|
||||
HT(i, 2, s) ^ \
|
||||
HT(i, 3, s) ^ w[p + i]
|
||||
/* such order (2031) in HT16 is for VC6/K8 speed optimization) */
|
||||
#define HT16(m, s, p) \
|
||||
HT4(m, 2, s, p); \
|
||||
HT4(m, 0, s, p); \
|
||||
HT4(m, 3, s, p); \
|
||||
HT4(m, 1, s, p); \
|
||||
|
||||
#define FT(i, x) Sbox[gb ## x(m[(i + x) & 3])]
|
||||
#define HT16(m, s, p) \
|
||||
HT4(m, 0, s, p); \
|
||||
HT4(m, 1, s, p); \
|
||||
HT4(m, 2, s, p); \
|
||||
HT4(m, 3, s, p); \
|
||||
|
||||
#define FT(i, x) Sbox[gb(x, m[(i + x) & 3])]
|
||||
#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i];
|
||||
|
||||
#define HD(i, x, s) (D + (x << 8))[gb ## x(s[(i - x) & 3])]
|
||||
|
||||
#define HD(i, x, s) DD(x)[gb(x, s[(i - x) & 3])]
|
||||
|
||||
#define HD4(m, i, s, p) m[i] = \
|
||||
HD(i, 0, s) ^ \
|
||||
HD(i, 1, s) ^ \
|
||||
HD(i, 2, s) ^ \
|
||||
HD(i, 3, s) ^ w[p + i];
|
||||
/* such order (0231) in HD16 is for VC6/K8 speed optimization) */
|
||||
|
||||
#define HD16(m, s, p) \
|
||||
HD4(m, 0, s, p); \
|
||||
HD4(m, 1, s, p); \
|
||||
HD4(m, 2, s, p); \
|
||||
HD4(m, 3, s, p); \
|
||||
HD4(m, 1, s, p); \
|
||||
|
||||
#define FD(i, x) InvS[gb ## x(m[(i - x) & 3])]
|
||||
#define FD(i, x) InvS[gb(x, m[(i - x) & 3])]
|
||||
#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i];
|
||||
|
||||
void Aes_SetKeyEncode(CAes *p, const Byte *key, unsigned keySize)
|
||||
void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize)
|
||||
{
|
||||
unsigned i, wSize;
|
||||
UInt32 *w;
|
||||
wSize = keySize + 28;
|
||||
keySize /= 4;
|
||||
p->numRounds2 = keySize / 2 + 3;
|
||||
|
||||
wSize = (p->numRounds2 * 2 + 1) * 4;
|
||||
w = p->rkey;
|
||||
w[0] = ((UInt32)keySize / 2) + 3;
|
||||
w += 4;
|
||||
|
||||
for (i = 0; i < keySize; i++, key += 4)
|
||||
w[i] = Ui32(key[0], key[1], key[2], key[3]);
|
||||
w[i] = GetUi32(key);
|
||||
|
||||
for (; i < wSize; i++)
|
||||
{
|
||||
UInt32 t = w[i - 1];
|
||||
UInt32 t = w[(size_t)i - 1];
|
||||
unsigned rem = i % keySize;
|
||||
if (rem == 0)
|
||||
t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]);
|
||||
@@ -129,28 +163,33 @@ void Aes_SetKeyEncode(CAes *p, const Byte *key, unsigned keySize)
|
||||
}
|
||||
}
|
||||
|
||||
void Aes_SetKeyDecode(CAes *p, const Byte *key, unsigned keySize)
|
||||
void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)
|
||||
{
|
||||
unsigned i, num;
|
||||
UInt32 *w;
|
||||
Aes_SetKeyEncode(p, key, keySize);
|
||||
num = p->numRounds2 * 8 - 4;
|
||||
w = p->rkey + 4;
|
||||
Aes_SetKey_Enc(w, key, keySize);
|
||||
num = keySize + 20;
|
||||
w += 8;
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
UInt32 r = w[i];
|
||||
w[i] =
|
||||
D[ Sbox[gb0(r)]] ^
|
||||
D[0x100 + Sbox[gb1(r)]] ^
|
||||
D[0x200 + Sbox[gb2(r)]] ^
|
||||
D[0x300 + Sbox[gb3(r)]];
|
||||
DD(0)[Sbox[gb0(r)]] ^
|
||||
DD(1)[Sbox[gb1(r)]] ^
|
||||
DD(2)[Sbox[gb2(r)]] ^
|
||||
DD(3)[Sbox[gb3(r)]];
|
||||
}
|
||||
}
|
||||
|
||||
static void AesEncode32(UInt32 *dest, const UInt32 *src, const UInt32 *w, unsigned numRounds2)
|
||||
/* Aes_Encode and Aes_Decode functions work with little-endian words.
|
||||
src and dest are pointers to 4 UInt32 words.
|
||||
src and dest can point to same block */
|
||||
|
||||
static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src)
|
||||
{
|
||||
UInt32 s[4];
|
||||
UInt32 m[4];
|
||||
UInt32 numRounds2 = w[0];
|
||||
w += 4;
|
||||
s[0] = src[0] ^ w[0];
|
||||
s[1] = src[1] ^ w[1];
|
||||
s[2] = src[2] ^ w[2];
|
||||
@@ -168,11 +207,12 @@ static void AesEncode32(UInt32 *dest, const UInt32 *src, const UInt32 *w, unsign
|
||||
FT4(0); FT4(1); FT4(2); FT4(3);
|
||||
}
|
||||
|
||||
static void AesDecode32(UInt32 *dest, const UInt32 *src, const UInt32 *w, unsigned numRounds2)
|
||||
static void Aes_Decode(const UInt32 *w, UInt32 *dest, const UInt32 *src)
|
||||
{
|
||||
UInt32 s[4];
|
||||
UInt32 m[4];
|
||||
w += numRounds2 * 8;
|
||||
UInt32 numRounds2 = w[0];
|
||||
w += 4 + numRounds2 * 8;
|
||||
s[0] = src[0] ^ w[0];
|
||||
s[1] = src[1] ^ w[1];
|
||||
s[2] = src[2] ^ w[2];
|
||||
@@ -188,75 +228,79 @@ static void AesDecode32(UInt32 *dest, const UInt32 *src, const UInt32 *w, unsign
|
||||
FD4(0); FD4(1); FD4(2); FD4(3);
|
||||
}
|
||||
|
||||
void Aes_Encode32(const CAes *p, UInt32 *dest, const UInt32 *src)
|
||||
{
|
||||
AesEncode32(dest, src, p->rkey, p->numRounds2);
|
||||
}
|
||||
|
||||
void Aes_Decode32(const CAes *p, UInt32 *dest, const UInt32 *src)
|
||||
{
|
||||
AesDecode32(dest, src, p->rkey, p->numRounds2);
|
||||
}
|
||||
|
||||
void AesCbc_Init(CAesCbc *p, const Byte *iv)
|
||||
void AesCbc_Init(UInt32 *p, const Byte *iv)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; i++)
|
||||
p->prev[i] = GetUi32(iv + i * 4);
|
||||
p[i] = GetUi32(iv + i * 4);
|
||||
}
|
||||
|
||||
SizeT AesCbc_Encode(CAesCbc *p, Byte *data, SizeT size)
|
||||
void MY_FAST_CALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks)
|
||||
{
|
||||
SizeT i;
|
||||
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)
|
||||
for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)
|
||||
{
|
||||
p->prev[0] ^= GetUi32(data);
|
||||
p->prev[1] ^= GetUi32(data + 4);
|
||||
p->prev[2] ^= GetUi32(data + 8);
|
||||
p->prev[3] ^= GetUi32(data + 12);
|
||||
p[0] ^= GetUi32(data);
|
||||
p[1] ^= GetUi32(data + 4);
|
||||
p[2] ^= GetUi32(data + 8);
|
||||
p[3] ^= GetUi32(data + 12);
|
||||
|
||||
AesEncode32(p->prev, p->prev, p->aes.rkey, p->aes.numRounds2);
|
||||
Aes_Encode(p + 4, p, p);
|
||||
|
||||
SetUi32(data, p->prev[0]);
|
||||
SetUi32(data + 4, p->prev[1]);
|
||||
SetUi32(data + 8, p->prev[2]);
|
||||
SetUi32(data + 12, p->prev[3]);
|
||||
SetUi32(data, p[0]);
|
||||
SetUi32(data + 4, p[1]);
|
||||
SetUi32(data + 8, p[2]);
|
||||
SetUi32(data + 12, p[3]);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
SizeT AesCbc_Decode(CAesCbc *p, Byte *data, SizeT size)
|
||||
void MY_FAST_CALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks)
|
||||
{
|
||||
SizeT i;
|
||||
UInt32 in[4], out[4];
|
||||
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)
|
||||
for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)
|
||||
{
|
||||
in[0] = GetUi32(data);
|
||||
in[1] = GetUi32(data + 4);
|
||||
in[2] = GetUi32(data + 8);
|
||||
in[3] = GetUi32(data + 12);
|
||||
|
||||
Aes_Decode(p + 4, out, in);
|
||||
|
||||
SetUi32(data, p[0] ^ out[0]);
|
||||
SetUi32(data + 4, p[1] ^ out[1]);
|
||||
SetUi32(data + 8, p[2] ^ out[2]);
|
||||
SetUi32(data + 12, p[3] ^ out[3]);
|
||||
|
||||
AesDecode32(out, in, p->aes.rkey, p->aes.numRounds2);
|
||||
|
||||
SetUi32(data, p->prev[0] ^ out[0]);
|
||||
SetUi32(data + 4, p->prev[1] ^ out[1]);
|
||||
SetUi32(data + 8, p->prev[2] ^ out[2]);
|
||||
SetUi32(data + 12, p->prev[3] ^ out[3]);
|
||||
|
||||
p->prev[0] = in[0];
|
||||
p->prev[1] = in[1];
|
||||
p->prev[2] = in[2];
|
||||
p->prev[3] = in[3];
|
||||
p[0] = in[0];
|
||||
p[1] = in[1];
|
||||
p[2] = in[2];
|
||||
p[3] = in[3];
|
||||
}
|
||||
}
|
||||
|
||||
void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)
|
||||
{
|
||||
for (; numBlocks != 0; numBlocks--)
|
||||
{
|
||||
UInt32 temp[4];
|
||||
unsigned i;
|
||||
|
||||
if (++p[0] == 0)
|
||||
p[1]++;
|
||||
|
||||
Aes_Encode(p + 4, temp, p);
|
||||
|
||||
for (i = 0; i < 4; i++, data += 4)
|
||||
{
|
||||
UInt32 t = temp[i];
|
||||
|
||||
#ifdef MY_CPU_LE_UNALIGN
|
||||
*((UInt32 *)data) ^= t;
|
||||
#else
|
||||
data[0] ^= (t & 0xFF);
|
||||
data[1] ^= ((t >> 8) & 0xFF);
|
||||
data[2] ^= ((t >> 16) & 0xFF);
|
||||
data[3] ^= ((t >> 24));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
54
C/Aes.h
Executable file → Normal file
54
C/Aes.h
Executable file → Normal file
@@ -1,48 +1,38 @@
|
||||
/* Aes.h -- AES encryption / decryption
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __AES_H
|
||||
#define __AES_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned numRounds2; /* = numRounds / 2 */
|
||||
UInt32 rkey[(14 + 1) * 4];
|
||||
} CAes;
|
||||
|
||||
/* Call AesGenTables one time before other AES functions */
|
||||
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) */
|
||||
void Aes_SetKeyEncode(CAes *p, const Byte *key, unsigned keySize);
|
||||
void Aes_SetKeyDecode(CAes *p, const Byte *key, unsigned keySize);
|
||||
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);
|
||||
|
||||
/* Aes_Encode32 and Aes_Decode32 functions work with little-endian words.
|
||||
src and dest are pointers to 4 UInt32 words.
|
||||
arc and dest can point to same block */
|
||||
void Aes_Encode32(const CAes *p, UInt32 *dest, const UInt32 *src);
|
||||
void Aes_Decode32(const CAes *p, UInt32 *dest, const UInt32 *src);
|
||||
/* 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;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 prev[4];
|
||||
CAes aes;
|
||||
} CAesCbc;
|
||||
|
||||
void AesCbc_Init(CAesCbc *p, const Byte *iv); /* iv size is AES_BLOCK_SIZE */
|
||||
|
||||
/* AesCbc_Encode and AesCbc_Decode:
|
||||
if (res <= size): Filter have converted res bytes
|
||||
if (res > size): Filter have not converted anything. And it needs at
|
||||
least res = AES_BLOCK_SIZE bytes to convert one block */
|
||||
|
||||
SizeT AesCbc_Encode(CAesCbc *p, Byte *data, SizeT size);
|
||||
SizeT AesCbc_Decode(CAesCbc *p, Byte *data, SizeT size);
|
||||
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
|
||||
2017-06-08 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
#if (_MSC_VER > 1500) || (_MSC_FULL_VER >= 150030729)
|
||||
#define USE_INTEL_AES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_INTEL_AES
|
||||
|
||||
#include <wmmintrin.h>
|
||||
|
||||
void MY_FAST_CALL AesCbc_Encode_Intel(__m128i *p, __m128i *data, size_t numBlocks)
|
||||
{
|
||||
__m128i m = *p;
|
||||
for (; numBlocks != 0; numBlocks--, data++)
|
||||
{
|
||||
UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;
|
||||
const __m128i *w = p + 3;
|
||||
m = _mm_xor_si128(m, *data);
|
||||
m = _mm_xor_si128(m, p[2]);
|
||||
do
|
||||
{
|
||||
m = _mm_aesenc_si128(m, w[0]);
|
||||
m = _mm_aesenc_si128(m, w[1]);
|
||||
w += 2;
|
||||
}
|
||||
while (--numRounds2 != 0);
|
||||
m = _mm_aesenc_si128(m, w[0]);
|
||||
m = _mm_aesenclast_si128(m, w[1]);
|
||||
*data = m;
|
||||
}
|
||||
*p = m;
|
||||
}
|
||||
|
||||
#define NUM_WAYS 3
|
||||
|
||||
#define AES_OP_W(op, n) { \
|
||||
const __m128i t = w[n]; \
|
||||
m0 = op(m0, t); \
|
||||
m1 = op(m1, t); \
|
||||
m2 = op(m2, t); \
|
||||
}
|
||||
|
||||
#define AES_DEC(n) AES_OP_W(_mm_aesdec_si128, n)
|
||||
#define AES_DEC_LAST(n) AES_OP_W(_mm_aesdeclast_si128, n)
|
||||
#define AES_ENC(n) AES_OP_W(_mm_aesenc_si128, n)
|
||||
#define AES_ENC_LAST(n) AES_OP_W(_mm_aesenclast_si128, n)
|
||||
|
||||
void MY_FAST_CALL AesCbc_Decode_Intel(__m128i *p, __m128i *data, size_t numBlocks)
|
||||
{
|
||||
__m128i iv = *p;
|
||||
for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)
|
||||
{
|
||||
UInt32 numRounds2 = *(const UInt32 *)(p + 1);
|
||||
const __m128i *w = p + numRounds2 * 2;
|
||||
__m128i m0, m1, m2;
|
||||
{
|
||||
const __m128i t = w[2];
|
||||
m0 = _mm_xor_si128(t, data[0]);
|
||||
m1 = _mm_xor_si128(t, data[1]);
|
||||
m2 = _mm_xor_si128(t, data[2]);
|
||||
}
|
||||
numRounds2--;
|
||||
do
|
||||
{
|
||||
AES_DEC(1)
|
||||
AES_DEC(0)
|
||||
w -= 2;
|
||||
}
|
||||
while (--numRounds2 != 0);
|
||||
AES_DEC(1)
|
||||
AES_DEC_LAST(0)
|
||||
|
||||
{
|
||||
__m128i t;
|
||||
t = _mm_xor_si128(m0, iv); iv = data[0]; data[0] = t;
|
||||
t = _mm_xor_si128(m1, iv); iv = data[1]; data[1] = t;
|
||||
t = _mm_xor_si128(m2, iv); iv = data[2]; data[2] = t;
|
||||
}
|
||||
}
|
||||
for (; numBlocks != 0; numBlocks--, data++)
|
||||
{
|
||||
UInt32 numRounds2 = *(const UInt32 *)(p + 1);
|
||||
const __m128i *w = p + numRounds2 * 2;
|
||||
__m128i m = _mm_xor_si128(w[2], *data);
|
||||
numRounds2--;
|
||||
do
|
||||
{
|
||||
m = _mm_aesdec_si128(m, w[1]);
|
||||
m = _mm_aesdec_si128(m, w[0]);
|
||||
w -= 2;
|
||||
}
|
||||
while (--numRounds2 != 0);
|
||||
m = _mm_aesdec_si128(m, w[1]);
|
||||
m = _mm_aesdeclast_si128(m, w[0]);
|
||||
|
||||
m = _mm_xor_si128(m, iv);
|
||||
iv = *data;
|
||||
*data = m;
|
||||
}
|
||||
*p = iv;
|
||||
}
|
||||
|
||||
void MY_FAST_CALL AesCtr_Code_Intel(__m128i *p, __m128i *data, size_t numBlocks)
|
||||
{
|
||||
__m128i ctr = *p;
|
||||
__m128i one;
|
||||
one.m128i_u64[0] = 1;
|
||||
one.m128i_u64[1] = 0;
|
||||
for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)
|
||||
{
|
||||
UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;
|
||||
const __m128i *w = p;
|
||||
__m128i m0, m1, m2;
|
||||
{
|
||||
const __m128i t = w[2];
|
||||
ctr = _mm_add_epi64(ctr, one); m0 = _mm_xor_si128(ctr, t);
|
||||
ctr = _mm_add_epi64(ctr, one); m1 = _mm_xor_si128(ctr, t);
|
||||
ctr = _mm_add_epi64(ctr, one); m2 = _mm_xor_si128(ctr, t);
|
||||
}
|
||||
w += 3;
|
||||
do
|
||||
{
|
||||
AES_ENC(0)
|
||||
AES_ENC(1)
|
||||
w += 2;
|
||||
}
|
||||
while (--numRounds2 != 0);
|
||||
AES_ENC(0)
|
||||
AES_ENC_LAST(1)
|
||||
data[0] = _mm_xor_si128(data[0], m0);
|
||||
data[1] = _mm_xor_si128(data[1], m1);
|
||||
data[2] = _mm_xor_si128(data[2], m2);
|
||||
}
|
||||
for (; numBlocks != 0; numBlocks--, data++)
|
||||
{
|
||||
UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;
|
||||
const __m128i *w = p;
|
||||
__m128i m;
|
||||
ctr = _mm_add_epi64(ctr, one);
|
||||
m = _mm_xor_si128(ctr, p[2]);
|
||||
w += 3;
|
||||
do
|
||||
{
|
||||
m = _mm_aesenc_si128(m, w[0]);
|
||||
m = _mm_aesenc_si128(m, w[1]);
|
||||
w += 2;
|
||||
}
|
||||
while (--numRounds2 != 0);
|
||||
m = _mm_aesenc_si128(m, w[0]);
|
||||
m = _mm_aesenclast_si128(m, w[1]);
|
||||
*data = _mm_xor_si128(*data, m);
|
||||
}
|
||||
*p = ctr;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
|
||||
void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *p, Byte *data, size_t numBlocks)
|
||||
{
|
||||
AesCbc_Encode(p, data, numBlocks);
|
||||
}
|
||||
|
||||
void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *p, Byte *data, size_t numBlocks)
|
||||
{
|
||||
AesCbc_Decode(p, data, numBlocks);
|
||||
}
|
||||
|
||||
void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *p, Byte *data, size_t numBlocks)
|
||||
{
|
||||
AesCtr_Code(p, data, numBlocks);
|
||||
}
|
||||
|
||||
#endif
|
||||
400
C/Alloc.c
Executable file → Normal file
400
C/Alloc.c
Executable file → Normal file
@@ -1,7 +1,9 @@
|
||||
/* Alloc.c -- Memory allocation functions
|
||||
2008-09-24
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2018-04-27 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
@@ -14,20 +16,127 @@ Public domain */
|
||||
|
||||
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
int g_allocCount = 0;
|
||||
int g_allocCountMid = 0;
|
||||
int g_allocCountBig = 0;
|
||||
|
||||
|
||||
#define CONVERT_INT_TO_STR(charType, tempSize) \
|
||||
unsigned char temp[tempSize]; unsigned i = 0; \
|
||||
while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \
|
||||
*s++ = (charType)('0' + (unsigned)val); \
|
||||
while (i != 0) { i--; *s++ = temp[i]; } \
|
||||
*s = 0;
|
||||
|
||||
static void ConvertUInt64ToString(UInt64 val, char *s)
|
||||
{
|
||||
CONVERT_INT_TO_STR(char, 24);
|
||||
}
|
||||
|
||||
#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
|
||||
|
||||
static void ConvertUInt64ToHex(UInt64 val, char *s)
|
||||
{
|
||||
UInt64 v = val;
|
||||
unsigned i;
|
||||
for (i = 1;; i++)
|
||||
{
|
||||
v >>= 4;
|
||||
if (v == 0)
|
||||
break;
|
||||
}
|
||||
s[i] = 0;
|
||||
do
|
||||
{
|
||||
unsigned t = (unsigned)(val & 0xF);
|
||||
val >>= 4;
|
||||
s[--i] = GET_HEX_CHAR(t);
|
||||
}
|
||||
while (i);
|
||||
}
|
||||
|
||||
#define DEBUG_OUT_STREAM stderr
|
||||
|
||||
static void Print(const char *s)
|
||||
{
|
||||
fputs(s, DEBUG_OUT_STREAM);
|
||||
}
|
||||
|
||||
static void PrintAligned(const char *s, size_t align)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
for(;;)
|
||||
{
|
||||
fputc(' ', DEBUG_OUT_STREAM);
|
||||
if (len >= align)
|
||||
break;
|
||||
++len;
|
||||
}
|
||||
Print(s);
|
||||
}
|
||||
|
||||
static void PrintLn()
|
||||
{
|
||||
Print("\n");
|
||||
}
|
||||
|
||||
static void PrintHex(UInt64 v, size_t align)
|
||||
{
|
||||
char s[32];
|
||||
ConvertUInt64ToHex(v, s);
|
||||
PrintAligned(s, align);
|
||||
}
|
||||
|
||||
static void PrintDec(UInt64 v, size_t align)
|
||||
{
|
||||
char s[32];
|
||||
ConvertUInt64ToString(v, s);
|
||||
PrintAligned(s, align);
|
||||
}
|
||||
|
||||
static void PrintAddr(void *p)
|
||||
{
|
||||
PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12);
|
||||
}
|
||||
|
||||
|
||||
#define PRINT_ALLOC(name, cnt, size, ptr) \
|
||||
Print(name " "); \
|
||||
PrintDec(cnt++, 10); \
|
||||
PrintHex(size, 10); \
|
||||
PrintAddr(ptr); \
|
||||
PrintLn();
|
||||
|
||||
#define PRINT_FREE(name, cnt, ptr) if (ptr) { \
|
||||
Print(name " "); \
|
||||
PrintDec(--cnt, 10); \
|
||||
PrintAddr(ptr); \
|
||||
PrintLn(); }
|
||||
|
||||
#else
|
||||
|
||||
#define PRINT_ALLOC(name, cnt, size, ptr)
|
||||
#define PRINT_FREE(name, cnt, ptr)
|
||||
#define Print(s)
|
||||
#define PrintLn()
|
||||
#define PrintHex(v, align)
|
||||
#define PrintDec(v, align)
|
||||
#define PrintAddr(p)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void *MyAlloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
return NULL;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
{
|
||||
void *p = malloc(size);
|
||||
fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p);
|
||||
PRINT_ALLOC("Alloc ", g_allocCount, size, p);
|
||||
return p;
|
||||
}
|
||||
#else
|
||||
@@ -37,10 +146,8 @@ void *MyAlloc(size_t size)
|
||||
|
||||
void MyFree(void *address)
|
||||
{
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address);
|
||||
#endif
|
||||
PRINT_FREE("Free ", g_allocCount, address);
|
||||
|
||||
free(address);
|
||||
}
|
||||
|
||||
@@ -49,20 +156,18 @@ void MyFree(void *address)
|
||||
void *MidAlloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++);
|
||||
#endif
|
||||
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
return NULL;
|
||||
|
||||
PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, NULL);
|
||||
|
||||
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void MidFree(void *address)
|
||||
{
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
|
||||
#endif
|
||||
if (address == 0)
|
||||
PRINT_FREE("Free-Mid", g_allocCountMid, address);
|
||||
|
||||
if (!address)
|
||||
return;
|
||||
VirtualFree(address, 0, MEM_RELEASE);
|
||||
}
|
||||
@@ -79,10 +184,10 @@ typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
|
||||
void SetLargePageSize()
|
||||
{
|
||||
#ifdef _7ZIP_LARGE_PAGES
|
||||
SIZE_T size = 0;
|
||||
SIZE_T size;
|
||||
GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
|
||||
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
|
||||
if (largePageMinimum == 0)
|
||||
if (!largePageMinimum)
|
||||
return;
|
||||
size = largePageMinimum();
|
||||
if (size == 0 || (size & (size - 1)) != 0)
|
||||
@@ -95,33 +200,256 @@ void SetLargePageSize()
|
||||
void *BigAlloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++);
|
||||
#endif
|
||||
return NULL;
|
||||
|
||||
PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL);
|
||||
|
||||
#ifdef _7ZIP_LARGE_PAGES
|
||||
if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))
|
||||
{
|
||||
void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
|
||||
MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
|
||||
if (res != 0)
|
||||
return res;
|
||||
SIZE_T ps = g_LargePageSize;
|
||||
if (ps != 0 && ps <= (1 << 30) && size > (ps / 2))
|
||||
{
|
||||
size_t size2;
|
||||
ps--;
|
||||
size2 = (size + ps) & ~ps;
|
||||
if (size2 >= size)
|
||||
{
|
||||
void *res = VirtualAlloc(NULL, size2, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void BigFree(void *address)
|
||||
{
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
|
||||
#endif
|
||||
PRINT_FREE("Free-Big", g_allocCountBig, address);
|
||||
|
||||
if (address == 0)
|
||||
if (!address)
|
||||
return;
|
||||
VirtualFree(address, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
|
||||
static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MyFree(address); }
|
||||
const ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MidAlloc(size); }
|
||||
static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MidFree(address); }
|
||||
const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };
|
||||
|
||||
static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); }
|
||||
static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); BigFree(address); }
|
||||
const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||
|
||||
|
||||
/*
|
||||
uintptr_t : <stdint.h> C99 (optional)
|
||||
: unsupported in VS6
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef UINT_PTR UIntPtr;
|
||||
#else
|
||||
/*
|
||||
typedef uintptr_t UIntPtr;
|
||||
*/
|
||||
typedef ptrdiff_t UIntPtr;
|
||||
#endif
|
||||
|
||||
|
||||
#define ADJUST_ALLOC_SIZE 0
|
||||
/*
|
||||
#define ADJUST_ALLOC_SIZE (sizeof(void *) - 1)
|
||||
*/
|
||||
/*
|
||||
Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if
|
||||
MyAlloc() can return address that is NOT multiple of sizeof(void *).
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1))))
|
||||
*/
|
||||
#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1))))
|
||||
|
||||
#define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align)
|
||||
|
||||
|
||||
#if (_POSIX_C_SOURCE >= 200112L) && !defined(_WIN32)
|
||||
#define USE_posix_memalign
|
||||
#endif
|
||||
|
||||
/*
|
||||
This posix_memalign() is for test purposes only.
|
||||
We also need special Free() function instead of free(),
|
||||
if this posix_memalign() is used.
|
||||
*/
|
||||
|
||||
/*
|
||||
static int posix_memalign(void **ptr, size_t align, size_t size)
|
||||
{
|
||||
size_t newSize = size + align;
|
||||
void *p;
|
||||
void *pAligned;
|
||||
*ptr = NULL;
|
||||
if (newSize < size)
|
||||
return 12; // ENOMEM
|
||||
p = MyAlloc(newSize);
|
||||
if (!p)
|
||||
return 12; // ENOMEM
|
||||
pAligned = MY_ALIGN_PTR_UP_PLUS(p, align);
|
||||
((void **)pAligned)[-1] = p;
|
||||
*ptr = pAligned;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
ALLOC_ALIGN_SIZE >= sizeof(void *)
|
||||
ALLOC_ALIGN_SIZE >= cache_line_size
|
||||
*/
|
||||
|
||||
#define ALLOC_ALIGN_SIZE ((size_t)1 << 7)
|
||||
|
||||
static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
|
||||
{
|
||||
#ifndef USE_posix_memalign
|
||||
|
||||
void *p;
|
||||
void *pAligned;
|
||||
size_t newSize;
|
||||
UNUSED_VAR(pp);
|
||||
|
||||
/* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
|
||||
block to prevent cache line sharing with another allocated blocks */
|
||||
|
||||
newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE;
|
||||
if (newSize < size)
|
||||
return NULL;
|
||||
|
||||
p = MyAlloc(newSize);
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE);
|
||||
|
||||
Print(" size="); PrintHex(size, 8);
|
||||
Print(" a_size="); PrintHex(newSize, 8);
|
||||
Print(" ptr="); PrintAddr(p);
|
||||
Print(" a_ptr="); PrintAddr(pAligned);
|
||||
PrintLn();
|
||||
|
||||
((void **)pAligned)[-1] = p;
|
||||
|
||||
return pAligned;
|
||||
|
||||
#else
|
||||
|
||||
void *p;
|
||||
UNUSED_VAR(pp);
|
||||
if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size))
|
||||
return NULL;
|
||||
|
||||
Print(" posix_memalign="); PrintAddr(p);
|
||||
PrintLn();
|
||||
|
||||
return p;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void SzAlignedFree(ISzAllocPtr pp, void *address)
|
||||
{
|
||||
UNUSED_VAR(pp);
|
||||
#ifndef USE_posix_memalign
|
||||
if (address)
|
||||
MyFree(((void **)address)[-1]);
|
||||
#else
|
||||
free(address);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree };
|
||||
|
||||
|
||||
|
||||
#define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *))
|
||||
|
||||
/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */
|
||||
#define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1]
|
||||
/*
|
||||
#define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1]
|
||||
*/
|
||||
|
||||
static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)
|
||||
{
|
||||
CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt);
|
||||
void *adr;
|
||||
void *pAligned;
|
||||
size_t newSize;
|
||||
size_t extra;
|
||||
size_t alignSize = (size_t)1 << p->numAlignBits;
|
||||
|
||||
if (alignSize < sizeof(void *))
|
||||
alignSize = sizeof(void *);
|
||||
|
||||
if (p->offset >= alignSize)
|
||||
return NULL;
|
||||
|
||||
/* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
|
||||
block to prevent cache line sharing with another allocated blocks */
|
||||
extra = p->offset & (sizeof(void *) - 1);
|
||||
newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE;
|
||||
if (newSize < size)
|
||||
return NULL;
|
||||
|
||||
adr = ISzAlloc_Alloc(p->baseAlloc, newSize);
|
||||
|
||||
if (!adr)
|
||||
return NULL;
|
||||
|
||||
pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr +
|
||||
alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset;
|
||||
|
||||
PrintLn();
|
||||
Print("- Aligned: ");
|
||||
Print(" size="); PrintHex(size, 8);
|
||||
Print(" a_size="); PrintHex(newSize, 8);
|
||||
Print(" ptr="); PrintAddr(adr);
|
||||
Print(" a_ptr="); PrintAddr(pAligned);
|
||||
PrintLn();
|
||||
|
||||
REAL_BLOCK_PTR_VAR(pAligned) = adr;
|
||||
|
||||
return pAligned;
|
||||
}
|
||||
|
||||
|
||||
static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address)
|
||||
{
|
||||
if (address)
|
||||
{
|
||||
CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt);
|
||||
PrintLn();
|
||||
Print("- Aligned Free: ");
|
||||
PrintLn();
|
||||
ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p)
|
||||
{
|
||||
p->vt.Alloc = AlignOffsetAlloc_Alloc;
|
||||
p->vt.Free = AlignOffsetAlloc_Free;
|
||||
}
|
||||
|
||||
27
C/Alloc.h
Executable file → Normal file
27
C/Alloc.h
Executable file → Normal file
@@ -1,12 +1,12 @@
|
||||
/* Alloc.h -- Memory allocation functions
|
||||
2008-03-13
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2018-02-19 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __COMMON_ALLOC_H
|
||||
#define __COMMON_ALLOC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
void *MyAlloc(size_t size);
|
||||
void MyFree(void *address);
|
||||
@@ -29,4 +29,23 @@ void BigFree(void *address);
|
||||
|
||||
#endif
|
||||
|
||||
extern const ISzAlloc g_Alloc;
|
||||
extern const ISzAlloc g_BigAlloc;
|
||||
extern const ISzAlloc g_MidAlloc;
|
||||
extern const ISzAlloc g_AlignedAlloc;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISzAlloc vt;
|
||||
ISzAllocPtr baseAlloc;
|
||||
unsigned numAlignBits; /* ((1 << numAlignBits) >= sizeof(void *)) */
|
||||
size_t offset; /* (offset == (k * sizeof(void *)) && offset < (1 << numAlignBits) */
|
||||
} CAlignOffsetAlloc;
|
||||
|
||||
void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p);
|
||||
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=7z - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "7z.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "7z - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FAs /YX /FD /c
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "7z - Win32 Release"
|
||||
# Name "7z - Win32 Debug"
|
||||
# Begin Group "Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\7zBuf.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\7zBuf.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\7zCrc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\7zCrc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\7zFile.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\7zFile.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\7zStream.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Bcj2.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Bcj2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Bra.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Bra86.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\LzmaDec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\LzmaDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Types.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zAlloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zAlloc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zDecode.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zDecode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zExtract.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zExtract.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zHeader.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zHeader.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zIn.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zIn.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zItem.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zItem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zMain.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -1,29 +0,0 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "7z"=.\7z.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/* 7zAlloc.h -- Allocation functions
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_ALLOC_H
|
||||
#define __7Z_ALLOC_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void *SzAlloc(void *p, size_t size);
|
||||
void SzFree(void *p, void *address);
|
||||
|
||||
void *SzAllocTemp(void *p, size_t size);
|
||||
void SzFreeTemp(void *p, void *address);
|
||||
|
||||
#endif
|
||||
@@ -1,254 +0,0 @@
|
||||
/* 7zDecode.c -- Decoding from 7z folder
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../../Bcj2.h"
|
||||
#include "../../Bra.h"
|
||||
#include "../../LzmaDec.h"
|
||||
#include "7zDecode.h"
|
||||
|
||||
#define k_Copy 0
|
||||
#define k_LZMA 0x30101
|
||||
#define k_BCJ 0x03030103
|
||||
#define k_BCJ2 0x0303011B
|
||||
|
||||
static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||
{
|
||||
CLzmaDec state;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
LzmaDec_Construct(&state);
|
||||
RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
|
||||
state.dic = outBuffer;
|
||||
state.dicBufSize = outSize;
|
||||
LzmaDec_Init(&state);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
{
|
||||
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
|
||||
ELzmaStatus status;
|
||||
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
|
||||
{
|
||||
if (state.dicBufSize != outSize || lookahead != 0 ||
|
||||
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
||||
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
res = inStream->Skip((void *)inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LzmaDec_FreeProbs(&state, allocMain);
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
|
||||
{
|
||||
while (inSize > 0)
|
||||
{
|
||||
void *inBuf;
|
||||
size_t curSize = (1 << 18);
|
||||
if (curSize > inSize)
|
||||
curSize = (size_t)inSize;
|
||||
RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize));
|
||||
if (curSize == 0)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
memcpy(outBuffer, inBuf, curSize);
|
||||
outBuffer += curSize;
|
||||
inSize -= curSize;
|
||||
RINOK(inStream->Skip((void *)inStream, curSize));
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
|
||||
#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
||||
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
||||
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
|
||||
|
||||
SRes CheckSupportedFolder(const CSzFolder *f)
|
||||
{
|
||||
if (f->NumCoders < 1 || f->NumCoders > 4)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (IS_UNSUPPORTED_CODER(f->Coders[0]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (f->NumCoders == 1)
|
||||
{
|
||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (f->NumCoders == 2)
|
||||
{
|
||||
if (IS_NO_BCJ(f->Coders[1]) ||
|
||||
f->NumPackStreams != 1 || f->PackStreams[0] != 0 ||
|
||||
f->NumBindPairs != 1 ||
|
||||
f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (f->NumCoders == 4)
|
||||
{
|
||||
if (IS_UNSUPPORTED_CODER(f->Coders[1]) ||
|
||||
IS_UNSUPPORTED_CODER(f->Coders[2]) ||
|
||||
IS_NO_BCJ2(f->Coders[3]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (f->NumPackStreams != 4 ||
|
||||
f->PackStreams[0] != 2 ||
|
||||
f->PackStreams[1] != 6 ||
|
||||
f->PackStreams[2] != 1 ||
|
||||
f->PackStreams[3] != 0 ||
|
||||
f->NumBindPairs != 3 ||
|
||||
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
|
||||
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
|
||||
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
UInt64 GetSum(const UInt64 *values, UInt32 index)
|
||||
{
|
||||
UInt64 sum = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < index; i++)
|
||||
sum += values[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
|
||||
Byte *tempBuf[])
|
||||
{
|
||||
UInt32 ci;
|
||||
SizeT tempSizes[3] = { 0, 0, 0};
|
||||
SizeT tempSize3 = 0;
|
||||
Byte *tempBuf3 = 0;
|
||||
|
||||
RINOK(CheckSupportedFolder(folder));
|
||||
|
||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||
{
|
||||
CSzCoderInfo *coder = &folder->Coders[ci];
|
||||
|
||||
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
|
||||
{
|
||||
UInt32 si = 0;
|
||||
UInt64 offset;
|
||||
UInt64 inSize;
|
||||
Byte *outBufCur = outBuffer;
|
||||
SizeT outSizeCur = outSize;
|
||||
if (folder->NumCoders == 4)
|
||||
{
|
||||
UInt32 indices[] = { 3, 2, 0 };
|
||||
UInt64 unpackSize = folder->UnpackSizes[ci];
|
||||
si = indices[ci];
|
||||
if (ci < 2)
|
||||
{
|
||||
Byte *temp;
|
||||
outSizeCur = (SizeT)unpackSize;
|
||||
if (outSizeCur != unpackSize)
|
||||
return SZ_ERROR_MEM;
|
||||
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
|
||||
if (temp == 0 && outSizeCur != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
outBufCur = tempBuf[1 - ci] = temp;
|
||||
tempSizes[1 - ci] = outSizeCur;
|
||||
}
|
||||
else if (ci == 2)
|
||||
{
|
||||
if (unpackSize > outSize) /* check it */
|
||||
return SZ_ERROR_PARAM;
|
||||
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
||||
tempSize3 = outSizeCur = (SizeT)unpackSize;
|
||||
}
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
offset = GetSum(packSizes, si);
|
||||
inSize = packSizes[si];
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
|
||||
if (coder->MethodID == k_Copy)
|
||||
{
|
||||
if (inSize != outSizeCur) /* check it */
|
||||
return SZ_ERROR_DATA;
|
||||
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ)
|
||||
{
|
||||
UInt32 state;
|
||||
if (ci != 1)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
x86_Convert_Init(state);
|
||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ2)
|
||||
{
|
||||
UInt64 offset = GetSum(packSizes, 1);
|
||||
UInt64 s3Size = packSizes[1];
|
||||
SRes res;
|
||||
if (ci != 3)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
tempSizes[2] = (SizeT)s3Size;
|
||||
if (tempSizes[2] != s3Size)
|
||||
return SZ_ERROR_MEM;
|
||||
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
|
||||
if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
||||
RINOK(res)
|
||||
|
||||
res = Bcj2_Decode(
|
||||
tempBuf3, tempSize3,
|
||||
tempBuf[0], tempSizes[0],
|
||||
tempBuf[1], tempSizes[1],
|
||||
tempBuf[2], tempSizes[2],
|
||||
outBuffer, outSize);
|
||||
RINOK(res)
|
||||
}
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
{
|
||||
Byte *tempBuf[3] = { 0, 0, 0};
|
||||
int i;
|
||||
SRes res = SzDecode2(packSizes, folder, inStream, startPos,
|
||||
outBuffer, (SizeT)outSize, allocMain, tempBuf);
|
||||
for (i = 0; i < 3; i++)
|
||||
IAlloc_Free(allocMain, tempBuf[i]);
|
||||
return res;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/* 7zDecode.h -- Decoding from 7z folder
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_DECODE_H
|
||||
#define __7Z_DECODE_H
|
||||
|
||||
#include "7zItem.h"
|
||||
|
||||
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
|
||||
ILookInStream *stream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
||||
|
||||
#endif
|
||||
@@ -1,93 +0,0 @@
|
||||
/* 7zExtract.c -- Extracting from 7z archive
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "../../7zCrc.h"
|
||||
#include "7zDecode.h"
|
||||
#include "7zExtract.h"
|
||||
|
||||
SRes SzAr_Extract(
|
||||
const CSzArEx *p,
|
||||
ILookInStream *inStream,
|
||||
UInt32 fileIndex,
|
||||
UInt32 *blockIndex,
|
||||
Byte **outBuffer,
|
||||
size_t *outBufferSize,
|
||||
size_t *offset,
|
||||
size_t *outSizeProcessed,
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp)
|
||||
{
|
||||
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
|
||||
SRes res = SZ_OK;
|
||||
*offset = 0;
|
||||
*outSizeProcessed = 0;
|
||||
if (folderIndex == (UInt32)-1)
|
||||
{
|
||||
IAlloc_Free(allocMain, *outBuffer);
|
||||
*blockIndex = folderIndex;
|
||||
*outBuffer = 0;
|
||||
*outBufferSize = 0;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (*outBuffer == 0 || *blockIndex != folderIndex)
|
||||
{
|
||||
CSzFolder *folder = p->db.Folders + folderIndex;
|
||||
UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
|
||||
size_t unpackSize = (size_t)unpackSizeSpec;
|
||||
UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
|
||||
|
||||
if (unpackSize != unpackSizeSpec)
|
||||
return SZ_ERROR_MEM;
|
||||
*blockIndex = folderIndex;
|
||||
IAlloc_Free(allocMain, *outBuffer);
|
||||
*outBuffer = 0;
|
||||
|
||||
RINOK(LookInStream_SeekTo(inStream, startOffset));
|
||||
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
*outBufferSize = unpackSize;
|
||||
if (unpackSize != 0)
|
||||
{
|
||||
*outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
|
||||
if (*outBuffer == 0)
|
||||
res = SZ_ERROR_MEM;
|
||||
}
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
res = SzDecode(p->db.PackSizes +
|
||||
p->FolderStartPackStreamIndex[folderIndex], folder,
|
||||
inStream, startOffset,
|
||||
*outBuffer, unpackSize, allocTemp);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
if (folder->UnpackCRCDefined)
|
||||
{
|
||||
if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
|
||||
res = SZ_ERROR_CRC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
UInt32 i;
|
||||
CSzFileItem *fileItem = p->db.Files + fileIndex;
|
||||
*offset = 0;
|
||||
for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
|
||||
*offset += (UInt32)p->db.Files[i].Size;
|
||||
*outSizeProcessed = (size_t)fileItem->Size;
|
||||
if (*offset + *outSizeProcessed > *outBufferSize)
|
||||
return SZ_ERROR_FAIL;
|
||||
{
|
||||
if (fileItem->FileCRCDefined)
|
||||
{
|
||||
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
|
||||
res = SZ_ERROR_CRC;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/* 7zExtract.h -- Extracting from 7z archive
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_EXTRACT_H
|
||||
#define __7Z_EXTRACT_H
|
||||
|
||||
#include "7zIn.h"
|
||||
|
||||
/*
|
||||
SzExtract extracts file from archive
|
||||
|
||||
*outBuffer must be 0 before first call for each new archive.
|
||||
|
||||
Extracting cache:
|
||||
If you need to decompress more than one file, you can send
|
||||
these values from previous call:
|
||||
*blockIndex,
|
||||
*outBuffer,
|
||||
*outBufferSize
|
||||
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
||||
it will increase decompression speed.
|
||||
|
||||
If you use external function, you can declare these 3 cache variables
|
||||
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
||||
|
||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||
*/
|
||||
|
||||
SRes SzAr_Extract(
|
||||
const CSzArEx *db,
|
||||
ILookInStream *inStream,
|
||||
UInt32 fileIndex, /* index of file */
|
||||
UInt32 *blockIndex, /* index of solid block */
|
||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||
size_t *outBufferSize, /* buffer size for output buffer */
|
||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp);
|
||||
|
||||
#endif
|
||||
@@ -1,6 +0,0 @@
|
||||
/* 7zHeader.c -- 7z Headers
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "7zHeader.h"
|
||||
|
||||
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
||||
@@ -1,57 +0,0 @@
|
||||
/* 7zHeader.h -- 7z Headers
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_HEADER_H
|
||||
#define __7Z_HEADER_H
|
||||
|
||||
#include "../../Types.h"
|
||||
|
||||
#define k7zSignatureSize 6
|
||||
extern Byte k7zSignature[k7zSignatureSize];
|
||||
|
||||
#define k7zMajorVersion 0
|
||||
|
||||
#define k7zStartHeaderSize 0x20
|
||||
|
||||
enum EIdEnum
|
||||
{
|
||||
k7zIdEnd,
|
||||
|
||||
k7zIdHeader,
|
||||
|
||||
k7zIdArchiveProperties,
|
||||
|
||||
k7zIdAdditionalStreamsInfo,
|
||||
k7zIdMainStreamsInfo,
|
||||
k7zIdFilesInfo,
|
||||
|
||||
k7zIdPackInfo,
|
||||
k7zIdUnpackInfo,
|
||||
k7zIdSubStreamsInfo,
|
||||
|
||||
k7zIdSize,
|
||||
k7zIdCRC,
|
||||
|
||||
k7zIdFolder,
|
||||
|
||||
k7zIdCodersUnpackSize,
|
||||
k7zIdNumUnpackStream,
|
||||
|
||||
k7zIdEmptyStream,
|
||||
k7zIdEmptyFile,
|
||||
k7zIdAnti,
|
||||
|
||||
k7zIdName,
|
||||
k7zIdCTime,
|
||||
k7zIdATime,
|
||||
k7zIdMTime,
|
||||
k7zIdWinAttributes,
|
||||
k7zIdComment,
|
||||
|
||||
k7zIdEncodedHeader,
|
||||
|
||||
k7zIdStartPos,
|
||||
k7zIdDummy
|
||||
};
|
||||
|
||||
#endif
|
||||
1204
C/Archive/7z/7zIn.c
1204
C/Archive/7z/7zIn.c
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
/* 7zIn.h -- 7z Input functions
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_IN_H
|
||||
#define __7Z_IN_H
|
||||
|
||||
#include "7zHeader.h"
|
||||
#include "7zItem.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzAr db;
|
||||
|
||||
UInt64 startPosAfterHeader;
|
||||
UInt64 dataPos;
|
||||
|
||||
UInt32 *FolderStartPackStreamIndex;
|
||||
UInt64 *PackStreamStartPositions;
|
||||
UInt32 *FolderStartFileIndex;
|
||||
UInt32 *FileIndexToFolderIndexMap;
|
||||
} CSzArEx;
|
||||
|
||||
void SzArEx_Init(CSzArEx *p);
|
||||
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
|
||||
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
||||
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
||||
|
||||
/*
|
||||
Errors:
|
||||
SZ_ERROR_NO_ARCHIVE
|
||||
SZ_ERROR_ARCHIVE
|
||||
SZ_ERROR_UNSUPPORTED
|
||||
SZ_ERROR_MEM
|
||||
SZ_ERROR_CRC
|
||||
SZ_ERROR_INPUT_EOF
|
||||
SZ_ERROR_FAIL
|
||||
*/
|
||||
|
||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||
|
||||
#endif
|
||||
@@ -1,127 +0,0 @@
|
||||
/* 7zItem.c -- 7z Items
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "7zItem.h"
|
||||
|
||||
void SzCoderInfo_Init(CSzCoderInfo *p)
|
||||
{
|
||||
Buf_Init(&p->Props);
|
||||
}
|
||||
|
||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
|
||||
{
|
||||
Buf_Free(&p->Props, alloc);
|
||||
SzCoderInfo_Init(p);
|
||||
}
|
||||
|
||||
void SzFolder_Init(CSzFolder *p)
|
||||
{
|
||||
p->Coders = 0;
|
||||
p->BindPairs = 0;
|
||||
p->PackStreams = 0;
|
||||
p->UnpackSizes = 0;
|
||||
p->NumCoders = 0;
|
||||
p->NumBindPairs = 0;
|
||||
p->NumPackStreams = 0;
|
||||
p->UnpackCRCDefined = 0;
|
||||
p->UnpackCRC = 0;
|
||||
p->NumUnpackStreams = 0;
|
||||
}
|
||||
|
||||
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
|
||||
{
|
||||
UInt32 i;
|
||||
if (p->Coders)
|
||||
for (i = 0; i < p->NumCoders; i++)
|
||||
SzCoderInfo_Free(&p->Coders[i], alloc);
|
||||
IAlloc_Free(alloc, p->Coders);
|
||||
IAlloc_Free(alloc, p->BindPairs);
|
||||
IAlloc_Free(alloc, p->PackStreams);
|
||||
IAlloc_Free(alloc, p->UnpackSizes);
|
||||
SzFolder_Init(p);
|
||||
}
|
||||
|
||||
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
|
||||
{
|
||||
UInt32 result = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < p->NumCoders; i++)
|
||||
result += p->Coders[i].NumOutStreams;
|
||||
return result;
|
||||
}
|
||||
|
||||
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < p->NumBindPairs; i++)
|
||||
if (p->BindPairs[i].InIndex == inStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < p->NumBindPairs; i++)
|
||||
if (p->BindPairs[i].OutIndex == outStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
|
||||
{
|
||||
int i = (int)SzFolder_GetNumOutStreams(p);
|
||||
if (i == 0)
|
||||
return 0;
|
||||
for (i--; i >= 0; i--)
|
||||
if (SzFolder_FindBindPairForOutStream(p, i) < 0)
|
||||
return p->UnpackSizes[i];
|
||||
/* throw 1; */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SzFile_Init(CSzFileItem *p)
|
||||
{
|
||||
p->HasStream = 1;
|
||||
p->IsDir = 0;
|
||||
p->IsAnti = 0;
|
||||
p->FileCRCDefined = 0;
|
||||
p->MTimeDefined = 0;
|
||||
p->Name = 0;
|
||||
}
|
||||
|
||||
static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc)
|
||||
{
|
||||
IAlloc_Free(alloc, p->Name);
|
||||
SzFile_Init(p);
|
||||
}
|
||||
|
||||
void SzAr_Init(CSzAr *p)
|
||||
{
|
||||
p->PackSizes = 0;
|
||||
p->PackCRCsDefined = 0;
|
||||
p->PackCRCs = 0;
|
||||
p->Folders = 0;
|
||||
p->Files = 0;
|
||||
p->NumPackStreams = 0;
|
||||
p->NumFolders = 0;
|
||||
p->NumFiles = 0;
|
||||
}
|
||||
|
||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
|
||||
{
|
||||
UInt32 i;
|
||||
if (p->Folders)
|
||||
for (i = 0; i < p->NumFolders; i++)
|
||||
SzFolder_Free(&p->Folders[i], alloc);
|
||||
if (p->Files)
|
||||
for (i = 0; i < p->NumFiles; i++)
|
||||
SzFile_Free(&p->Files[i], alloc);
|
||||
IAlloc_Free(alloc, p->PackSizes);
|
||||
IAlloc_Free(alloc, p->PackCRCsDefined);
|
||||
IAlloc_Free(alloc, p->PackCRCs);
|
||||
IAlloc_Free(alloc, p->Folders);
|
||||
IAlloc_Free(alloc, p->Files);
|
||||
SzAr_Init(p);
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/* 7zItem.h -- 7z Items
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_ITEM_H
|
||||
#define __7Z_ITEM_H
|
||||
|
||||
#include "../../7zBuf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
UInt64 MethodID;
|
||||
CBuf Props;
|
||||
} CSzCoderInfo;
|
||||
|
||||
void SzCoderInfo_Init(CSzCoderInfo *p);
|
||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 InIndex;
|
||||
UInt32 OutIndex;
|
||||
} CBindPair;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzCoderInfo *Coders;
|
||||
CBindPair *BindPairs;
|
||||
UInt32 *PackStreams;
|
||||
UInt64 *UnpackSizes;
|
||||
UInt32 NumCoders;
|
||||
UInt32 NumBindPairs;
|
||||
UInt32 NumPackStreams;
|
||||
int UnpackCRCDefined;
|
||||
UInt32 UnpackCRC;
|
||||
|
||||
UInt32 NumUnpackStreams;
|
||||
} CSzFolder;
|
||||
|
||||
void SzFolder_Init(CSzFolder *p);
|
||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
|
||||
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
|
||||
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
|
||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 Low;
|
||||
UInt32 High;
|
||||
} CNtfsFileTime;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CNtfsFileTime MTime;
|
||||
UInt64 Size;
|
||||
char *Name;
|
||||
UInt32 FileCRC;
|
||||
|
||||
Byte HasStream;
|
||||
Byte IsDir;
|
||||
Byte IsAnti;
|
||||
Byte FileCRCDefined;
|
||||
Byte MTimeDefined;
|
||||
} CSzFileItem;
|
||||
|
||||
void SzFile_Init(CSzFileItem *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 *PackSizes;
|
||||
Byte *PackCRCsDefined;
|
||||
UInt32 *PackCRCs;
|
||||
CSzFolder *Folders;
|
||||
CSzFileItem *Files;
|
||||
UInt32 NumPackStreams;
|
||||
UInt32 NumFolders;
|
||||
UInt32 NumFiles;
|
||||
} CSzAr;
|
||||
|
||||
void SzAr_Init(CSzAr *p);
|
||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
||||
|
||||
#endif
|
||||
@@ -1,262 +0,0 @@
|
||||
/* 7zMain.c - Test application for 7z Decoder
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../7zCrc.h"
|
||||
#include "../../7zFile.h"
|
||||
#include "../../7zVersion.h"
|
||||
|
||||
#include "7zAlloc.h"
|
||||
#include "7zExtract.h"
|
||||
#include "7zIn.h"
|
||||
|
||||
static void ConvertNumberToString(UInt64 value, char *s)
|
||||
{
|
||||
char temp[32];
|
||||
int pos = 0;
|
||||
do
|
||||
{
|
||||
temp[pos++] = (char)('0' + (int)(value % 10));
|
||||
value /= 10;
|
||||
}
|
||||
while (value != 0);
|
||||
do
|
||||
*s++ = temp[--pos];
|
||||
while (pos > 0);
|
||||
*s = '\0';
|
||||
}
|
||||
|
||||
#define PERIOD_4 (4 * 365 + 1)
|
||||
#define PERIOD_100 (PERIOD_4 * 25 - 1)
|
||||
#define PERIOD_400 (PERIOD_100 * 4 + 1)
|
||||
|
||||
static void ConvertFileTimeToString(CNtfsFileTime *ft, char *s)
|
||||
{
|
||||
unsigned year, mon, day, hour, min, sec;
|
||||
UInt64 v64 = ft->Low | ((UInt64)ft->High << 32);
|
||||
Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
unsigned temp;
|
||||
UInt32 v;
|
||||
v64 /= 10000000;
|
||||
sec = (unsigned)(v64 % 60);
|
||||
v64 /= 60;
|
||||
min = (unsigned)(v64 % 60);
|
||||
v64 /= 60;
|
||||
hour = (unsigned)(v64 % 24);
|
||||
v64 /= 24;
|
||||
|
||||
v = (UInt32)v64;
|
||||
|
||||
year = (unsigned)(1601 + v / PERIOD_400 * 400);
|
||||
v %= PERIOD_400;
|
||||
|
||||
temp = (unsigned)(v / PERIOD_100);
|
||||
if (temp == 4)
|
||||
temp = 3;
|
||||
year += temp * 100;
|
||||
v -= temp * PERIOD_100;
|
||||
|
||||
temp = v / PERIOD_4;
|
||||
if (temp == 25)
|
||||
temp = 24;
|
||||
year += temp * 4;
|
||||
v -= temp * PERIOD_4;
|
||||
|
||||
temp = v / 365;
|
||||
if (temp == 4)
|
||||
temp = 3;
|
||||
year += temp;
|
||||
v -= temp * 365;
|
||||
|
||||
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
|
||||
ms[1] = 29;
|
||||
for (mon = 1; mon <= 12; mon++)
|
||||
{
|
||||
unsigned s = ms[mon - 1];
|
||||
if (v < s)
|
||||
break;
|
||||
v -= s;
|
||||
}
|
||||
day = (unsigned)v + 1;
|
||||
sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec);
|
||||
}
|
||||
|
||||
void PrintError(char *sz)
|
||||
{
|
||||
printf("\nERROR: %s\n", sz);
|
||||
}
|
||||
|
||||
int MY_CDECL main(int numargs, char *args[])
|
||||
{
|
||||
CFileInStream archiveStream;
|
||||
CLookToRead lookStream;
|
||||
CSzArEx db;
|
||||
SRes res;
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
|
||||
printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n");
|
||||
if (numargs == 1)
|
||||
{
|
||||
printf(
|
||||
"\nUsage: 7zDec <command> <archive_name>\n\n"
|
||||
"<Commands>\n"
|
||||
" e: Extract files from archive\n"
|
||||
" l: List contents of archive\n"
|
||||
" t: Test integrity of archive\n");
|
||||
return 0;
|
||||
}
|
||||
if (numargs < 3)
|
||||
{
|
||||
PrintError("incorrect command");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (InFile_Open(&archiveStream.file, args[2]))
|
||||
{
|
||||
PrintError("can not open input file");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
FileInStream_CreateVTable(&archiveStream);
|
||||
LookToRead_CreateVTable(&lookStream, False);
|
||||
|
||||
lookStream.realStream = &archiveStream.s;
|
||||
LookToRead_Init(&lookStream);
|
||||
|
||||
allocImp.Alloc = SzAlloc;
|
||||
allocImp.Free = SzFree;
|
||||
|
||||
allocTempImp.Alloc = SzAllocTemp;
|
||||
allocTempImp.Free = SzFreeTemp;
|
||||
|
||||
CrcGenerateTable();
|
||||
|
||||
SzArEx_Init(&db);
|
||||
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
char *command = args[1];
|
||||
int listCommand = 0, testCommand = 0, extractCommand = 0;
|
||||
if (strcmp(command, "l") == 0) listCommand = 1;
|
||||
else if (strcmp(command, "t") == 0) testCommand = 1;
|
||||
else if (strcmp(command, "e") == 0) extractCommand = 1;
|
||||
|
||||
if (listCommand)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < db.db.NumFiles; i++)
|
||||
{
|
||||
CSzFileItem *f = db.db.Files + i;
|
||||
char s[32], t[32];
|
||||
ConvertNumberToString(f->Size, s);
|
||||
if (f->MTimeDefined)
|
||||
ConvertFileTimeToString(&f->MTime, t);
|
||||
else
|
||||
strcpy(t, " ");
|
||||
|
||||
printf("%s %10s %s\n", t, s, f->Name);
|
||||
}
|
||||
}
|
||||
else if (testCommand || extractCommand)
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
/*
|
||||
if you need cache, use these 3 variables.
|
||||
if you use external function, you can make these variable as static.
|
||||
*/
|
||||
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
|
||||
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
|
||||
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
|
||||
|
||||
printf("\n");
|
||||
for (i = 0; i < db.db.NumFiles; i++)
|
||||
{
|
||||
size_t offset;
|
||||
size_t outSizeProcessed;
|
||||
CSzFileItem *f = db.db.Files + i;
|
||||
if (f->IsDir)
|
||||
printf("Directory ");
|
||||
else
|
||||
printf(testCommand ?
|
||||
"Testing ":
|
||||
"Extracting");
|
||||
printf(" %s", f->Name);
|
||||
if (f->IsDir)
|
||||
{
|
||||
printf("\n");
|
||||
continue;
|
||||
}
|
||||
res = SzAr_Extract(&db, &lookStream.s, i,
|
||||
&blockIndex, &outBuffer, &outBufferSize,
|
||||
&offset, &outSizeProcessed,
|
||||
&allocImp, &allocTempImp);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (!testCommand)
|
||||
{
|
||||
CSzFile outFile;
|
||||
size_t processedSize;
|
||||
char *fileName = f->Name;
|
||||
size_t nameLen = strlen(f->Name);
|
||||
for (; nameLen > 0; nameLen--)
|
||||
if (f->Name[nameLen - 1] == '/')
|
||||
{
|
||||
fileName = f->Name + nameLen;
|
||||
break;
|
||||
}
|
||||
|
||||
if (OutFile_Open(&outFile, fileName))
|
||||
{
|
||||
PrintError("can not open output file");
|
||||
res = SZ_ERROR_FAIL;
|
||||
break;
|
||||
}
|
||||
processedSize = outSizeProcessed;
|
||||
if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 ||
|
||||
processedSize != outSizeProcessed)
|
||||
{
|
||||
PrintError("can not write output file");
|
||||
res = SZ_ERROR_FAIL;
|
||||
break;
|
||||
}
|
||||
if (File_Close(&outFile))
|
||||
{
|
||||
PrintError("can not close output file");
|
||||
res = SZ_ERROR_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
IAlloc_Free(&allocImp, outBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintError("incorrect command");
|
||||
res = SZ_ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
SzArEx_Free(&db, &allocImp);
|
||||
|
||||
File_Close(&archiveStream.file);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
printf("\nEverything is Ok\n");
|
||||
return 0;
|
||||
}
|
||||
if (res == SZ_ERROR_UNSUPPORTED)
|
||||
PrintError("decoder doesn't support this archive");
|
||||
else if (res == SZ_ERROR_MEM)
|
||||
PrintError("can not allocate memory");
|
||||
else if (res == SZ_ERROR_CRC)
|
||||
PrintError("CRC error");
|
||||
else
|
||||
printf("\nERROR #%d\n", res);
|
||||
return 1;
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
PROG = 7zDec
|
||||
CXX = g++
|
||||
LIB =
|
||||
RM = rm -f
|
||||
CFLAGS = -c -O2 -Wall
|
||||
|
||||
OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
$(PROG): $(OBJS)
|
||||
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
|
||||
|
||||
7zAlloc.o: 7zAlloc.c
|
||||
$(CXX) $(CFLAGS) 7zAlloc.c
|
||||
|
||||
7zBuf.o: ../../7zBuf.c
|
||||
$(CXX) $(CFLAGS) ../../7zBuf.c
|
||||
|
||||
7zBuf2.o: ../../7zBuf2.c
|
||||
$(CXX) $(CFLAGS) ../../7zBuf2.c
|
||||
|
||||
7zCrc.o: ../../7zCrc.c
|
||||
$(CXX) $(CFLAGS) ../../7zCrc.c
|
||||
|
||||
7zDecode.o: 7zDecode.c
|
||||
$(CXX) $(CFLAGS) 7zDecode.c
|
||||
|
||||
7zExtract.o: 7zExtract.c
|
||||
$(CXX) $(CFLAGS) 7zExtract.c
|
||||
|
||||
7zHeader.o: 7zHeader.c
|
||||
$(CXX) $(CFLAGS) 7zHeader.c
|
||||
|
||||
7zIn.o: 7zIn.c
|
||||
$(CXX) $(CFLAGS) 7zIn.c
|
||||
|
||||
7zItem.o: 7zItem.c
|
||||
$(CXX) $(CFLAGS) 7zItem.c
|
||||
|
||||
7zMain.o: 7zMain.c
|
||||
$(CXX) $(CFLAGS) 7zMain.c
|
||||
|
||||
LzmaDec.o: ../../LzmaDec.c
|
||||
$(CXX) $(CFLAGS) ../../LzmaDec.c
|
||||
|
||||
Bra86.o: ../../Bra86.c
|
||||
$(CXX) $(CFLAGS) ../../Bra86.c
|
||||
|
||||
Bcj2.o: ../../Bcj2.c
|
||||
$(CXX) $(CFLAGS) ../../Bcj2.c
|
||||
|
||||
7zFile.o: ../../7zFile.c
|
||||
$(CXX) $(CFLAGS) ../../7zFile.c
|
||||
|
||||
7zStream.o: ../../7zStream.c
|
||||
$(CXX) $(CFLAGS) ../../7zStream.c
|
||||
|
||||
clean:
|
||||
-$(RM) $(PROG) $(OBJS)
|
||||
|
||||
335
C/Bcj2.c
Executable file → Normal file
335
C/Bcj2.c
Executable file → Normal file
@@ -1,132 +1,257 @@
|
||||
/* Bcj2.c -- Converter for x86 code (BCJ2)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
|
||||
2018-04-28 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "Bcj2.h"
|
||||
#include "CpuArch.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 kTopValue ((UInt32)1 << 24)
|
||||
#define kNumModelBits 11
|
||||
#define kBitModelTotal (1 << kNumModelBits)
|
||||
#define kNumMoveBits 5
|
||||
|
||||
#define RC_READ_BYTE (*buffer++)
|
||||
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
|
||||
#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \
|
||||
{ int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
|
||||
#define _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));
|
||||
|
||||
#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }
|
||||
|
||||
#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
|
||||
#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
|
||||
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
|
||||
|
||||
int Bcj2_Decode(
|
||||
const Byte *buf0, SizeT size0,
|
||||
const Byte *buf1, SizeT size1,
|
||||
const Byte *buf2, SizeT size2,
|
||||
const Byte *buf3, SizeT size3,
|
||||
Byte *outBuf, SizeT outSize)
|
||||
void Bcj2Dec_Init(CBcj2Dec *p)
|
||||
{
|
||||
CProb p[256 + 2];
|
||||
SizeT inPos = 0, outPos = 0;
|
||||
unsigned i;
|
||||
|
||||
const Byte *buffer, *bufferLim;
|
||||
UInt32 range, code;
|
||||
Byte prevByte = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
|
||||
p[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;
|
||||
}
|
||||
|
||||
buffer = buf3;
|
||||
bufferLim = buffer + size3;
|
||||
RC_INIT2
|
||||
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[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0];
|
||||
p->state++;
|
||||
p->dest = dest + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (outSize == 0)
|
||||
return SZ_OK;
|
||||
/*
|
||||
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 (;;)
|
||||
{
|
||||
Byte b;
|
||||
CProb *prob;
|
||||
UInt32 bound;
|
||||
UInt32 ttt;
|
||||
|
||||
SizeT limit = size0 - inPos;
|
||||
if (outSize - outPos < limit)
|
||||
limit = outSize - outPos;
|
||||
while (limit != 0)
|
||||
{
|
||||
Byte b = buf0[inPos];
|
||||
outBuf[outPos++] = b;
|
||||
if (IsJ(prevByte, b))
|
||||
break;
|
||||
inPos++;
|
||||
prevByte = b;
|
||||
limit--;
|
||||
}
|
||||
|
||||
if (limit == 0 || outPos == outSize)
|
||||
break;
|
||||
|
||||
b = buf0[inPos++];
|
||||
|
||||
if (b == 0xE8)
|
||||
prob = p + prevByte;
|
||||
else if (b == 0xE9)
|
||||
prob = p + 256;
|
||||
else
|
||||
prob = p + 257;
|
||||
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
UPDATE_0(prob)
|
||||
prevByte = b;
|
||||
}
|
||||
if (BCJ2_IS_32BIT_STREAM(p->state))
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
else
|
||||
{
|
||||
UInt32 dest;
|
||||
const Byte *v;
|
||||
UPDATE_1(prob)
|
||||
if (b == 0xE8)
|
||||
if (p->range < kTopValue)
|
||||
{
|
||||
v = buf1;
|
||||
if (size1 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf1 += 4;
|
||||
size1 -= 4;
|
||||
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])++;
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
v = buf2;
|
||||
if (size2 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf2 += 4;
|
||||
size2 -= 4;
|
||||
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
|
||||
|
||||
}
|
||||
}
|
||||
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
|
||||
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
|
||||
outBuf[outPos++] = (Byte)dest;
|
||||
if (outPos == outSize)
|
||||
}
|
||||
|
||||
{
|
||||
UInt32 val;
|
||||
unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
|
||||
const Byte *cur = p->bufs[cj];
|
||||
Byte *dest;
|
||||
SizeT rem;
|
||||
|
||||
if (cur == p->lims[cj])
|
||||
{
|
||||
p->state = cj;
|
||||
break;
|
||||
outBuf[outPos++] = (Byte)(dest >> 8);
|
||||
if (outPos == outSize)
|
||||
}
|
||||
|
||||
val = GetBe32(cur);
|
||||
p->bufs[cj] = cur + 4;
|
||||
|
||||
p->ip += 4;
|
||||
val -= p->ip;
|
||||
dest = p->dest;
|
||||
rem = p->destLim - dest;
|
||||
|
||||
if (rem < 4)
|
||||
{
|
||||
p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8;
|
||||
p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8;
|
||||
p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8;
|
||||
p->temp[3] = (Byte)val;
|
||||
p->dest = dest + rem;
|
||||
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
|
||||
break;
|
||||
outBuf[outPos++] = (Byte)(dest >> 16);
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
|
||||
}
|
||||
|
||||
SetUi32(dest, val);
|
||||
p->temp[3] = (Byte)(val >> 24);
|
||||
p->dest = dest + 4;
|
||||
}
|
||||
}
|
||||
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
|
||||
|
||||
if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])
|
||||
{
|
||||
p->range <<= 8;
|
||||
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||
}
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
156
C/Bcj2.h
Executable file → Normal file
156
C/Bcj2.h
Executable file → Normal file
@@ -1,30 +1,146 @@
|
||||
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
/* Bcj2.h -- BCJ2 Converter for x86 code
|
||||
2014-11-10 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BCJ2_H
|
||||
#define __BCJ2_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define BCJ2_NUM_STREAMS 4
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_STREAM_MAIN,
|
||||
BCJ2_STREAM_CALL,
|
||||
BCJ2_STREAM_JUMP,
|
||||
BCJ2_STREAM_RC
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS,
|
||||
BCJ2_DEC_STATE_ORIG_1,
|
||||
BCJ2_DEC_STATE_ORIG_2,
|
||||
BCJ2_DEC_STATE_ORIG_3,
|
||||
|
||||
BCJ2_DEC_STATE_ORIG,
|
||||
BCJ2_DEC_STATE_OK
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS,
|
||||
BCJ2_ENC_STATE_OK
|
||||
};
|
||||
|
||||
|
||||
#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP)
|
||||
|
||||
/*
|
||||
Conditions:
|
||||
outSize <= FullOutputSize,
|
||||
where FullOutputSize is full size of output stream of x86_2 filter.
|
||||
|
||||
If buf0 overlaps outBuf, there are two required conditions:
|
||||
1) (buf0 >= outBuf)
|
||||
2) (buf0 + size0 >= outBuf + FullOutputSize).
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
SZ_ERROR_DATA - Data error
|
||||
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
|
||||
*/
|
||||
|
||||
int Bcj2_Decode(
|
||||
const Byte *buf0, SizeT size0,
|
||||
const Byte *buf1, SizeT size1,
|
||||
const Byte *buf2, SizeT size2,
|
||||
const Byte *buf3, SizeT size3,
|
||||
Byte *outBuf, SizeT outSize);
|
||||
/*
|
||||
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
|
||||
|
||||
311
C/Bcj2Enc.c
Normal file
311
C/Bcj2Enc.c
Normal file
@@ -0,0 +1,311 @@
|
||||
/* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code)
|
||||
2019-02-02 : 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 <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 BoolInt 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]);
|
||||
BoolInt 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;
|
||||
EBcj2Enc_FinishMode finishMode = p->finishMode;
|
||||
|
||||
p->src = p->temp;
|
||||
p->srcLim = p->temp + p->tempPos;
|
||||
if (src != srcLim)
|
||||
p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;
|
||||
|
||||
PRF(printf(" ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));
|
||||
|
||||
Bcj2Enc_Encode_2(p);
|
||||
|
||||
{
|
||||
unsigned num = (unsigned)(p->src - p->temp);
|
||||
unsigned tempPos = p->tempPos - num;
|
||||
unsigned i;
|
||||
p->tempPos = tempPos;
|
||||
for (i = 0; i < tempPos; i++)
|
||||
p->temp[i] = p->temp[(size_t)i + num];
|
||||
|
||||
p->src = src;
|
||||
p->srcLim = srcLim;
|
||||
p->finishMode = finishMode;
|
||||
|
||||
if (p->state != BCJ2_ENC_STATE_ORIG || src == srcLim)
|
||||
return;
|
||||
|
||||
if (extra >= tempPos)
|
||||
{
|
||||
p->src = src - tempPos;
|
||||
p->tempPos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
p->temp[tempPos] = src[0];
|
||||
p->tempPos = tempPos + 1;
|
||||
p->src = src + 1;
|
||||
extra++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRF(printf("++++ ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));
|
||||
|
||||
Bcj2Enc_Encode_2(p);
|
||||
|
||||
if (p->state == BCJ2_ENC_STATE_ORIG)
|
||||
{
|
||||
const Byte *src = p->src;
|
||||
unsigned rem = (unsigned)(p->srcLim - src);
|
||||
unsigned i;
|
||||
for (i = 0; i < rem; i++)
|
||||
p->temp[i] = src[i];
|
||||
p->tempPos = rem;
|
||||
p->src = src + rem;
|
||||
}
|
||||
}
|
||||
48
C/Blake2.h
Normal file
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);
|
||||
}
|
||||
291
C/Bra.c
Executable file → Normal file
291
C/Bra.c
Executable file → Normal file
@@ -1,133 +1,230 @@
|
||||
/* Bra.c -- Converters for RISC code
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2017-04-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
#include "Bra.h"
|
||||
|
||||
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)
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)3;
|
||||
ip += 4;
|
||||
p = data;
|
||||
lim = data + size;
|
||||
|
||||
if (encoding)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (data[i + 3] == 0xEB)
|
||||
for (;;)
|
||||
{
|
||||
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;
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
p += 4;
|
||||
if (p[-1] == 0xEB)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v = GetUi32(p - 4);
|
||||
v <<= 2;
|
||||
v += ip + (UInt32)(p - data);
|
||||
v >>= 2;
|
||||
v &= 0x00FFFFFF;
|
||||
v |= 0xEB000000;
|
||||
SetUi32(p - 4, v);
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
p += 4;
|
||||
if (p[-1] == 0xEB)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v = GetUi32(p - 4);
|
||||
v <<= 2;
|
||||
v -= ip + (UInt32)(p - data);
|
||||
v >>= 2;
|
||||
v &= 0x00FFFFFF;
|
||||
v |= 0xEB000000;
|
||||
SetUi32(p - 4, v);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||
{
|
||||
SizeT i;
|
||||
if (size < 4)
|
||||
return 0;
|
||||
size -= 4;
|
||||
ip += 4;
|
||||
for (i = 0; i <= size; i += 2)
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)1;
|
||||
p = data;
|
||||
lim = data + size - 4;
|
||||
|
||||
if (encoding)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if ((data[i + 1] & 0xF8) == 0xF0 &&
|
||||
(data[i + 3] & 0xF8) == 0xF8)
|
||||
UInt32 b1;
|
||||
for (;;)
|
||||
{
|
||||
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;
|
||||
UInt32 b3;
|
||||
if (p > lim)
|
||||
return p - data;
|
||||
b1 = p[1];
|
||||
b3 = p[3];
|
||||
p += 2;
|
||||
b1 ^= 8;
|
||||
if ((b3 & b1) >= 0xF8)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v =
|
||||
((UInt32)b1 << 19)
|
||||
+ (((UInt32)p[1] & 0x7) << 8)
|
||||
+ (((UInt32)p[-2] << 11))
|
||||
+ (p[0]);
|
||||
|
||||
p += 2;
|
||||
{
|
||||
UInt32 cur = (ip + (UInt32)(p - data)) >> 1;
|
||||
v += cur;
|
||||
}
|
||||
|
||||
p[-4] = (Byte)(v >> 11);
|
||||
p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7));
|
||||
p[-2] = (Byte)v;
|
||||
p[-1] = (Byte)(0xF8 | (v >> 8));
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt32 b1;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 b3;
|
||||
if (p > lim)
|
||||
return p - data;
|
||||
b1 = p[1];
|
||||
b3 = p[3];
|
||||
p += 2;
|
||||
b1 ^= 8;
|
||||
if ((b3 & b1) >= 0xF8)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v =
|
||||
((UInt32)b1 << 19)
|
||||
+ (((UInt32)p[1] & 0x7) << 8)
|
||||
+ (((UInt32)p[-2] << 11))
|
||||
+ (p[0]);
|
||||
|
||||
p += 2;
|
||||
{
|
||||
UInt32 cur = (ip + (UInt32)(p - data)) >> 1;
|
||||
v -= cur;
|
||||
}
|
||||
|
||||
/*
|
||||
SetUi16(p - 4, (UInt16)(((v >> 11) & 0x7FF) | 0xF000));
|
||||
SetUi16(p - 2, (UInt16)(v | 0xF800));
|
||||
*/
|
||||
|
||||
p[-4] = (Byte)(v >> 11);
|
||||
p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7));
|
||||
p[-2] = (Byte)v;
|
||||
p[-1] = (Byte)(0xF8 | (v >> 8));
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||
{
|
||||
SizeT i;
|
||||
if (size < 4)
|
||||
return 0;
|
||||
size -= 4;
|
||||
for (i = 0; i <= size; i += 4)
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)3;
|
||||
ip -= 4;
|
||||
p = data;
|
||||
lim = data + size;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
|
||||
for (;;)
|
||||
{
|
||||
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 (p >= lim)
|
||||
return p - data;
|
||||
p += 4;
|
||||
/* if ((v & 0xFC000003) == 0x48000001) */
|
||||
if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v = GetBe32(p - 4);
|
||||
if (encoding)
|
||||
dest = ip + (UInt32)i + src;
|
||||
v += ip + (UInt32)(p - data);
|
||||
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;
|
||||
v -= ip + (UInt32)(p - data);
|
||||
v &= 0x03FFFFFF;
|
||||
v |= 0x48000000;
|
||||
SetBe32(p - 4, v);
|
||||
}
|
||||
}
|
||||
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;
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)3;
|
||||
ip -= 4;
|
||||
p = data;
|
||||
lim = data + size;
|
||||
|
||||
data[i + 0] = (Byte)(dest >> 24);
|
||||
data[i + 1] = (Byte)(dest >> 16);
|
||||
data[i + 2] = (Byte)(dest >> 8);
|
||||
data[i + 3] = (Byte)dest;
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
/*
|
||||
v = GetBe32(p);
|
||||
p += 4;
|
||||
m = v + ((UInt32)5 << 29);
|
||||
m ^= (UInt32)7 << 29;
|
||||
m += (UInt32)1 << 22;
|
||||
if ((m & ((UInt32)0x1FF << 23)) == 0)
|
||||
break;
|
||||
*/
|
||||
p += 4;
|
||||
if ((p[-4] == 0x40 && (p[-3] & 0xC0) == 0) ||
|
||||
(p[-4] == 0x7F && (p[-3] >= 0xC0)))
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v = GetBe32(p - 4);
|
||||
v <<= 2;
|
||||
if (encoding)
|
||||
v += ip + (UInt32)(p - data);
|
||||
else
|
||||
v -= ip + (UInt32)(p - data);
|
||||
|
||||
v &= 0x01FFFFFF;
|
||||
v -= (UInt32)1 << 24;
|
||||
v ^= 0xFF000000;
|
||||
v >>= 2;
|
||||
v |= 0x40000000;
|
||||
SetBe32(p - 4, v);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
8
C/Bra.h
Executable file → Normal file
8
C/Bra.h
Executable file → Normal file
@@ -1,10 +1,12 @@
|
||||
/* Bra.h -- Branch converters for executables
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BRA_H
|
||||
#define __BRA_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/*
|
||||
These functions convert relative addresses to absolute addresses
|
||||
@@ -57,4 +59,6 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
99
C/Bra86.c
Executable file → Normal file
99
C/Bra86.c
Executable file → Normal file
@@ -1,85 +1,82 @@
|
||||
/* Bra86.c -- Converter for x86 code (BCJ)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "Bra.h"
|
||||
|
||||
#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};
|
||||
#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)
|
||||
|
||||
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
|
||||
{
|
||||
SizeT bufferPos = 0, prevPosT;
|
||||
UInt32 prevMask = *state & 0x7;
|
||||
SizeT pos = 0;
|
||||
UInt32 mask = *state & 7;
|
||||
if (size < 5)
|
||||
return 0;
|
||||
size -= 4;
|
||||
ip += 5;
|
||||
prevPosT = (SizeT)0 - 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *p = data + bufferPos;
|
||||
Byte *limit = data + size - 4;
|
||||
Byte *p = data + pos;
|
||||
const Byte *limit = data + size;
|
||||
for (; p < limit; p++)
|
||||
if ((*p & 0xFE) == 0xE8)
|
||||
break;
|
||||
bufferPos = (SizeT)(p - data);
|
||||
if (p >= limit)
|
||||
break;
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
if (prevPosT > 3)
|
||||
prevMask = 0;
|
||||
else
|
||||
|
||||
{
|
||||
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
|
||||
if (prevMask != 0)
|
||||
SizeT d = (SizeT)(p - data - pos);
|
||||
pos = (SizeT)(p - data);
|
||||
if (p >= limit)
|
||||
{
|
||||
Byte b = p[4 - kMaskToBitNumber[prevMask]];
|
||||
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
|
||||
*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[(size_t)(mask >> 1) + 1])))
|
||||
{
|
||||
prevPosT = bufferPos;
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
mask = (mask >> 1) | 4;
|
||||
pos++;
|
||||
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 (;;)
|
||||
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)
|
||||
{
|
||||
Byte b;
|
||||
int index;
|
||||
if (encoding)
|
||||
dest = (ip + (UInt32)bufferPos) + src;
|
||||
else
|
||||
dest = src - (ip + (UInt32)bufferPos);
|
||||
if (prevMask == 0)
|
||||
break;
|
||||
index = kMaskToBitNumber[prevMask] * 8;
|
||||
b = (Byte)(dest >> (24 - index));
|
||||
if (!Test86MSByte(b))
|
||||
break;
|
||||
src = dest ^ ((1 << (32 - index)) - 1);
|
||||
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[4] = (Byte)(~(((dest >> 24) & 1) - 1));
|
||||
p[3] = (Byte)(dest >> 16);
|
||||
p[2] = (Byte)(dest >> 8);
|
||||
p[1] = (Byte)dest;
|
||||
bufferPos += 5;
|
||||
p[1] = (Byte)v;
|
||||
p[2] = (Byte)(v >> 8);
|
||||
p[3] = (Byte)(v >> 16);
|
||||
p[4] = (Byte)(0 - ((v >> 24) & 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
mask = (mask >> 1) | 4;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
||||
return bufferPos;
|
||||
}
|
||||
|
||||
84
C/BraIA64.c
Executable file → Normal file
84
C/BraIA64.c
Executable file → Normal file
@@ -1,67 +1,53 @@
|
||||
/* BraIA64.c -- Converter for IA-64 code
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2017-01-26 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
#include "Bra.h"
|
||||
|
||||
static const Byte kBranchTable[32] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 4, 6, 6, 0, 0, 7, 7,
|
||||
4, 4, 0, 0, 4, 4, 0, 0
|
||||
};
|
||||
|
||||
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||
{
|
||||
SizeT i;
|
||||
if (size < 16)
|
||||
return 0;
|
||||
size -= 16;
|
||||
for (i = 0; i <= size; i += 16)
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
UInt32 instrTemplate = data[i] & 0x1F;
|
||||
UInt32 mask = kBranchTable[instrTemplate];
|
||||
UInt32 bitPos = 5;
|
||||
int slot;
|
||||
for (slot = 0; slot < 3; slot++, bitPos += 41)
|
||||
unsigned m = ((UInt32)0x334B0000 >> (data[i] & 0x1E)) & 3;
|
||||
if (m)
|
||||
{
|
||||
UInt32 bytePos, bitRes;
|
||||
UInt64 instruction, instNorm;
|
||||
int j;
|
||||
if (((mask >> slot) & 1) == 0)
|
||||
continue;
|
||||
bytePos = (bitPos >> 3);
|
||||
bitRes = bitPos & 0x7;
|
||||
instruction = 0;
|
||||
for (j = 0; j < 6; j++)
|
||||
instruction += (UInt64)data[i + j + bytePos] << (8 * j);
|
||||
|
||||
instNorm = instruction >> bitRes;
|
||||
if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0)
|
||||
m++;
|
||||
do
|
||||
{
|
||||
UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);
|
||||
UInt32 dest;
|
||||
src |= ((UInt32)(instNorm >> 36) & 1) << 20;
|
||||
|
||||
src <<= 4;
|
||||
|
||||
if (encoding)
|
||||
dest = ip + (UInt32)i + src;
|
||||
else
|
||||
dest = src - (ip + (UInt32)i);
|
||||
|
||||
dest >>= 4;
|
||||
|
||||
instNorm &= ~((UInt64)(0x8FFFFF) << 13);
|
||||
instNorm |= ((UInt64)(dest & 0xFFFFF) << 13);
|
||||
instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20));
|
||||
|
||||
instruction &= (1 << bitRes) - 1;
|
||||
instruction |= (instNorm << bitRes);
|
||||
for (j = 0; j < 6; j++)
|
||||
data[i + j + bytePos] = (Byte)(instruction >> (8 * j));
|
||||
Byte *p = data + (i + (size_t)m * 5 - 8);
|
||||
if (((p[3] >> m) & 15) == 5
|
||||
&& (((p[-1] | ((UInt32)p[0] << 8)) >> m) & 0x70) == 0)
|
||||
{
|
||||
unsigned raw = GetUi32(p);
|
||||
unsigned v = raw >> m;
|
||||
v = (v & 0xFFFFF) | ((v & (1 << 23)) >> 3);
|
||||
|
||||
v <<= 4;
|
||||
if (encoding)
|
||||
v += ip + (UInt32)i;
|
||||
else
|
||||
v -= ip + (UInt32)i;
|
||||
v >>= 4;
|
||||
|
||||
v &= 0x1FFFFF;
|
||||
v += 0x700000;
|
||||
v &= 0x8FFFFF;
|
||||
raw &= ~((UInt32)0x8FFFFF << m);
|
||||
raw |= (v << m);
|
||||
SetUi32(p, raw);
|
||||
}
|
||||
}
|
||||
while (++m <= 4);
|
||||
}
|
||||
i += 16;
|
||||
}
|
||||
while (i <= size);
|
||||
return i;
|
||||
}
|
||||
|
||||
27
C/BwtSort.c
Executable file → Normal file
27
C/BwtSort.c
Executable file → Normal file
@@ -1,7 +1,7 @@
|
||||
/* BwtSort.c -- BWT block sorting
|
||||
2008-08-17
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2018-07-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "BwtSort.h"
|
||||
#include "Sort.h"
|
||||
@@ -314,7 +314,7 @@ UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 group
|
||||
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
||||
UInt32 subGroupSize = ((ind2[j] & ~0xC0000000) >> kNumBitsMax);
|
||||
if ((ind2[j] & 0x40000000) != 0)
|
||||
subGroupSize += ((ind2[j + 1] >> kNumBitsMax) << kNumExtra0Bits);
|
||||
subGroupSize += ((ind2[(size_t)j + 1] >> kNumBitsMax) << kNumExtra0Bits);
|
||||
subGroupSize++;
|
||||
for (;;)
|
||||
{
|
||||
@@ -362,7 +362,7 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
||||
for (i = 0; i < kNumHashValues; i++)
|
||||
counters[i] = 0;
|
||||
for (i = 0; i < blockSize - 1; i++)
|
||||
counters[((UInt32)data[i] << 8) | data[i + 1]]++;
|
||||
counters[((UInt32)data[i] << 8) | data[(size_t)i + 1]]++;
|
||||
counters[((UInt32)data[i] << 8) | data[0]]++;
|
||||
|
||||
Groups = counters + BS_TEMP_SIZE;
|
||||
@@ -392,11 +392,11 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
||||
}
|
||||
|
||||
for (i = 0; i < blockSize - 1; i++)
|
||||
Groups[i] = counters[((UInt32)data[i] << 8) | data[i + 1]];
|
||||
Groups[i] = counters[((UInt32)data[i] << 8) | data[(size_t)i + 1]];
|
||||
Groups[i] = counters[((UInt32)data[i] << 8) | data[0]];
|
||||
|
||||
for (i = 0; i < blockSize - 1; i++)
|
||||
Indices[counters[((UInt32)data[i] << 8) | data[i + 1]]++] = i;
|
||||
Indices[counters[((UInt32)data[i] << 8) | data[(size_t)i + 1]]++] = i;
|
||||
Indices[counters[((UInt32)data[i] << 8) | data[0]]++] = i;
|
||||
|
||||
#ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
||||
@@ -448,11 +448,11 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
||||
|
||||
groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax);
|
||||
{
|
||||
Bool finishedGroup = ((Indices[i] & 0x80000000) == 0);
|
||||
BoolInt finishedGroup = ((Indices[i] & 0x80000000) == 0);
|
||||
if ((Indices[i] & 0x40000000) != 0)
|
||||
{
|
||||
groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits);
|
||||
Indices[i + 1] &= kIndexMask;
|
||||
groupSize += ((Indices[(size_t)i + 1] >> kNumBitsMax) << kNumExtra0Bits);
|
||||
Indices[(size_t)i + 1] &= kIndexMask;
|
||||
}
|
||||
Indices[i] &= kIndexMask;
|
||||
groupSize++;
|
||||
@@ -460,7 +460,7 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
||||
{
|
||||
Indices[i - finishedGroupSize] &= kIndexMask;
|
||||
if (finishedGroupSize > 1)
|
||||
Indices[i - finishedGroupSize + 1] &= kIndexMask;
|
||||
Indices[(size_t)(i - finishedGroupSize) + 1] &= kIndexMask;
|
||||
{
|
||||
UInt32 newGroupSize = groupSize + finishedGroupSize;
|
||||
SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize);
|
||||
@@ -503,8 +503,8 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
||||
UInt32 groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax);
|
||||
if ((Indices[i] & 0x40000000) != 0)
|
||||
{
|
||||
groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits);
|
||||
Indices[i + 1] &= kIndexMask;
|
||||
groupSize += ((Indices[(size_t)i + 1] >> kNumBitsMax) << kNumExtra0Bits);
|
||||
Indices[(size_t)i + 1] &= kIndexMask;
|
||||
}
|
||||
Indices[i] &= kIndexMask;
|
||||
groupSize++;
|
||||
@@ -513,4 +513,3 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
||||
#endif
|
||||
return Groups[0];
|
||||
}
|
||||
|
||||
|
||||
14
C/BwtSort.h
Executable file → Normal file
14
C/BwtSort.h
Executable file → Normal file
@@ -1,12 +1,12 @@
|
||||
/* BwtSort.h -- BWT block sorting
|
||||
2008-03-26
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BWTSORT_H
|
||||
#define __BWTSORT_H
|
||||
#ifndef __BWT_SORT_H
|
||||
#define __BWT_SORT_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */
|
||||
/* #define BLOCK_SORT_EXTERNAL_FLAGS */
|
||||
@@ -21,4 +21,6 @@ Public domain */
|
||||
|
||||
UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
33
C/Compiler.h
Normal file
33
C/Compiler.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Compiler.h
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_COMPILER_H
|
||||
#define __7Z_COMPILER_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#ifdef UNDER_CE
|
||||
#define RPC_NO_WINDOWS_H
|
||||
/* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */
|
||||
#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
|
||||
#pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int
|
||||
#endif
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
#pragma warning(disable : 4996) // This function or variable may be unsafe
|
||||
#else
|
||||
#pragma warning(disable : 4511) // copy constructor could not be generated
|
||||
#pragma warning(disable : 4512) // assignment operator could not be generated
|
||||
#pragma warning(disable : 4514) // unreferenced inline function has been removed
|
||||
#pragma warning(disable : 4702) // unreachable code
|
||||
#pragma warning(disable : 4710) // not inlined
|
||||
#pragma warning(disable : 4714) // function marked as __forceinline not inlined
|
||||
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define UNUSED_VAR(x) (void)x;
|
||||
/* #define UNUSED_VAR(x) x=x; */
|
||||
|
||||
#endif
|
||||
218
C/CpuArch.c
Normal file
218
C/CpuArch.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/* CpuArch.c -- CPU specific code
|
||||
2018-02-18: 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
|
||||
}
|
||||
|
||||
BoolInt 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;
|
||||
}
|
||||
|
||||
BoolInt 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 BoolInt 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
|
||||
|
||||
BoolInt CPU_Is_Aes_Supported()
|
||||
{
|
||||
Cx86cpuid p;
|
||||
CHECK_SYS_SSE_SUPPORT
|
||||
if (!x86cpuid_CheckAndRead(&p))
|
||||
return False;
|
||||
return (p.c >> 25) & 1;
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_PageGB()
|
||||
{
|
||||
Cx86cpuid cpuid;
|
||||
if (!x86cpuid_CheckAndRead(&cpuid))
|
||||
return False;
|
||||
{
|
||||
UInt32 d[4] = { 0 };
|
||||
MyCPUID(0x80000000, &d[0], &d[1], &d[2], &d[3]);
|
||||
if (d[0] < 0x80000001)
|
||||
return False;
|
||||
}
|
||||
{
|
||||
UInt32 d[4] = { 0 };
|
||||
MyCPUID(0x80000001, &d[0], &d[1], &d[2], &d[3]);
|
||||
return (d[3] >> 26) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
323
C/CpuArch.h
Executable file → Normal file
323
C/CpuArch.h
Executable file → Normal file
@@ -1,33 +1,216 @@
|
||||
/* CpuArch.h
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
/* CpuArch.h -- CPU specific code
|
||||
2018-02-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __CPUARCH_H
|
||||
#define __CPUARCH_H
|
||||
#ifndef __CPU_ARCH_H
|
||||
#define __CPU_ARCH_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/*
|
||||
LITTLE_ENDIAN_UNALIGN means:
|
||||
1) CPU is LITTLE_ENDIAN
|
||||
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__)
|
||||
#define LITTLE_ENDIAN_UNALIGN
|
||||
#if defined(_M_X64) \
|
||||
|| defined(_M_AMD64) \
|
||||
|| defined(__x86_64__) \
|
||||
|| defined(__AMD64__) \
|
||||
|| defined(__amd64__)
|
||||
#define MY_CPU_AMD64
|
||||
#ifdef __ILP32__
|
||||
#define MY_CPU_NAME "x32"
|
||||
#else
|
||||
#define MY_CPU_NAME "x64"
|
||||
#endif
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
||||
#ifdef LITTLE_ENDIAN_UNALIGN
|
||||
|
||||
#define GetUi16(p) (*(const UInt16 *)(p))
|
||||
#define GetUi32(p) (*(const UInt32 *)(p))
|
||||
#define GetUi64(p) (*(const UInt64 *)(p))
|
||||
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
|
||||
#if defined(_M_IX86) \
|
||||
|| defined(__i386__)
|
||||
#define MY_CPU_X86
|
||||
#define MY_CPU_NAME "x86"
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_M_ARM64) \
|
||||
|| defined(__AARCH64EL__) \
|
||||
|| defined(__AARCH64EB__) \
|
||||
|| defined(__aarch64__)
|
||||
#define MY_CPU_ARM64
|
||||
#define MY_CPU_NAME "arm64"
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_M_ARM) \
|
||||
|| defined(_M_ARM_NT) \
|
||||
|| defined(_M_ARMT) \
|
||||
|| defined(__arm__) \
|
||||
|| defined(__thumb__) \
|
||||
|| defined(__ARMEL__) \
|
||||
|| defined(__ARMEB__) \
|
||||
|| defined(__THUMBEL__) \
|
||||
|| defined(__THUMBEB__)
|
||||
#define MY_CPU_ARM
|
||||
#define MY_CPU_NAME "arm"
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_M_IA64) \
|
||||
|| defined(__ia64__)
|
||||
#define MY_CPU_IA64
|
||||
#define MY_CPU_NAME "ia64"
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__mips64) \
|
||||
|| defined(__mips64__) \
|
||||
|| (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3))
|
||||
#define MY_CPU_NAME "mips64"
|
||||
#define MY_CPU_64BIT
|
||||
#elif defined(__mips__)
|
||||
#define MY_CPU_NAME "mips"
|
||||
/* #define MY_CPU_32BIT */
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__ppc64__) \
|
||||
|| defined(__powerpc64__)
|
||||
#ifdef __ILP32__
|
||||
#define MY_CPU_NAME "ppc64-32"
|
||||
#else
|
||||
#define MY_CPU_NAME "ppc64"
|
||||
#endif
|
||||
#define MY_CPU_64BIT
|
||||
#elif defined(__ppc__) \
|
||||
|| defined(__powerpc__)
|
||||
#define MY_CPU_NAME "ppc"
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__sparc64__)
|
||||
#define MY_CPU_NAME "sparc64"
|
||||
#define MY_CPU_64BIT
|
||||
#elif defined(__sparc__)
|
||||
#define MY_CPU_NAME "sparc"
|
||||
/* #define MY_CPU_32BIT */
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
|
||||
#define MY_CPU_X86_OR_AMD64
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifdef MY_CPU_ARM
|
||||
#define MY_CPU_ARM_LE
|
||||
#endif
|
||||
|
||||
#ifdef MY_CPU_ARM64
|
||||
#define MY_CPU_ARM64_LE
|
||||
#endif
|
||||
|
||||
#ifdef _M_IA64
|
||||
#define MY_CPU_IA64_LE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||
|| defined(MY_CPU_ARM_LE) \
|
||||
|| defined(MY_CPU_ARM64_LE) \
|
||||
|| defined(MY_CPU_IA64_LE) \
|
||||
|| defined(__LITTLE_ENDIAN__) \
|
||||
|| defined(__ARMEL__) \
|
||||
|| defined(__THUMBEL__) \
|
||||
|| defined(__AARCH64EL__) \
|
||||
|| defined(__MIPSEL__) \
|
||||
|| defined(__MIPSEL) \
|
||||
|| defined(_MIPSEL) \
|
||||
|| defined(__BFIN__) \
|
||||
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||
#define MY_CPU_LE
|
||||
#endif
|
||||
|
||||
#if defined(__BIG_ENDIAN__) \
|
||||
|| defined(__ARMEB__) \
|
||||
|| defined(__THUMBEB__) \
|
||||
|| defined(__AARCH64EB__) \
|
||||
|| defined(__MIPSEB__) \
|
||||
|| defined(__MIPSEB) \
|
||||
|| defined(_MIPSEB) \
|
||||
|| defined(__m68k__) \
|
||||
|| defined(__s390__) \
|
||||
|| defined(__s390x__) \
|
||||
|| defined(__zarch__) \
|
||||
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
#define MY_CPU_BE
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
|
||||
#error Stop_Compiling_Bad_Endian
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT)
|
||||
#error Stop_Compiling_Bad_32_64_BIT
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MY_CPU_NAME
|
||||
#ifdef MY_CPU_LE
|
||||
#define MY_CPU_NAME "LE"
|
||||
#elif defined(MY_CPU_BE)
|
||||
#define MY_CPU_NAME "BE"
|
||||
#else
|
||||
/*
|
||||
#define MY_CPU_NAME ""
|
||||
*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef MY_CPU_LE
|
||||
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||
|| defined(MY_CPU_ARM64) \
|
||||
|| defined(__ARM_FEATURE_UNALIGNED)
|
||||
#define MY_CPU_LE_UNALIGN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MY_CPU_LE_UNALIGN
|
||||
|
||||
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
|
||||
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
|
||||
#define GetUi64(p) (*(const UInt64 *)(const void *)(p))
|
||||
|
||||
#define SetUi16(p, v) { *(UInt16 *)(p) = (v); }
|
||||
#define SetUi32(p, v) { *(UInt32 *)(p) = (v); }
|
||||
#define SetUi64(p, v) { *(UInt64 *)(p) = (v); }
|
||||
|
||||
#else
|
||||
|
||||
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
|
||||
#define GetUi16(p) ( (UInt16) ( \
|
||||
((const Byte *)(p))[0] | \
|
||||
((UInt16)((const Byte *)(p))[1] << 8) ))
|
||||
|
||||
#define GetUi32(p) ( \
|
||||
((const Byte *)(p))[0] | \
|
||||
@@ -37,21 +220,54 @@ about these properties of platform.
|
||||
|
||||
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||
|
||||
#define SetUi32(p, d) { UInt32 _x_ = (d); \
|
||||
((Byte *)(p))[0] = (Byte)_x_; \
|
||||
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
|
||||
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
|
||||
((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
|
||||
#define 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(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
|
||||
#ifdef __has_builtin
|
||||
#define MY__has_builtin(x) __has_builtin(x)
|
||||
#else
|
||||
#define MY__has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
|
||||
|
||||
/* Note: we use bswap instruction, that is unsupported in 386 cpu */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#pragma intrinsic(_byteswap_ushort)
|
||||
#pragma intrinsic(_byteswap_ulong)
|
||||
#pragma intrinsic(_byteswap_uint64)
|
||||
|
||||
/* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */
|
||||
#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))) \
|
||||
|| (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) )
|
||||
|
||||
/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const Byte *)(p)) */
|
||||
#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p))
|
||||
#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p))
|
||||
|
||||
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v)
|
||||
|
||||
#else
|
||||
|
||||
#define GetBe32(p) ( \
|
||||
@@ -62,8 +278,59 @@ about these properties of platform.
|
||||
|
||||
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||
|
||||
#endif
|
||||
|
||||
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
|
||||
#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
|
||||
|
||||
|
||||
#ifndef GetBe16
|
||||
|
||||
#define GetBe16(p) ( (UInt16) ( \
|
||||
((UInt16)((const Byte *)(p))[0] << 8) | \
|
||||
((const Byte *)(p))[1] ))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 maxFunc;
|
||||
UInt32 vendor[3];
|
||||
UInt32 ver;
|
||||
UInt32 b;
|
||||
UInt32 c;
|
||||
UInt32 d;
|
||||
} Cx86cpuid;
|
||||
|
||||
enum
|
||||
{
|
||||
CPU_FIRM_INTEL,
|
||||
CPU_FIRM_AMD,
|
||||
CPU_FIRM_VIA
|
||||
};
|
||||
|
||||
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
|
||||
|
||||
BoolInt 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)
|
||||
|
||||
BoolInt CPU_Is_InOrder();
|
||||
BoolInt CPU_Is_Aes_Supported();
|
||||
BoolInt CPU_IsSupported_PageGB();
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#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
|
||||
108
C/DllSecur.c
Normal file
108
C/DllSecur.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/* DllSecur.c -- DLL loading security
|
||||
2018-02-21 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "DllSecur.h"
|
||||
|
||||
#ifndef UNDER_CE
|
||||
|
||||
typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags);
|
||||
|
||||
#define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400
|
||||
#define MY_LOAD_LIBRARY_SEARCH_SYSTEM32 0x800
|
||||
|
||||
static const char * const g_Dlls =
|
||||
#ifndef _CONSOLE
|
||||
"UXTHEME\0"
|
||||
#endif
|
||||
"USERENV\0"
|
||||
"SETUPAPI\0"
|
||||
"APPHELP\0"
|
||||
"PROPSYS\0"
|
||||
"DWMAPI\0"
|
||||
"CRYPTBASE\0"
|
||||
"OLEACC\0"
|
||||
"CLBCATQ\0"
|
||||
"VERSION\0"
|
||||
;
|
||||
|
||||
#endif
|
||||
|
||||
void My_SetDefaultDllDirectories()
|
||||
{
|
||||
#ifndef UNDER_CE
|
||||
|
||||
OSVERSIONINFO vi;
|
||||
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||
GetVersionEx(&vi);
|
||||
if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0)
|
||||
{
|
||||
Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories)
|
||||
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories");
|
||||
if (setDllDirs)
|
||||
if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS))
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void LoadSecurityDlls()
|
||||
{
|
||||
#ifndef UNDER_CE
|
||||
|
||||
wchar_t buf[MAX_PATH + 100];
|
||||
|
||||
{
|
||||
// at Vista (ver 6.0) : CoCreateInstance(CLSID_ShellLink, ...) doesn't work after SetDefaultDllDirectories() : Check it ???
|
||||
OSVERSIONINFO vi;
|
||||
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||
if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0)
|
||||
{
|
||||
Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories)
|
||||
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories");
|
||||
if (setDllDirs)
|
||||
if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
unsigned len = GetSystemDirectoryW(buf, MAX_PATH + 2);
|
||||
if (len == 0 || len > MAX_PATH)
|
||||
return;
|
||||
}
|
||||
{
|
||||
const char *dll;
|
||||
unsigned pos = (unsigned)lstrlenW(buf);
|
||||
|
||||
if (buf[pos - 1] != '\\')
|
||||
buf[pos++] = '\\';
|
||||
|
||||
for (dll = g_Dlls; dll[0] != 0;)
|
||||
{
|
||||
unsigned k = 0;
|
||||
for (;;)
|
||||
{
|
||||
char c = *dll++;
|
||||
buf[pos + k] = (Byte)c;
|
||||
k++;
|
||||
if (c == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
lstrcatW(buf, L".dll");
|
||||
LoadLibraryExW(buf, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
20
C/DllSecur.h
Normal file
20
C/DllSecur.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* DllSecur.h -- DLL loading for security
|
||||
2018-02-19 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __DLL_SECUR_H
|
||||
#define __DLL_SECUR_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void My_SetDefaultDllDirectories();
|
||||
void LoadSecurityDlls();
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
26
C/HuffEnc.c
Executable file → Normal file
26
C/HuffEnc.c
Executable file → Normal file
@@ -1,7 +1,7 @@
|
||||
/* HuffEnc.c -- functions for Huffman encoding
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "HuffEnc.h"
|
||||
#include "Sort.h"
|
||||
@@ -67,11 +67,11 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
|
||||
|
||||
if (num < 2)
|
||||
{
|
||||
int minCode = 0;
|
||||
int maxCode = 1;
|
||||
unsigned minCode = 0;
|
||||
unsigned maxCode = 1;
|
||||
if (num == 1)
|
||||
{
|
||||
maxCode = (int)(p[0] & MASK);
|
||||
maxCode = (unsigned)p[0] & MASK;
|
||||
if (maxCode == 0)
|
||||
maxCode++;
|
||||
}
|
||||
@@ -113,7 +113,7 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
|
||||
if (len >= maxLen)
|
||||
for (len = maxLen - 1; lenCounters[len] == 0; len--);
|
||||
lenCounters[len]--;
|
||||
lenCounters[len + 1] += 2;
|
||||
lenCounters[(size_t)len + 1] += 2;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -121,8 +121,8 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
|
||||
i = 0;
|
||||
for (len = maxLen; len != 0; len--)
|
||||
{
|
||||
UInt32 num;
|
||||
for (num = lenCounters[len]; num != 0; num--)
|
||||
UInt32 k;
|
||||
for (k = lenCounters[len]; k != 0; k--)
|
||||
lens[p[i++] & MASK] = (Byte)len;
|
||||
}
|
||||
}
|
||||
@@ -133,14 +133,14 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymb
|
||||
UInt32 code = 0;
|
||||
UInt32 len;
|
||||
for (len = 1; len <= kMaxLen; len++)
|
||||
nextCodes[len] = code = (code + lenCounters[len - 1]) << 1;
|
||||
nextCodes[len] = code = (code + lenCounters[(size_t)len - 1]) << 1;
|
||||
}
|
||||
/* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */
|
||||
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < numSymbols; i++)
|
||||
p[i] = nextCodes[lens[i]]++;
|
||||
UInt32 k;
|
||||
for (k = 0; k < numSymbols; k++)
|
||||
p[k] = nextCodes[lens[k]]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
C/HuffEnc.h
Executable file → Normal file
16
C/HuffEnc.h
Executable file → Normal file
@@ -1,12 +1,12 @@
|
||||
/* HuffEnc.h -- functions for Huffman encoding
|
||||
2008-03-26
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
/* HuffEnc.h -- Huffman encoding
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __HUFFENC_H
|
||||
#define __HUFFENC_H
|
||||
#ifndef __HUFF_ENC_H
|
||||
#define __HUFF_ENC_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/*
|
||||
Conditions:
|
||||
@@ -18,4 +18,6 @@ Conditions:
|
||||
|
||||
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
696
C/LzFind.c
Executable file → Normal file
696
C/LzFind.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
48
C/LzFind.h
Executable file → Normal file
48
C/LzFind.h
Executable file → Normal file
@@ -1,10 +1,12 @@
|
||||
/* LzFind.h -- Match finder for LZ algorithms
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2017-06-10 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZFIND_H
|
||||
#define __LZFIND_H
|
||||
#ifndef __LZ_FIND_H
|
||||
#define __LZ_FIND_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
typedef UInt32 CLzRef;
|
||||
|
||||
@@ -19,6 +21,11 @@ typedef struct _CMatchFinder
|
||||
UInt32 cyclicBufferPos;
|
||||
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
|
||||
|
||||
Byte streamEndWasReached;
|
||||
Byte btMode;
|
||||
Byte bigHash;
|
||||
Byte directInput;
|
||||
|
||||
UInt32 matchMaxLen;
|
||||
CLzRef *hash;
|
||||
CLzRef *son;
|
||||
@@ -27,30 +34,32 @@ typedef struct _CMatchFinder
|
||||
|
||||
Byte *bufferBase;
|
||||
ISeqInStream *stream;
|
||||
int streamEndWasReached;
|
||||
|
||||
|
||||
UInt32 blockSize;
|
||||
UInt32 keepSizeBefore;
|
||||
UInt32 keepSizeAfter;
|
||||
|
||||
UInt32 numHashBytes;
|
||||
int directInput;
|
||||
int btMode;
|
||||
/* int skipModeBits; */
|
||||
int bigHash;
|
||||
size_t directInputRem;
|
||||
UInt32 historySize;
|
||||
UInt32 fixedHashSize;
|
||||
UInt32 hashSizeSum;
|
||||
UInt32 numSons;
|
||||
SRes result;
|
||||
UInt32 crc[256];
|
||||
size_t numRefs;
|
||||
|
||||
UInt64 expectedDataSize;
|
||||
} CMatchFinder;
|
||||
|
||||
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
|
||||
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
|
||||
|
||||
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
|
||||
|
||||
#define Inline_MatchFinder_IsFinishedOK(p) \
|
||||
((p)->streamEndWasReached \
|
||||
&& (p)->streamPos == (p)->pos \
|
||||
&& (!(p)->directInput || (p)->directInputRem == 0))
|
||||
|
||||
int MatchFinder_NeedMove(CMatchFinder *p);
|
||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
||||
void MatchFinder_MoveBlock(CMatchFinder *p);
|
||||
@@ -64,9 +73,9 @@ void MatchFinder_Construct(CMatchFinder *p);
|
||||
*/
|
||||
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
||||
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
|
||||
ISzAlloc *alloc);
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
|
||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
|
||||
ISzAllocPtr alloc);
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc);
|
||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);
|
||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
|
||||
|
||||
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
|
||||
@@ -80,7 +89,6 @@ Conditions:
|
||||
*/
|
||||
|
||||
typedef void (*Mf_Init_Func)(void *object);
|
||||
typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
|
||||
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
|
||||
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
|
||||
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
|
||||
@@ -89,7 +97,6 @@ typedef void (*Mf_Skip_Func)(void *object, UInt32);
|
||||
typedef struct _IMatchFinder
|
||||
{
|
||||
Mf_Init_Func Init;
|
||||
Mf_GetIndexByte_Func GetIndexByte;
|
||||
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
|
||||
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
|
||||
Mf_GetMatches_Func GetMatches;
|
||||
@@ -98,10 +105,17 @@ typedef struct _IMatchFinder
|
||||
|
||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
||||
|
||||
void MatchFinder_Init_LowHash(CMatchFinder *p);
|
||||
void MatchFinder_Init_HighHash(CMatchFinder *p);
|
||||
void MatchFinder_Init_3(CMatchFinder *p, int readData);
|
||||
void MatchFinder_Init(CMatchFinder *p);
|
||||
|
||||
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
|
||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
368
C/LzFindMt.c
Executable file → Normal file
368
C/LzFindMt.c
Executable file → Normal file
@@ -1,11 +1,13 @@
|
||||
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2018-12-29 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "LzHash.h"
|
||||
|
||||
#include "LzFindMt.h"
|
||||
|
||||
void MtSync_Construct(CMtSync *p)
|
||||
static void MtSync_Construct(CMtSync *p)
|
||||
{
|
||||
p->wasCreated = False;
|
||||
p->csWasInitialized = False;
|
||||
@@ -18,7 +20,7 @@ void MtSync_Construct(CMtSync *p)
|
||||
Semaphore_Construct(&p->filledSemaphore);
|
||||
}
|
||||
|
||||
void MtSync_GetNextBlock(CMtSync *p)
|
||||
static void MtSync_GetNextBlock(CMtSync *p)
|
||||
{
|
||||
if (p->needStart)
|
||||
{
|
||||
@@ -31,6 +33,8 @@ void MtSync_GetNextBlock(CMtSync *p)
|
||||
|
||||
Event_Set(&p->canStart);
|
||||
Event_Wait(&p->wasStarted);
|
||||
|
||||
// if (mt) MatchFinder_Init_LowHash(mt->MatchFinder);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -46,7 +50,7 @@ void MtSync_GetNextBlock(CMtSync *p)
|
||||
|
||||
/* MtSync_StopWriting must be called if Writing was started */
|
||||
|
||||
void MtSync_StopWriting(CMtSync *p)
|
||||
static void MtSync_StopWriting(CMtSync *p)
|
||||
{
|
||||
UInt32 myNumBlocks = p->numProcessedBlocks;
|
||||
if (!Thread_WasCreated(&p->thread) || p->needStart)
|
||||
@@ -69,7 +73,7 @@ void MtSync_StopWriting(CMtSync *p)
|
||||
p->needStart = True;
|
||||
}
|
||||
|
||||
void MtSync_Destruct(CMtSync *p)
|
||||
static void MtSync_Destruct(CMtSync *p)
|
||||
{
|
||||
if (Thread_WasCreated(&p->thread))
|
||||
{
|
||||
@@ -97,7 +101,7 @@ void MtSync_Destruct(CMtSync *p)
|
||||
|
||||
#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
|
||||
|
||||
static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
|
||||
static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)
|
||||
{
|
||||
if (p->wasCreated)
|
||||
return SZ_OK;
|
||||
@@ -119,7 +123,7 @@ static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
|
||||
static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)
|
||||
{
|
||||
SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
|
||||
if (res != SZ_OK)
|
||||
@@ -132,20 +136,20 @@ void MtSync_Init(CMtSync *p) { p->needStart = True; }
|
||||
#define kMtMaxValForNormalize 0xFFFFFFFF
|
||||
|
||||
#define DEF_GetHeads2(name, v, action) \
|
||||
static void GetHeads ## name(const Byte *p, UInt32 pos, \
|
||||
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
|
||||
{ action; for (; numHeads != 0; numHeads--) { \
|
||||
const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
|
||||
static void GetHeads ## name(const Byte *p, UInt32 pos, \
|
||||
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
|
||||
{ action; for (; numHeads != 0; numHeads--) { \
|
||||
const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
|
||||
|
||||
#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
|
||||
|
||||
DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; )
|
||||
DEF_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)
|
||||
/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
|
||||
|
||||
void HashThreadFunc(CMatchFinderMt *mt)
|
||||
static void HashThreadFunc(CMatchFinderMt *mt)
|
||||
{
|
||||
CMtSync *p = &mt->hashSync;
|
||||
for (;;)
|
||||
@@ -153,6 +157,9 @@ void HashThreadFunc(CMatchFinderMt *mt)
|
||||
UInt32 numProcessedBlocks = 0;
|
||||
Event_Wait(&p->canStart);
|
||||
Event_Set(&p->wasStarted);
|
||||
|
||||
MatchFinder_Init_HighHash(mt->MatchFinder);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (p->exit)
|
||||
@@ -171,12 +178,12 @@ void HashThreadFunc(CMatchFinderMt *mt)
|
||||
CriticalSection_Enter(&mt->btSync.cs);
|
||||
CriticalSection_Enter(&mt->hashSync.cs);
|
||||
{
|
||||
const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
|
||||
const Byte *afterPtr;
|
||||
const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf);
|
||||
ptrdiff_t offset;
|
||||
MatchFinder_MoveBlock(mf);
|
||||
afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
|
||||
mt->pointerToCurPos -= beforePtr - afterPtr;
|
||||
mt->buffer -= beforePtr - afterPtr;
|
||||
offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf);
|
||||
mt->pointerToCurPos -= offset;
|
||||
mt->buffer -= offset;
|
||||
}
|
||||
CriticalSection_Leave(&mt->btSync.cs);
|
||||
CriticalSection_Leave(&mt->hashSync.cs);
|
||||
@@ -190,7 +197,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
|
||||
{
|
||||
UInt32 subValue = (mf->pos - mf->historySize - 1);
|
||||
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;
|
||||
@@ -203,7 +210,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
|
||||
if (num > kMtHashBlockSize - 2)
|
||||
num = kMtHashBlockSize - 2;
|
||||
mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);
|
||||
heads[0] += num;
|
||||
heads[0] = 2 + num;
|
||||
}
|
||||
mf->pos += num;
|
||||
mf->buffer += num;
|
||||
@@ -215,7 +222,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
|
||||
}
|
||||
}
|
||||
|
||||
void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
|
||||
static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
|
||||
{
|
||||
MtSync_GetNextBlock(&p->hashSync);
|
||||
p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
|
||||
@@ -225,38 +232,57 @@ void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
|
||||
|
||||
#define kEmptyHashValue 0
|
||||
|
||||
/* #define MFMT_GM_INLINE */
|
||||
#define MFMT_GM_INLINE
|
||||
|
||||
#ifdef MFMT_GM_INLINE
|
||||
|
||||
#define NO_INLINE MY_FAST_CALL
|
||||
/*
|
||||
we use size_t for _cyclicBufferPos instead of UInt32
|
||||
to eliminate "movsx" BUG in old MSVC x64 compiler.
|
||||
*/
|
||||
|
||||
Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
|
||||
MY_NO_INLINE
|
||||
static UInt32 *GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||
size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||
UInt32 *distances, UInt32 _maxLen, const UInt32 *hash, const UInt32 *limit, UInt32 size, UInt32 *posRes)
|
||||
{
|
||||
do
|
||||
{
|
||||
UInt32 *distances = _distances + 1;
|
||||
UInt32 curMatch = pos - *hash++;
|
||||
UInt32 *_distances = ++distances;
|
||||
UInt32 delta = *hash++;
|
||||
|
||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
||||
UInt32 len0 = 0, len1 = 0;
|
||||
CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
|
||||
unsigned len0 = 0, len1 = 0;
|
||||
UInt32 cutValue = _cutValue;
|
||||
UInt32 maxLen = _maxLen;
|
||||
for (;;)
|
||||
unsigned maxLen = (unsigned)_maxLen;
|
||||
|
||||
/*
|
||||
if (size > 1)
|
||||
{
|
||||
UInt32 delta = pos - curMatch;
|
||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||
UInt32 delta = *hash;
|
||||
if (delta < _cyclicBufferSize)
|
||||
{
|
||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||
break;
|
||||
UInt32 cyc1 = _cyclicBufferPos + 1;
|
||||
CLzRef *pair = son + ((size_t)(cyc1 - delta + ((delta > cyc1) ? _cyclicBufferSize : 0)) << 1);
|
||||
Byte b = *(cur + 1 - delta);
|
||||
_distances[0] = pair[0];
|
||||
_distances[1] = b;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (cutValue == 0 || delta >= _cyclicBufferSize)
|
||||
{
|
||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||
}
|
||||
else
|
||||
for(;;)
|
||||
{
|
||||
{
|
||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||
CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((_cyclicBufferPos < delta) ? _cyclicBufferSize : 0)) << 1);
|
||||
const Byte *pb = cur - delta;
|
||||
UInt32 len = (len0 < len1 ? len0 : len1);
|
||||
unsigned len = (len0 < len1 ? len0 : len1);
|
||||
UInt32 pair0 = *pair;
|
||||
if (pb[len] == cur[len])
|
||||
{
|
||||
if (++len != lenLimit && pb[len] == cur[len])
|
||||
@@ -265,55 +291,69 @@ Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CL
|
||||
break;
|
||||
if (maxLen < len)
|
||||
{
|
||||
*distances++ = maxLen = len;
|
||||
maxLen = len;
|
||||
*distances++ = (UInt32)len;
|
||||
*distances++ = delta - 1;
|
||||
if (len == lenLimit)
|
||||
{
|
||||
*ptr1 = pair[0];
|
||||
*ptr0 = pair[1];
|
||||
UInt32 pair1 = pair[1];
|
||||
*ptr1 = pair0;
|
||||
*ptr0 = pair1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pb[len] < cur[len])
|
||||
{
|
||||
*ptr1 = curMatch;
|
||||
ptr1 = pair + 1;
|
||||
curMatch = *ptr1;
|
||||
len1 = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr0 = curMatch;
|
||||
ptr0 = pair;
|
||||
curMatch = *ptr0;
|
||||
len0 = len;
|
||||
UInt32 curMatch = pos - delta;
|
||||
// delta = pos - *pair;
|
||||
// delta = pos - pair[((UInt32)pb[len] - (UInt32)cur[len]) >> 31];
|
||||
if (pb[len] < cur[len])
|
||||
{
|
||||
delta = pos - pair[1];
|
||||
*ptr1 = curMatch;
|
||||
ptr1 = pair + 1;
|
||||
len1 = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = pos - *pair;
|
||||
*ptr0 = curMatch;
|
||||
ptr0 = pair;
|
||||
len0 = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (--cutValue == 0 || delta >= _cyclicBufferSize)
|
||||
{
|
||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
_cyclicBufferPos++;
|
||||
cur++;
|
||||
{
|
||||
UInt32 num = (UInt32)(distances - _distances);
|
||||
*_distances = num - 1;
|
||||
_distances += num;
|
||||
limit -= num;
|
||||
_distances[-1] = num;
|
||||
}
|
||||
}
|
||||
while (limit > 0 && --size != 0);
|
||||
while (distances < limit && --size != 0);
|
||||
*posRes = pos;
|
||||
return limit;
|
||||
return distances;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
|
||||
|
||||
static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 numProcessed = 0;
|
||||
UInt32 curPos = 2;
|
||||
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
|
||||
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); // * 2
|
||||
|
||||
distances[1] = p->hashNumAvail;
|
||||
|
||||
while (curPos < limit)
|
||||
{
|
||||
if (p->hashBufPos == p->hashBufPosLimit)
|
||||
@@ -322,9 +362,11 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
distances[1] = numProcessed + p->hashNumAvail;
|
||||
if (p->hashNumAvail >= p->numHashBytes)
|
||||
continue;
|
||||
distances[0] = curPos + p->hashNumAvail;
|
||||
distances += curPos;
|
||||
for (; p->hashNumAvail != 0; p->hashNumAvail--)
|
||||
distances[curPos++] = 0;
|
||||
break;
|
||||
*distances++ = 0;
|
||||
return;
|
||||
}
|
||||
{
|
||||
UInt32 size = p->hashBufPosLimit - p->hashBufPos;
|
||||
@@ -341,13 +383,14 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
if (size2 < size)
|
||||
size = size2;
|
||||
}
|
||||
|
||||
#ifndef MFMT_GM_INLINE
|
||||
while (curPos < limit && size-- != 0)
|
||||
{
|
||||
UInt32 *startDistances = distances + curPos;
|
||||
UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
|
||||
pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
||||
startDistances + 1, p->numHashBytes - 1) - startDistances);
|
||||
pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
||||
startDistances + 1, p->numHashBytes - 1) - startDistances);
|
||||
*startDistances = num - 1;
|
||||
curPos += num;
|
||||
cyclicBufferPos++;
|
||||
@@ -357,8 +400,10 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
#else
|
||||
{
|
||||
UInt32 posRes;
|
||||
curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
||||
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
|
||||
curPos = (UInt32)(GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
||||
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos,
|
||||
distances + limit,
|
||||
size, &posRes) - distances);
|
||||
p->hashBufPos += posRes - pos;
|
||||
cyclicBufferPos += posRes - pos;
|
||||
p->buffer += posRes - pos;
|
||||
@@ -374,10 +419,11 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
p->cyclicBufferPos = cyclicBufferPos;
|
||||
}
|
||||
}
|
||||
|
||||
distances[0] = curPos;
|
||||
}
|
||||
|
||||
void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
|
||||
static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
|
||||
{
|
||||
CMtSync *sync = &p->hashSync;
|
||||
if (!sync->needStart)
|
||||
@@ -391,7 +437,7 @@ void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
|
||||
if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -430,18 +476,18 @@ void BtThreadFunc(CMatchFinderMt *mt)
|
||||
|
||||
void MatchFinderMt_Construct(CMatchFinderMt *p)
|
||||
{
|
||||
p->hashBuf = 0;
|
||||
p->hashBuf = NULL;
|
||||
MtSync_Construct(&p->hashSync);
|
||||
MtSync_Construct(&p->btSync);
|
||||
}
|
||||
|
||||
void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
|
||||
static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAllocPtr alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->hashBuf);
|
||||
p->hashBuf = 0;
|
||||
ISzAlloc_Free(alloc, p->hashBuf);
|
||||
p->hashBuf = NULL;
|
||||
}
|
||||
|
||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
|
||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc)
|
||||
{
|
||||
MtSync_Destruct(&p->hashSync);
|
||||
MtSync_Destruct(&p->btSync);
|
||||
@@ -451,28 +497,29 @@ void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
|
||||
#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
|
||||
#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
|
||||
|
||||
static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
|
||||
static unsigned MY_STD_CALL BtThreadFunc2(void *p)
|
||||
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
|
||||
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)
|
||||
{
|
||||
Byte allocaDummy[0x180];
|
||||
int i = 0;
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < 16; i++)
|
||||
allocaDummy[i] = (Byte)i;
|
||||
BtThreadFunc((CMatchFinderMt *)p);
|
||||
allocaDummy[i] = (Byte)0;
|
||||
if (allocaDummy[0] == 0)
|
||||
BtThreadFunc((CMatchFinderMt *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
|
||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)
|
||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc)
|
||||
{
|
||||
CMatchFinder *mf = p->MatchFinder;
|
||||
p->historySize = historySize;
|
||||
if (kMtBtBlockSize <= matchMaxLen * 4)
|
||||
return SZ_ERROR_PARAM;
|
||||
if (p->hashBuf == 0)
|
||||
if (!p->hashBuf)
|
||||
{
|
||||
p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
|
||||
if (p->hashBuf == 0)
|
||||
p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
|
||||
if (!p->hashBuf)
|
||||
return SZ_ERROR_MEM;
|
||||
p->btBuf = p->hashBuf + kHashBufferSize;
|
||||
}
|
||||
@@ -487,13 +534,20 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
|
||||
}
|
||||
|
||||
/* Call it after ReleaseStream / SetStream */
|
||||
void MatchFinderMt_Init(CMatchFinderMt *p)
|
||||
static void MatchFinderMt_Init(CMatchFinderMt *p)
|
||||
{
|
||||
CMatchFinder *mf = p->MatchFinder;
|
||||
p->btBufPos = p->btBufPosLimit = 0;
|
||||
p->hashBufPos = p->hashBufPosLimit = 0;
|
||||
MatchFinder_Init(mf);
|
||||
p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
|
||||
|
||||
p->btBufPos =
|
||||
p->btBufPosLimit = 0;
|
||||
p->hashBufPos =
|
||||
p->hashBufPosLimit = 0;
|
||||
|
||||
/* Init without data reading. We don't want to read data in this thread */
|
||||
MatchFinder_Init_3(mf, False);
|
||||
MatchFinder_Init_LowHash(mf);
|
||||
|
||||
p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf);
|
||||
p->btNumAvailBytes = 0;
|
||||
p->lzPos = p->historySize + 1;
|
||||
|
||||
@@ -518,13 +572,13 @@ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
|
||||
/* 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);
|
||||
p->lzPos = p->historySize + 1;
|
||||
}
|
||||
|
||||
void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
|
||||
static void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
|
||||
{
|
||||
UInt32 blockIndex;
|
||||
MtSync_GetNextBlock(&p->btSync);
|
||||
@@ -536,34 +590,29 @@ void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
|
||||
MatchFinderMt_Normalize(p);
|
||||
}
|
||||
|
||||
const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
|
||||
static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
|
||||
{
|
||||
return p->pointerToCurPos;
|
||||
}
|
||||
|
||||
#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
|
||||
|
||||
UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
|
||||
static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
|
||||
{
|
||||
GET_NEXT_BLOCK_IF_REQUIRED;
|
||||
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;
|
||||
const Byte *cur = p->pointerToCurPos;
|
||||
UInt32 lzPos = p->lzPos;
|
||||
MT_HASH2_CALC
|
||||
|
||||
curMatch2 = hash[hash2Value];
|
||||
hash[hash2Value] = lzPos;
|
||||
curMatch2 = hash[h2];
|
||||
hash[h2] = lzPos;
|
||||
|
||||
if (curMatch2 >= matchMinPos)
|
||||
if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||
@@ -571,23 +620,23 @@ UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
*distances++ = 2;
|
||||
*distances++ = lzPos - curMatch2 - 1;
|
||||
}
|
||||
|
||||
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;
|
||||
const Byte *cur = p->pointerToCurPos;
|
||||
UInt32 lzPos = p->lzPos;
|
||||
MT_HASH3_CALC
|
||||
|
||||
curMatch2 = hash[ hash2Value];
|
||||
curMatch3 = hash[kFix3HashSize + hash3Value];
|
||||
curMatch2 = hash[ h2];
|
||||
curMatch3 = (hash + kFix3HashSize)[h3];
|
||||
|
||||
hash[ hash2Value] =
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
lzPos;
|
||||
hash[ h2] = lzPos;
|
||||
(hash + kFix3HashSize)[h3] = lzPos;
|
||||
|
||||
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||
{
|
||||
@@ -600,43 +649,45 @@ UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
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)
|
||||
static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
|
||||
UInt32 h2, h3, h4, curMatch2, curMatch3, curMatch4;
|
||||
UInt32 *hash = p->hash;
|
||||
const Byte *cur = p->pointerToCurPos;
|
||||
UInt32 lzPos = p->lzPos;
|
||||
MT_HASH4_CALC
|
||||
|
||||
curMatch2 = hash[ hash2Value];
|
||||
curMatch3 = hash[kFix3HashSize + hash3Value];
|
||||
curMatch4 = hash[kFix4HashSize + hash4Value];
|
||||
curMatch2 = hash[ h2];
|
||||
curMatch3 = (hash + kFix3HashSize)[h3];
|
||||
curMatch4 = (hash + kFix4HashSize)[h4];
|
||||
|
||||
hash[ hash2Value] =
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
hash[kFix4HashSize + hash4Value] =
|
||||
lzPos;
|
||||
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;
|
||||
distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
|
||||
return distances + 2;
|
||||
}
|
||||
distances[0] = 2;
|
||||
distances += 2;
|
||||
}
|
||||
|
||||
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
||||
{
|
||||
distances[1] = lzPos - curMatch3 - 1;
|
||||
@@ -658,13 +709,14 @@ UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
*distances++ = 4;
|
||||
*distances++ = lzPos - curMatch4 - 1;
|
||||
}
|
||||
|
||||
return distances;
|
||||
}
|
||||
*/
|
||||
|
||||
#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;
|
||||
UInt32 len = *btBuf++;
|
||||
@@ -674,15 +726,19 @@ UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
UInt32 i;
|
||||
for (i = 0; i < len; i += 2)
|
||||
{
|
||||
*distances++ = *btBuf++;
|
||||
*distances++ = *btBuf++;
|
||||
UInt32 v0 = btBuf[0];
|
||||
UInt32 v1 = btBuf[1];
|
||||
btBuf += 2;
|
||||
distances[0] = v0;
|
||||
distances[1] = v1;
|
||||
distances += 2;
|
||||
}
|
||||
}
|
||||
INCREASE_LZ_POS
|
||||
return len;
|
||||
}
|
||||
|
||||
UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
static UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
{
|
||||
const UInt32 *btBuf = p->btBuf + p->btBufPos;
|
||||
UInt32 len = *btBuf++;
|
||||
@@ -690,6 +746,7 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
/* change for bt5 ! */
|
||||
if (p->btNumAvailBytes-- >= 4)
|
||||
len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
|
||||
}
|
||||
@@ -701,72 +758,76 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
|
||||
do
|
||||
{
|
||||
*distances2++ = *btBuf++;
|
||||
*distances2++ = *btBuf++;
|
||||
UInt32 v0 = btBuf[0];
|
||||
UInt32 v1 = btBuf[1];
|
||||
btBuf += 2;
|
||||
distances2[0] = v0;
|
||||
distances2[1] = v1;
|
||||
distances2 += 2;
|
||||
}
|
||||
while ((len -= 2) != 0);
|
||||
len = (UInt32)(distances2 - (distances));
|
||||
len = (UInt32)(distances2 - (distances));
|
||||
}
|
||||
INCREASE_LZ_POS
|
||||
return len;
|
||||
}
|
||||
|
||||
#define SKIP_HEADER2 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_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
|
||||
#define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED
|
||||
#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
|
||||
#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
|
||||
|
||||
void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
{
|
||||
SKIP_HEADER2 { p->btNumAvailBytes--;
|
||||
SKIP_FOOTER
|
||||
SKIP_HEADER2_MT { p->btNumAvailBytes--;
|
||||
SKIP_FOOTER_MT
|
||||
}
|
||||
|
||||
void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
{
|
||||
SKIP_HEADER(2)
|
||||
UInt32 hash2Value;
|
||||
SKIP_HEADER_MT(2)
|
||||
UInt32 h2;
|
||||
MT_HASH2_CALC
|
||||
hash[hash2Value] = p->lzPos;
|
||||
SKIP_FOOTER
|
||||
hash[h2] = p->lzPos;
|
||||
SKIP_FOOTER_MT
|
||||
}
|
||||
|
||||
void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
{
|
||||
SKIP_HEADER(3)
|
||||
UInt32 hash2Value, hash3Value;
|
||||
SKIP_HEADER_MT(3)
|
||||
UInt32 h2, h3;
|
||||
MT_HASH3_CALC
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
hash[ hash2Value] =
|
||||
(hash + kFix3HashSize)[h3] =
|
||||
hash[ h2] =
|
||||
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)
|
||||
UInt32 hash2Value, hash3Value, hash4Value;
|
||||
SKIP_HEADER_MT(4)
|
||||
UInt32 h2, h3, h4;
|
||||
MT_HASH4_CALC
|
||||
hash[kFix4HashSize + hash4Value] =
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
hash[ hash2Value] =
|
||||
(hash + kFix4HashSize)[h4] =
|
||||
(hash + kFix3HashSize)[h3] =
|
||||
hash[ h2] =
|
||||
p->lzPos;
|
||||
SKIP_FOOTER
|
||||
SKIP_FOOTER_MT
|
||||
}
|
||||
*/
|
||||
|
||||
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
|
||||
{
|
||||
vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
|
||||
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
|
||||
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
|
||||
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
|
||||
switch(p->MatchFinder->numHashBytes)
|
||||
|
||||
switch (p->MatchFinder->numHashBytes)
|
||||
{
|
||||
case 2:
|
||||
p->GetHeadsFunc = GetHeads2;
|
||||
p->MixMatchesFunc = (Mf_Mix_Matches)0;
|
||||
p->MixMatchesFunc = (Mf_Mix_Matches)NULL;
|
||||
vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
|
||||
break;
|
||||
@@ -778,7 +839,6 @@ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
|
||||
default:
|
||||
/* case 4: */
|
||||
p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
|
||||
/* p->GetHeadsFunc = GetHeads4; */
|
||||
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
|
||||
vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
|
||||
break;
|
||||
|
||||
30
C/LzFindMt.h
Executable file → Normal file
30
C/LzFindMt.h
Executable file → Normal file
@@ -1,11 +1,13 @@
|
||||
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2018-07-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZFINDMT_H
|
||||
#define __LZFINDMT_H
|
||||
#ifndef __LZ_FIND_MT_H
|
||||
#define __LZ_FIND_MT_H
|
||||
|
||||
#include "Threads.h"
|
||||
#include "LzFind.h"
|
||||
#include "Threads.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define kMtHashBlockSize (1 << 13)
|
||||
#define kMtHashNumBlocks (1 << 3)
|
||||
@@ -17,10 +19,10 @@
|
||||
|
||||
typedef struct _CMtSync
|
||||
{
|
||||
Bool wasCreated;
|
||||
Bool needStart;
|
||||
Bool exit;
|
||||
Bool stopWriting;
|
||||
BoolInt wasCreated;
|
||||
BoolInt needStart;
|
||||
BoolInt exit;
|
||||
BoolInt stopWriting;
|
||||
|
||||
CThread thread;
|
||||
CAutoResetEvent canStart;
|
||||
@@ -28,8 +30,8 @@ typedef struct _CMtSync
|
||||
CAutoResetEvent wasStopped;
|
||||
CSemaphore freeSemaphore;
|
||||
CSemaphore filledSemaphore;
|
||||
Bool csWasInitialized;
|
||||
Bool csWasEntered;
|
||||
BoolInt csWasInitialized;
|
||||
BoolInt csWasEntered;
|
||||
CCriticalSection cs;
|
||||
UInt32 numProcessedBlocks;
|
||||
} CMtSync;
|
||||
@@ -73,7 +75,7 @@ typedef struct _CMatchFinderMt
|
||||
UInt32 matchMaxLen;
|
||||
UInt32 numHashBytes;
|
||||
UInt32 pos;
|
||||
Byte *buffer;
|
||||
const Byte *buffer;
|
||||
UInt32 cyclicBufferPos;
|
||||
UInt32 cyclicBufferSize; /* it must be historySize + 1 */
|
||||
UInt32 cutValue;
|
||||
@@ -88,10 +90,12 @@ typedef struct _CMatchFinderMt
|
||||
} CMatchFinderMt;
|
||||
|
||||
void MatchFinderMt_Construct(CMatchFinderMt *p);
|
||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);
|
||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc);
|
||||
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
|
||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc);
|
||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc);
|
||||
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
|
||||
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
47
C/LzHash.h
Executable file → Normal file
47
C/LzHash.h
Executable file → Normal file
@@ -1,8 +1,8 @@
|
||||
/* LzHash.h -- HASH functions for LZ algorithms
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2015-04-12 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZHASH_H
|
||||
#define __LZHASH_H
|
||||
#ifndef __LZ_HASH_H
|
||||
#define __LZ_HASH_H
|
||||
|
||||
#define kHash2Size (1 << 10)
|
||||
#define kHash3Size (1 << 16)
|
||||
@@ -12,43 +12,46 @@
|
||||
#define kFix4HashSize (kHash2Size + kHash3Size)
|
||||
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
||||
|
||||
#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
|
||||
#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);
|
||||
|
||||
#define HASH3_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
||||
|
||||
#define HASH4_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
|
||||
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]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
|
||||
hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
|
||||
hash4Value &= (kHash4Size - 1); }
|
||||
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 hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
|
||||
#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||
/* #define 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 \
|
||||
hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
||||
h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
||||
|
||||
#define MT_HASH3_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
||||
|
||||
#define MT_HASH4_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
temp ^= ((UInt32)cur[2] << 8); \
|
||||
h3 = temp & (kHash3Size - 1); \
|
||||
h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
|
||||
|
||||
#endif
|
||||
|
||||
488
C/Lzma2Dec.c
Normal file
488
C/Lzma2Dec.c
Normal file
@@ -0,0 +1,488 @@
|
||||
/* Lzma2Dec.c -- LZMA2 Decoder
|
||||
2019-02-02 : Igor Pavlov : Public domain */
|
||||
|
||||
/* #define SHOW_DEBUG_INFO */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Lzma2Dec.h"
|
||||
|
||||
/*
|
||||
00000000 - End of data
|
||||
00000001 U U - Uncompressed, reset dic, need reset state and set new prop
|
||||
00000010 U U - Uncompressed, no reset
|
||||
100uuuuu U U P P - LZMA, no reset
|
||||
101uuuuu U U P P - LZMA, reset state
|
||||
110uuuuu U U P P S - LZMA, reset state + set new prop
|
||||
111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic
|
||||
|
||||
u, U - Unpack Size
|
||||
P - Pack Size
|
||||
S - Props
|
||||
*/
|
||||
|
||||
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
||||
|
||||
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
|
||||
|
||||
#define LZMA2_LCLP_MAX 4
|
||||
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
#define PRF(x) x
|
||||
#else
|
||||
#define PRF(x)
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA2_STATE_CONTROL,
|
||||
LZMA2_STATE_UNPACK0,
|
||||
LZMA2_STATE_UNPACK1,
|
||||
LZMA2_STATE_PACK0,
|
||||
LZMA2_STATE_PACK1,
|
||||
LZMA2_STATE_PROP,
|
||||
LZMA2_STATE_DATA,
|
||||
LZMA2_STATE_DATA_CONT,
|
||||
LZMA2_STATE_FINISHED,
|
||||
LZMA2_STATE_ERROR
|
||||
} ELzma2State;
|
||||
|
||||
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
|
||||
{
|
||||
UInt32 dicSize;
|
||||
if (prop > 40)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
||||
props[0] = (Byte)LZMA2_LCLP_MAX;
|
||||
props[1] = (Byte)(dicSize);
|
||||
props[2] = (Byte)(dicSize >> 8);
|
||||
props[3] = (Byte)(dicSize >> 16);
|
||||
props[4] = (Byte)(dicSize >> 24);
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
|
||||
{
|
||||
Byte props[LZMA_PROPS_SIZE];
|
||||
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
}
|
||||
|
||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
|
||||
{
|
||||
Byte props[LZMA_PROPS_SIZE];
|
||||
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
}
|
||||
|
||||
void Lzma2Dec_Init(CLzma2Dec *p)
|
||||
{
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
p->needInitLevel = 0xE0;
|
||||
p->isExtraMode = False;
|
||||
p->unpackSize = 0;
|
||||
|
||||
// p->decoder.dicPos = 0; // we can use it instead of full init
|
||||
LzmaDec_Init(&p->decoder);
|
||||
}
|
||||
|
||||
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||
{
|
||||
switch (p->state)
|
||||
{
|
||||
case LZMA2_STATE_CONTROL:
|
||||
p->isExtraMode = False;
|
||||
p->control = b;
|
||||
PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
|
||||
PRF(printf(" %02X", (unsigned)b));
|
||||
if (b == 0)
|
||||
return LZMA2_STATE_FINISHED;
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if (b == LZMA2_CONTROL_COPY_RESET_DIC)
|
||||
p->needInitLevel = 0xC0;
|
||||
else if (b > 2 || p->needInitLevel == 0xE0)
|
||||
return LZMA2_STATE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (b < p->needInitLevel)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->needInitLevel = 0;
|
||||
p->unpackSize = (UInt32)(b & 0x1F) << 16;
|
||||
}
|
||||
return LZMA2_STATE_UNPACK0;
|
||||
|
||||
case LZMA2_STATE_UNPACK0:
|
||||
p->unpackSize |= (UInt32)b << 8;
|
||||
return LZMA2_STATE_UNPACK1;
|
||||
|
||||
case LZMA2_STATE_UNPACK1:
|
||||
p->unpackSize |= (UInt32)b;
|
||||
p->unpackSize++;
|
||||
PRF(printf(" %7u", (unsigned)p->unpackSize));
|
||||
return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||
|
||||
case LZMA2_STATE_PACK0:
|
||||
p->packSize = (UInt32)b << 8;
|
||||
return LZMA2_STATE_PACK1;
|
||||
|
||||
case LZMA2_STATE_PACK1:
|
||||
p->packSize |= (UInt32)b;
|
||||
p->packSize++;
|
||||
// if (p->packSize < 5) return LZMA2_STATE_ERROR;
|
||||
PRF(printf(" %5u", (unsigned)p->packSize));
|
||||
return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
|
||||
|
||||
case LZMA2_STATE_PROP:
|
||||
{
|
||||
unsigned lc, lp;
|
||||
if (b >= (9 * 5 * 5))
|
||||
return LZMA2_STATE_ERROR;
|
||||
lc = b % 9;
|
||||
b /= 9;
|
||||
p->decoder.prop.pb = (Byte)(b / 5);
|
||||
lp = b % 5;
|
||||
if (lc + lp > LZMA2_LCLP_MAX)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->decoder.prop.lc = (Byte)lc;
|
||||
p->decoder.prop.lp = (Byte)lp;
|
||||
return LZMA2_STATE_DATA;
|
||||
}
|
||||
}
|
||||
return LZMA2_STATE_ERROR;
|
||||
}
|
||||
|
||||
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
|
||||
{
|
||||
memcpy(p->dic + p->dicPos, src, size);
|
||||
p->dicPos += size;
|
||||
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
p->processedPos += (UInt32)size;
|
||||
}
|
||||
|
||||
void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
|
||||
|
||||
|
||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT inSize = *srcLen;
|
||||
*srcLen = 0;
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
|
||||
while (p->state != LZMA2_STATE_ERROR)
|
||||
{
|
||||
SizeT dicPos;
|
||||
|
||||
if (p->state == LZMA2_STATE_FINISHED)
|
||||
{
|
||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
dicPos = p->decoder.dicPos;
|
||||
|
||||
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
(*srcLen)++;
|
||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||
if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
SizeT inCur = inSize - *srcLen;
|
||||
SizeT outCur = dicLimit - dicPos;
|
||||
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
|
||||
|
||||
if (outCur >= p->unpackSize)
|
||||
{
|
||||
outCur = (SizeT)p->unpackSize;
|
||||
curFinishMode = LZMA_FINISH_END;
|
||||
}
|
||||
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if (inCur == 0)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
|
||||
}
|
||||
|
||||
if (inCur > outCur)
|
||||
inCur = outCur;
|
||||
if (inCur == 0)
|
||||
break;
|
||||
|
||||
LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
|
||||
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
p->unpackSize -= (UInt32)inCur;
|
||||
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
else
|
||||
{
|
||||
SRes res;
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
BoolInt initDic = (p->control >= 0xE0);
|
||||
BoolInt initState = (p->control >= 0xA0);
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||
p->state = LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
|
||||
if (inCur > p->packSize)
|
||||
inCur = (SizeT)p->packSize;
|
||||
|
||||
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
|
||||
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
p->packSize -= (UInt32)inCur;
|
||||
outCur = p->decoder.dicPos - dicPos;
|
||||
p->unpackSize -= (UInt32)outCur;
|
||||
|
||||
if (res != 0)
|
||||
break;
|
||||
|
||||
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
{
|
||||
if (p->packSize == 0)
|
||||
break;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (inCur == 0 && outCur == 0)
|
||||
{
|
||||
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
|| p->unpackSize != 0
|
||||
|| p->packSize != 0)
|
||||
break;
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
}
|
||||
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
|
||||
SizeT outSize,
|
||||
const Byte *src, SizeT *srcLen,
|
||||
int checkFinishBlock)
|
||||
{
|
||||
SizeT inSize = *srcLen;
|
||||
*srcLen = 0;
|
||||
|
||||
while (p->state != LZMA2_STATE_ERROR)
|
||||
{
|
||||
if (p->state == LZMA2_STATE_FINISHED)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
|
||||
if (outSize == 0 && !checkFinishBlock)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||
|
||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
(*srcLen)++;
|
||||
|
||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||
|
||||
if (p->state == LZMA2_STATE_UNPACK0)
|
||||
{
|
||||
// if (p->decoder.dicPos != 0)
|
||||
if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
|
||||
return LZMA2_PARSE_STATUS_NEW_BLOCK;
|
||||
// if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
|
||||
}
|
||||
|
||||
// The following code can be commented.
|
||||
// It's not big problem, if we read additional input bytes.
|
||||
// It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
|
||||
|
||||
if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
|
||||
{
|
||||
// checkFinishBlock is true. So we expect that block must be finished,
|
||||
// We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
|
||||
// break;
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||
}
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
return LZMA2_PARSE_STATUS_NEW_CHUNK;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (outSize == 0)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||
|
||||
{
|
||||
SizeT inCur = inSize - *srcLen;
|
||||
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if (inCur == 0)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
if (inCur > p->unpackSize)
|
||||
inCur = p->unpackSize;
|
||||
if (inCur > outSize)
|
||||
inCur = outSize;
|
||||
p->decoder.dicPos += inCur;
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
outSize -= inCur;
|
||||
p->unpackSize -= (UInt32)inCur;
|
||||
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->isExtraMode = True;
|
||||
|
||||
if (inCur == 0)
|
||||
{
|
||||
if (p->packSize != 0)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
}
|
||||
else if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
p->state = LZMA2_STATE_DATA_CONT;
|
||||
if (*src != 0)
|
||||
{
|
||||
// first byte of lzma chunk must be Zero
|
||||
*srcLen += 1;
|
||||
p->packSize--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inCur > p->packSize)
|
||||
inCur = (SizeT)p->packSize;
|
||||
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
p->packSize -= (UInt32)inCur;
|
||||
|
||||
if (p->packSize == 0)
|
||||
{
|
||||
SizeT rem = outSize;
|
||||
if (rem > p->unpackSize)
|
||||
rem = p->unpackSize;
|
||||
p->decoder.dicPos += rem;
|
||||
p->unpackSize -= (UInt32)rem;
|
||||
outSize -= rem;
|
||||
if (p->unpackSize == 0)
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT outSize = *destLen, inSize = *srcLen;
|
||||
*srcLen = *destLen = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SizeT inCur = inSize, outCur, dicPos;
|
||||
ELzmaFinishMode curFinishMode;
|
||||
SRes res;
|
||||
|
||||
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
||||
p->decoder.dicPos = 0;
|
||||
dicPos = p->decoder.dicPos;
|
||||
curFinishMode = LZMA_FINISH_ANY;
|
||||
outCur = p->decoder.dicBufSize - dicPos;
|
||||
|
||||
if (outCur >= outSize)
|
||||
{
|
||||
outCur = outSize;
|
||||
curFinishMode = finishMode;
|
||||
}
|
||||
|
||||
res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
|
||||
|
||||
src += inCur;
|
||||
inSize -= inCur;
|
||||
*srcLen += inCur;
|
||||
outCur = p->decoder.dicPos - dicPos;
|
||||
memcpy(dest, p->decoder.dic + dicPos, outCur);
|
||||
dest += outCur;
|
||||
outSize -= outCur;
|
||||
*destLen += outCur;
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (outCur == 0 || outSize == 0)
|
||||
return SZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
|
||||
{
|
||||
CLzma2Dec p;
|
||||
SRes res;
|
||||
SizeT outSize = *destLen, inSize = *srcLen;
|
||||
*destLen = *srcLen = 0;
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
Lzma2Dec_Construct(&p);
|
||||
RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
|
||||
p.decoder.dic = dest;
|
||||
p.decoder.dicBufSize = outSize;
|
||||
Lzma2Dec_Init(&p);
|
||||
*srcLen = inSize;
|
||||
res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
|
||||
*destLen = p.decoder.dicPos;
|
||||
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
res = SZ_ERROR_INPUT_EOF;
|
||||
Lzma2Dec_FreeProbs(&p, alloc);
|
||||
return res;
|
||||
}
|
||||
120
C/Lzma2Dec.h
Normal file
120
C/Lzma2Dec.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/* Lzma2Dec.h -- LZMA2 Decoder
|
||||
2018-02-19 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA2_DEC_H
|
||||
#define __LZMA2_DEC_H
|
||||
|
||||
#include "LzmaDec.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* ---------- State Interface ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned state;
|
||||
Byte control;
|
||||
Byte needInitLevel;
|
||||
Byte isExtraMode;
|
||||
Byte _pad_;
|
||||
UInt32 packSize;
|
||||
UInt32 unpackSize;
|
||||
CLzmaDec decoder;
|
||||
} CLzma2Dec;
|
||||
|
||||
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
|
||||
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc)
|
||||
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc)
|
||||
|
||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
|
||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
|
||||
void Lzma2Dec_Init(CLzma2Dec *p);
|
||||
|
||||
/*
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
|
||||
LZMA_FINISH_ANY - use smallest number of input bytes
|
||||
LZMA_FINISH_END - read EndOfStream marker after decoding
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
SZ_ERROR_DATA - Data error
|
||||
*/
|
||||
|
||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- LZMA2 block and chunk parsing ---------- */
|
||||
|
||||
/*
|
||||
Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data.
|
||||
It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code:
|
||||
- LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input.
|
||||
- LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read.
|
||||
CLzma2Dec::unpackSize contains unpack size of that chunk
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/*
|
||||
LZMA_STATUS_NOT_SPECIFIED // data error
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED //
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused
|
||||
*/
|
||||
LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1,
|
||||
LZMA2_PARSE_STATUS_NEW_CHUNK
|
||||
} ELzma2ParseStatus;
|
||||
|
||||
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
|
||||
SizeT outSize, // output size
|
||||
const Byte *src, SizeT *srcLen,
|
||||
int checkFinishBlock // set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position.
|
||||
);
|
||||
|
||||
/*
|
||||
LZMA2 parser doesn't decode LZMA chunks, so we must read
|
||||
full input LZMA chunk to decode some part of LZMA chunk.
|
||||
|
||||
Lzma2Dec_GetUnpackExtra() returns the value that shows
|
||||
max possible number of output bytes that can be output by decoder
|
||||
at current input positon.
|
||||
*/
|
||||
|
||||
#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0);
|
||||
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
|
||||
/*
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - use smallest number of input bytes
|
||||
LZMA_FINISH_END - read EndOfStream marker after decoding
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
*/
|
||||
|
||||
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
1082
C/Lzma2DecMt.c
Normal file
1082
C/Lzma2DecMt.c
Normal file
File diff suppressed because it is too large
Load Diff
79
C/Lzma2DecMt.h
Normal file
79
C/Lzma2DecMt.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* Lzma2DecMt.h -- LZMA2 Decoder Multi-thread
|
||||
2018-02-17 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA2_DEC_MT_H
|
||||
#define __LZMA2_DEC_MT_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t inBufSize_ST;
|
||||
size_t outStep_ST;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
unsigned numThreads;
|
||||
size_t inBufSize_MT;
|
||||
size_t outBlockMax;
|
||||
size_t inBlockMax;
|
||||
#endif
|
||||
} CLzma2DecMtProps;
|
||||
|
||||
/* init to single-thread mode */
|
||||
void Lzma2DecMtProps_Init(CLzma2DecMtProps *p);
|
||||
|
||||
|
||||
/* ---------- CLzma2DecMtHandle Interface ---------- */
|
||||
|
||||
/* Lzma2DecMt_ * functions can return the following exit codes:
|
||||
SRes:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||
SZ_ERROR_WRITE - ISeqOutStream write callback error
|
||||
// SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
|
||||
SZ_ERROR_PROGRESS - some break from progress callback
|
||||
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
typedef void * CLzma2DecMtHandle;
|
||||
|
||||
CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid);
|
||||
void Lzma2DecMt_Destroy(CLzma2DecMtHandle p);
|
||||
|
||||
SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p,
|
||||
Byte prop,
|
||||
const CLzma2DecMtProps *props,
|
||||
ISeqOutStream *outStream,
|
||||
const UInt64 *outDataSize, // NULL means undefined
|
||||
int finishMode, // 0 - partial unpacking is allowed, 1 - if lzma2 stream must be finished
|
||||
// Byte *outBuf, size_t *outBufSize,
|
||||
ISeqInStream *inStream,
|
||||
// const Byte *inData, size_t inDataSize,
|
||||
|
||||
// out variables:
|
||||
UInt64 *inProcessed,
|
||||
int *isMT, /* out: (*isMT == 0), if single thread decoding was used */
|
||||
|
||||
// UInt64 *outProcessed,
|
||||
ICompressProgress *progress);
|
||||
|
||||
|
||||
/* ---------- Read from CLzma2DecMtHandle Interface ---------- */
|
||||
|
||||
SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,
|
||||
Byte prop,
|
||||
const CLzma2DecMtProps *props,
|
||||
const UInt64 *outDataSize, int finishMode,
|
||||
ISeqInStream *inStream);
|
||||
|
||||
SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,
|
||||
Byte *data, size_t *outSize,
|
||||
UInt64 *inStreamProcessed);
|
||||
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
803
C/Lzma2Enc.c
Normal file
803
C/Lzma2Enc.c
Normal file
@@ -0,0 +1,803 @@
|
||||
/* Lzma2Enc.c -- LZMA2 Encoder
|
||||
2018-07-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* #define _7ZIP_ST */
|
||||
|
||||
#include "Lzma2Enc.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#include "MtCoder.h"
|
||||
#else
|
||||
#define MTCODER__THREADS_MAX 1
|
||||
#endif
|
||||
|
||||
#define LZMA2_CONTROL_LZMA (1 << 7)
|
||||
#define LZMA2_CONTROL_COPY_NO_RESET 2
|
||||
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
||||
#define LZMA2_CONTROL_EOF 0
|
||||
|
||||
#define LZMA2_LCLP_MAX 4
|
||||
|
||||
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||
|
||||
#define LZMA2_PACK_SIZE_MAX (1 << 16)
|
||||
#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX
|
||||
#define LZMA2_UNPACK_SIZE_MAX (1 << 21)
|
||||
#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX
|
||||
|
||||
#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16)
|
||||
|
||||
|
||||
#define PRF(x) /* x */
|
||||
|
||||
|
||||
/* ---------- CLimitedSeqInStream ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream vt;
|
||||
ISeqInStream *realStream;
|
||||
UInt64 limit;
|
||||
UInt64 processed;
|
||||
int finished;
|
||||
} CLimitedSeqInStream;
|
||||
|
||||
static void LimitedSeqInStream_Init(CLimitedSeqInStream *p)
|
||||
{
|
||||
p->limit = (UInt64)(Int64)-1;
|
||||
p->processed = 0;
|
||||
p->finished = 0;
|
||||
}
|
||||
|
||||
static SRes LimitedSeqInStream_Read(const ISeqInStream *pp, void *data, size_t *size)
|
||||
{
|
||||
CLimitedSeqInStream *p = CONTAINER_FROM_VTBL(pp, CLimitedSeqInStream, vt);
|
||||
size_t size2 = *size;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
if (p->limit != (UInt64)(Int64)-1)
|
||||
{
|
||||
UInt64 rem = p->limit - p->processed;
|
||||
if (size2 > rem)
|
||||
size2 = (size_t)rem;
|
||||
}
|
||||
if (size2 != 0)
|
||||
{
|
||||
res = ISeqInStream_Read(p->realStream, data, &size2);
|
||||
p->finished = (size2 == 0 ? 1 : 0);
|
||||
p->processed += size2;
|
||||
}
|
||||
*size = size2;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- CLzma2EncInt ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaEncHandle enc;
|
||||
Byte propsAreSet;
|
||||
Byte propsByte;
|
||||
Byte needInitState;
|
||||
Byte needInitProp;
|
||||
UInt64 srcPos;
|
||||
} CLzma2EncInt;
|
||||
|
||||
|
||||
static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props)
|
||||
{
|
||||
if (!p->propsAreSet)
|
||||
{
|
||||
SizeT propsSize = LZMA_PROPS_SIZE;
|
||||
Byte propsEncoded[LZMA_PROPS_SIZE];
|
||||
RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
|
||||
RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
|
||||
p->propsByte = propsEncoded[0];
|
||||
p->propsAreSet = True;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static void Lzma2EncInt_InitBlock(CLzma2EncInt *p)
|
||||
{
|
||||
p->srcPos = 0;
|
||||
p->needInitState = True;
|
||||
p->needInitProp = True;
|
||||
}
|
||||
|
||||
|
||||
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
|
||||
ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
|
||||
UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,
|
||||
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
|
||||
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
|
||||
void LzmaEnc_Finish(CLzmaEncHandle pp);
|
||||
void LzmaEnc_SaveState(CLzmaEncHandle pp);
|
||||
void LzmaEnc_RestoreState(CLzmaEncHandle pp);
|
||||
|
||||
/*
|
||||
UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp);
|
||||
*/
|
||||
|
||||
static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
|
||||
size_t *packSizeRes, ISeqOutStream *outStream)
|
||||
{
|
||||
size_t packSizeLimit = *packSizeRes;
|
||||
size_t packSize = packSizeLimit;
|
||||
UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
|
||||
unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
|
||||
BoolInt useCopyBlock;
|
||||
SRes res;
|
||||
|
||||
*packSizeRes = 0;
|
||||
if (packSize < lzHeaderSize)
|
||||
return SZ_ERROR_OUTPUT_EOF;
|
||||
packSize -= lzHeaderSize;
|
||||
|
||||
LzmaEnc_SaveState(p->enc);
|
||||
res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,
|
||||
outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);
|
||||
|
||||
PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize));
|
||||
|
||||
if (unpackSize == 0)
|
||||
return res;
|
||||
|
||||
if (res == SZ_OK)
|
||||
useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));
|
||||
else
|
||||
{
|
||||
if (res != SZ_ERROR_OUTPUT_EOF)
|
||||
return res;
|
||||
res = SZ_OK;
|
||||
useCopyBlock = True;
|
||||
}
|
||||
|
||||
if (useCopyBlock)
|
||||
{
|
||||
size_t destPos = 0;
|
||||
PRF(printf("################# COPY "));
|
||||
|
||||
while (unpackSize > 0)
|
||||
{
|
||||
UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
|
||||
if (packSizeLimit - destPos < u + 3)
|
||||
return SZ_ERROR_OUTPUT_EOF;
|
||||
outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);
|
||||
outBuf[destPos++] = (Byte)((u - 1) >> 8);
|
||||
outBuf[destPos++] = (Byte)(u - 1);
|
||||
memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);
|
||||
unpackSize -= u;
|
||||
destPos += u;
|
||||
p->srcPos += u;
|
||||
|
||||
if (outStream)
|
||||
{
|
||||
*packSizeRes += destPos;
|
||||
if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
|
||||
return SZ_ERROR_WRITE;
|
||||
destPos = 0;
|
||||
}
|
||||
else
|
||||
*packSizeRes = destPos;
|
||||
/* needInitState = True; */
|
||||
}
|
||||
|
||||
LzmaEnc_RestoreState(p->enc);
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
{
|
||||
size_t destPos = 0;
|
||||
UInt32 u = unpackSize - 1;
|
||||
UInt32 pm = (UInt32)(packSize - 1);
|
||||
unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);
|
||||
|
||||
PRF(printf(" "));
|
||||
|
||||
outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));
|
||||
outBuf[destPos++] = (Byte)(u >> 8);
|
||||
outBuf[destPos++] = (Byte)u;
|
||||
outBuf[destPos++] = (Byte)(pm >> 8);
|
||||
outBuf[destPos++] = (Byte)pm;
|
||||
|
||||
if (p->needInitProp)
|
||||
outBuf[destPos++] = p->propsByte;
|
||||
|
||||
p->needInitProp = False;
|
||||
p->needInitState = False;
|
||||
destPos += packSize;
|
||||
p->srcPos += unpackSize;
|
||||
|
||||
if (outStream)
|
||||
if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
|
||||
return SZ_ERROR_WRITE;
|
||||
|
||||
*packSizeRes = destPos;
|
||||
return SZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ---------- Lzma2 Props ---------- */
|
||||
|
||||
void Lzma2EncProps_Init(CLzma2EncProps *p)
|
||||
{
|
||||
LzmaEncProps_Init(&p->lzmaProps);
|
||||
p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO;
|
||||
p->numBlockThreads_Reduced = -1;
|
||||
p->numBlockThreads_Max = -1;
|
||||
p->numTotalThreads = -1;
|
||||
}
|
||||
|
||||
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
|
||||
{
|
||||
UInt64 fileSize;
|
||||
int t1, t1n, t2, t2r, t3;
|
||||
{
|
||||
CLzmaEncProps lzmaProps = p->lzmaProps;
|
||||
LzmaEncProps_Normalize(&lzmaProps);
|
||||
t1n = lzmaProps.numThreads;
|
||||
}
|
||||
|
||||
t1 = p->lzmaProps.numThreads;
|
||||
t2 = p->numBlockThreads_Max;
|
||||
t3 = p->numTotalThreads;
|
||||
|
||||
if (t2 > MTCODER__THREADS_MAX)
|
||||
t2 = MTCODER__THREADS_MAX;
|
||||
|
||||
if (t3 <= 0)
|
||||
{
|
||||
if (t2 <= 0)
|
||||
t2 = 1;
|
||||
t3 = t1n * t2;
|
||||
}
|
||||
else if (t2 <= 0)
|
||||
{
|
||||
t2 = t3 / t1n;
|
||||
if (t2 == 0)
|
||||
{
|
||||
t1 = 1;
|
||||
t2 = t3;
|
||||
}
|
||||
if (t2 > MTCODER__THREADS_MAX)
|
||||
t2 = MTCODER__THREADS_MAX;
|
||||
}
|
||||
else if (t1 <= 0)
|
||||
{
|
||||
t1 = t3 / t2;
|
||||
if (t1 == 0)
|
||||
t1 = 1;
|
||||
}
|
||||
else
|
||||
t3 = t1n * t2;
|
||||
|
||||
p->lzmaProps.numThreads = t1;
|
||||
|
||||
t2r = t2;
|
||||
|
||||
fileSize = p->lzmaProps.reduceSize;
|
||||
|
||||
if ( p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
|
||||
&& p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO
|
||||
&& (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))
|
||||
p->lzmaProps.reduceSize = p->blockSize;
|
||||
|
||||
LzmaEncProps_Normalize(&p->lzmaProps);
|
||||
|
||||
p->lzmaProps.reduceSize = fileSize;
|
||||
|
||||
t1 = p->lzmaProps.numThreads;
|
||||
|
||||
if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID)
|
||||
{
|
||||
t2r = t2 = 1;
|
||||
t3 = t1;
|
||||
}
|
||||
else if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO && t2 <= 1)
|
||||
{
|
||||
/* if there is no block multi-threading, we use SOLID block */
|
||||
p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO)
|
||||
{
|
||||
const UInt32 kMinSize = (UInt32)1 << 20;
|
||||
const UInt32 kMaxSize = (UInt32)1 << 28;
|
||||
const UInt32 dictSize = p->lzmaProps.dictSize;
|
||||
UInt64 blockSize = (UInt64)dictSize << 2;
|
||||
if (blockSize < kMinSize) blockSize = kMinSize;
|
||||
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
||||
if (blockSize < dictSize) blockSize = dictSize;
|
||||
blockSize += (kMinSize - 1);
|
||||
blockSize &= ~(UInt64)(kMinSize - 1);
|
||||
p->blockSize = blockSize;
|
||||
}
|
||||
|
||||
if (t2 > 1 && fileSize != (UInt64)(Int64)-1)
|
||||
{
|
||||
UInt64 numBlocks = fileSize / p->blockSize;
|
||||
if (numBlocks * p->blockSize != fileSize)
|
||||
numBlocks++;
|
||||
if (numBlocks < (unsigned)t2)
|
||||
{
|
||||
t2r = (unsigned)numBlocks;
|
||||
if (t2r == 0)
|
||||
t2r = 1;
|
||||
t3 = t1 * t2r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p->numBlockThreads_Max = t2;
|
||||
p->numBlockThreads_Reduced = t2r;
|
||||
p->numTotalThreads = t3;
|
||||
}
|
||||
|
||||
|
||||
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
|
||||
{
|
||||
return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- Lzma2 ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte propEncoded;
|
||||
CLzma2EncProps props;
|
||||
UInt64 expectedDataSize;
|
||||
|
||||
Byte *tempBufLzma;
|
||||
|
||||
ISzAllocPtr alloc;
|
||||
ISzAllocPtr allocBig;
|
||||
|
||||
CLzma2EncInt coders[MTCODER__THREADS_MAX];
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
ISeqOutStream *outStream;
|
||||
Byte *outBuf;
|
||||
size_t outBuf_Rem; /* remainder in outBuf */
|
||||
|
||||
size_t outBufSize; /* size of allocated outBufs[i] */
|
||||
size_t outBufsDataSizes[MTCODER__BLOCKS_MAX];
|
||||
BoolInt mtCoder_WasConstructed;
|
||||
CMtCoder mtCoder;
|
||||
Byte *outBufs[MTCODER__BLOCKS_MAX];
|
||||
|
||||
#endif
|
||||
|
||||
} CLzma2Enc;
|
||||
|
||||
|
||||
|
||||
CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)
|
||||
{
|
||||
CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc));
|
||||
if (!p)
|
||||
return NULL;
|
||||
Lzma2EncProps_Init(&p->props);
|
||||
Lzma2EncProps_Normalize(&p->props);
|
||||
p->expectedDataSize = (UInt64)(Int64)-1;
|
||||
p->tempBufLzma = NULL;
|
||||
p->alloc = alloc;
|
||||
p->allocBig = allocBig;
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < MTCODER__THREADS_MAX; i++)
|
||||
p->coders[i].enc = NULL;
|
||||
}
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
p->mtCoder_WasConstructed = False;
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
|
||||
p->outBufs[i] = NULL;
|
||||
p->outBufSize = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
|
||||
if (p->outBufs[i])
|
||||
{
|
||||
ISzAlloc_Free(p->alloc, p->outBufs[i]);
|
||||
p->outBufs[i] = NULL;
|
||||
}
|
||||
p->outBufSize = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void Lzma2Enc_Destroy(CLzma2EncHandle pp)
|
||||
{
|
||||
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||
unsigned i;
|
||||
for (i = 0; i < MTCODER__THREADS_MAX; i++)
|
||||
{
|
||||
CLzma2EncInt *t = &p->coders[i];
|
||||
if (t->enc)
|
||||
{
|
||||
LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
|
||||
t->enc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
if (p->mtCoder_WasConstructed)
|
||||
{
|
||||
MtCoder_Destruct(&p->mtCoder);
|
||||
p->mtCoder_WasConstructed = False;
|
||||
}
|
||||
Lzma2Enc_FreeOutBufs(p);
|
||||
#endif
|
||||
|
||||
ISzAlloc_Free(p->alloc, p->tempBufLzma);
|
||||
p->tempBufLzma = NULL;
|
||||
|
||||
ISzAlloc_Free(p->alloc, pp);
|
||||
}
|
||||
|
||||
|
||||
SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
|
||||
{
|
||||
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||
CLzmaEncProps lzmaProps = props->lzmaProps;
|
||||
LzmaEncProps_Normalize(&lzmaProps);
|
||||
if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
|
||||
return SZ_ERROR_PARAM;
|
||||
p->props = *props;
|
||||
Lzma2EncProps_Normalize(&p->props);
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
void Lzma2Enc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
|
||||
{
|
||||
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||
p->expectedDataSize = expectedDataSiize;
|
||||
}
|
||||
|
||||
|
||||
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
|
||||
{
|
||||
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||
unsigned i;
|
||||
UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
|
||||
for (i = 0; i < 40; i++)
|
||||
if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))
|
||||
break;
|
||||
return (Byte)i;
|
||||
}
|
||||
|
||||
|
||||
static SRes Lzma2Enc_EncodeMt1(
|
||||
CLzma2Enc *me,
|
||||
CLzma2EncInt *p,
|
||||
ISeqOutStream *outStream,
|
||||
Byte *outBuf, size_t *outBufSize,
|
||||
ISeqInStream *inStream,
|
||||
const Byte *inData, size_t inDataSize,
|
||||
int finished,
|
||||
ICompressProgress *progress)
|
||||
{
|
||||
UInt64 unpackTotal = 0;
|
||||
UInt64 packTotal = 0;
|
||||
size_t outLim = 0;
|
||||
CLimitedSeqInStream limitedInStream;
|
||||
|
||||
if (outBuf)
|
||||
{
|
||||
outLim = *outBufSize;
|
||||
*outBufSize = 0;
|
||||
}
|
||||
|
||||
if (!p->enc)
|
||||
{
|
||||
p->propsAreSet = False;
|
||||
p->enc = LzmaEnc_Create(me->alloc);
|
||||
if (!p->enc)
|
||||
return SZ_ERROR_MEM;
|
||||
}
|
||||
|
||||
limitedInStream.realStream = inStream;
|
||||
if (inStream)
|
||||
{
|
||||
limitedInStream.vt.Read = LimitedSeqInStream_Read;
|
||||
}
|
||||
|
||||
if (!outBuf)
|
||||
{
|
||||
// outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma
|
||||
if (!me->tempBufLzma)
|
||||
{
|
||||
me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
|
||||
if (!me->tempBufLzma)
|
||||
return SZ_ERROR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(Lzma2EncInt_InitStream(p, &me->props));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
size_t inSizeCur = 0;
|
||||
|
||||
Lzma2EncInt_InitBlock(p);
|
||||
|
||||
LimitedSeqInStream_Init(&limitedInStream);
|
||||
limitedInStream.limit = me->props.blockSize;
|
||||
|
||||
if (inStream)
|
||||
{
|
||||
UInt64 expected = (UInt64)(Int64)-1;
|
||||
// inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize
|
||||
if (me->expectedDataSize != (UInt64)(Int64)-1
|
||||
&& me->expectedDataSize >= unpackTotal)
|
||||
expected = me->expectedDataSize - unpackTotal;
|
||||
if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
|
||||
&& expected > me->props.blockSize)
|
||||
expected = (size_t)me->props.blockSize;
|
||||
|
||||
LzmaEnc_SetDataSize(p->enc, expected);
|
||||
|
||||
RINOK(LzmaEnc_PrepareForLzma2(p->enc,
|
||||
&limitedInStream.vt,
|
||||
LZMA2_KEEP_WINDOW_SIZE,
|
||||
me->alloc,
|
||||
me->allocBig));
|
||||
}
|
||||
else
|
||||
{
|
||||
inSizeCur = inDataSize - (size_t)unpackTotal;
|
||||
if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
|
||||
&& inSizeCur > me->props.blockSize)
|
||||
inSizeCur = (size_t)me->props.blockSize;
|
||||
|
||||
// LzmaEnc_SetDataSize(p->enc, inSizeCur);
|
||||
|
||||
RINOK(LzmaEnc_MemPrepare(p->enc,
|
||||
inData + (size_t)unpackTotal, inSizeCur,
|
||||
LZMA2_KEEP_WINDOW_SIZE,
|
||||
me->alloc,
|
||||
me->allocBig));
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
|
||||
if (outBuf)
|
||||
packSize = outLim - (size_t)packTotal;
|
||||
|
||||
res = Lzma2EncInt_EncodeSubblock(p,
|
||||
outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize,
|
||||
outBuf ? NULL : outStream);
|
||||
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
packTotal += packSize;
|
||||
if (outBuf)
|
||||
*outBufSize = (size_t)packTotal;
|
||||
|
||||
res = Progress(progress, unpackTotal + p->srcPos, packTotal);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
/*
|
||||
if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0)
|
||||
break;
|
||||
*/
|
||||
|
||||
if (packSize == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
LzmaEnc_Finish(p->enc);
|
||||
|
||||
unpackTotal += p->srcPos;
|
||||
|
||||
RINOK(res);
|
||||
|
||||
if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur))
|
||||
return SZ_ERROR_FAIL;
|
||||
|
||||
if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize))
|
||||
{
|
||||
if (finished)
|
||||
{
|
||||
if (outBuf)
|
||||
{
|
||||
size_t destPos = *outBufSize;
|
||||
if (destPos >= outLim)
|
||||
return SZ_ERROR_OUTPUT_EOF;
|
||||
outBuf[destPos] = 0;
|
||||
*outBufSize = destPos + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Byte b = 0;
|
||||
if (ISeqOutStream_Write(outStream, &b, 1) != 1)
|
||||
return SZ_ERROR_WRITE;
|
||||
}
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
static SRes Lzma2Enc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex,
|
||||
const Byte *src, size_t srcSize, int finished)
|
||||
{
|
||||
CLzma2Enc *me = (CLzma2Enc *)pp;
|
||||
size_t destSize = me->outBufSize;
|
||||
SRes res;
|
||||
CMtProgressThunk progressThunk;
|
||||
|
||||
Byte *dest = me->outBufs[outBufIndex];
|
||||
|
||||
me->outBufsDataSizes[outBufIndex] = 0;
|
||||
|
||||
if (!dest)
|
||||
{
|
||||
dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);
|
||||
if (!dest)
|
||||
return SZ_ERROR_MEM;
|
||||
me->outBufs[outBufIndex] = dest;
|
||||
}
|
||||
|
||||
MtProgressThunk_CreateVTable(&progressThunk);
|
||||
progressThunk.mtProgress = &me->mtCoder.mtProgress;
|
||||
progressThunk.inSize = 0;
|
||||
progressThunk.outSize = 0;
|
||||
|
||||
res = Lzma2Enc_EncodeMt1(me,
|
||||
&me->coders[coderIndex],
|
||||
NULL, dest, &destSize,
|
||||
NULL, src, srcSize,
|
||||
finished,
|
||||
&progressThunk.vt);
|
||||
|
||||
me->outBufsDataSizes[outBufIndex] = destSize;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static SRes Lzma2Enc_MtCallback_Write(void *pp, unsigned outBufIndex)
|
||||
{
|
||||
CLzma2Enc *me = (CLzma2Enc *)pp;
|
||||
size_t size = me->outBufsDataSizes[outBufIndex];
|
||||
const Byte *data = me->outBufs[outBufIndex];
|
||||
|
||||
if (me->outStream)
|
||||
return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE;
|
||||
|
||||
if (size > me->outBuf_Rem)
|
||||
return SZ_ERROR_OUTPUT_EOF;
|
||||
memcpy(me->outBuf, data, size);
|
||||
me->outBuf_Rem -= size;
|
||||
me->outBuf += size;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
SRes Lzma2Enc_Encode2(CLzma2EncHandle pp,
|
||||
ISeqOutStream *outStream,
|
||||
Byte *outBuf, size_t *outBufSize,
|
||||
ISeqInStream *inStream,
|
||||
const Byte *inData, size_t inDataSize,
|
||||
ICompressProgress *progress)
|
||||
{
|
||||
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||
|
||||
if (inStream && inData)
|
||||
return SZ_ERROR_PARAM;
|
||||
|
||||
if (outStream && outBuf)
|
||||
return SZ_ERROR_PARAM;
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < MTCODER__THREADS_MAX; i++)
|
||||
p->coders[i].propsAreSet = False;
|
||||
}
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
if (p->props.numBlockThreads_Reduced > 1)
|
||||
{
|
||||
IMtCoderCallback2 vt;
|
||||
|
||||
if (!p->mtCoder_WasConstructed)
|
||||
{
|
||||
p->mtCoder_WasConstructed = True;
|
||||
MtCoder_Construct(&p->mtCoder);
|
||||
}
|
||||
|
||||
vt.Code = Lzma2Enc_MtCallback_Code;
|
||||
vt.Write = Lzma2Enc_MtCallback_Write;
|
||||
|
||||
p->outStream = outStream;
|
||||
p->outBuf = NULL;
|
||||
p->outBuf_Rem = 0;
|
||||
if (!outStream)
|
||||
{
|
||||
p->outBuf = outBuf;
|
||||
p->outBuf_Rem = *outBufSize;
|
||||
*outBufSize = 0;
|
||||
}
|
||||
|
||||
p->mtCoder.allocBig = p->allocBig;
|
||||
p->mtCoder.progress = progress;
|
||||
p->mtCoder.inStream = inStream;
|
||||
p->mtCoder.inData = inData;
|
||||
p->mtCoder.inDataSize = inDataSize;
|
||||
p->mtCoder.mtCallback = &vt;
|
||||
p->mtCoder.mtCallbackObject = p;
|
||||
|
||||
p->mtCoder.blockSize = (size_t)p->props.blockSize;
|
||||
if (p->mtCoder.blockSize != p->props.blockSize)
|
||||
return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */
|
||||
|
||||
{
|
||||
size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16;
|
||||
if (destBlockSize < p->mtCoder.blockSize)
|
||||
return SZ_ERROR_PARAM;
|
||||
if (p->outBufSize != destBlockSize)
|
||||
Lzma2Enc_FreeOutBufs(p);
|
||||
p->outBufSize = destBlockSize;
|
||||
}
|
||||
|
||||
p->mtCoder.numThreadsMax = p->props.numBlockThreads_Max;
|
||||
p->mtCoder.expectedDataSize = p->expectedDataSize;
|
||||
|
||||
{
|
||||
SRes res = MtCoder_Code(&p->mtCoder);
|
||||
if (!outStream)
|
||||
*outBufSize = p->outBuf - outBuf;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
return Lzma2Enc_EncodeMt1(p,
|
||||
&p->coders[0],
|
||||
outStream, outBuf, outBufSize,
|
||||
inStream, inData, inDataSize,
|
||||
True, /* finished */
|
||||
progress);
|
||||
}
|
||||
55
C/Lzma2Enc.h
Normal file
55
C/Lzma2Enc.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* Lzma2Enc.h -- LZMA2 Encoder
|
||||
2017-07-27 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA2_ENC_H
|
||||
#define __LZMA2_ENC_H
|
||||
|
||||
#include "LzmaEnc.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO 0
|
||||
#define LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID ((UInt64)(Int64)-1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaEncProps lzmaProps;
|
||||
UInt64 blockSize;
|
||||
int numBlockThreads_Reduced;
|
||||
int numBlockThreads_Max;
|
||||
int numTotalThreads;
|
||||
} CLzma2EncProps;
|
||||
|
||||
void Lzma2EncProps_Init(CLzma2EncProps *p);
|
||||
void Lzma2EncProps_Normalize(CLzma2EncProps *p);
|
||||
|
||||
/* ---------- CLzmaEnc2Handle Interface ---------- */
|
||||
|
||||
/* Lzma2Enc_* functions can return the following exit codes:
|
||||
SRes:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||
SZ_ERROR_WRITE - ISeqOutStream write callback error
|
||||
SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
|
||||
SZ_ERROR_PROGRESS - some break from progress callback
|
||||
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
typedef void * CLzma2EncHandle;
|
||||
|
||||
CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
void Lzma2Enc_Destroy(CLzma2EncHandle p);
|
||||
SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
|
||||
void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize);
|
||||
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
|
||||
SRes Lzma2Enc_Encode2(CLzma2EncHandle p,
|
||||
ISeqOutStream *outStream,
|
||||
Byte *outBuf, size_t *outBufSize,
|
||||
ISeqInStream *inStream,
|
||||
const Byte *inData, size_t inDataSize,
|
||||
ICompressProgress *progress);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
59
C/LzmaUtil/Lzma86Enc.h → C/Lzma86.h
Executable file → Normal file
59
C/LzmaUtil/Lzma86Enc.h → C/Lzma86.h
Executable file → Normal file
@@ -1,12 +1,15 @@
|
||||
/* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
/* Lzma86.h -- LZMA + x86 (BCJ) Filter
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA86ENC_H
|
||||
#define __LZMA86ENC_H
|
||||
#ifndef __LZMA86_H
|
||||
#define __LZMA86_H
|
||||
|
||||
#include "../Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define LZMA86_SIZE_OFFSET (1 + 5)
|
||||
#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)
|
||||
|
||||
/*
|
||||
It's an example for LZMA + x86 Filter use.
|
||||
@@ -14,8 +17,8 @@ You can use .lzma86 extension, if you write that stream to file.
|
||||
.lzma86 header adds one additional byte to standard .lzma header.
|
||||
.lzma86 header (14 bytes):
|
||||
Offset Size Description
|
||||
0 1 = 0 - no filter,
|
||||
= 1 - x86 filter
|
||||
0 1 = 0 - no filter, pure LZMA
|
||||
= 1 - x86 filter + LZMA
|
||||
1 1 lc, lp and pb in encoded form
|
||||
2 4 dictSize (little endian)
|
||||
6 8 uncompressed size (little endian)
|
||||
@@ -25,7 +28,6 @@ Lzma86_Encode
|
||||
-------------
|
||||
level - compression level: 0 <= level <= 9, the default value for "level" is 5.
|
||||
|
||||
|
||||
dictSize - The dictionary size in bytes. The maximum value is
|
||||
128 MB = (1 << 27) bytes for 32-bit version
|
||||
1 GB = (1 << 30) bytes for 64-bit version
|
||||
@@ -69,4 +71,41 @@ enum ESzFilterMode
|
||||
SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
|
||||
int level, UInt32 dictSize, int filterMode);
|
||||
|
||||
|
||||
/*
|
||||
Lzma86_GetUnpackSize:
|
||||
In:
|
||||
src - input data
|
||||
srcLen - input data size
|
||||
Out:
|
||||
unpackSize - size of uncompressed stream
|
||||
Return code:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_INPUT_EOF - Error in headers
|
||||
*/
|
||||
|
||||
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize);
|
||||
|
||||
/*
|
||||
Lzma86_Decode:
|
||||
In:
|
||||
dest - output data
|
||||
destLen - output data size
|
||||
src - input data
|
||||
srcLen - input data size
|
||||
Out:
|
||||
destLen - processed output size
|
||||
srcLen - processed input size
|
||||
Return code:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - unsupported file
|
||||
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer
|
||||
*/
|
||||
|
||||
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
19
C/LzmaUtil/Lzma86Dec.c → C/Lzma86Dec.c
Executable file → Normal file
19
C/LzmaUtil/Lzma86Dec.c → C/Lzma86Dec.c
Executable file → Normal file
@@ -1,20 +1,13 @@
|
||||
/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder
|
||||
2008-04-07
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2016-05-16 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Lzma86Dec.h"
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "../Alloc.h"
|
||||
#include "../Bra.h"
|
||||
#include "../LzmaDec.h"
|
||||
#include "Lzma86.h"
|
||||
|
||||
#define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE)
|
||||
#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)
|
||||
|
||||
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
#include "Alloc.h"
|
||||
#include "Bra.h"
|
||||
#include "LzmaDec.h"
|
||||
|
||||
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)
|
||||
{
|
||||
29
C/LzmaUtil/Lzma86Enc.c → C/Lzma86Enc.c
Executable file → Normal file
29
C/LzmaUtil/Lzma86Enc.c → C/Lzma86Enc.c
Executable file → Normal file
@@ -1,31 +1,24 @@
|
||||
/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2018-07-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Lzma86Enc.h"
|
||||
#include "Lzma86.h"
|
||||
|
||||
#include "../Alloc.h"
|
||||
#include "../Bra.h"
|
||||
#include "../LzmaEnc.h"
|
||||
#include "Alloc.h"
|
||||
#include "Bra.h"
|
||||
#include "LzmaEnc.h"
|
||||
|
||||
#define SZE_OUT_OVERFLOW SZE_DATA_ERROR
|
||||
|
||||
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
#define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE)
|
||||
#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)
|
||||
|
||||
int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
|
||||
int level, UInt32 dictSize, int filterMode)
|
||||
{
|
||||
size_t outSize2 = *destLen;
|
||||
Byte *filteredStream;
|
||||
Bool useFilter;
|
||||
BoolInt useFilter;
|
||||
int mainResult = SZ_ERROR_OUTPUT_EOF;
|
||||
CLzmaEncProps props;
|
||||
LzmaEncProps_Init(&props);
|
||||
@@ -63,7 +56,7 @@ int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
|
||||
|
||||
{
|
||||
size_t minSize = 0;
|
||||
Bool bestIsFiltered = False;
|
||||
BoolInt bestIsFiltered = False;
|
||||
|
||||
/* passes for SZ_FILTER_AUTO:
|
||||
0 - BCJ + LZMA
|
||||
@@ -78,7 +71,7 @@ int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
|
||||
size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;
|
||||
size_t outPropsSize = 5;
|
||||
SRes curRes;
|
||||
Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
|
||||
BoolInt curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
|
||||
if (curModeIsFiltered && !bestIsFiltered)
|
||||
break;
|
||||
if (useFilter && i == 0)
|
||||
@@ -104,7 +97,7 @@ int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
|
||||
}
|
||||
}
|
||||
}
|
||||
dest[0] = (bestIsFiltered ? 1 : 0);
|
||||
dest[0] = (Byte)(bestIsFiltered ? 1 : 0);
|
||||
*destLen = LZMA86_HEADER_SIZE + minSize;
|
||||
}
|
||||
if (useFilter)
|
||||
634
C/LzmaDec.c
Executable file → Normal file
634
C/LzmaDec.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
57
C/LzmaDec.h
Executable file → Normal file
57
C/LzmaDec.h
Executable file → Normal file
@@ -1,20 +1,24 @@
|
||||
/* LzmaDec.h -- LZMA Decoder
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2018-04-21 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMADEC_H
|
||||
#define __LZMADEC_H
|
||||
#ifndef __LZMA_DEC_H
|
||||
#define __LZMA_DEC_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* #define _LZMA_PROB32 */
|
||||
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
||||
but memory usage for CLzmaDec::probs will be doubled in that case */
|
||||
|
||||
typedef
|
||||
#ifdef _LZMA_PROB32
|
||||
#define CLzmaProb UInt32
|
||||
UInt32
|
||||
#else
|
||||
#define CLzmaProb UInt16
|
||||
UInt16
|
||||
#endif
|
||||
CLzmaProb;
|
||||
|
||||
|
||||
/* ---------- LZMA Properties ---------- */
|
||||
@@ -23,7 +27,10 @@
|
||||
|
||||
typedef struct _CLzmaProps
|
||||
{
|
||||
unsigned lc, lp, pb;
|
||||
Byte lc;
|
||||
Byte lp;
|
||||
Byte pb;
|
||||
Byte _pad_;
|
||||
UInt32 dicSize;
|
||||
} CLzmaProps;
|
||||
|
||||
@@ -45,32 +52,34 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Don't change this structure. ASM code can use it. */
|
||||
CLzmaProps prop;
|
||||
CLzmaProb *probs;
|
||||
CLzmaProb *probs_1664;
|
||||
Byte *dic;
|
||||
const Byte *buf;
|
||||
UInt32 range, code;
|
||||
SizeT dicPos;
|
||||
SizeT dicBufSize;
|
||||
SizeT dicPos;
|
||||
const Byte *buf;
|
||||
UInt32 range;
|
||||
UInt32 code;
|
||||
UInt32 processedPos;
|
||||
UInt32 checkDicSize;
|
||||
unsigned state;
|
||||
UInt32 reps[4];
|
||||
unsigned remainLen;
|
||||
int needFlush;
|
||||
int needInitState;
|
||||
UInt32 state;
|
||||
UInt32 remainLen;
|
||||
|
||||
UInt32 numProbs;
|
||||
unsigned tempBufSize;
|
||||
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
||||
} CLzmaDec;
|
||||
|
||||
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
|
||||
#define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; }
|
||||
|
||||
void LzmaDec_Init(CLzmaDec *p);
|
||||
|
||||
/* There are two types of LZMA streams:
|
||||
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||
- Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||
- Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -127,11 +136,11 @@ LzmaDec_Allocate* can return:
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
|
||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
|
||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
|
||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);
|
||||
|
||||
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
|
||||
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
|
||||
SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
|
||||
void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);
|
||||
|
||||
/* ---------- Dictionary Interface ---------- */
|
||||
|
||||
@@ -140,7 +149,7 @@ void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
|
||||
You must work with CLzmaDec variables directly in this interface.
|
||||
|
||||
STEPS:
|
||||
LzmaDec_Constr()
|
||||
LzmaDec_Construct()
|
||||
LzmaDec_Allocate()
|
||||
for (each new stream)
|
||||
{
|
||||
@@ -218,6 +227,8 @@ Returns:
|
||||
|
||||
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||
ELzmaStatus *status, ISzAlloc *alloc);
|
||||
ELzmaStatus *status, ISzAllocPtr alloc);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
3069
C/LzmaEnc.c
Executable file → Normal file
3069
C/LzmaEnc.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
56
C/LzmaEnc.h
Executable file → Normal file
56
C/LzmaEnc.h
Executable file → Normal file
@@ -1,19 +1,21 @@
|
||||
/* LzmaEnc.h -- LZMA Encoder
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2017-07-27 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMAENC_H
|
||||
#define __LZMAENC_H
|
||||
#ifndef __LZMA_ENC_H
|
||||
#define __LZMA_ENC_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define LZMA_PROPS_SIZE 5
|
||||
|
||||
typedef struct _CLzmaEncProps
|
||||
{
|
||||
int level; /* 0 <= level <= 9 */
|
||||
int level; /* 0 <= level <= 9 */
|
||||
UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
|
||||
(1 << 12) <= dictSize <= (1 << 30) for 64-bit version
|
||||
default = (1 << 24) */
|
||||
(1 << 12) <= dictSize <= (3 << 29) for 64-bit version
|
||||
default = (1 << 24) */
|
||||
int lc; /* 0 <= lc <= 8, default = 3 */
|
||||
int lp; /* 0 <= lp <= 4, default = 0 */
|
||||
int pb; /* 0 <= pb <= 4, default = 2 */
|
||||
@@ -21,9 +23,12 @@ typedef struct _CLzmaEncProps
|
||||
int fb; /* 5 <= fb <= 273, default = 32 */
|
||||
int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
|
||||
int numHashBytes; /* 2, 3 or 4, default = 4 */
|
||||
UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
|
||||
UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
|
||||
unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
|
||||
int numThreads; /* 1 or 2, default = 2 */
|
||||
|
||||
UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1.
|
||||
Encoder uses this value to reduce dictionary size */
|
||||
} CLzmaEncProps;
|
||||
|
||||
void LzmaEncProps_Init(CLzmaEncProps *p);
|
||||
@@ -33,40 +38,39 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
|
||||
|
||||
/* ---------- CLzmaEncHandle Interface ---------- */
|
||||
|
||||
/* LzmaEnc_* functions can return the following exit codes:
|
||||
Returns:
|
||||
/* LzmaEnc* functions can return the following exit codes:
|
||||
SRes:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||
SZ_ERROR_WRITE - Write callback error.
|
||||
SZ_ERROR_WRITE - ISeqOutStream write callback error
|
||||
SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
|
||||
SZ_ERROR_PROGRESS - some break from progress callback
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
typedef void * CLzmaEncHandle;
|
||||
|
||||
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
|
||||
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc);
|
||||
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
|
||||
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
|
||||
void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize);
|
||||
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
|
||||
unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p);
|
||||
|
||||
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
|
||||
/* LzmaEncode
|
||||
Return code:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater
|
||||
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
16
C/LzmaLib.c
Executable file → Normal file
16
C/LzmaLib.c
Executable file → Normal file
@@ -1,18 +1,12 @@
|
||||
/* LzmaLib.c -- LZMA library wrapper
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2015-06-13 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "LzmaEnc.h"
|
||||
#include "LzmaDec.h"
|
||||
#include "Alloc.h"
|
||||
#include "LzmaDec.h"
|
||||
#include "LzmaEnc.h"
|
||||
#include "LzmaLib.h"
|
||||
|
||||
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
|
||||
MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
|
||||
unsigned char *outProps, size_t *outPropsSize,
|
||||
int level, /* 0 <= level <= 9, default = 5 */
|
||||
unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */
|
||||
@@ -38,7 +32,7 @@ MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned cha
|
||||
}
|
||||
|
||||
|
||||
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen,
|
||||
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen,
|
||||
const unsigned char *props, size_t propsSize)
|
||||
{
|
||||
ELzmaStatus status;
|
||||
|
||||
20
C/LzmaLib.h
Executable file → Normal file
20
C/LzmaLib.h
Executable file → Normal file
@@ -1,20 +1,14 @@
|
||||
/* LzmaLib.h -- LZMA library interface
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMALIB_H
|
||||
#define __LZMALIB_H
|
||||
#ifndef __LZMA_LIB_H
|
||||
#define __LZMA_LIB_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define MY_EXTERN_C extern "C"
|
||||
#else
|
||||
#define MY_EXTERN_C extern
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL
|
||||
#define MY_STDAPI int MY_STD_CALL
|
||||
|
||||
#define LZMA_PROPS_SIZE 5
|
||||
|
||||
@@ -132,4 +126,6 @@ Returns:
|
||||
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
|
||||
const unsigned char *props, size_t propsSize);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=LzmaLib - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "LzmaLib.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "LzmaLib - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "LzmaLib - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "LzmaLib - Win32 Release"
|
||||
# Name "LzmaLib - Win32 Debug"
|
||||
# Begin Group "Spec"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LzmaLib.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LzmaLibExports.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Alloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Alloc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\IStream.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzFind.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzFind.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzFindMt.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzFindMt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzHash.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzmaDec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzmaDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzmaEnc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzmaEnc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzmaLib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzmaLib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.rc
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Threads.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Threads.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Types.h
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -1,29 +0,0 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#ifndef __LZMA86DEC_H
|
||||
#define __LZMA86DEC_H
|
||||
|
||||
#include "../Types.h"
|
||||
|
||||
/*
|
||||
Lzma86_GetUnpackSize:
|
||||
In:
|
||||
src - input data
|
||||
srcLen - input data size
|
||||
Out:
|
||||
unpackSize - size of uncompressed stream
|
||||
Return code:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_INPUT_EOF - Error in headers
|
||||
*/
|
||||
|
||||
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize);
|
||||
|
||||
/*
|
||||
Lzma86_Decode:
|
||||
In:
|
||||
dest - output data
|
||||
destLen - output data size
|
||||
src - input data
|
||||
srcLen - input data size
|
||||
Out:
|
||||
destLen - processed output size
|
||||
srcLen - processed input size
|
||||
Return code:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - unsupported file
|
||||
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer
|
||||
*/
|
||||
|
||||
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);
|
||||
|
||||
#endif
|
||||
@@ -1,168 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=LzmaUtil - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "LzmaUtil.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "LzmaUtil - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\lzmac.exe"
|
||||
|
||||
!ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\lzmac.exe" /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "LzmaUtil - Win32 Release"
|
||||
# Name "LzmaUtil - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\7zFile.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\7zFile.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\7zStream.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\7zVersion.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Alloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Alloc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\CpuArch.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzFind.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzFind.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzFindMt.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzFindMt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzHash.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzmaDec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzmaDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzmaEnc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\LzmaEnc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LzmaUtil.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Threads.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Threads.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Types.h
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -1,29 +0,0 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
PROG = lzma
|
||||
CXX = g++
|
||||
LIB =
|
||||
RM = rm -f
|
||||
CFLAGS = -c -O2 -Wall
|
||||
|
||||
OBJS = \
|
||||
LzmaUtil.o \
|
||||
Alloc.o \
|
||||
LzFind.o \
|
||||
LzmaDec.o \
|
||||
LzmaEnc.o \
|
||||
7zFile.o \
|
||||
7zStream.o \
|
||||
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
$(PROG): $(OBJS)
|
||||
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)
|
||||
|
||||
LzmaUtil.o: LzmaUtil.c
|
||||
$(CXX) $(CFLAGS) LzmaUtil.c
|
||||
|
||||
Alloc.o: ../Alloc.c
|
||||
$(CXX) $(CFLAGS) ../Alloc.c
|
||||
|
||||
LzFind.o: ../LzFind.c
|
||||
$(CXX) $(CFLAGS) ../LzFind.c
|
||||
|
||||
LzmaDec.o: ../LzmaDec.c
|
||||
$(CXX) $(CFLAGS) ../LzmaDec.c
|
||||
|
||||
LzmaEnc.o: ../LzmaEnc.c
|
||||
$(CXX) $(CFLAGS) ../LzmaEnc.c
|
||||
|
||||
7zFile.o: ../7zFile.c
|
||||
$(CXX) $(CFLAGS) ../7zFile.c
|
||||
|
||||
7zStream.o: ../7zStream.c
|
||||
$(CXX) $(CFLAGS) ../7zStream.c
|
||||
|
||||
clean:
|
||||
-$(RM) $(PROG) $(OBJS)
|
||||
601
C/MtCoder.c
Normal file
601
C/MtCoder.c
Normal file
@@ -0,0 +1,601 @@
|
||||
/* MtCoder.c -- Multi-thread Coder
|
||||
2018-07-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "MtCoder.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
SRes MtProgressThunk_Progress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize)
|
||||
{
|
||||
CMtProgressThunk *thunk = CONTAINER_FROM_VTBL(pp, CMtProgressThunk, vt);
|
||||
UInt64 inSize2 = 0;
|
||||
UInt64 outSize2 = 0;
|
||||
if (inSize != (UInt64)(Int64)-1)
|
||||
{
|
||||
inSize2 = inSize - thunk->inSize;
|
||||
thunk->inSize = inSize;
|
||||
}
|
||||
if (outSize != (UInt64)(Int64)-1)
|
||||
{
|
||||
outSize2 = outSize - thunk->outSize;
|
||||
thunk->outSize = outSize;
|
||||
}
|
||||
return MtProgress_ProgressAdd(thunk->mtProgress, inSize2, outSize2);
|
||||
}
|
||||
|
||||
|
||||
void MtProgressThunk_CreateVTable(CMtProgressThunk *p)
|
||||
{
|
||||
p->vt.Progress = MtProgressThunk_Progress;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
|
||||
|
||||
|
||||
static WRes ArEvent_OptCreate_And_Reset(CEvent *p)
|
||||
{
|
||||
if (Event_IsCreated(p))
|
||||
return Event_Reset(p);
|
||||
return AutoResetEvent_CreateNotSignaled(p);
|
||||
}
|
||||
|
||||
|
||||
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp);
|
||||
|
||||
|
||||
static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t)
|
||||
{
|
||||
WRes wres = ArEvent_OptCreate_And_Reset(&t->startEvent);
|
||||
if (wres == 0)
|
||||
{
|
||||
t->stop = False;
|
||||
if (!Thread_WasCreated(&t->thread))
|
||||
wres = Thread_Create(&t->thread, ThreadFunc, t);
|
||||
if (wres == 0)
|
||||
wres = Event_Set(&t->startEvent);
|
||||
}
|
||||
if (wres == 0)
|
||||
return SZ_OK;
|
||||
return MY_SRes_HRESULT_FROM_WRes(wres);
|
||||
}
|
||||
|
||||
|
||||
static void MtCoderThread_Destruct(CMtCoderThread *t)
|
||||
{
|
||||
if (Thread_WasCreated(&t->thread))
|
||||
{
|
||||
t->stop = 1;
|
||||
Event_Set(&t->startEvent);
|
||||
Thread_Wait(&t->thread);
|
||||
Thread_Close(&t->thread);
|
||||
}
|
||||
|
||||
Event_Close(&t->startEvent);
|
||||
|
||||
if (t->inBuf)
|
||||
{
|
||||
ISzAlloc_Free(t->mtCoder->allocBig, t->inBuf);
|
||||
t->inBuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
|
||||
{
|
||||
size_t size = *processedSize;
|
||||
*processedSize = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
size_t cur = size;
|
||||
SRes res = ISeqInStream_Read(stream, data, &cur);
|
||||
*processedSize += cur;
|
||||
data += cur;
|
||||
size -= cur;
|
||||
RINOK(res);
|
||||
if (cur == 0)
|
||||
return SZ_OK;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ThreadFunc2() returns:
|
||||
SZ_OK - in all normal cases (even for stream error or memory allocation error)
|
||||
SZ_ERROR_THREAD - in case of failure in system synch function
|
||||
*/
|
||||
|
||||
static SRes ThreadFunc2(CMtCoderThread *t)
|
||||
{
|
||||
CMtCoder *mtc = t->mtCoder;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned bi;
|
||||
SRes res;
|
||||
SRes res2;
|
||||
BoolInt finished;
|
||||
unsigned bufIndex;
|
||||
size_t size;
|
||||
const Byte *inData;
|
||||
UInt64 readProcessed = 0;
|
||||
|
||||
RINOK_THREAD(Event_Wait(&mtc->readEvent))
|
||||
|
||||
/* after Event_Wait(&mtc->readEvent) we must call Event_Set(&mtc->readEvent) in any case to unlock another threads */
|
||||
|
||||
if (mtc->stopReading)
|
||||
{
|
||||
return Event_Set(&mtc->readEvent) == 0 ? SZ_OK : SZ_ERROR_THREAD;
|
||||
}
|
||||
|
||||
res = MtProgress_GetError(&mtc->mtProgress);
|
||||
|
||||
size = 0;
|
||||
inData = NULL;
|
||||
finished = True;
|
||||
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
size = mtc->blockSize;
|
||||
if (mtc->inStream)
|
||||
{
|
||||
if (!t->inBuf)
|
||||
{
|
||||
t->inBuf = (Byte *)ISzAlloc_Alloc(mtc->allocBig, mtc->blockSize);
|
||||
if (!t->inBuf)
|
||||
res = SZ_ERROR_MEM;
|
||||
}
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
res = FullRead(mtc->inStream, t->inBuf, &size);
|
||||
readProcessed = mtc->readProcessed + size;
|
||||
mtc->readProcessed = readProcessed;
|
||||
}
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
mtc->readRes = res;
|
||||
/* after reading error - we can stop encoding of previous blocks */
|
||||
MtProgress_SetError(&mtc->mtProgress, res);
|
||||
}
|
||||
else
|
||||
finished = (size != mtc->blockSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t rem;
|
||||
readProcessed = mtc->readProcessed;
|
||||
rem = mtc->inDataSize - (size_t)readProcessed;
|
||||
if (size > rem)
|
||||
size = rem;
|
||||
inData = mtc->inData + (size_t)readProcessed;
|
||||
readProcessed += size;
|
||||
mtc->readProcessed = readProcessed;
|
||||
finished = (mtc->inDataSize == (size_t)readProcessed);
|
||||
}
|
||||
}
|
||||
|
||||
/* we must get some block from blocksSemaphore before Event_Set(&mtc->readEvent) */
|
||||
|
||||
res2 = SZ_OK;
|
||||
|
||||
if (Semaphore_Wait(&mtc->blocksSemaphore) != 0)
|
||||
{
|
||||
res2 = SZ_ERROR_THREAD;
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
res = res2;
|
||||
// MtProgress_SetError(&mtc->mtProgress, res);
|
||||
}
|
||||
}
|
||||
|
||||
bi = mtc->blockIndex;
|
||||
|
||||
if (++mtc->blockIndex >= mtc->numBlocksMax)
|
||||
mtc->blockIndex = 0;
|
||||
|
||||
bufIndex = (unsigned)(int)-1;
|
||||
|
||||
if (res == SZ_OK)
|
||||
res = MtProgress_GetError(&mtc->mtProgress);
|
||||
|
||||
if (res != SZ_OK)
|
||||
finished = True;
|
||||
|
||||
if (!finished)
|
||||
{
|
||||
if (mtc->numStartedThreads < mtc->numStartedThreadsLimit
|
||||
&& mtc->expectedDataSize != readProcessed)
|
||||
{
|
||||
res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]);
|
||||
if (res == SZ_OK)
|
||||
mtc->numStartedThreads++;
|
||||
else
|
||||
{
|
||||
MtProgress_SetError(&mtc->mtProgress, res);
|
||||
finished = True;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (finished)
|
||||
mtc->stopReading = True;
|
||||
|
||||
RINOK_THREAD(Event_Set(&mtc->readEvent))
|
||||
|
||||
if (res2 != SZ_OK)
|
||||
return res2;
|
||||
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
CriticalSection_Enter(&mtc->cs);
|
||||
bufIndex = mtc->freeBlockHead;
|
||||
mtc->freeBlockHead = mtc->freeBlockList[bufIndex];
|
||||
CriticalSection_Leave(&mtc->cs);
|
||||
|
||||
res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex,
|
||||
mtc->inStream ? t->inBuf : inData, size, finished);
|
||||
|
||||
// MtProgress_Reinit(&mtc->mtProgress, t->index);
|
||||
|
||||
if (res != SZ_OK)
|
||||
MtProgress_SetError(&mtc->mtProgress, res);
|
||||
}
|
||||
|
||||
{
|
||||
CMtCoderBlock *block = &mtc->blocks[bi];
|
||||
block->res = res;
|
||||
block->bufIndex = bufIndex;
|
||||
block->finished = finished;
|
||||
}
|
||||
|
||||
#ifdef MTCODER__USE_WRITE_THREAD
|
||||
RINOK_THREAD(Event_Set(&mtc->writeEvents[bi]))
|
||||
#else
|
||||
{
|
||||
unsigned wi;
|
||||
{
|
||||
CriticalSection_Enter(&mtc->cs);
|
||||
wi = mtc->writeIndex;
|
||||
if (wi == bi)
|
||||
mtc->writeIndex = (unsigned)(int)-1;
|
||||
else
|
||||
mtc->ReadyBlocks[bi] = True;
|
||||
CriticalSection_Leave(&mtc->cs);
|
||||
}
|
||||
|
||||
if (wi != bi)
|
||||
{
|
||||
if (res != SZ_OK || finished)
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mtc->writeRes != SZ_OK)
|
||||
res = mtc->writeRes;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (res == SZ_OK && bufIndex != (unsigned)(int)-1)
|
||||
{
|
||||
res = mtc->mtCallback->Write(mtc->mtCallbackObject, bufIndex);
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
mtc->writeRes = res;
|
||||
MtProgress_SetError(&mtc->mtProgress, res);
|
||||
}
|
||||
}
|
||||
|
||||
if (++wi >= mtc->numBlocksMax)
|
||||
wi = 0;
|
||||
{
|
||||
BoolInt isReady;
|
||||
|
||||
CriticalSection_Enter(&mtc->cs);
|
||||
|
||||
if (bufIndex != (unsigned)(int)-1)
|
||||
{
|
||||
mtc->freeBlockList[bufIndex] = mtc->freeBlockHead;
|
||||
mtc->freeBlockHead = bufIndex;
|
||||
}
|
||||
|
||||
isReady = mtc->ReadyBlocks[wi];
|
||||
|
||||
if (isReady)
|
||||
mtc->ReadyBlocks[wi] = False;
|
||||
else
|
||||
mtc->writeIndex = wi;
|
||||
|
||||
CriticalSection_Leave(&mtc->cs);
|
||||
|
||||
RINOK_THREAD(Semaphore_Release1(&mtc->blocksSemaphore))
|
||||
|
||||
if (!isReady)
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
CMtCoderBlock *block = &mtc->blocks[wi];
|
||||
if (res == SZ_OK && block->res != SZ_OK)
|
||||
res = block->res;
|
||||
bufIndex = block->bufIndex;
|
||||
finished = block->finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (finished || res != SZ_OK)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
|
||||
{
|
||||
CMtCoderThread *t = (CMtCoderThread *)pp;
|
||||
for (;;)
|
||||
{
|
||||
if (Event_Wait(&t->startEvent) != 0)
|
||||
return SZ_ERROR_THREAD;
|
||||
if (t->stop)
|
||||
return 0;
|
||||
{
|
||||
SRes res = ThreadFunc2(t);
|
||||
CMtCoder *mtc = t->mtCoder;
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
MtProgress_SetError(&mtc->mtProgress, res);
|
||||
}
|
||||
|
||||
#ifndef MTCODER__USE_WRITE_THREAD
|
||||
{
|
||||
unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads);
|
||||
if (numFinished == mtc->numStartedThreads)
|
||||
if (Event_Set(&mtc->finishedEvent) != 0)
|
||||
return SZ_ERROR_THREAD;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MtCoder_Construct(CMtCoder *p)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
p->blockSize = 0;
|
||||
p->numThreadsMax = 0;
|
||||
p->expectedDataSize = (UInt64)(Int64)-1;
|
||||
|
||||
p->inStream = NULL;
|
||||
p->inData = NULL;
|
||||
p->inDataSize = 0;
|
||||
|
||||
p->progress = NULL;
|
||||
p->allocBig = NULL;
|
||||
|
||||
p->mtCallback = NULL;
|
||||
p->mtCallbackObject = NULL;
|
||||
|
||||
p->allocatedBufsSize = 0;
|
||||
|
||||
Event_Construct(&p->readEvent);
|
||||
Semaphore_Construct(&p->blocksSemaphore);
|
||||
|
||||
for (i = 0; i < MTCODER__THREADS_MAX; i++)
|
||||
{
|
||||
CMtCoderThread *t = &p->threads[i];
|
||||
t->mtCoder = p;
|
||||
t->index = i;
|
||||
t->inBuf = NULL;
|
||||
t->stop = False;
|
||||
Event_Construct(&t->startEvent);
|
||||
Thread_Construct(&t->thread);
|
||||
}
|
||||
|
||||
#ifdef MTCODER__USE_WRITE_THREAD
|
||||
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
|
||||
Event_Construct(&p->writeEvents[i]);
|
||||
#else
|
||||
Event_Construct(&p->finishedEvent);
|
||||
#endif
|
||||
|
||||
CriticalSection_Init(&p->cs);
|
||||
CriticalSection_Init(&p->mtProgress.cs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void MtCoder_Free(CMtCoder *p)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/*
|
||||
p->stopReading = True;
|
||||
if (Event_IsCreated(&p->readEvent))
|
||||
Event_Set(&p->readEvent);
|
||||
*/
|
||||
|
||||
for (i = 0; i < MTCODER__THREADS_MAX; i++)
|
||||
MtCoderThread_Destruct(&p->threads[i]);
|
||||
|
||||
Event_Close(&p->readEvent);
|
||||
Semaphore_Close(&p->blocksSemaphore);
|
||||
|
||||
#ifdef MTCODER__USE_WRITE_THREAD
|
||||
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
|
||||
Event_Close(&p->writeEvents[i]);
|
||||
#else
|
||||
Event_Close(&p->finishedEvent);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void MtCoder_Destruct(CMtCoder *p)
|
||||
{
|
||||
MtCoder_Free(p);
|
||||
|
||||
CriticalSection_Delete(&p->cs);
|
||||
CriticalSection_Delete(&p->mtProgress.cs);
|
||||
}
|
||||
|
||||
|
||||
SRes MtCoder_Code(CMtCoder *p)
|
||||
{
|
||||
unsigned numThreads = p->numThreadsMax;
|
||||
unsigned numBlocksMax;
|
||||
unsigned i;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
if (numThreads > MTCODER__THREADS_MAX)
|
||||
numThreads = MTCODER__THREADS_MAX;
|
||||
numBlocksMax = MTCODER__GET_NUM_BLOCKS_FROM_THREADS(numThreads);
|
||||
|
||||
if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++;
|
||||
if (p->blockSize < ((UInt32)1 << 24)) numBlocksMax++;
|
||||
if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++;
|
||||
|
||||
if (numBlocksMax > MTCODER__BLOCKS_MAX)
|
||||
numBlocksMax = MTCODER__BLOCKS_MAX;
|
||||
|
||||
if (p->blockSize != p->allocatedBufsSize)
|
||||
{
|
||||
for (i = 0; i < MTCODER__THREADS_MAX; i++)
|
||||
{
|
||||
CMtCoderThread *t = &p->threads[i];
|
||||
if (t->inBuf)
|
||||
{
|
||||
ISzAlloc_Free(p->allocBig, t->inBuf);
|
||||
t->inBuf = NULL;
|
||||
}
|
||||
}
|
||||
p->allocatedBufsSize = p->blockSize;
|
||||
}
|
||||
|
||||
p->readRes = SZ_OK;
|
||||
|
||||
MtProgress_Init(&p->mtProgress, p->progress);
|
||||
|
||||
#ifdef MTCODER__USE_WRITE_THREAD
|
||||
for (i = 0; i < numBlocksMax; i++)
|
||||
{
|
||||
RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->writeEvents[i]));
|
||||
}
|
||||
#else
|
||||
RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->finishedEvent));
|
||||
#endif
|
||||
|
||||
{
|
||||
RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->readEvent));
|
||||
|
||||
if (Semaphore_IsCreated(&p->blocksSemaphore))
|
||||
{
|
||||
RINOK_THREAD(Semaphore_Close(&p->blocksSemaphore));
|
||||
}
|
||||
RINOK_THREAD(Semaphore_Create(&p->blocksSemaphore, numBlocksMax, numBlocksMax));
|
||||
}
|
||||
|
||||
for (i = 0; i < MTCODER__BLOCKS_MAX - 1; i++)
|
||||
p->freeBlockList[i] = i + 1;
|
||||
p->freeBlockList[MTCODER__BLOCKS_MAX - 1] = (unsigned)(int)-1;
|
||||
p->freeBlockHead = 0;
|
||||
|
||||
p->readProcessed = 0;
|
||||
p->blockIndex = 0;
|
||||
p->numBlocksMax = numBlocksMax;
|
||||
p->stopReading = False;
|
||||
|
||||
#ifndef MTCODER__USE_WRITE_THREAD
|
||||
p->writeIndex = 0;
|
||||
p->writeRes = SZ_OK;
|
||||
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
|
||||
p->ReadyBlocks[i] = False;
|
||||
p->numFinishedThreads = 0;
|
||||
#endif
|
||||
|
||||
p->numStartedThreadsLimit = numThreads;
|
||||
p->numStartedThreads = 0;
|
||||
|
||||
// for (i = 0; i < numThreads; i++)
|
||||
{
|
||||
CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++];
|
||||
RINOK(MtCoderThread_CreateAndStart(nextThread));
|
||||
}
|
||||
|
||||
RINOK_THREAD(Event_Set(&p->readEvent))
|
||||
|
||||
#ifdef MTCODER__USE_WRITE_THREAD
|
||||
{
|
||||
unsigned bi = 0;
|
||||
|
||||
for (;; bi++)
|
||||
{
|
||||
if (bi >= numBlocksMax)
|
||||
bi = 0;
|
||||
|
||||
RINOK_THREAD(Event_Wait(&p->writeEvents[bi]))
|
||||
|
||||
{
|
||||
const CMtCoderBlock *block = &p->blocks[bi];
|
||||
unsigned bufIndex = block->bufIndex;
|
||||
BoolInt finished = block->finished;
|
||||
if (res == SZ_OK && block->res != SZ_OK)
|
||||
res = block->res;
|
||||
|
||||
if (bufIndex != (unsigned)(int)-1)
|
||||
{
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
res = p->mtCallback->Write(p->mtCallbackObject, bufIndex);
|
||||
if (res != SZ_OK)
|
||||
MtProgress_SetError(&p->mtProgress, res);
|
||||
}
|
||||
|
||||
CriticalSection_Enter(&p->cs);
|
||||
{
|
||||
p->freeBlockList[bufIndex] = p->freeBlockHead;
|
||||
p->freeBlockHead = bufIndex;
|
||||
}
|
||||
CriticalSection_Leave(&p->cs);
|
||||
}
|
||||
|
||||
RINOK_THREAD(Semaphore_Release1(&p->blocksSemaphore))
|
||||
|
||||
if (finished)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
WRes wres = Event_Wait(&p->finishedEvent);
|
||||
res = MY_SRes_HRESULT_FROM_WRes(wres);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (res == SZ_OK)
|
||||
res = p->readRes;
|
||||
|
||||
if (res == SZ_OK)
|
||||
res = p->mtProgress.res;
|
||||
|
||||
#ifndef MTCODER__USE_WRITE_THREAD
|
||||
if (res == SZ_OK)
|
||||
res = p->writeRes;
|
||||
#endif
|
||||
|
||||
if (res != SZ_OK)
|
||||
MtCoder_Free(p);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
141
C/MtCoder.h
Normal file
141
C/MtCoder.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/* MtCoder.h -- Multi-thread Coder
|
||||
2018-07-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __MT_CODER_H
|
||||
#define __MT_CODER_H
|
||||
|
||||
#include "MtDec.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/*
|
||||
if ( defined MTCODER__USE_WRITE_THREAD) : main thread writes all data blocks to output stream
|
||||
if (not defined MTCODER__USE_WRITE_THREAD) : any coder thread can write data blocks to output stream
|
||||
*/
|
||||
/* #define MTCODER__USE_WRITE_THREAD */
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#define MTCODER__GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1)
|
||||
#define MTCODER__THREADS_MAX 64
|
||||
#define MTCODER__BLOCKS_MAX (MTCODER__GET_NUM_BLOCKS_FROM_THREADS(MTCODER__THREADS_MAX) + 3)
|
||||
#else
|
||||
#define MTCODER__THREADS_MAX 1
|
||||
#define MTCODER__BLOCKS_MAX 1
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ICompressProgress vt;
|
||||
CMtProgress *mtProgress;
|
||||
UInt64 inSize;
|
||||
UInt64 outSize;
|
||||
} CMtProgressThunk;
|
||||
|
||||
void MtProgressThunk_CreateVTable(CMtProgressThunk *p);
|
||||
|
||||
#define MtProgressThunk_Init(p) { (p)->inSize = 0; (p)->outSize = 0; }
|
||||
|
||||
|
||||
struct _CMtCoder;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct _CMtCoder *mtCoder;
|
||||
unsigned index;
|
||||
int stop;
|
||||
Byte *inBuf;
|
||||
|
||||
CAutoResetEvent startEvent;
|
||||
CThread thread;
|
||||
} CMtCoderThread;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Code)(void *p, unsigned coderIndex, unsigned outBufIndex,
|
||||
const Byte *src, size_t srcSize, int finished);
|
||||
SRes (*Write)(void *p, unsigned outBufIndex);
|
||||
} IMtCoderCallback2;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes res;
|
||||
unsigned bufIndex;
|
||||
BoolInt finished;
|
||||
} CMtCoderBlock;
|
||||
|
||||
|
||||
typedef struct _CMtCoder
|
||||
{
|
||||
/* input variables */
|
||||
|
||||
size_t blockSize; /* size of input block */
|
||||
unsigned numThreadsMax;
|
||||
UInt64 expectedDataSize;
|
||||
|
||||
ISeqInStream *inStream;
|
||||
const Byte *inData;
|
||||
size_t inDataSize;
|
||||
|
||||
ICompressProgress *progress;
|
||||
ISzAllocPtr allocBig;
|
||||
|
||||
IMtCoderCallback2 *mtCallback;
|
||||
void *mtCallbackObject;
|
||||
|
||||
|
||||
/* internal variables */
|
||||
|
||||
size_t allocatedBufsSize;
|
||||
|
||||
CAutoResetEvent readEvent;
|
||||
CSemaphore blocksSemaphore;
|
||||
|
||||
BoolInt stopReading;
|
||||
SRes readRes;
|
||||
|
||||
#ifdef MTCODER__USE_WRITE_THREAD
|
||||
CAutoResetEvent writeEvents[MTCODER__BLOCKS_MAX];
|
||||
#else
|
||||
CAutoResetEvent finishedEvent;
|
||||
SRes writeRes;
|
||||
unsigned writeIndex;
|
||||
Byte ReadyBlocks[MTCODER__BLOCKS_MAX];
|
||||
LONG numFinishedThreads;
|
||||
#endif
|
||||
|
||||
unsigned numStartedThreadsLimit;
|
||||
unsigned numStartedThreads;
|
||||
|
||||
unsigned numBlocksMax;
|
||||
unsigned blockIndex;
|
||||
UInt64 readProcessed;
|
||||
|
||||
CCriticalSection cs;
|
||||
|
||||
unsigned freeBlockHead;
|
||||
unsigned freeBlockList[MTCODER__BLOCKS_MAX];
|
||||
|
||||
CMtProgress mtProgress;
|
||||
CMtCoderBlock blocks[MTCODER__BLOCKS_MAX];
|
||||
CMtCoderThread threads[MTCODER__THREADS_MAX];
|
||||
} CMtCoder;
|
||||
|
||||
|
||||
void MtCoder_Construct(CMtCoder *p);
|
||||
void MtCoder_Destruct(CMtCoder *p);
|
||||
SRes MtCoder_Code(CMtCoder *p);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
201
C/MtDec.h
Normal file
201
C/MtDec.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/* MtDec.h -- Multi-thread Decoder
|
||||
2018-07-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __MT_DEC_H
|
||||
#define __MT_DEC_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#include "Threads.h"
|
||||
#endif
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#define MTDEC__THREADS_MAX 32
|
||||
#else
|
||||
#define MTDEC__THREADS_MAX 1
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ICompressProgress *progress;
|
||||
SRes res;
|
||||
UInt64 totalInSize;
|
||||
UInt64 totalOutSize;
|
||||
CCriticalSection cs;
|
||||
} CMtProgress;
|
||||
|
||||
void MtProgress_Init(CMtProgress *p, ICompressProgress *progress);
|
||||
SRes MtProgress_Progress_ST(CMtProgress *p);
|
||||
SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize);
|
||||
SRes MtProgress_GetError(CMtProgress *p);
|
||||
void MtProgress_SetError(CMtProgress *p, SRes res);
|
||||
|
||||
struct _CMtDec;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct _CMtDec *mtDec;
|
||||
unsigned index;
|
||||
void *inBuf;
|
||||
|
||||
size_t inDataSize_Start; // size of input data in start block
|
||||
UInt64 inDataSize; // total size of input data in all blocks
|
||||
|
||||
CThread thread;
|
||||
CAutoResetEvent canRead;
|
||||
CAutoResetEvent canWrite;
|
||||
void *allocaPtr;
|
||||
} CMtDecThread;
|
||||
|
||||
void MtDecThread_FreeInBufs(CMtDecThread *t);
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MTDEC_PARSE_CONTINUE, // continue this block with more input data
|
||||
MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread
|
||||
MTDEC_PARSE_NEW, // new block
|
||||
MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue)
|
||||
} EMtDecParseState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// in
|
||||
int startCall;
|
||||
const Byte *src;
|
||||
size_t srcSize;
|
||||
// in : (srcSize == 0) is allowed
|
||||
// out : it's allowed to return less that actually was used ?
|
||||
int srcFinished;
|
||||
|
||||
// out
|
||||
EMtDecParseState state;
|
||||
BoolInt canCreateNewThread;
|
||||
UInt64 outPos; // check it (size_t)
|
||||
} CMtDecCallbackInfo;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci);
|
||||
|
||||
// PreCode() and Code():
|
||||
// (SRes_return_result != SZ_OK) means stop decoding, no need another blocks
|
||||
SRes (*PreCode)(void *p, unsigned coderIndex);
|
||||
SRes (*Code)(void *p, unsigned coderIndex,
|
||||
const Byte *src, size_t srcSize, int srcFinished,
|
||||
UInt64 *inCodePos, UInt64 *outCodePos, int *stop);
|
||||
// stop - means stop another Code calls
|
||||
|
||||
|
||||
/* Write() must be called, if Parse() was called
|
||||
set (needWrite) if
|
||||
{
|
||||
&& (was not interrupted by progress)
|
||||
&& (was not interrupted in previous block)
|
||||
}
|
||||
|
||||
out:
|
||||
if (*needContinue), decoder still need to continue decoding with new iteration,
|
||||
even after MTDEC_PARSE_END
|
||||
if (*canRecode), we didn't flush current block data, so we still can decode current block later.
|
||||
*/
|
||||
SRes (*Write)(void *p, unsigned coderIndex,
|
||||
BoolInt needWriteToStream,
|
||||
const Byte *src, size_t srcSize,
|
||||
// int srcFinished,
|
||||
BoolInt *needContinue,
|
||||
BoolInt *canRecode);
|
||||
} IMtDecCallback;
|
||||
|
||||
|
||||
|
||||
typedef struct _CMtDec
|
||||
{
|
||||
/* input variables */
|
||||
|
||||
size_t inBufSize; /* size of input block */
|
||||
unsigned numThreadsMax;
|
||||
// size_t inBlockMax;
|
||||
unsigned numThreadsMax_2;
|
||||
|
||||
ISeqInStream *inStream;
|
||||
// const Byte *inData;
|
||||
// size_t inDataSize;
|
||||
|
||||
ICompressProgress *progress;
|
||||
ISzAllocPtr alloc;
|
||||
|
||||
IMtDecCallback *mtCallback;
|
||||
void *mtCallbackObject;
|
||||
|
||||
|
||||
/* internal variables */
|
||||
|
||||
size_t allocatedBufsSize;
|
||||
|
||||
BoolInt exitThread;
|
||||
WRes exitThreadWRes;
|
||||
|
||||
UInt64 blockIndex;
|
||||
BoolInt isAllocError;
|
||||
BoolInt overflow;
|
||||
SRes threadingErrorSRes;
|
||||
|
||||
BoolInt needContinue;
|
||||
|
||||
// CAutoResetEvent finishedEvent;
|
||||
|
||||
SRes readRes;
|
||||
SRes codeRes;
|
||||
|
||||
BoolInt wasInterrupted;
|
||||
|
||||
unsigned numStartedThreads_Limit;
|
||||
unsigned numStartedThreads;
|
||||
|
||||
Byte *crossBlock;
|
||||
size_t crossStart;
|
||||
size_t crossEnd;
|
||||
UInt64 readProcessed;
|
||||
BoolInt readWasFinished;
|
||||
UInt64 inProcessed;
|
||||
|
||||
unsigned filledThreadStart;
|
||||
unsigned numFilledThreads;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
BoolInt needInterrupt;
|
||||
UInt64 interruptIndex;
|
||||
CMtProgress mtProgress;
|
||||
CMtDecThread threads[MTDEC__THREADS_MAX];
|
||||
#endif
|
||||
} CMtDec;
|
||||
|
||||
|
||||
void MtDec_Construct(CMtDec *p);
|
||||
void MtDec_Destruct(CMtDec *p);
|
||||
|
||||
/*
|
||||
MtDec_Code() returns:
|
||||
SZ_OK - in most cases
|
||||
MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function
|
||||
*/
|
||||
|
||||
SRes MtDec_Code(CMtDec *p);
|
||||
Byte *MtDec_GetCrossBuff(CMtDec *p);
|
||||
|
||||
int MtDec_PrepareRead(CMtDec *p);
|
||||
const Byte *MtDec_Read(CMtDec *p, size_t *inLim);
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
85
C/Ppmd.h
Normal file
85
C/Ppmd.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* Ppmd.h -- PPMD codec common code
|
||||
2017-04-03 : Igor Pavlov : Public domain
|
||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
#ifndef __PPMD_H
|
||||
#define __PPMD_H
|
||||
|
||||
#include "CpuArch.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#ifdef MY_CPU_32BIT
|
||||
#define PPMD_32BIT
|
||||
#endif
|
||||
|
||||
#define PPMD_INT_BITS 7
|
||||
#define PPMD_PERIOD_BITS 7
|
||||
#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
|
||||
|
||||
#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
|
||||
#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
|
||||
#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
|
||||
#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
|
||||
|
||||
#define PPMD_N1 4
|
||||
#define PPMD_N2 4
|
||||
#define PPMD_N3 4
|
||||
#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
|
||||
#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */
|
||||
|
||||
/* SEE-contexts for PPM-contexts with masked symbols */
|
||||
typedef struct
|
||||
{
|
||||
UInt16 Summ; /* Freq */
|
||||
Byte Shift; /* Speed of Freq change; low Shift is for fast change */
|
||||
Byte Count; /* Count to next change of Shift */
|
||||
} CPpmd_See;
|
||||
|
||||
#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
|
||||
{ (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte Symbol;
|
||||
Byte Freq;
|
||||
UInt16 SuccessorLow;
|
||||
UInt16 SuccessorHigh;
|
||||
} CPpmd_State;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
CPpmd_State *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_State_Ref;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
void *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_Void_Ref;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
Byte *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_Byte_Ref;
|
||||
|
||||
#define PPMD_SetAllBitsIn256Bytes(p) \
|
||||
{ size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \
|
||||
p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }}
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
712
C/Ppmd7.c
Normal file
712
C/Ppmd7.c
Normal file
@@ -0,0 +1,712 @@
|
||||
/* Ppmd7.c -- PPMdH codec
|
||||
2018-07-04 : Igor Pavlov : Public domain
|
||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Ppmd7.h"
|
||||
|
||||
const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
|
||||
static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
|
||||
|
||||
#define MAX_FREQ 124
|
||||
#define UNIT_SIZE 12
|
||||
|
||||
#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
|
||||
#define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1])
|
||||
#define I2U(indx) (p->Indx2Units[indx])
|
||||
|
||||
#ifdef PPMD_32BIT
|
||||
#define REF(ptr) (ptr)
|
||||
#else
|
||||
#define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
|
||||
#endif
|
||||
|
||||
#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
|
||||
|
||||
#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
|
||||
#define STATS(ctx) Ppmd7_GetStats(p, ctx)
|
||||
#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
|
||||
#define SUFFIX(ctx) CTX((ctx)->Suffix)
|
||||
|
||||
typedef CPpmd7_Context * CTX_PTR;
|
||||
|
||||
struct CPpmd7_Node_;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
struct CPpmd7_Node_ *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd7_Node_Ref;
|
||||
|
||||
typedef struct CPpmd7_Node_
|
||||
{
|
||||
UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
|
||||
UInt16 NU;
|
||||
CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
|
||||
CPpmd7_Node_Ref Prev;
|
||||
} CPpmd7_Node;
|
||||
|
||||
#ifdef PPMD_32BIT
|
||||
#define NODE(ptr) (ptr)
|
||||
#else
|
||||
#define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
|
||||
#endif
|
||||
|
||||
void Ppmd7_Construct(CPpmd7 *p)
|
||||
{
|
||||
unsigned i, k, m;
|
||||
|
||||
p->Base = 0;
|
||||
|
||||
for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
|
||||
{
|
||||
unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
|
||||
do { p->Units2Indx[k++] = (Byte)i; } while (--step);
|
||||
p->Indx2Units[i] = (Byte)k;
|
||||
}
|
||||
|
||||
p->NS2BSIndx[0] = (0 << 1);
|
||||
p->NS2BSIndx[1] = (1 << 1);
|
||||
memset(p->NS2BSIndx + 2, (2 << 1), 9);
|
||||
memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
p->NS2Indx[i] = (Byte)i;
|
||||
for (m = i, k = 1; i < 256; i++)
|
||||
{
|
||||
p->NS2Indx[i] = (Byte)m;
|
||||
if (--k == 0)
|
||||
k = (++m) - 2;
|
||||
}
|
||||
|
||||
memset(p->HB2Flag, 0, 0x40);
|
||||
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
|
||||
}
|
||||
|
||||
void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc)
|
||||
{
|
||||
ISzAlloc_Free(alloc, p->Base);
|
||||
p->Size = 0;
|
||||
p->Base = 0;
|
||||
}
|
||||
|
||||
BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc)
|
||||
{
|
||||
if (!p->Base || p->Size != size)
|
||||
{
|
||||
size_t size2;
|
||||
Ppmd7_Free(p, alloc);
|
||||
size2 = 0
|
||||
#ifndef PPMD_32BIT
|
||||
+ UNIT_SIZE
|
||||
#endif
|
||||
;
|
||||
p->AlignOffset =
|
||||
#ifdef PPMD_32BIT
|
||||
(4 - size) & 3;
|
||||
#else
|
||||
4 - (size & 3);
|
||||
#endif
|
||||
if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size + size2)) == 0)
|
||||
return False;
|
||||
p->Size = size;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
|
||||
{
|
||||
*((CPpmd_Void_Ref *)node) = p->FreeList[indx];
|
||||
p->FreeList[indx] = REF(node);
|
||||
}
|
||||
|
||||
static void *RemoveNode(CPpmd7 *p, unsigned indx)
|
||||
{
|
||||
CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
|
||||
p->FreeList[indx] = *node;
|
||||
return node;
|
||||
}
|
||||
|
||||
static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
|
||||
{
|
||||
unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
|
||||
ptr = (Byte *)ptr + U2B(I2U(newIndx));
|
||||
if (I2U(i = U2I(nu)) != nu)
|
||||
{
|
||||
unsigned k = I2U(--i);
|
||||
InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
|
||||
}
|
||||
InsertNode(p, ptr, i);
|
||||
}
|
||||
|
||||
static void GlueFreeBlocks(CPpmd7 *p)
|
||||
{
|
||||
#ifdef PPMD_32BIT
|
||||
CPpmd7_Node headItem;
|
||||
CPpmd7_Node_Ref head = &headItem;
|
||||
#else
|
||||
CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
|
||||
#endif
|
||||
|
||||
CPpmd7_Node_Ref n = head;
|
||||
unsigned i;
|
||||
|
||||
p->GlueCount = 255;
|
||||
|
||||
/* create doubly-linked list of free blocks */
|
||||
for (i = 0; i < PPMD_NUM_INDEXES; i++)
|
||||
{
|
||||
UInt16 nu = I2U(i);
|
||||
CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
|
||||
p->FreeList[i] = 0;
|
||||
while (next != 0)
|
||||
{
|
||||
CPpmd7_Node *node = NODE(next);
|
||||
node->Next = n;
|
||||
n = NODE(n)->Prev = next;
|
||||
next = *(const CPpmd7_Node_Ref *)node;
|
||||
node->Stamp = 0;
|
||||
node->NU = (UInt16)nu;
|
||||
}
|
||||
}
|
||||
NODE(head)->Stamp = 1;
|
||||
NODE(head)->Next = n;
|
||||
NODE(n)->Prev = head;
|
||||
if (p->LoUnit != p->HiUnit)
|
||||
((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
|
||||
|
||||
/* Glue free blocks */
|
||||
while (n != head)
|
||||
{
|
||||
CPpmd7_Node *node = NODE(n);
|
||||
UInt32 nu = (UInt32)node->NU;
|
||||
for (;;)
|
||||
{
|
||||
CPpmd7_Node *node2 = NODE(n) + nu;
|
||||
nu += node2->NU;
|
||||
if (node2->Stamp != 0 || nu >= 0x10000)
|
||||
break;
|
||||
NODE(node2->Prev)->Next = node2->Next;
|
||||
NODE(node2->Next)->Prev = node2->Prev;
|
||||
node->NU = (UInt16)nu;
|
||||
}
|
||||
n = node->Next;
|
||||
}
|
||||
|
||||
/* Fill lists of free blocks */
|
||||
for (n = NODE(head)->Next; n != head;)
|
||||
{
|
||||
CPpmd7_Node *node = NODE(n);
|
||||
unsigned nu;
|
||||
CPpmd7_Node_Ref next = node->Next;
|
||||
for (nu = node->NU; nu > 128; nu -= 128, node += 128)
|
||||
InsertNode(p, node, PPMD_NUM_INDEXES - 1);
|
||||
if (I2U(i = U2I(nu)) != nu)
|
||||
{
|
||||
unsigned k = I2U(--i);
|
||||
InsertNode(p, node + k, nu - k - 1);
|
||||
}
|
||||
InsertNode(p, node, i);
|
||||
n = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
|
||||
{
|
||||
unsigned i;
|
||||
void *retVal;
|
||||
if (p->GlueCount == 0)
|
||||
{
|
||||
GlueFreeBlocks(p);
|
||||
if (p->FreeList[indx] != 0)
|
||||
return RemoveNode(p, indx);
|
||||
}
|
||||
i = indx;
|
||||
do
|
||||
{
|
||||
if (++i == PPMD_NUM_INDEXES)
|
||||
{
|
||||
UInt32 numBytes = U2B(I2U(indx));
|
||||
p->GlueCount--;
|
||||
return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
|
||||
}
|
||||
}
|
||||
while (p->FreeList[i] == 0);
|
||||
retVal = RemoveNode(p, i);
|
||||
SplitBlock(p, retVal, i, indx);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static void *AllocUnits(CPpmd7 *p, unsigned indx)
|
||||
{
|
||||
UInt32 numBytes;
|
||||
if (p->FreeList[indx] != 0)
|
||||
return RemoveNode(p, indx);
|
||||
numBytes = U2B(I2U(indx));
|
||||
if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
|
||||
{
|
||||
void *retVal = p->LoUnit;
|
||||
p->LoUnit += numBytes;
|
||||
return retVal;
|
||||
}
|
||||
return AllocUnitsRare(p, indx);
|
||||
}
|
||||
|
||||
#define MyMem12Cpy(dest, src, num) \
|
||||
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
|
||||
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while (--n); }
|
||||
|
||||
static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
|
||||
{
|
||||
unsigned i0 = U2I(oldNU);
|
||||
unsigned i1 = U2I(newNU);
|
||||
if (i0 == i1)
|
||||
return oldPtr;
|
||||
if (p->FreeList[i1] != 0)
|
||||
{
|
||||
void *ptr = RemoveNode(p, i1);
|
||||
MyMem12Cpy(ptr, oldPtr, newNU);
|
||||
InsertNode(p, oldPtr, i0);
|
||||
return ptr;
|
||||
}
|
||||
SplitBlock(p, oldPtr, i0, i1);
|
||||
return oldPtr;
|
||||
}
|
||||
|
||||
#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
|
||||
|
||||
static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
|
||||
{
|
||||
(p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
|
||||
(p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
static void RestartModel(CPpmd7 *p)
|
||||
{
|
||||
unsigned i, k, m;
|
||||
|
||||
memset(p->FreeList, 0, sizeof(p->FreeList));
|
||||
p->Text = p->Base + p->AlignOffset;
|
||||
p->HiUnit = p->Text + p->Size;
|
||||
p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
|
||||
p->GlueCount = 0;
|
||||
|
||||
p->OrderFall = p->MaxOrder;
|
||||
p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
|
||||
p->PrevSuccess = 0;
|
||||
|
||||
p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
|
||||
p->MinContext->Suffix = 0;
|
||||
p->MinContext->NumStats = 256;
|
||||
p->MinContext->SummFreq = 256 + 1;
|
||||
p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
|
||||
p->LoUnit += U2B(256 / 2);
|
||||
p->MinContext->Stats = REF(p->FoundState);
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
CPpmd_State *s = &p->FoundState[i];
|
||||
s->Symbol = (Byte)i;
|
||||
s->Freq = 1;
|
||||
SetSuccessor(s, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
for (k = 0; k < 8; k++)
|
||||
{
|
||||
UInt16 *dest = p->BinSumm[i] + k;
|
||||
UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
|
||||
for (m = 0; m < 64; m += 8)
|
||||
dest[m] = val;
|
||||
}
|
||||
|
||||
for (i = 0; i < 25; i++)
|
||||
for (k = 0; k < 16; k++)
|
||||
{
|
||||
CPpmd_See *s = &p->See[i][k];
|
||||
s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
|
||||
s->Count = 4;
|
||||
}
|
||||
}
|
||||
|
||||
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
|
||||
{
|
||||
p->MaxOrder = maxOrder;
|
||||
RestartModel(p);
|
||||
p->DummySee.Shift = PPMD_PERIOD_BITS;
|
||||
p->DummySee.Summ = 0; /* unused */
|
||||
p->DummySee.Count = 64; /* unused */
|
||||
}
|
||||
|
||||
static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip)
|
||||
{
|
||||
CPpmd_State upState;
|
||||
CTX_PTR c = p->MinContext;
|
||||
CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
|
||||
CPpmd_State *ps[PPMD7_MAX_ORDER];
|
||||
unsigned numPs = 0;
|
||||
|
||||
if (!skip)
|
||||
ps[numPs++] = p->FoundState;
|
||||
|
||||
while (c->Suffix)
|
||||
{
|
||||
CPpmd_Void_Ref successor;
|
||||
CPpmd_State *s;
|
||||
c = SUFFIX(c);
|
||||
if (c->NumStats != 1)
|
||||
{
|
||||
for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
|
||||
}
|
||||
else
|
||||
s = ONE_STATE(c);
|
||||
successor = SUCCESSOR(s);
|
||||
if (successor != upBranch)
|
||||
{
|
||||
c = CTX(successor);
|
||||
if (numPs == 0)
|
||||
return c;
|
||||
break;
|
||||
}
|
||||
ps[numPs++] = s;
|
||||
}
|
||||
|
||||
upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
|
||||
SetSuccessor(&upState, upBranch + 1);
|
||||
|
||||
if (c->NumStats == 1)
|
||||
upState.Freq = ONE_STATE(c)->Freq;
|
||||
else
|
||||
{
|
||||
UInt32 cf, s0;
|
||||
CPpmd_State *s;
|
||||
for (s = STATS(c); s->Symbol != upState.Symbol; s++);
|
||||
cf = s->Freq - 1;
|
||||
s0 = c->SummFreq - c->NumStats - cf;
|
||||
upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* Create Child */
|
||||
CTX_PTR c1; /* = AllocContext(p); */
|
||||
if (p->HiUnit != p->LoUnit)
|
||||
c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
|
||||
else if (p->FreeList[0] != 0)
|
||||
c1 = (CTX_PTR)RemoveNode(p, 0);
|
||||
else
|
||||
{
|
||||
c1 = (CTX_PTR)AllocUnitsRare(p, 0);
|
||||
if (!c1)
|
||||
return NULL;
|
||||
}
|
||||
c1->NumStats = 1;
|
||||
*ONE_STATE(c1) = upState;
|
||||
c1->Suffix = REF(c);
|
||||
SetSuccessor(ps[--numPs], REF(c1));
|
||||
c = c1;
|
||||
}
|
||||
while (numPs != 0);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
|
||||
{
|
||||
CPpmd_State tmp = *t1;
|
||||
*t1 = *t2;
|
||||
*t2 = tmp;
|
||||
}
|
||||
|
||||
static void UpdateModel(CPpmd7 *p)
|
||||
{
|
||||
CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
|
||||
CTX_PTR c;
|
||||
unsigned s0, ns;
|
||||
|
||||
if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
|
||||
{
|
||||
c = SUFFIX(p->MinContext);
|
||||
|
||||
if (c->NumStats == 1)
|
||||
{
|
||||
CPpmd_State *s = ONE_STATE(c);
|
||||
if (s->Freq < 32)
|
||||
s->Freq++;
|
||||
}
|
||||
else
|
||||
{
|
||||
CPpmd_State *s = STATS(c);
|
||||
if (s->Symbol != p->FoundState->Symbol)
|
||||
{
|
||||
do { s++; } while (s->Symbol != p->FoundState->Symbol);
|
||||
if (s[0].Freq >= s[-1].Freq)
|
||||
{
|
||||
SwapStates(&s[0], &s[-1]);
|
||||
s--;
|
||||
}
|
||||
}
|
||||
if (s->Freq < MAX_FREQ - 9)
|
||||
{
|
||||
s->Freq += 2;
|
||||
c->SummFreq += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p->OrderFall == 0)
|
||||
{
|
||||
p->MinContext = p->MaxContext = CreateSuccessors(p, True);
|
||||
if (p->MinContext == 0)
|
||||
{
|
||||
RestartModel(p);
|
||||
return;
|
||||
}
|
||||
SetSuccessor(p->FoundState, REF(p->MinContext));
|
||||
return;
|
||||
}
|
||||
|
||||
*p->Text++ = p->FoundState->Symbol;
|
||||
successor = REF(p->Text);
|
||||
if (p->Text >= p->UnitsStart)
|
||||
{
|
||||
RestartModel(p);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fSuccessor)
|
||||
{
|
||||
if (fSuccessor <= successor)
|
||||
{
|
||||
CTX_PTR cs = CreateSuccessors(p, False);
|
||||
if (cs == NULL)
|
||||
{
|
||||
RestartModel(p);
|
||||
return;
|
||||
}
|
||||
fSuccessor = REF(cs);
|
||||
}
|
||||
if (--p->OrderFall == 0)
|
||||
{
|
||||
successor = fSuccessor;
|
||||
p->Text -= (p->MaxContext != p->MinContext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSuccessor(p->FoundState, successor);
|
||||
fSuccessor = REF(p->MinContext);
|
||||
}
|
||||
|
||||
s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
|
||||
|
||||
for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
|
||||
{
|
||||
unsigned ns1;
|
||||
UInt32 cf, sf;
|
||||
if ((ns1 = c->NumStats) != 1)
|
||||
{
|
||||
if ((ns1 & 1) == 0)
|
||||
{
|
||||
/* Expand for one UNIT */
|
||||
unsigned oldNU = ns1 >> 1;
|
||||
unsigned i = U2I(oldNU);
|
||||
if (i != U2I((size_t)oldNU + 1))
|
||||
{
|
||||
void *ptr = AllocUnits(p, i + 1);
|
||||
void *oldPtr;
|
||||
if (!ptr)
|
||||
{
|
||||
RestartModel(p);
|
||||
return;
|
||||
}
|
||||
oldPtr = STATS(c);
|
||||
MyMem12Cpy(ptr, oldPtr, oldNU);
|
||||
InsertNode(p, oldPtr, i);
|
||||
c->Stats = STATS_REF(ptr);
|
||||
}
|
||||
}
|
||||
c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
|
||||
if (!s)
|
||||
{
|
||||
RestartModel(p);
|
||||
return;
|
||||
}
|
||||
*s = *ONE_STATE(c);
|
||||
c->Stats = REF(s);
|
||||
if (s->Freq < MAX_FREQ / 4 - 1)
|
||||
s->Freq <<= 1;
|
||||
else
|
||||
s->Freq = MAX_FREQ - 4;
|
||||
c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
|
||||
}
|
||||
cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
|
||||
sf = (UInt32)s0 + c->SummFreq;
|
||||
if (cf < 6 * sf)
|
||||
{
|
||||
cf = 1 + (cf > sf) + (cf >= 4 * sf);
|
||||
c->SummFreq += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
|
||||
c->SummFreq = (UInt16)(c->SummFreq + cf);
|
||||
}
|
||||
{
|
||||
CPpmd_State *s = STATS(c) + ns1;
|
||||
SetSuccessor(s, successor);
|
||||
s->Symbol = p->FoundState->Symbol;
|
||||
s->Freq = (Byte)cf;
|
||||
c->NumStats = (UInt16)(ns1 + 1);
|
||||
}
|
||||
}
|
||||
p->MaxContext = p->MinContext = CTX(fSuccessor);
|
||||
}
|
||||
|
||||
static void Rescale(CPpmd7 *p)
|
||||
{
|
||||
unsigned i, adder, sumFreq, escFreq;
|
||||
CPpmd_State *stats = STATS(p->MinContext);
|
||||
CPpmd_State *s = p->FoundState;
|
||||
{
|
||||
CPpmd_State tmp = *s;
|
||||
for (; s != stats; s--)
|
||||
s[0] = s[-1];
|
||||
*s = tmp;
|
||||
}
|
||||
escFreq = p->MinContext->SummFreq - s->Freq;
|
||||
s->Freq += 4;
|
||||
adder = (p->OrderFall != 0);
|
||||
s->Freq = (Byte)((s->Freq + adder) >> 1);
|
||||
sumFreq = s->Freq;
|
||||
|
||||
i = p->MinContext->NumStats - 1;
|
||||
do
|
||||
{
|
||||
escFreq -= (++s)->Freq;
|
||||
s->Freq = (Byte)((s->Freq + adder) >> 1);
|
||||
sumFreq += s->Freq;
|
||||
if (s[0].Freq > s[-1].Freq)
|
||||
{
|
||||
CPpmd_State *s1 = s;
|
||||
CPpmd_State tmp = *s1;
|
||||
do
|
||||
s1[0] = s1[-1];
|
||||
while (--s1 != stats && tmp.Freq > s1[-1].Freq);
|
||||
*s1 = tmp;
|
||||
}
|
||||
}
|
||||
while (--i);
|
||||
|
||||
if (s->Freq == 0)
|
||||
{
|
||||
unsigned numStats = p->MinContext->NumStats;
|
||||
unsigned n0, n1;
|
||||
do { i++; } while ((--s)->Freq == 0);
|
||||
escFreq += i;
|
||||
p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
|
||||
if (p->MinContext->NumStats == 1)
|
||||
{
|
||||
CPpmd_State tmp = *stats;
|
||||
do
|
||||
{
|
||||
tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
|
||||
escFreq >>= 1;
|
||||
}
|
||||
while (escFreq > 1);
|
||||
InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
|
||||
*(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
|
||||
return;
|
||||
}
|
||||
n0 = (numStats + 1) >> 1;
|
||||
n1 = (p->MinContext->NumStats + 1) >> 1;
|
||||
if (n0 != n1)
|
||||
p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
|
||||
}
|
||||
p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
|
||||
p->FoundState = STATS(p->MinContext);
|
||||
}
|
||||
|
||||
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
|
||||
{
|
||||
CPpmd_See *see;
|
||||
unsigned nonMasked = p->MinContext->NumStats - numMasked;
|
||||
if (p->MinContext->NumStats != 256)
|
||||
{
|
||||
see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] +
|
||||
(nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
|
||||
2 * (unsigned)(p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
|
||||
4 * (unsigned)(numMasked > nonMasked) +
|
||||
p->HiBitsFlag;
|
||||
{
|
||||
unsigned r = (see->Summ >> see->Shift);
|
||||
see->Summ = (UInt16)(see->Summ - r);
|
||||
*escFreq = r + (r == 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
see = &p->DummySee;
|
||||
*escFreq = 1;
|
||||
}
|
||||
return see;
|
||||
}
|
||||
|
||||
static void NextContext(CPpmd7 *p)
|
||||
{
|
||||
CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
|
||||
if (p->OrderFall == 0 && (Byte *)c > p->Text)
|
||||
p->MinContext = p->MaxContext = c;
|
||||
else
|
||||
UpdateModel(p);
|
||||
}
|
||||
|
||||
void Ppmd7_Update1(CPpmd7 *p)
|
||||
{
|
||||
CPpmd_State *s = p->FoundState;
|
||||
s->Freq += 4;
|
||||
p->MinContext->SummFreq += 4;
|
||||
if (s[0].Freq > s[-1].Freq)
|
||||
{
|
||||
SwapStates(&s[0], &s[-1]);
|
||||
p->FoundState = --s;
|
||||
if (s->Freq > MAX_FREQ)
|
||||
Rescale(p);
|
||||
}
|
||||
NextContext(p);
|
||||
}
|
||||
|
||||
void Ppmd7_Update1_0(CPpmd7 *p)
|
||||
{
|
||||
p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
|
||||
p->RunLength += p->PrevSuccess;
|
||||
p->MinContext->SummFreq += 4;
|
||||
if ((p->FoundState->Freq += 4) > MAX_FREQ)
|
||||
Rescale(p);
|
||||
NextContext(p);
|
||||
}
|
||||
|
||||
void Ppmd7_UpdateBin(CPpmd7 *p)
|
||||
{
|
||||
p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
|
||||
p->PrevSuccess = 1;
|
||||
p->RunLength++;
|
||||
NextContext(p);
|
||||
}
|
||||
|
||||
void Ppmd7_Update2(CPpmd7 *p)
|
||||
{
|
||||
p->MinContext->SummFreq += 4;
|
||||
if ((p->FoundState->Freq += 4) > MAX_FREQ)
|
||||
Rescale(p);
|
||||
p->RunLength = p->InitRL;
|
||||
UpdateModel(p);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user