aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSen Jiang <senj@google.com>2018-05-11 12:25:51 -0700
committerandroid-build-merger <android-build-merger@google.com>2018-05-11 12:25:51 -0700
commitbacc687a8cd280f007f4c5dad5c937563d772b20 (patch)
tree598a63536cfeda1e2c8d50a947bf33027be148b3
parent7ce54e6b08655cca0fa24cfe96ca113434158149 (diff)
parent9de96196e4ea41a6f2183d9cc41c6cba14687744 (diff)
downloadlzma-bacc687a8cd280f007f4c5dad5c937563d772b20.tar.gz
Merge "Update LZMA SDK to 18.05." am: 4267675b1e am: c9c6d76d19
am: 9de96196e4 Change-Id: Ic3f30a6fcdf9420edbec8074c1a66ed887e9f43b
-rw-r--r--Asm/x86/7zAsm.asm44
-rw-r--r--Asm/x86/LzmaDecOpt.asm1258
-rw-r--r--C/7z.h12
-rw-r--r--C/7zAlloc.c12
-rw-r--r--C/7zAlloc.h20
-rw-r--r--C/7zArcIn.c98
-rw-r--r--C/7zBuf.c12
-rw-r--r--C/7zBuf.h10
-rw-r--r--C/7zBuf2.c17
-rw-r--r--C/7zCrc.c16
-rw-r--r--C/7zCrcOpt.c50
-rw-r--r--C/7zDec.c54
-rw-r--r--C/7zFile.c26
-rw-r--r--C/7zFile.h8
-rw-r--r--C/7zStream.c111
-rw-r--r--C/7zTypes.h220
-rw-r--r--C/7zVersion.h22
-rw-r--r--C/Aes.c67
-rw-r--r--C/AesOpt.c4
-rw-r--r--C/Alloc.c399
-rw-r--r--C/Alloc.h20
-rw-r--r--C/Android.bp3
-rw-r--r--C/Bcj2.c13
-rw-r--r--C/Bcj2Enc.c5
-rw-r--r--C/Bra.c279
-rw-r--r--C/Bra86.c4
-rw-r--r--C/BraIA64.c82
-rw-r--r--C/Compiler.h3
-rw-r--r--C/CpuArch.h166
-rw-r--r--C/LzFind.c163
-rw-r--r--C/LzFind.h12
-rw-r--r--C/LzFindMt.c67
-rw-r--r--C/LzFindMt.h6
-rw-r--r--C/Lzma2Dec.c350
-rw-r--r--C/Lzma2Dec.h66
-rw-r--r--C/Lzma2DecMt.c1082
-rw-r--r--C/Lzma2DecMt.h79
-rw-r--r--C/Lzma2Enc.c677
-rw-r--r--C/Lzma2Enc.h45
-rw-r--r--C/LzmaDec.c401
-rw-r--r--C/LzmaDec.h47
-rw-r--r--C/LzmaEnc.c2334
-rw-r--r--C/LzmaEnc.h48
-rw-r--r--C/MtCoder.c710
-rw-r--r--C/MtCoder.h149
-rw-r--r--C/MtDec.c1137
-rw-r--r--C/MtDec.h201
-rw-r--r--C/Ppmd.h4
-rw-r--r--C/Ppmd7.c28
-rw-r--r--C/Ppmd7.h26
-rw-r--r--C/Ppmd7Dec.c34
-rw-r--r--C/Ppmd7Enc.c4
-rw-r--r--C/Sha256.c6
-rw-r--r--C/Threads.c14
-rw-r--r--C/Threads.h5
-rw-r--r--C/Util/7z/7zMain.c160
-rw-r--r--C/Util/Lzma/LzmaUtil.c40
-rw-r--r--C/Util/Lzma/LzmaUtil.dsp8
-rw-r--r--C/Util/SfxSetup/SfxSetup.c30
-rw-r--r--C/Util/SfxSetup/makefile1
-rw-r--r--C/Util/SfxSetup/makefile_con1
-rw-r--r--C/Xz.c18
-rw-r--r--C/Xz.h237
-rw-r--r--C/XzCrc64.c22
-rw-r--r--C/XzCrc64Opt.c30
-rw-r--r--C/XzDec.c2268
-rw-r--r--C/XzEnc.c1227
-rw-r--r--C/XzEnc.h27
-rw-r--r--C/XzIn.c60
-rw-r--r--CPP/7zip/Aes.mak2
-rw-r--r--CPP/7zip/Archive/7z/7zCompressionMode.h2
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.cpp66
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.h6
-rw-r--r--CPP/7zip/Archive/7z/7zEncode.cpp30
-rw-r--r--CPP/7zip/Archive/7z/7zExtract.cpp29
-rw-r--r--CPP/7zip/Archive/7z/7zFolderInStream.cpp15
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.cpp21
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.h40
-rw-r--r--CPP/7zip/Archive/7z/7zHandlerOut.cpp62
-rw-r--r--CPP/7zip/Archive/7z/7zIn.cpp138
-rw-r--r--CPP/7zip/Archive/7z/7zIn.h4
-rw-r--r--CPP/7zip/Archive/7z/7zItem.h47
-rw-r--r--CPP/7zip/Archive/7z/7zOut.cpp95
-rw-r--r--CPP/7zip/Archive/7z/7zOut.h32
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.cpp90
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2.cpp88
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2.h30
-rw-r--r--CPP/7zip/Archive/Common/HandlerOut.cpp165
-rw-r--r--CPP/7zip/Archive/Common/HandlerOut.h77
-rw-r--r--CPP/7zip/Archive/Common/ItemNameUtils.cpp78
-rw-r--r--CPP/7zip/Archive/Common/ItemNameUtils.h27
-rw-r--r--CPP/7zip/Archive/IArchive.h10
-rw-r--r--CPP/7zip/Archive/LzmaHandler.cpp78
-rw-r--r--CPP/7zip/Archive/SplitHandler.cpp2
-rw-r--r--CPP/7zip/Archive/XzHandler.cpp936
-rw-r--r--CPP/7zip/Archive/XzHandler.h54
-rw-r--r--CPP/7zip/Asm.mak2
-rw-r--r--CPP/7zip/Bundles/Alone7z/Alone.dsp92
-rw-r--r--CPP/7zip/Bundles/Alone7z/makefile9
-rw-r--r--CPP/7zip/Bundles/Alone7z/resource.rc4
-rw-r--r--CPP/7zip/Bundles/Format7zExtractR/makefile3
-rw-r--r--CPP/7zip/Bundles/Format7zR/makefile3
-rw-r--r--CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp47
-rw-r--r--CPP/7zip/Bundles/SFXCon/SFXCon.dsp34
-rw-r--r--CPP/7zip/Bundles/SFXCon/SfxCon.cpp32
-rw-r--r--CPP/7zip/Bundles/SFXCon/makefile6
-rw-r--r--CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp6
-rw-r--r--CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp6
-rw-r--r--CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp34
-rw-r--r--CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp24
-rw-r--r--CPP/7zip/Bundles/SFXSetup/makefile7
-rw-r--r--CPP/7zip/Bundles/SFXWin/SFXWin.dsp26
-rw-r--r--CPP/7zip/Bundles/SFXWin/SfxWin.cpp2
-rw-r--r--CPP/7zip/Bundles/SFXWin/makefile6
-rw-r--r--CPP/7zip/Common/CWrappers.cpp126
-rw-r--r--CPP/7zip/Common/CWrappers.h28
-rw-r--r--CPP/7zip/Common/CreateCoder.cpp113
-rw-r--r--CPP/7zip/Common/CreateCoder.h26
-rw-r--r--CPP/7zip/Common/FilePathAutoRename.cpp9
-rw-r--r--CPP/7zip/Common/FilterCoder.h9
-rw-r--r--CPP/7zip/Common/InBuffer.cpp28
-rw-r--r--CPP/7zip/Common/InBuffer.h4
-rw-r--r--CPP/7zip/Common/InOutTempBuffer.cpp2
-rw-r--r--CPP/7zip/Common/MethodProps.cpp75
-rw-r--r--CPP/7zip/Common/MethodProps.h86
-rw-r--r--CPP/7zip/Common/OutBuffer.h7
-rw-r--r--CPP/7zip/Compress/Bcj2Coder.cpp12
-rw-r--r--CPP/7zip/Compress/Bcj2Coder.h5
-rw-r--r--CPP/7zip/Compress/CopyCoder.cpp5
-rw-r--r--CPP/7zip/Compress/CopyCoder.h5
-rw-r--r--CPP/7zip/Compress/Lzma2Decoder.cpp391
-rw-r--r--CPP/7zip/Compress/Lzma2Decoder.h66
-rw-r--r--CPP/7zip/Compress/Lzma2Encoder.cpp65
-rw-r--r--CPP/7zip/Compress/Lzma2Encoder.h8
-rw-r--r--CPP/7zip/Compress/LzmaDecoder.cpp301
-rw-r--r--CPP/7zip/Compress/LzmaDecoder.h50
-rw-r--r--CPP/7zip/Compress/LzmaEncoder.cpp54
-rw-r--r--CPP/7zip/Compress/LzmaEncoder.h10
-rw-r--r--CPP/7zip/Compress/PpmdDecoder.cpp9
-rw-r--r--CPP/7zip/Compress/PpmdDecoder.h26
-rw-r--r--CPP/7zip/Compress/PpmdEncoder.cpp2
-rw-r--r--CPP/7zip/Compress/XzDecoder.cpp150
-rw-r--r--CPP/7zip/Compress/XzDecoder.h92
-rw-r--r--CPP/7zip/Compress/XzEncoder.cpp245
-rw-r--r--CPP/7zip/Compress/XzEncoder.h46
-rw-r--r--CPP/7zip/Crc.mak2
-rw-r--r--CPP/7zip/Crc64.mak2
-rw-r--r--CPP/7zip/Crypto/MyAes.h2
-rw-r--r--CPP/7zip/GuiCommon.rc3
-rw-r--r--CPP/7zip/Guid.txt4
-rw-r--r--CPP/7zip/ICoder.h60
-rw-r--r--CPP/7zip/LzmaDec.mak5
-rw-r--r--CPP/7zip/UI/Client7z/Client7z.cpp163
-rw-r--r--CPP/7zip/UI/Client7z/Client7z.dsp2
-rw-r--r--CPP/7zip/UI/Client7z/resource.rc2
-rw-r--r--CPP/7zip/UI/Common/ArchiveCommandLine.cpp278
-rw-r--r--CPP/7zip/UI/Common/ArchiveCommandLine.h21
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.cpp266
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.h73
-rw-r--r--CPP/7zip/UI/Common/ArchiveName.cpp2
-rw-r--r--CPP/7zip/UI/Common/Bench.cpp532
-rw-r--r--CPP/7zip/UI/Common/Bench.h17
-rw-r--r--CPP/7zip/UI/Common/DirItem.h35
-rw-r--r--CPP/7zip/UI/Common/EnumDirItems.cpp208
-rw-r--r--CPP/7zip/UI/Common/EnumDirItems.h20
-rw-r--r--CPP/7zip/UI/Common/Extract.cpp20
-rw-r--r--CPP/7zip/UI/Common/ExtractingFilePath.cpp87
-rw-r--r--CPP/7zip/UI/Common/ExtractingFilePath.h14
-rw-r--r--CPP/7zip/UI/Common/HashCalc.cpp8
-rw-r--r--CPP/7zip/UI/Common/HashCalc.h1
-rw-r--r--CPP/7zip/UI/Common/LoadCodecs.cpp26
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.cpp48
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.h19
-rw-r--r--CPP/7zip/UI/Common/PropIDUtils.cpp230
-rw-r--r--CPP/7zip/UI/Common/PropIDUtils.h4
-rw-r--r--CPP/7zip/UI/Common/Update.cpp274
-rw-r--r--CPP/7zip/UI/Common/Update.h2
-rw-r--r--CPP/7zip/UI/Common/UpdateCallback.cpp26
-rw-r--r--CPP/7zip/UI/Common/UpdateCallback.h17
-rw-r--r--CPP/7zip/UI/Common/UpdatePair.cpp9
-rw-r--r--CPP/7zip/UI/Common/UpdateProduce.cpp2
-rw-r--r--CPP/7zip/UI/Common/ZipRegistry.h7
-rw-r--r--CPP/7zip/UI/Console/Console.manifest13
-rw-r--r--CPP/7zip/UI/Console/ExtractCallbackConsole.cpp161
-rw-r--r--CPP/7zip/UI/Console/HashCon.cpp8
-rw-r--r--CPP/7zip/UI/Console/List.cpp127
-rw-r--r--CPP/7zip/UI/Console/Main.cpp119
-rw-r--r--CPP/7zip/UI/Console/MainAr.cpp14
-rw-r--r--CPP/7zip/UI/Console/OpenCallbackConsole.cpp12
-rw-r--r--CPP/7zip/UI/Console/OpenCallbackConsole.h7
-rw-r--r--CPP/7zip/UI/Console/PercentPrinter.cpp8
-rw-r--r--CPP/7zip/UI/Console/UpdateCallbackConsole.cpp68
-rw-r--r--CPP/7zip/UI/Console/UserInputUtils.cpp44
-rw-r--r--CPP/7zip/UI/Console/UserInputUtils.h7
-rw-r--r--CPP/7zip/UI/Console/resource.rc6
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog.cpp37
-rw-r--r--CPP/7zip/UI/FileManager/ExtractCallback.cpp28
-rw-r--r--CPP/7zip/UI/FileManager/OverwriteDialog.cpp15
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.cpp56
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.h70
-rw-r--r--CPP/7zip/UI/FileManager/resource.h2
-rw-r--r--CPP/7zip/UI/GUI/ExtractDialog.cpp6
-rw-r--r--CPP/7zip/UI/GUI/ExtractGUI.cpp80
-rw-r--r--CPP/7zip/UI/GUI/HashGUI.h11
-rw-r--r--CPP/Build.mak48
-rw-r--r--CPP/Common/ComTry.h6
-rw-r--r--CPP/Common/CommandLineParser.cpp54
-rw-r--r--CPP/Common/CommandLineParser.h10
-rw-r--r--CPP/Common/Common.h32
-rw-r--r--CPP/Common/IntToString.cpp57
-rw-r--r--CPP/Common/IntToString.h4
-rw-r--r--CPP/Common/Lang.h2
-rw-r--r--CPP/Common/ListFileUtils.cpp6
-rw-r--r--CPP/Common/MyBuffer.h25
-rw-r--r--CPP/Common/MyBuffer2.h45
-rw-r--r--CPP/Common/MyCom.h21
-rw-r--r--CPP/Common/MyString.cpp259
-rw-r--r--CPP/Common/MyString.h181
-rw-r--r--CPP/Common/MyVector.h30
-rw-r--r--CPP/Common/MyWindows.h15
-rw-r--r--CPP/Common/NewHandler.cpp2
-rw-r--r--CPP/Common/NewHandler.h51
-rw-r--r--CPP/Common/StdInStream.cpp65
-rw-r--r--CPP/Common/StdInStream.h13
-rw-r--r--CPP/Common/StdOutStream.cpp65
-rw-r--r--CPP/Common/StdOutStream.h11
-rw-r--r--CPP/Common/StringConvert.cpp6
-rw-r--r--CPP/Common/StringConvert.h123
-rw-r--r--CPP/Common/TextConfig.cpp8
-rw-r--r--CPP/Common/TextConfig.h4
-rw-r--r--CPP/Common/Wildcard.cpp28
-rw-r--r--CPP/Common/Wildcard.h2
-rw-r--r--CPP/Common/XzCrc64Init.cpp7
-rw-r--r--CPP/Windows/Control/Dialog.cpp1
-rw-r--r--CPP/Windows/Control/Dialog.h3
-rw-r--r--CPP/Windows/Control/PropertyPage.cpp2
-rw-r--r--CPP/Windows/DLL.cpp7
-rw-r--r--CPP/Windows/ErrorMsg.cpp4
-rw-r--r--CPP/Windows/FileDir.cpp50
-rw-r--r--CPP/Windows/FileDir.h13
-rw-r--r--CPP/Windows/FileFind.cpp16
-rw-r--r--CPP/Windows/FileFind.h2
-rw-r--r--CPP/Windows/FileIO.h13
-rw-r--r--CPP/Windows/FileLink.cpp16
-rw-r--r--CPP/Windows/FileName.cpp24
-rw-r--r--CPP/Windows/FileName.h6
-rw-r--r--CPP/Windows/MemoryLock.cpp25
-rw-r--r--CPP/Windows/MemoryLock.h2
-rw-r--r--CPP/Windows/PropVariant.cpp2
-rw-r--r--CPP/Windows/PropVariant.h2
-rw-r--r--CPP/Windows/PropVariantConv.cpp79
-rw-r--r--CPP/Windows/PropVariantConv.h11
-rw-r--r--CPP/Windows/Registry.cpp2
-rw-r--r--CPP/Windows/Shell.cpp4
-rw-r--r--CPP/Windows/System.cpp30
-rw-r--r--CPP/Windows/System.h23
-rw-r--r--CPP/Windows/TimeUtils.cpp16
-rw-r--r--CPP/Windows/TimeUtils.h8
-rw-r--r--DOC/Methods.txt16
-rw-r--r--DOC/lzma-history.txt61
-rw-r--r--DOC/lzma-sdk.txt2
-rw-r--r--DOC/lzma.txt8
263 files changed, 18671 insertions, 5830 deletions
diff --git a/Asm/x86/7zAsm.asm b/Asm/x86/7zAsm.asm
index 53a9e3f..8c30d7b 100644
--- a/Asm/x86/7zAsm.asm
+++ b/Asm/x86/7zAsm.asm
@@ -1,5 +1,5 @@
; 7zAsm.asm -- ASM macros
-; 2012-12-30 : Igor Pavlov : Public domain
+; 2018-02-03 : Igor Pavlov : Public domain
MY_ASM_START macro
ifdef x64
@@ -52,6 +52,15 @@ endif
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
@@ -63,6 +72,10 @@ endif
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
@@ -103,3 +116,32 @@ MY_POP_4_REGS macro
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
diff --git a/Asm/x86/LzmaDecOpt.asm b/Asm/x86/LzmaDecOpt.asm
new file mode 100644
index 0000000..0a89eb7
--- /dev/null
+++ b/Asm/x86/LzmaDecOpt.asm
@@ -0,0 +1,1258 @@
+; LzmaDecOpt.asm -- ASM version of LzmaDec_DecodeReal_3() function
+; 2018-02-06: Igor Pavlov : Public domain
+;
+; 3 - is the code compatibility version of LzmaDec_DecodeReal_*()
+; function for check at link time.
+; That code is tightly coupled with LzmaDec_TryDummy()
+; and with another functions in LzmaDec.c file.
+; CLzmaDec structure, (probs) array layout, input and output of
+; LzmaDec_DecodeReal_*() must be equal in both versions (C / ASM).
+
+ifndef x64
+; x64=1
+; .err <x64_IS_REQUIRED>
+endif
+
+include 7zAsm.asm
+
+MY_ASM_START
+
+_TEXT$LZMADECOPT SEGMENT ALIGN(64) 'CODE'
+
+MY_ALIGN macro num:req
+ align num
+endm
+
+MY_ALIGN_16 macro
+ MY_ALIGN 16
+endm
+
+MY_ALIGN_32 macro
+ MY_ALIGN 32
+endm
+
+MY_ALIGN_64 macro
+ MY_ALIGN 64
+endm
+
+
+; _LZMA_SIZE_OPT equ 1
+
+; _LZMA_PROB32 equ 1
+
+ifdef _LZMA_PROB32
+ PSHIFT equ 2
+ PLOAD macro dest, mem
+ mov dest, dword ptr [mem]
+ endm
+ PSTORE macro src, mem
+ mov dword ptr [mem], src
+ endm
+else
+ PSHIFT equ 1
+ PLOAD macro dest, mem
+ movzx dest, word ptr [mem]
+ endm
+ PSTORE macro src, mem
+ mov word ptr [mem], @CatStr(src, _W)
+ endm
+endif
+
+PMULT equ (1 SHL PSHIFT)
+PMULT_HALF equ (1 SHL (PSHIFT - 1))
+PMULT_2 equ (1 SHL (PSHIFT + 1))
+
+
+; x0 range
+; x1 pbPos / (prob) TREE
+; x2 probBranch / prm (MATCHED) / pbPos / cnt
+; x3 sym
+;====== r4 === RSP
+; x5 cod
+; x6 t1 NORM_CALC / probs_state / dist
+; x7 t0 NORM_CALC / prob2 IF_BIT_1
+; x8 state
+; x9 match (MATCHED) / sym2 / dist2 / lpMask_reg
+; x10 kBitModelTotal_reg
+; r11 probs
+; x12 offs (MATCHED) / dic / len_temp
+; x13 processedPos
+; x14 bit (MATCHED) / dicPos
+; r15 buf
+
+
+cod equ x5
+cod_L equ x5_L
+range equ x0
+state equ x8
+state_R equ r8
+buf equ r15
+processedPos equ x13
+kBitModelTotal_reg equ x10
+
+probBranch equ x2
+probBranch_R equ r2
+probBranch_W equ x2_W
+
+pbPos equ x1
+pbPos_R equ r1
+
+cnt equ x2
+cnt_R equ r2
+
+lpMask_reg equ x9
+dicPos equ r14
+
+sym equ x3
+sym_R equ r3
+sym_L equ x3_L
+
+probs equ r11
+dic equ r12
+
+t0 equ x7
+t0_W equ x7_W
+t0_R equ r7
+
+prob2 equ t0
+prob2_W equ t0_W
+
+t1 equ x6
+t1_R equ r6
+
+probs_state equ t1
+probs_state_R equ t1_R
+
+prm equ r2
+match equ x9
+match_R equ r9
+offs equ x12
+offs_R equ r12
+bit equ x14
+bit_R equ r14
+
+sym2 equ x9
+sym2_R equ r9
+
+len_temp equ x12
+
+dist equ sym
+dist2 equ x9
+
+
+
+kNumBitModelTotalBits equ 11
+kBitModelTotal equ (1 SHL kNumBitModelTotalBits)
+kNumMoveBits equ 5
+kBitModelOffset equ ((1 SHL kNumMoveBits) - 1)
+kTopValue equ (1 SHL 24)
+
+NORM_2 macro
+ ; movzx t0, BYTE PTR [buf]
+ shl cod, 8
+ mov cod_L, BYTE PTR [buf]
+ shl range, 8
+ ; or cod, t0
+ inc buf
+endm
+
+
+NORM macro
+ cmp range, kTopValue
+ jae SHORT @F
+ NORM_2
+@@:
+endm
+
+
+; ---------- Branch MACROS ----------
+
+UPDATE_0 macro probsArray:req, probOffset:req, probDisp:req
+ mov prob2, kBitModelTotal_reg
+ sub prob2, probBranch
+ shr prob2, kNumMoveBits
+ add probBranch, prob2
+ PSTORE probBranch, probOffset * 1 + probsArray + probDisp * PMULT
+endm
+
+
+UPDATE_1 macro probsArray:req, probOffset:req, probDisp:req
+ sub prob2, range
+ sub cod, range
+ mov range, prob2
+ mov prob2, probBranch
+ shr probBranch, kNumMoveBits
+ sub prob2, probBranch
+ PSTORE prob2, probOffset * 1 + probsArray + probDisp * PMULT
+endm
+
+
+CMP_COD macro probsArray:req, probOffset:req, probDisp:req
+ PLOAD probBranch, probOffset * 1 + probsArray + probDisp * PMULT
+ NORM
+ mov prob2, range
+ shr range, kNumBitModelTotalBits
+ imul range, probBranch
+ cmp cod, range
+endm
+
+
+IF_BIT_1_NOUP macro probsArray:req, probOffset:req, probDisp:req, toLabel:req
+ CMP_COD probsArray, probOffset, probDisp
+ jae toLabel
+endm
+
+
+IF_BIT_1 macro probsArray:req, probOffset:req, probDisp:req, toLabel:req
+ IF_BIT_1_NOUP probsArray, probOffset, probDisp, toLabel
+ UPDATE_0 probsArray, probOffset, probDisp
+endm
+
+
+IF_BIT_0_NOUP macro probsArray:req, probOffset:req, probDisp:req, toLabel:req
+ CMP_COD probsArray, probOffset, probDisp
+ jb toLabel
+endm
+
+
+; ---------- CMOV MACROS ----------
+
+NORM_CALC macro prob:req
+ NORM
+ mov t0, range
+ shr range, kNumBitModelTotalBits
+ imul range, prob
+ sub t0, range
+ mov t1, cod
+ sub cod, range
+endm
+
+
+PUP macro prob:req, probPtr:req
+ sub t0, prob
+ ; only sar works for both 16/32 bit prob modes
+ sar t0, kNumMoveBits
+ add t0, prob
+ PSTORE t0, probPtr
+endm
+
+
+PUP_SUB macro prob:req, probPtr:req, symSub:req
+ sbb sym, symSub
+ PUP prob, probPtr
+endm
+
+
+PUP_COD macro prob:req, probPtr:req, symSub:req
+ mov t0, kBitModelOffset
+ cmovb cod, t1
+ mov t1, sym
+ cmovb t0, kBitModelTotal_reg
+ PUP_SUB prob, probPtr, symSub
+endm
+
+
+BIT_0 macro prob:req, probNext:req
+ PLOAD prob, probs + 1 * PMULT
+ PLOAD probNext, probs + 1 * PMULT_2
+
+ NORM_CALC prob
+
+ cmovae range, t0
+ PLOAD t0, probs + 1 * PMULT_2 + PMULT
+ cmovae probNext, t0
+ mov t0, kBitModelOffset
+ cmovb cod, t1
+ cmovb t0, kBitModelTotal_reg
+ mov sym, 2
+ PUP_SUB prob, probs + 1 * PMULT, 0 - 1
+endm
+
+
+BIT_1 macro prob:req, probNext:req
+ PLOAD probNext, probs + sym_R * PMULT_2
+ add sym, sym
+
+ NORM_CALC prob
+
+ cmovae range, t0
+ PLOAD t0, probs + sym_R * PMULT + PMULT
+ cmovae probNext, t0
+ PUP_COD prob, probs + t1_R * PMULT_HALF, 0 - 1
+endm
+
+
+BIT_2 macro prob:req, symSub:req
+ add sym, sym
+
+ NORM_CALC prob
+
+ cmovae range, t0
+ PUP_COD prob, probs + t1_R * PMULT_HALF, symSub
+endm
+
+
+; ---------- MATCHED LITERAL ----------
+
+LITM_0 macro
+ mov offs, 256 * PMULT
+ shl match, (PSHIFT + 1)
+ mov bit, offs
+ and bit, match
+ PLOAD x1, probs + 256 * PMULT + bit_R * 1 + 1 * PMULT
+ lea prm, [probs + 256 * PMULT + bit_R * 1 + 1 * PMULT]
+ ; lea prm, [probs + 256 * PMULT + 1 * PMULT]
+ ; add prm, bit_R
+ xor offs, bit
+ add match, match
+
+ NORM_CALC x1
+
+ cmovae offs, bit
+ mov bit, match
+ cmovae range, t0
+ mov t0, kBitModelOffset
+ cmovb cod, t1
+ cmovb t0, kBitModelTotal_reg
+ mov sym, 0
+ PUP_SUB x1, prm, -2-1
+endm
+
+
+LITM macro
+ and bit, offs
+ lea prm, [probs + offs_R * 1]
+ add prm, bit_R
+ PLOAD x1, prm + sym_R * PMULT
+ xor offs, bit
+ add sym, sym
+ add match, match
+
+ NORM_CALC x1
+
+ cmovae offs, bit
+ mov bit, match
+ cmovae range, t0
+ PUP_COD x1, prm + t1_R * PMULT_HALF, - 1
+endm
+
+
+LITM_2 macro
+ and bit, offs
+ lea prm, [probs + offs_R * 1]
+ add prm, bit_R
+ PLOAD x1, prm + sym_R * PMULT
+ add sym, sym
+
+ NORM_CALC x1
+
+ cmovae range, t0
+ PUP_COD x1, prm + t1_R * PMULT_HALF, 256 - 1
+endm
+
+
+; ---------- REVERSE BITS ----------
+
+REV_0 macro prob:req, probNext:req
+ ; PLOAD prob, probs + 1 * PMULT
+ ; lea sym2_R, [probs + 2 * PMULT]
+ ; PLOAD probNext, probs + 2 * PMULT
+ PLOAD probNext, sym2_R
+
+ NORM_CALC prob
+
+ cmovae range, t0
+ PLOAD t0, probs + 3 * PMULT
+ cmovae probNext, t0
+ cmovb cod, t1
+ mov t0, kBitModelOffset
+ cmovb t0, kBitModelTotal_reg
+ lea t1_R, [probs + 3 * PMULT]
+ cmovae sym2_R, t1_R
+ PUP prob, probs + 1 * PMULT
+endm
+
+
+REV_1 macro prob:req, probNext:req, step:req
+ add sym2_R, step * PMULT
+ PLOAD probNext, sym2_R
+
+ NORM_CALC prob
+
+ cmovae range, t0
+ PLOAD t0, sym2_R + step * PMULT
+ cmovae probNext, t0
+ cmovb cod, t1
+ mov t0, kBitModelOffset
+ cmovb t0, kBitModelTotal_reg
+ lea t1_R, [sym2_R + step * PMULT]
+ cmovae sym2_R, t1_R
+ PUP prob, t1_R - step * PMULT_2
+endm
+
+
+REV_2 macro prob:req, step:req
+ sub sym2_R, probs
+ shr sym2, PSHIFT
+ or sym, sym2
+
+ NORM_CALC prob
+
+ cmovae range, t0
+ lea t0, [sym - step]
+ cmovb sym, t0
+ cmovb cod, t1
+ mov t0, kBitModelOffset
+ cmovb t0, kBitModelTotal_reg
+ PUP prob, probs + sym2_R * PMULT
+endm
+
+
+REV_1_VAR macro prob:req
+ PLOAD prob, sym_R
+ mov probs, sym_R
+ add sym_R, sym2_R
+
+ NORM_CALC prob
+
+ cmovae range, t0
+ lea t0_R, [sym_R + sym2_R]
+ cmovae sym_R, t0_R
+ mov t0, kBitModelOffset
+ cmovb cod, t1
+ ; mov t1, kBitModelTotal
+ ; cmovb t0, t1
+ cmovb t0, kBitModelTotal_reg
+ add sym2, sym2
+ PUP prob, probs
+endm
+
+
+
+
+LIT_PROBS macro lpMaskParam:req
+ ; prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc);
+ mov t0, processedPos
+ shl t0, 8
+ add sym, t0
+ and sym, lpMaskParam
+ add probs_state_R, pbPos_R
+ mov x1, LOC lc2
+ lea sym, dword ptr[sym_R + 2 * sym_R]
+ add probs, Literal * PMULT
+ shl sym, x1_L
+ add probs, sym_R
+ UPDATE_0 probs_state_R, 0, IsMatch
+ inc processedPos
+endm
+
+
+
+kNumPosBitsMax equ 4
+kNumPosStatesMax equ (1 SHL kNumPosBitsMax)
+
+kLenNumLowBits equ 3
+kLenNumLowSymbols equ (1 SHL kLenNumLowBits)
+kLenNumHighBits equ 8
+kLenNumHighSymbols equ (1 SHL kLenNumHighBits)
+kNumLenProbs equ (2 * kLenNumLowSymbols * kNumPosStatesMax + kLenNumHighSymbols)
+
+LenLow equ 0
+LenChoice equ LenLow
+LenChoice2 equ (LenLow + kLenNumLowSymbols)
+LenHigh equ (LenLow + 2 * kLenNumLowSymbols * kNumPosStatesMax)
+
+kNumStates equ 12
+kNumStates2 equ 16
+kNumLitStates equ 7
+
+kStartPosModelIndex equ 4
+kEndPosModelIndex equ 14
+kNumFullDistances equ (1 SHL (kEndPosModelIndex SHR 1))
+
+kNumPosSlotBits equ 6
+kNumLenToPosStates equ 4
+
+kNumAlignBits equ 4
+kAlignTableSize equ (1 SHL kNumAlignBits)
+
+kMatchMinLen equ 2
+kMatchSpecLenStart equ (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols)
+
+kStartOffset equ 1664
+SpecPos equ (-kStartOffset)
+IsRep0Long equ (SpecPos + kNumFullDistances)
+RepLenCoder equ (IsRep0Long + (kNumStates2 SHL kNumPosBitsMax))
+LenCoder equ (RepLenCoder + kNumLenProbs)
+IsMatch equ (LenCoder + kNumLenProbs)
+kAlign equ (IsMatch + (kNumStates2 SHL kNumPosBitsMax))
+IsRep equ (kAlign + kAlignTableSize)
+IsRepG0 equ (IsRep + kNumStates)
+IsRepG1 equ (IsRepG0 + kNumStates)
+IsRepG2 equ (IsRepG1 + kNumStates)
+PosSlot equ (IsRepG2 + kNumStates)
+Literal equ (PosSlot + (kNumLenToPosStates SHL kNumPosSlotBits))
+NUM_BASE_PROBS equ (Literal + kStartOffset)
+
+if kAlign ne 0
+ .err <Stop_Compiling_Bad_LZMA_kAlign>
+endif
+
+if NUM_BASE_PROBS ne 1984
+ .err <Stop_Compiling_Bad_LZMA_PROBS>
+endif
+
+
+PTR_FIELD equ dq ?
+
+CLzmaDec_Asm struct
+ lc db ?
+ lp db ?
+ pb db ?
+ _pad_ db ?
+ dicSize dd ?
+
+ probs_Spec PTR_FIELD
+ probs_1664 PTR_FIELD
+ dic_Spec PTR_FIELD
+ dicBufSize PTR_FIELD
+ dicPos_Spec PTR_FIELD
+ buf_Spec PTR_FIELD
+
+ range_Spec dd ?
+ code_Spec dd ?
+ processedPos_Spec dd ?
+ checkDicSize dd ?
+ rep0 dd ?
+ rep1 dd ?
+ rep2 dd ?
+ rep3 dd ?
+ state_Spec dd ?
+ remainLen dd ?
+CLzmaDec_Asm ends
+
+
+CLzmaDec_Asm_Loc struct
+ OLD_RSP PTR_FIELD
+ lzmaPtr PTR_FIELD
+ _pad0_ PTR_FIELD
+ _pad1_ PTR_FIELD
+ _pad2_ PTR_FIELD
+ dicBufSize PTR_FIELD
+ probs_Spec PTR_FIELD
+ dic_Spec PTR_FIELD
+
+ limit PTR_FIELD
+ bufLimit PTR_FIELD
+ lc2 dd ?
+ lpMask dd ?
+ pbMask dd ?
+ checkDicSize dd ?
+
+ _pad_ dd ?
+ remainLen dd ?
+ dicPos_Spec PTR_FIELD
+ rep0 dd ?
+ rep1 dd ?
+ rep2 dd ?
+ rep3 dd ?
+CLzmaDec_Asm_Loc ends
+
+
+GLOB_2 equ [sym_R].CLzmaDec_Asm.
+GLOB equ [r1].CLzmaDec_Asm.
+LOC_0 equ [r0].CLzmaDec_Asm_Loc.
+LOC equ [RSP].CLzmaDec_Asm_Loc.
+
+
+COPY_VAR macro name
+ mov t0, GLOB_2 name
+ mov LOC_0 name, t0
+endm
+
+
+RESTORE_VAR macro name
+ mov t0, LOC name
+ mov GLOB name, t0
+endm
+
+
+
+IsMatchBranch_Pre macro reg
+ ; prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+ mov pbPos, LOC pbMask
+ and pbPos, processedPos
+ shl pbPos, (kLenNumLowBits + 1 + PSHIFT)
+ lea probs_state_R, [probs + state_R]
+endm
+
+
+IsMatchBranch macro reg
+ IsMatchBranch_Pre
+ IF_BIT_1 probs_state_R, pbPos_R, IsMatch, IsMatch_label
+endm
+
+
+CheckLimits macro reg
+ cmp buf, LOC bufLimit
+ jae fin_OK
+ cmp dicPos, LOC limit
+ jae fin_OK
+endm
+
+
+
+; RSP is (16x + 8) bytes aligned in WIN64-x64
+; LocalSize equ ((((SIZEOF CLzmaDec_Asm_Loc) + 7) / 16 * 16) + 8)
+
+PARAM_lzma equ REG_PARAM_0
+PARAM_limit equ REG_PARAM_1
+PARAM_bufLimit equ REG_PARAM_2
+
+; MY_ALIGN_64
+MY_PROC LzmaDec_DecodeReal_3, 3
+MY_PUSH_PRESERVED_REGS
+
+ lea r0, [RSP - (SIZEOF CLzmaDec_Asm_Loc)]
+ and r0, -128
+ mov r5, RSP
+ mov RSP, r0
+ mov LOC_0 Old_RSP, r5
+ mov LOC_0 lzmaPtr, PARAM_lzma
+
+ mov LOC_0 remainLen, 0 ; remainLen must be ZERO
+
+ mov LOC_0 bufLimit, PARAM_bufLimit
+ mov sym_R, PARAM_lzma ; CLzmaDec_Asm_Loc pointer for GLOB_2
+ mov dic, GLOB_2 dic_Spec
+ add PARAM_limit, dic
+ mov LOC_0 limit, PARAM_limit
+
+ COPY_VAR(rep0)
+ COPY_VAR(rep1)
+ COPY_VAR(rep2)
+ COPY_VAR(rep3)
+
+ mov dicPos, GLOB_2 dicPos_Spec
+ add dicPos, dic
+ mov LOC_0 dicPos_Spec, dicPos
+ mov LOC_0 dic_Spec, dic
+
+ mov x1_L, GLOB_2 pb
+ mov t0, 1
+ shl t0, x1_L
+ dec t0
+ mov LOC_0 pbMask, t0
+
+ ; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
+ ; unsigned lc = p->prop.lc;
+ ; unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc);
+
+ mov x1_L, GLOB_2 lc
+ mov x2, 100h
+ mov t0, x2
+ shr x2, x1_L
+ ; inc x1
+ add x1_L, PSHIFT
+ mov LOC_0 lc2, x1
+ mov x1_L, GLOB_2 lp
+ shl t0, x1_L
+ sub t0, x2
+ mov LOC_0 lpMask, t0
+ mov lpMask_reg, t0
+
+ ; mov probs, GLOB_2 probs_Spec
+ ; add probs, kStartOffset SHL PSHIFT
+ mov probs, GLOB_2 probs_1664
+ mov LOC_0 probs_Spec, probs
+
+ mov t0_R, GLOB_2 dicBufSize
+ mov LOC_0 dicBufSize, t0_R
+
+ mov x1, GLOB_2 checkDicSize
+ mov LOC_0 checkDicSize, x1
+
+ mov processedPos, GLOB_2 processedPos_Spec
+
+ mov state, GLOB_2 state_Spec
+ shl state, PSHIFT
+
+ mov buf, GLOB_2 buf_Spec
+ mov range, GLOB_2 range_Spec
+ mov cod, GLOB_2 code_Spec
+ mov kBitModelTotal_reg, kBitModelTotal
+ xor sym, sym
+
+ ; if (processedPos != 0 || checkDicSize != 0)
+ or x1, processedPos
+ jz @f
+
+ add t0_R, dic
+ cmp dicPos, dic
+ cmovnz t0_R, dicPos
+ movzx sym, byte ptr[t0_R - 1]
+
+@@:
+ IsMatchBranch_Pre
+ cmp state, 4 * PMULT
+ jb lit_end
+ cmp state, kNumLitStates * PMULT
+ jb lit_matched_end
+ jmp lz_end
+
+
+
+
+; ---------- LITERAL ----------
+MY_ALIGN_64
+lit_start:
+ xor state, state
+lit_start_2:
+ LIT_PROBS lpMask_reg
+
+ ifdef _LZMA_SIZE_OPT
+
+ PLOAD x1, probs + 1 * PMULT
+ mov sym, 1
+MY_ALIGN_16
+lit_loop:
+ BIT_1 x1, x2
+ mov x1, x2
+ cmp sym, 127
+ jbe lit_loop
+
+ else
+
+ BIT_0 x1, x2
+ BIT_1 x2, x1
+ BIT_1 x1, x2
+ BIT_1 x2, x1
+ BIT_1 x1, x2
+ BIT_1 x2, x1
+ BIT_1 x1, x2
+
+ endif
+
+ BIT_2 x2, 256 - 1
+
+ ; mov dic, LOC dic_Spec
+ mov probs, LOC probs_Spec
+ IsMatchBranch_Pre
+ mov byte ptr[dicPos], sym_L
+ inc dicPos
+
+ CheckLimits
+lit_end:
+ IF_BIT_0_NOUP probs_state_R, pbPos_R, IsMatch, lit_start
+
+ ; jmp IsMatch_label
+
+; ---------- MATCHES ----------
+; MY_ALIGN_32
+IsMatch_label:
+ UPDATE_1 probs_state_R, pbPos_R, IsMatch
+ IF_BIT_1 probs_state_R, 0, IsRep, IsRep_label
+
+ add probs, LenCoder * PMULT
+ add state, kNumStates * PMULT
+
+; ---------- LEN DECODE ----------
+len_decode:
+ mov len_temp, 8 - 1 - kMatchMinLen
+ IF_BIT_0_NOUP probs, 0, 0, len_mid_0
+ UPDATE_1 probs, 0, 0
+ add probs, (1 SHL (kLenNumLowBits + PSHIFT))
+ mov len_temp, -1 - kMatchMinLen
+ IF_BIT_0_NOUP probs, 0, 0, len_mid_0
+ UPDATE_1 probs, 0, 0
+ add probs, LenHigh * PMULT - (1 SHL (kLenNumLowBits + PSHIFT))
+ mov sym, 1
+ PLOAD x1, probs + 1 * PMULT
+
+MY_ALIGN_32
+len8_loop:
+ BIT_1 x1, x2
+ mov x1, x2
+ cmp sym, 64
+ jb len8_loop
+
+ mov len_temp, (kLenNumHighSymbols - kLenNumLowSymbols * 2) - 1 - kMatchMinLen
+ jmp len_mid_2
+
+MY_ALIGN_32
+len_mid_0:
+ UPDATE_0 probs, 0, 0
+ add probs, pbPos_R
+ BIT_0 x2, x1
+len_mid_2:
+ BIT_1 x1, x2
+ BIT_2 x2, len_temp
+ mov probs, LOC probs_Spec
+ cmp state, kNumStates * PMULT
+ jb copy_match
+
+
+; ---------- DECODE DISTANCE ----------
+ ; probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
+
+ mov t0, 3 + kMatchMinLen
+ cmp sym, 3 + kMatchMinLen
+ cmovb t0, sym
+ add probs, PosSlot * PMULT - (kMatchMinLen SHL (kNumPosSlotBits + PSHIFT))
+ shl t0, (kNumPosSlotBits + PSHIFT)
+ add probs, t0_R
+
+ ; sym = Len
+ ; mov LOC remainLen, sym
+ mov len_temp, sym
+
+ ifdef _LZMA_SIZE_OPT
+
+ PLOAD x1, probs + 1 * PMULT
+ mov sym, 1
+MY_ALIGN_16
+slot_loop:
+ BIT_1 x1, x2
+ mov x1, x2
+ cmp sym, 32
+ jb slot_loop
+
+ else
+
+ BIT_0 x1, x2
+ BIT_1 x2, x1
+ BIT_1 x1, x2
+ BIT_1 x2, x1
+ BIT_1 x1, x2
+
+ endif
+
+ mov x1, sym
+ BIT_2 x2, 64-1
+
+ and sym, 3
+ mov probs, LOC probs_Spec
+ cmp x1, 32 + kEndPosModelIndex / 2
+ jb short_dist
+
+ ; unsigned numDirectBits = (unsigned)(((distance >> 1) - 1));
+ sub x1, (32 + 1 + kNumAlignBits)
+ ; distance = (2 | (distance & 1));
+ or sym, 2
+ PLOAD x2, probs + 1 * PMULT
+ shl sym, kNumAlignBits + 1
+ lea sym2_R, [probs + 2 * PMULT]
+
+ jmp direct_norm
+ ; lea t1, [sym_R + (1 SHL kNumAlignBits)]
+ ; cmp range, kTopValue
+ ; jb direct_norm
+
+; ---------- DIRECT DISTANCE ----------
+MY_ALIGN_32
+direct_loop:
+ shr range, 1
+ mov t0, cod
+ sub cod, range
+ cmovs cod, t0
+ cmovns sym, t1
+
+ comment ~
+ sub cod, range
+ mov x2, cod
+ sar x2, 31
+ lea sym, dword ptr [r2 + sym_R * 2 + 1]
+ and x2, range
+ add cod, x2
+ ~
+ dec x1
+ je direct_end
+
+ add sym, sym
+direct_norm:
+ lea t1, [sym_R + (1 SHL kNumAlignBits)]
+ cmp range, kTopValue
+ jae near ptr direct_loop
+ ; we align for 32 here with "near ptr" command above
+ NORM_2
+ jmp direct_loop
+
+MY_ALIGN_32
+direct_end:
+ ; prob = + kAlign;
+ ; distance <<= kNumAlignBits;
+ REV_0 x2, x1
+ REV_1 x1, x2, 2
+ REV_1 x2, x1, 4
+ REV_2 x1, 8
+
+decode_dist_end:
+
+ ; if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize))
+
+ mov t0, LOC checkDicSize
+ test t0, t0
+ cmove t0, processedPos
+ cmp sym, t0
+ jae end_of_payload
+
+ ; rep3 = rep2;
+ ; rep2 = rep1;
+ ; rep1 = rep0;
+ ; rep0 = distance + 1;
+
+ inc sym
+ mov t0, LOC rep0
+ mov t1, LOC rep1
+ mov x1, LOC rep2
+ mov LOC rep0, sym
+ ; mov sym, LOC remainLen
+ mov sym, len_temp
+ mov LOC rep1, t0
+ mov LOC rep2, t1
+ mov LOC rep3, x1
+
+ ; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
+ cmp state, (kNumStates + kNumLitStates) * PMULT
+ mov state, kNumLitStates * PMULT
+ mov t0, (kNumLitStates + 3) * PMULT
+ cmovae state, t0
+
+
+; ---------- COPY MATCH ----------
+copy_match:
+
+ ; len += kMatchMinLen;
+ ; add sym, kMatchMinLen
+
+ ; if ((rem = limit - dicPos) == 0)
+ ; {
+ ; p->dicPos = dicPos;
+ ; return SZ_ERROR_DATA;
+ ; }
+ mov cnt_R, LOC limit
+ sub cnt_R, dicPos
+ jz fin_ERROR
+
+ ; curLen = ((rem < len) ? (unsigned)rem : len);
+ cmp cnt_R, sym_R
+ ; cmovae cnt_R, sym_R ; 64-bit
+ cmovae cnt, sym ; 32-bit
+
+ mov dic, LOC dic_Spec
+ mov x1, LOC rep0
+
+ mov t0_R, dicPos
+ add dicPos, cnt_R
+ ; processedPos += curLen;
+ add processedPos, cnt
+ ; len -= curLen;
+ sub sym, cnt
+ mov LOC remainLen, sym
+
+ sub t0_R, dic
+
+ ; pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
+ sub t0_R, r1
+ jae @f
+
+ mov r1, LOC dicBufSize
+ add t0_R, r1
+ sub r1, t0_R
+ cmp cnt_R, r1
+ ja copy_match_cross
+@@:
+ ; if (curLen <= dicBufSize - pos)
+
+; ---------- COPY MATCH FAST ----------
+ ; Byte *dest = dic + dicPos;
+ ; mov r1, dic
+ ; ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
+ ; sub t0_R, dicPos
+ ; dicPos += curLen;
+
+ ; const Byte *lim = dest + curLen;
+ add t0_R, dic
+ movzx sym, byte ptr[t0_R]
+ add t0_R, cnt_R
+ neg cnt_R
+ ; lea r1, [dicPos - 1]
+copy_common:
+ dec dicPos
+ ; cmp LOC rep0, 1
+ ; je rep0Label
+
+ ; t0_R - src_lim
+ ; r1 - dest_lim - 1
+ ; cnt_R - (-cnt)
+
+ IsMatchBranch_Pre
+ inc cnt_R
+ jz copy_end
+MY_ALIGN_16
+@@:
+ mov byte ptr[cnt_R * 1 + dicPos], sym_L
+ movzx sym, byte ptr[cnt_R * 1 + t0_R]
+ inc cnt_R
+ jnz @b
+
+copy_end:
+lz_end_match:
+ mov byte ptr[dicPos], sym_L
+ inc dicPos
+
+ ; IsMatchBranch_Pre
+ CheckLimits
+lz_end:
+ IF_BIT_1_NOUP probs_state_R, pbPos_R, IsMatch, IsMatch_label
+
+
+
+; ---------- LITERAL MATCHED ----------
+
+ LIT_PROBS LOC lpMask
+
+ ; matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
+ mov x1, LOC rep0
+ ; mov dic, LOC dic_Spec
+ mov LOC dicPos_Spec, dicPos
+
+ ; state -= (state < 10) ? 3 : 6;
+ lea t0, [state_R - 6 * PMULT]
+ sub state, 3 * PMULT
+ cmp state, 7 * PMULT
+ cmovae state, t0
+
+ sub dicPos, dic
+ sub dicPos, r1
+ jae @f
+ add dicPos, LOC dicBufSize
+@@:
+ comment ~
+ xor t0, t0
+ sub dicPos, r1
+ cmovb t0_R, LOC dicBufSize
+ ~
+
+ movzx match, byte ptr[dic + dicPos * 1]
+
+ ifdef _LZMA_SIZE_OPT
+
+ mov offs, 256 * PMULT
+ shl match, (PSHIFT + 1)
+ mov bit, match
+ mov sym, 1
+MY_ALIGN_16
+litm_loop:
+ LITM
+ cmp sym, 256
+ jb litm_loop
+ sub sym, 256
+
+ else
+
+ LITM_0
+ LITM
+ LITM
+ LITM
+ LITM
+ LITM
+ LITM
+ LITM_2
+
+ endif
+
+ mov probs, LOC probs_Spec
+ IsMatchBranch_Pre
+ ; mov dic, LOC dic_Spec
+ mov dicPos, LOC dicPos_Spec
+ mov byte ptr[dicPos], sym_L
+ inc dicPos
+
+ CheckLimits
+lit_matched_end:
+ IF_BIT_1_NOUP probs_state_R, pbPos_R, IsMatch, IsMatch_label
+ ; IsMatchBranch
+ mov lpMask_reg, LOC lpMask
+ sub state, 3 * PMULT
+ jmp lit_start_2
+
+
+
+; ---------- REP 0 LITERAL ----------
+MY_ALIGN_32
+IsRep0Short_label:
+ UPDATE_0 probs_state_R, pbPos_R, IsRep0Long
+
+ ; dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
+ mov dic, LOC dic_Spec
+ mov t0_R, dicPos
+ mov probBranch, LOC rep0
+ sub t0_R, dic
+
+ sub probs, RepLenCoder * PMULT
+ inc processedPos
+ ; state = state < kNumLitStates ? 9 : 11;
+ or state, 1 * PMULT
+ IsMatchBranch_Pre
+
+ sub t0_R, probBranch_R
+ jae @f
+ add t0_R, LOC dicBufSize
+@@:
+ movzx sym, byte ptr[dic + t0_R * 1]
+ jmp lz_end_match
+
+
+MY_ALIGN_32
+IsRep_label:
+ UPDATE_1 probs_state_R, 0, IsRep
+
+ ; The (checkDicSize == 0 && processedPos == 0) case was checked before in LzmaDec.c with kBadRepCode.
+ ; So we don't check it here.
+
+ ; mov t0, processedPos
+ ; or t0, LOC checkDicSize
+ ; jz fin_ERROR_2
+
+ ; state = state < kNumLitStates ? 8 : 11;
+ cmp state, kNumLitStates * PMULT
+ mov state, 8 * PMULT
+ mov probBranch, 11 * PMULT
+ cmovae state, probBranch
+
+ ; prob = probs + RepLenCoder;
+ add probs, RepLenCoder * PMULT
+
+ IF_BIT_1 probs_state_R, 0, IsRepG0, IsRepG0_label
+ IF_BIT_0_NOUP probs_state_R, pbPos_R, IsRep0Long, IsRep0Short_label
+ UPDATE_1 probs_state_R, pbPos_R, IsRep0Long
+ jmp len_decode
+
+MY_ALIGN_32
+IsRepG0_label:
+ UPDATE_1 probs_state_R, 0, IsRepG0
+ mov dist2, LOC rep0
+ mov dist, LOC rep1
+ mov LOC rep1, dist2
+
+ IF_BIT_1 probs_state_R, 0, IsRepG1, IsRepG1_label
+ mov LOC rep0, dist
+ jmp len_decode
+
+; MY_ALIGN_32
+IsRepG1_label:
+ UPDATE_1 probs_state_R, 0, IsRepG1
+ mov dist2, LOC rep2
+ mov LOC rep2, dist
+
+ IF_BIT_1 probs_state_R, 0, IsRepG2, IsRepG2_label
+ mov LOC rep0, dist2
+ jmp len_decode
+
+; MY_ALIGN_32
+IsRepG2_label:
+ UPDATE_1 probs_state_R, 0, IsRepG2
+ mov dist, LOC rep3
+ mov LOC rep3, dist2
+ mov LOC rep0, dist
+ jmp len_decode
+
+
+
+; ---------- SPEC SHORT DISTANCE ----------
+
+MY_ALIGN_32
+short_dist:
+ sub x1, 32 + 1
+ jbe decode_dist_end
+ or sym, 2
+ shl sym, x1_L
+ lea sym_R, [probs + sym_R * PMULT + SpecPos * PMULT + 1 * PMULT]
+ mov sym2, PMULT ; step
+MY_ALIGN_32
+spec_loop:
+ REV_1_VAR x2
+ dec x1
+ jnz spec_loop
+
+ mov probs, LOC probs_Spec
+ sub sym, sym2
+ sub sym, SpecPos * PMULT
+ sub sym_R, probs
+ shr sym, PSHIFT
+
+ jmp decode_dist_end
+
+
+; ---------- COPY MATCH CROSS ----------
+copy_match_cross:
+ ; t0_R - src pos
+ ; r1 - len to dicBufSize
+ ; cnt_R - total copy len
+
+ mov t1_R, t0_R ; srcPos
+ mov t0_R, dic
+ mov r1, LOC dicBufSize ;
+ neg cnt_R
+@@:
+ movzx sym, byte ptr[t1_R * 1 + t0_R]
+ inc t1_R
+ mov byte ptr[cnt_R * 1 + dicPos], sym_L
+ inc cnt_R
+ cmp t1_R, r1
+ jne @b
+
+ movzx sym, byte ptr[t0_R]
+ sub t0_R, cnt_R
+ jmp copy_common
+
+
+
+
+fin_ERROR:
+ mov LOC remainLen, len_temp
+; fin_ERROR_2:
+ mov sym, 1
+ jmp fin
+
+end_of_payload:
+ cmp sym, 0FFFFFFFFh ; -1
+ jne fin_ERROR
+
+ mov LOC remainLen, kMatchSpecLenStart
+ sub state, kNumStates * PMULT
+
+fin_OK:
+ xor sym, sym
+
+fin:
+ NORM
+
+ mov r1, LOC lzmaPtr
+
+ sub dicPos, LOC dic_Spec
+ mov GLOB dicPos_Spec, dicPos
+ mov GLOB buf_Spec, buf
+ mov GLOB range_Spec, range
+ mov GLOB code_Spec, cod
+ shr state, PSHIFT
+ mov GLOB state_Spec, state
+ mov GLOB processedPos_Spec, processedPos
+
+ RESTORE_VAR(remainLen)
+ RESTORE_VAR(rep0)
+ RESTORE_VAR(rep1)
+ RESTORE_VAR(rep2)
+ RESTORE_VAR(rep3)
+
+ mov x0, sym
+
+ mov RSP, LOC Old_RSP
+
+MY_POP_PRESERVED_REGS
+MY_ENDP
+
+_TEXT$LZMADECOPT ENDS
+
+end
diff --git a/C/7z.h b/C/7z.h
index 216f381..82813c2 100644
--- a/C/7z.h
+++ b/C/7z.h
@@ -1,5 +1,5 @@
/* 7z.h -- 7z interface
-2015-11-18 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_H
#define __7Z_H
@@ -98,7 +98,7 @@ UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize,
- ISzAlloc *allocMain);
+ ISzAllocPtr allocMain);
typedef struct
{
@@ -131,7 +131,7 @@ typedef struct
#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i])
void SzArEx_Init(CSzArEx *p);
-void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
+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);
@@ -179,8 +179,8 @@ SRes SzArEx_Extract(
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);
+ ISzAllocPtr allocMain,
+ ISzAllocPtr allocTemp);
/*
@@ -195,7 +195,7 @@ SZ_ERROR_FAIL
*/
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
- ISzAlloc *allocMain, ISzAlloc *allocTemp);
+ ISzAllocPtr allocMain, ISzAllocPtr allocTemp);
EXTERN_C_END
diff --git a/C/7zAlloc.c b/C/7zAlloc.c
index 360da05..ea32809 100644
--- a/C/7zAlloc.c
+++ b/C/7zAlloc.c
@@ -1,8 +1,10 @@
/* 7zAlloc.c -- Allocation functions
-2015-11-09 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
+#include <stdlib.h>
+
#include "7zAlloc.h"
/* #define _SZ_ALLOC_DEBUG */
@@ -20,7 +22,7 @@ int g_allocCountTemp = 0;
#endif
-void *SzAlloc(void *p, size_t size)
+void *SzAlloc(ISzAllocPtr p, size_t size)
{
UNUSED_VAR(p);
if (size == 0)
@@ -32,7 +34,7 @@ void *SzAlloc(void *p, size_t size)
return malloc(size);
}
-void SzFree(void *p, void *address)
+void SzFree(ISzAllocPtr p, void *address)
{
UNUSED_VAR(p);
#ifdef _SZ_ALLOC_DEBUG
@@ -45,7 +47,7 @@ void SzFree(void *p, void *address)
free(address);
}
-void *SzAllocTemp(void *p, size_t size)
+void *SzAllocTemp(ISzAllocPtr p, size_t size)
{
UNUSED_VAR(p);
if (size == 0)
@@ -60,7 +62,7 @@ void *SzAllocTemp(void *p, size_t size)
return malloc(size);
}
-void SzFreeTemp(void *p, void *address)
+void SzFreeTemp(ISzAllocPtr p, void *address)
{
UNUSED_VAR(p);
#ifdef _SZ_ALLOC_DEBUG
diff --git a/C/7zAlloc.h b/C/7zAlloc.h
index 4d7502f..c0f89d7 100644
--- a/C/7zAlloc.h
+++ b/C/7zAlloc.h
@@ -1,23 +1,19 @@
/* 7zAlloc.h -- Allocation functions
-2013-03-25 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H
-#include <stdlib.h>
+#include "7zTypes.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+EXTERN_C_BEGIN
-void *SzAlloc(void *p, size_t size);
-void SzFree(void *p, void *address);
+void *SzAlloc(ISzAllocPtr p, size_t size);
+void SzFree(ISzAllocPtr p, void *address);
-void *SzAllocTemp(void *p, size_t size);
-void SzFreeTemp(void *p, void *address);
+void *SzAllocTemp(ISzAllocPtr p, size_t size);
+void SzFreeTemp(ISzAllocPtr p, void *address);
-#ifdef __cplusplus
-}
-#endif
+EXTERN_C_END
#endif
diff --git a/C/7zArcIn.c b/C/7zArcIn.c
index c324c37..70d7175 100644
--- a/C/7zArcIn.c
+++ b/C/7zArcIn.c
@@ -1,5 +1,5 @@
/* 7zArcIn.c -- 7z Input functions
-2016-05-16 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -11,7 +11,7 @@
#include "CpuArch.h"
#define MY_ALLOC(T, p, size, alloc) { \
- if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; }
+ if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; }
#define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) }
@@ -60,7 +60,7 @@ const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
#define SzBitUi32s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
-static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc)
+static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc)
{
if (num == 0)
{
@@ -75,18 +75,18 @@ static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc)
return SZ_OK;
}
-void SzBitUi32s_Free(CSzBitUi32s *p, ISzAlloc *alloc)
+void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc)
{
- IAlloc_Free(alloc, p->Defs); p->Defs = NULL;
- IAlloc_Free(alloc, p->Vals); p->Vals = NULL;
+ ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
+ ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
}
#define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
-void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc)
+void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc)
{
- IAlloc_Free(alloc, p->Defs); p->Defs = NULL;
- IAlloc_Free(alloc, p->Vals); p->Vals = NULL;
+ ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
+ ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
}
@@ -107,18 +107,18 @@ static void SzAr_Init(CSzAr *p)
p->CodersData = NULL;
}
-static void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
+static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc)
{
- IAlloc_Free(alloc, p->PackPositions);
+ ISzAlloc_Free(alloc, p->PackPositions);
SzBitUi32s_Free(&p->FolderCRCs, alloc);
- IAlloc_Free(alloc, p->FoCodersOffsets);
- IAlloc_Free(alloc, p->FoStartPackStreamIndex);
- IAlloc_Free(alloc, p->FoToCoderUnpackSizes);
- IAlloc_Free(alloc, p->FoToMainUnpackSizeIndex);
- IAlloc_Free(alloc, p->CoderUnpackSizes);
+ ISzAlloc_Free(alloc, p->FoCodersOffsets);
+ ISzAlloc_Free(alloc, p->FoStartPackStreamIndex);
+ ISzAlloc_Free(alloc, p->FoToCoderUnpackSizes);
+ ISzAlloc_Free(alloc, p->FoToMainUnpackSizeIndex);
+ ISzAlloc_Free(alloc, p->CoderUnpackSizes);
- IAlloc_Free(alloc, p->CodersData);
+ ISzAlloc_Free(alloc, p->CodersData);
SzAr_Init(p);
}
@@ -147,16 +147,16 @@ void SzArEx_Init(CSzArEx *p)
SzBitUi64s_Init(&p->CTime);
}
-void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
+void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc)
{
- IAlloc_Free(alloc, p->UnpackPositions);
- IAlloc_Free(alloc, p->IsDirs);
+ ISzAlloc_Free(alloc, p->UnpackPositions);
+ ISzAlloc_Free(alloc, p->IsDirs);
- IAlloc_Free(alloc, p->FolderToFile);
- IAlloc_Free(alloc, p->FileToFolder);
+ ISzAlloc_Free(alloc, p->FolderToFile);
+ ISzAlloc_Free(alloc, p->FileToFolder);
- IAlloc_Free(alloc, p->FileNameOffsets);
- IAlloc_Free(alloc, p->FileNames);
+ ISzAlloc_Free(alloc, p->FileNameOffsets);
+ ISzAlloc_Free(alloc, p->FileNames);
SzBitUi32s_Free(&p->CRCs, alloc);
SzBitUi32s_Free(&p->Attribs, alloc);
@@ -305,7 +305,7 @@ static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
return sum;
}
-static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAlloc *alloc)
+static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc)
{
Byte allAreDefined;
Byte *v2;
@@ -328,12 +328,12 @@ static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, I
{
unsigned numBits = (unsigned)numItems & 7;
if (numBits != 0)
- v2[numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));
+ v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));
}
return SZ_OK;
}
-static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc)
+static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
{
UInt32 i;
CSzData sd;
@@ -354,7 +354,7 @@ static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *c
return SZ_OK;
}
-static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc)
+static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
{
SzBitUi32s_Free(crcs, alloc);
RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc));
@@ -380,7 +380,7 @@ static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems)
return SZ_OK;
}
-static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAlloc *alloc)
+static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc)
{
RINOK(SzReadNumber32(sd, &p->NumPackStreams));
@@ -635,7 +635,7 @@ static SRes ReadUnpackInfo(CSzAr *p,
CSzData *sd2,
UInt32 numFoldersMax,
const CBuf *tempBufs, UInt32 numTempBufs,
- ISzAlloc *alloc)
+ ISzAllocPtr alloc)
{
CSzData sd;
@@ -934,7 +934,7 @@ static SRes SzReadStreamsInfo(CSzAr *p,
UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,
UInt64 *dataOffset,
CSubStreamInfo *ssi,
- ISzAlloc *alloc)
+ ISzAllocPtr alloc)
{
UInt64 type;
@@ -976,7 +976,7 @@ static SRes SzReadAndDecodePackedStreams(
UInt32 numFoldersMax,
UInt64 baseOffset,
CSzAr *p,
- ISzAlloc *allocTemp)
+ ISzAllocPtr allocTemp)
{
UInt64 dataStartPos;
UInt32 fo;
@@ -1043,7 +1043,7 @@ static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size
static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
CSzData *sd2,
const CBuf *tempBufs, UInt32 numTempBufs,
- ISzAlloc *alloc)
+ ISzAllocPtr alloc)
{
CSzData sd;
UInt32 i;
@@ -1096,8 +1096,8 @@ static SRes SzReadHeader2(
CSzData *sd,
ILookInStream *inStream,
CBuf *tempBufs, UInt32 *numTempBufs,
- ISzAlloc *allocMain,
- ISzAlloc *allocTemp
+ ISzAllocPtr allocMain,
+ ISzAllocPtr allocTemp
)
{
CSubStreamInfo ssi;
@@ -1472,8 +1472,8 @@ static SRes SzReadHeader(
CSzArEx *p,
CSzData *sd,
ILookInStream *inStream,
- ISzAlloc *allocMain,
- ISzAlloc *allocTemp)
+ ISzAllocPtr allocMain,
+ ISzAllocPtr allocTemp)
{
UInt32 i;
UInt32 numTempBufs = 0;
@@ -1501,8 +1501,8 @@ static SRes SzReadHeader(
static SRes SzArEx_Open2(
CSzArEx *p,
ILookInStream *inStream,
- ISzAlloc *allocMain,
- ISzAlloc *allocTemp)
+ ISzAllocPtr allocMain,
+ ISzAllocPtr allocTemp)
{
Byte header[k7zStartHeaderSize];
Int64 startArcPos;
@@ -1513,7 +1513,7 @@ static SRes SzArEx_Open2(
SRes res;
startArcPos = 0;
- RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));
+ RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR));
RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
@@ -1542,7 +1542,7 @@ static SRes SzArEx_Open2(
{
Int64 pos = 0;
- RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));
+ RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END));
if ((UInt64)pos < startArcPos + nextHeaderOffset ||
(UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
(UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
@@ -1623,7 +1623,7 @@ static SRes SzArEx_Open2(
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
- ISzAlloc *allocMain, ISzAlloc *allocTemp)
+ ISzAllocPtr allocMain, ISzAllocPtr allocTemp)
{
SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
if (res != SZ_OK)
@@ -1641,8 +1641,8 @@ SRes SzArEx_Extract(
size_t *outBufferSize,
size_t *offset,
size_t *outSizeProcessed,
- ISzAlloc *allocMain,
- ISzAlloc *allocTemp)
+ ISzAllocPtr allocMain,
+ ISzAllocPtr allocTemp)
{
UInt32 folderIndex = p->FileToFolder[fileIndex];
SRes res = SZ_OK;
@@ -1652,7 +1652,7 @@ SRes SzArEx_Extract(
if (folderIndex == (UInt32)-1)
{
- IAlloc_Free(allocMain, *tempBuf);
+ ISzAlloc_Free(allocMain, *tempBuf);
*blockIndex = folderIndex;
*tempBuf = NULL;
*outBufferSize = 0;
@@ -1664,7 +1664,7 @@ SRes SzArEx_Extract(
UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
/*
UInt64 unpackSizeSpec =
- p->UnpackPositions[p->FolderToFile[folderIndex + 1]] -
+ p->UnpackPositions[p->FolderToFile[(size_t)folderIndex + 1]] -
p->UnpackPositions[p->FolderToFile[folderIndex]];
*/
size_t unpackSize = (size_t)unpackSizeSpec;
@@ -1672,7 +1672,7 @@ SRes SzArEx_Extract(
if (unpackSize != unpackSizeSpec)
return SZ_ERROR_MEM;
*blockIndex = folderIndex;
- IAlloc_Free(allocMain, *tempBuf);
+ ISzAlloc_Free(allocMain, *tempBuf);
*tempBuf = NULL;
if (res == SZ_OK)
@@ -1680,7 +1680,7 @@ SRes SzArEx_Extract(
*outBufferSize = unpackSize;
if (unpackSize != 0)
{
- *tempBuf = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
+ *tempBuf = (Byte *)ISzAlloc_Alloc(allocMain, unpackSize);
if (*tempBuf == NULL)
res = SZ_ERROR_MEM;
}
@@ -1697,7 +1697,7 @@ SRes SzArEx_Extract(
{
UInt64 unpackPos = p->UnpackPositions[fileIndex];
*offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]);
- *outSizeProcessed = (size_t)(p->UnpackPositions[fileIndex + 1] - unpackPos);
+ *outSizeProcessed = (size_t)(p->UnpackPositions[(size_t)fileIndex + 1] - unpackPos);
if (*offset + *outSizeProcessed > *outBufferSize)
return SZ_ERROR_FAIL;
if (SzBitWithVals_Check(&p->CRCs, fileIndex))
diff --git a/C/7zBuf.c b/C/7zBuf.c
index b0ac110..438bba6 100644
--- a/C/7zBuf.c
+++ b/C/7zBuf.c
@@ -1,5 +1,5 @@
/* 7zBuf.c -- Byte Buffer
-2013-01-21 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.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;
}
diff --git a/C/7zBuf.h b/C/7zBuf.h
index e5f9218..5942d6e 100644
--- a/C/7zBuf.h
+++ b/C/7zBuf.h
@@ -1,5 +1,5 @@
/* 7zBuf.h -- Byte Buffer
-2013-01-18 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_BUF_H
#define __7Z_BUF_H
@@ -15,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
{
@@ -27,8 +27,8 @@ 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
diff --git a/C/7zBuf2.c b/C/7zBuf2.c
index 8e3fe92..49b4343 100644
--- a/C/7zBuf2.c
+++ b/C/7zBuf2.c
@@ -1,5 +1,5 @@
/* 7zBuf2.c -- Byte Buffer
-2014-08-22 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -19,19 +19,20 @@ 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;
}
if (size != 0)
@@ -42,9 +43,9 @@ int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc)
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;
diff --git a/C/7zCrc.c b/C/7zCrc.c
index 607db34..40ab759 100644
--- a/C/7zCrc.c
+++ b/C/7zCrc.c
@@ -1,5 +1,5 @@
/* 7zCrc.c -- CRC32 init
-2015-03-10 : Igor Pavlov : Public domain */
+2017-06-06 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -61,12 +61,12 @@ void MY_FAST_CALL CrcGenerateTable()
UInt32 r = i;
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 * CRC_NUM_TABLES; i++)
+ for (i = 256; i < 256 * CRC_NUM_TABLES; i++)
{
- UInt32 r = g_CrcTable[i - 256];
+ UInt32 r = g_CrcTable[(size_t)i - 256];
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
}
@@ -86,8 +86,8 @@ void MY_FAST_CALL CrcGenerateTable()
#ifdef MY_CPU_X86_OR_AMD64
if (!CPU_Is_InOrder())
- g_CrcUpdate = CrcUpdateT8;
#endif
+ g_CrcUpdate = CrcUpdateT8;
#endif
#else
@@ -101,7 +101,7 @@ void MY_FAST_CALL CrcGenerateTable()
g_CrcUpdate = CrcUpdateT4;
#if CRC_NUM_TABLES >= 8
g_CrcUpdateT8 = CrcUpdateT8;
- // g_CrcUpdate = CrcUpdateT8;
+ g_CrcUpdate = CrcUpdateT8;
#endif
}
else if (p[0] != 1 || p[1] != 2)
@@ -111,14 +111,14 @@ void MY_FAST_CALL CrcGenerateTable()
{
for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
{
- UInt32 x = g_CrcTable[i - 256];
+ 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;
+ g_CrcUpdate = CrcUpdateT1_BeT8;
#endif
}
}
diff --git a/C/7zCrcOpt.c b/C/7zCrcOpt.c
index 58628ef..2ee0de8 100644
--- a/C/7zCrcOpt.c
+++ b/C/7zCrcOpt.c
@@ -1,5 +1,5 @@
/* 7zCrcOpt.c -- CRC32 calculation
-2015-03-01 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -18,10 +18,10 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U
{
v ^= *(const UInt32 *)p;
v =
- table[0x300 + ((v ) & 0xFF)]
- ^ table[0x200 + ((v >> 8) & 0xFF)]
- ^ table[0x100 + ((v >> 16) & 0xFF)]
- ^ table[0x000 + ((v >> 24))];
+ (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);
@@ -38,16 +38,16 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U
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))];
+ (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))];
+ (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);
@@ -74,10 +74,10 @@ UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, co
{
v ^= *(const UInt32 *)p;
v =
- table[0x000 + ((v ) & 0xFF)]
- ^ table[0x100 + ((v >> 8) & 0xFF)]
- ^ table[0x200 + ((v >> 16) & 0xFF)]
- ^ table[0x300 + ((v >> 24))];
+ (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);
@@ -96,16 +96,16 @@ UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, co
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))];
+ (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))];
+ (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);
diff --git a/C/7zDec.c b/C/7zDec.c
index e39b4ff..9c98695 100644
--- a/C/7zDec.c
+++ b/C/7zDec.c
@@ -1,5 +1,5 @@
/* 7zDec.c -- Decoding from 7z folder
-2015-11-18 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -39,28 +39,28 @@
typedef struct
{
- IByteIn p;
+ IByteIn vt;
const Byte *cur;
const Byte *end;
const Byte *begin;
UInt64 processed;
Bool extra;
SRes res;
- ILookInStream *inStream;
+ const ILookInStream *inStream;
} CByteInToLook;
-static Byte ReadByte(void *pp)
+static Byte ReadByte(const IByteIn *pp)
{
- CByteInToLook *p = (CByteInToLook *)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 = p->inStream->Skip(p->inStream, size);
+ p->res = ILookInStream_Skip(p->inStream, size);
size = (1 << 25);
- p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
+ p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size);
p->cur = p->begin;
p->end = p->begin + size;
if (size != 0)
@@ -70,14 +70,14 @@ static Byte ReadByte(void *pp)
return 0;
}
-static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
- Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
+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.p.Read = ReadByte;
+ s.vt.Read = ReadByte;
s.inStream = inStream;
s.begin = s.end = s.cur = NULL;
s.extra = False;
@@ -103,7 +103,7 @@ static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, I
{
CPpmd7z_RangeDec rc;
Ppmd7z_RangeDec_CreateVTable(&rc);
- rc.Stream = &s.p;
+ rc.Stream = &s.vt;
if (!Ppmd7z_RangeDec_Init(&rc))
res = SZ_ERROR_DATA;
else if (s.extra)
@@ -113,7 +113,7 @@ static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, I
SizeT i;
for (i = 0; i < outSize; i++)
{
- int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
+ int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt);
if (s.extra || sym < 0)
break;
outBuffer[i] = (Byte)sym;
@@ -132,7 +132,7 @@ static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, I
static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
- Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
+ Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
{
CLzmaDec state;
SRes res = SZ_OK;
@@ -149,7 +149,7 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
- res = inStream->Look(inStream, &inBuf, &lookahead);
+ res = ILookInStream_Look(inStream, &inBuf, &lookahead);
if (res != SZ_OK)
break;
@@ -178,7 +178,7 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
break;
}
- res = inStream->Skip((void *)inStream, inProcessed);
+ res = ILookInStream_Skip(inStream, inProcessed);
if (res != SZ_OK)
break;
}
@@ -192,7 +192,7 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
#ifndef _7Z_NO_METHOD_LZMA2
static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
- Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
+ Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
{
CLzma2Dec state;
SRes res = SZ_OK;
@@ -211,7 +211,7 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
- res = inStream->Look(inStream, &inBuf, &lookahead);
+ res = ILookInStream_Look(inStream, &inBuf, &lookahead);
if (res != SZ_OK)
break;
@@ -237,7 +237,7 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
break;
}
- res = inStream->Skip((void *)inStream, inProcessed);
+ res = ILookInStream_Skip(inStream, inProcessed);
if (res != SZ_OK)
break;
}
@@ -258,13 +258,13 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
size_t curSize = (1 << 18);
if (curSize > inSize)
curSize = (size_t)inSize;
- RINOK(inStream->Look(inStream, &inBuf, &curSize));
+ RINOK(ILookInStream_Look(inStream, &inBuf, &curSize));
if (curSize == 0)
return SZ_ERROR_INPUT_EOF;
memcpy(outBuffer, inBuf, curSize);
outBuffer += curSize;
inSize -= curSize;
- RINOK(inStream->Skip((void *)inStream, curSize));
+ RINOK(ILookInStream_Skip(inStream, curSize));
}
return SZ_OK;
}
@@ -372,7 +372,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
const UInt64 *unpackSizes,
const UInt64 *packPositions,
ILookInStream *inStream, UInt64 startPos,
- Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
+ Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain,
Byte *tempBuf[])
{
UInt32 ci;
@@ -404,7 +404,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
outSizeCur = (SizeT)unpackSize;
if (outSizeCur != unpackSize)
return SZ_ERROR_MEM;
- temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
+ temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur);
if (!temp && outSizeCur != 0)
return SZ_ERROR_MEM;
outBufCur = tempBuf[1 - ci] = temp;
@@ -421,7 +421,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
return SZ_ERROR_UNSUPPORTED;
}
offset = packPositions[si];
- inSize = packPositions[si + 1] - offset;
+ inSize = packPositions[(size_t)si + 1] - offset;
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
if (coder->MethodID == k_Copy)
@@ -460,7 +460,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
tempSizes[2] = (SizeT)s3Size;
if (tempSizes[2] != s3Size)
return SZ_ERROR_MEM;
- tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
+ tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]);
if (!tempBuf[2] && tempSizes[2] != 0)
return SZ_ERROR_MEM;
@@ -549,7 +549,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, size_t outSize,
- ISzAlloc *allocMain)
+ ISzAllocPtr allocMain)
{
SRes res;
CSzFolder folder;
@@ -557,7 +557,7 @@ SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
sd.Data = data;
- sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex];
+ sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex];
res = SzGetNextFolderItem(&folder, &sd);
@@ -579,7 +579,7 @@ SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++)
- IAlloc_Free(allocMain, tempBuf[i]);
+ ISzAlloc_Free(allocMain, tempBuf[i]);
if (res == SZ_OK)
if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))
diff --git a/C/7zFile.c b/C/7zFile.c
index 98fe716..e486901 100644
--- a/C/7zFile.c
+++ b/C/7zFile.c
@@ -1,5 +1,5 @@
/* 7zFile.c -- File IO
-2009-11-24 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -238,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;
}
diff --git a/C/7zFile.h b/C/7zFile.h
index d62a192..7e263be 100644
--- a/C/7zFile.h
+++ b/C/7zFile.h
@@ -1,5 +1,5 @@
/* 7zFile.h -- File IO
-2013-01-18 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_FILE_H
#define __7Z_FILE_H
@@ -54,7 +54,7 @@ WRes File_GetLength(CSzFile *p, UInt64 *length);
typedef struct
{
- ISeqInStream s;
+ ISeqInStream vt;
CSzFile file;
} CFileSeqInStream;
@@ -63,7 +63,7 @@ void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
typedef struct
{
- ISeekInStream s;
+ ISeekInStream vt;
CSzFile file;
} CFileInStream;
@@ -72,7 +72,7 @@ void FileInStream_CreateVTable(CFileInStream *p);
typedef struct
{
- ISeqOutStream s;
+ ISeqOutStream vt;
CSzFile file;
} CFileOutStream;
diff --git a/C/7zStream.c b/C/7zStream.c
index 5a92d53..579741f 100644
--- a/C/7zStream.c
+++ b/C/7zStream.c
@@ -1,5 +1,5 @@
/* 7zStream.c -- 7z Stream functions
-2013-11-12 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -7,12 +7,12 @@
#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);
@@ -21,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)
{
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);
@@ -63,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, const 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, const 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);
@@ -126,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;
}
diff --git a/C/7zTypes.h b/C/7zTypes.h
index 903047b..4977cda 100644
--- a/C/7zTypes.h
+++ b/C/7zTypes.h
@@ -1,5 +1,5 @@
/* 7zTypes.h -- Basic types
-2013-11-12 : Igor Pavlov : Public domain */
+2017-07-17 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H
#define __7Z_TYPES_H
@@ -42,13 +42,23 @@ EXTERN_C_BEGIN
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
@@ -112,48 +122,72 @@ typedef int Bool;
#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
+typedef struct IByteIn IByteIn;
+struct IByteIn
{
- Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
-} 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
+
+typedef struct IByteOut IByteOut;
+struct IByteOut
{
- void (*Write)(void *p, Byte b);
-} IByteOut;
+ void (*Write)(const IByteOut *p, Byte b);
+};
+#define IByteOut_Write(p, b) (p)->Write(p, b)
-typedef struct
+
+typedef struct ISeqInStream ISeqInStream;
+struct ISeqInStream
{
- SRes (*Read)(void *p, void *buf, size_t *size);
+ 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 */
-} ISeqInStream;
+};
+#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)
/* it can return SZ_ERROR_INPUT_EOF */
-SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
-SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
-SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
+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
+
+typedef struct ISeqOutStream ISeqOutStream;
+struct ISeqOutStream
{
- size_t (*Write)(void *p, const void *buf, size_t size);
+ size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes.
(result < size) means error */
-} ISeqOutStream;
+};
+#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)
typedef enum
{
@@ -162,78 +196,162 @@ typedef enum
SZ_SEEK_END = 2
} ESzSeek;
-typedef struct
+
+typedef struct ISeekInStream ISeekInStream;
+struct ISeekInStream
{
- SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
- SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
-} 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
+
+typedef struct ILookInStream ILookInStream;
+struct ILookInStream
{
- SRes (*Look)(void *p, const void **buf, size_t *size);
+ 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)(void *p, size_t offset);
+ SRes (*Skip)(const ILookInStream *p, size_t offset);
/* offset must be <= output(*size) of Look */
- SRes (*Read)(void *p, void *buf, size_t *size);
+ SRes (*Read)(const ILookInStream *p, void *buf, size_t *size);
/* reads directly (without buffer). It's same as ISeqInStream::Read */
- SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
-} ILookInStream;
+ SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin);
+};
-SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
-SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
+#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(ILookInStream *stream, void *buf, size_t size, SRes errorType);
-SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
+SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType);
+SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size);
+
-#define LookToRead_BUF_SIZE (1 << 14)
typedef struct
{
- ILookInStream s;
- ISeekInStream *realStream;
+ ILookInStream vt;
+ const ISeekInStream *realStream;
+
size_t pos;
- size_t size;
- Byte buf[LookToRead_BUF_SIZE];
-} CLookToRead;
+ 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; }
-void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
-void LookToRead_Init(CLookToRead *p);
typedef struct
{
- ISeqInStream s;
- ILookInStream *realStream;
+ ISeqInStream vt;
+ const ILookInStream *realStream;
} CSecToLook;
void SecToLook_CreateVTable(CSecToLook *p);
+
+
typedef struct
{
- ISeqInStream s;
- ILookInStream *realStream;
+ ISeqInStream vt;
+ const ILookInStream *realStream;
} CSecToRead;
void SecToRead_CreateVTable(CSecToRead *p);
-typedef struct
+
+typedef struct ICompressProgress ICompressProgress;
+
+struct ICompressProgress
{
- SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
+ 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. */
-} ICompressProgress;
+};
+#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)
-typedef struct
+
+
+typedef struct ISzAlloc ISzAlloc;
+typedef const ISzAlloc * ISzAllocPtr;
+
+struct ISzAlloc
{
- void *(*Alloc)(void *p, size_t size);
- void (*Free)(void *p, void *address); /* address can be 0 */
-} 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)
+*/
+
-#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
-#define IAlloc_Free(p, a) (p)->Free((p), a)
#ifdef _WIN32
diff --git a/C/7zVersion.h b/C/7zVersion.h
index acb67a9..ed3aa94 100644
--- a/C/7zVersion.h
+++ b/C/7zVersion.h
@@ -1,14 +1,21 @@
-#define MY_VER_MAJOR 16
-#define MY_VER_MINOR 04
+#define MY_VER_MAJOR 18
+#define MY_VER_MINOR 05
#define MY_VER_BUILD 0
-#define MY_VERSION_NUMBERS "16.04"
-#define MY_VERSION "16.04"
-#define MY_DATE "2016-10-04"
+#define MY_VERSION_NUMBERS "18.05"
+#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 "2018-04-30"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
-#define MY_COPYRIGHT_CR "Copyright (c) 1999-2016 Igor Pavlov"
+#define MY_COPYRIGHT_CR "Copyright (c) 1999-2018 Igor Pavlov"
#ifdef USE_COPYRIGHT_CR
#define MY_COPYRIGHT MY_COPYRIGHT_CR
@@ -16,4 +23,5 @@
#define MY_COPYRIGHT MY_COPYRIGHT_PD
#endif
-#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " : " MY_COPYRIGHT " : " MY_DATE
+#define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE
+#define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE
diff --git a/C/Aes.c b/C/Aes.c
index 8e658e7..8f7d50e 100644
--- a/C/Aes.c
+++ b/C/Aes.c
@@ -1,5 +1,5 @@
/* Aes.c -- AES encryption / decryption
-2016-05-21 : Igor Pavlov : Public domain */
+2017-01-24 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -49,7 +49,13 @@ static const Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 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)
{
@@ -63,10 +69,10 @@ void AesGenTables(void)
UInt32 a1 = Sbox[i];
UInt32 a2 = xtime(a1);
UInt32 a3 = a2 ^ a1;
- T[ i] = Ui32(a2, a1, a1, a3);
- T[0x100 + i] = Ui32(a3, a2, a1, a1);
- T[0x200 + i] = Ui32(a1, a3, a2, a1);
- T[0x300 + i] = Ui32(a1, a1, a3, a2);
+ 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];
@@ -77,10 +83,10 @@ 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);
}
}
@@ -99,7 +105,7 @@ void AesGenTables(void)
}
-#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) ^ \
@@ -113,11 +119,11 @@ void AesGenTables(void)
HT4(m, 2, s, p); \
HT4(m, 3, s, p); \
-#define FT(i, x) Sbox[gb ## x(m[(i + x) & 3])]
+#define FT(i, x) Sbox[gb(x, m[(i + x) & 3])]
#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i];
-#define 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) ^ \
@@ -131,7 +137,7 @@ void AesGenTables(void)
HD4(m, 2, s, p); \
HD4(m, 3, 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 MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize)
@@ -147,7 +153,7 @@ void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize)
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)]);
@@ -167,10 +173,10 @@ void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)
{
UInt32 r = w[i];
w[i] =
- D[ (unsigned)Sbox[gb0(r)]] ^
- D[0x100 + (unsigned)Sbox[gb1(r)]] ^
- D[0x200 + (unsigned)Sbox[gb2(r)]] ^
- D[0x300 + (unsigned)Sbox[gb3(r)]];
+ DD(0)[Sbox[gb0(r)]] ^
+ DD(1)[Sbox[gb1(r)]] ^
+ DD(2)[Sbox[gb2(r)]] ^
+ DD(3)[Sbox[gb3(r)]];
}
}
@@ -276,20 +282,25 @@ void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)
for (; numBlocks != 0; numBlocks--)
{
UInt32 temp[4];
- Byte buf[16];
- int i;
+ unsigned i;
if (++p[0] == 0)
p[1]++;
Aes_Encode(p + 4, temp, p);
- SetUi32(buf, temp[0]);
- SetUi32(buf + 4, temp[1]);
- SetUi32(buf + 8, temp[2]);
- SetUi32(buf + 12, temp[3]);
-
- for (i = 0; i < 16; i++)
- *data++ ^= buf[i];
+ 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
+ }
}
}
diff --git a/C/AesOpt.c b/C/AesOpt.c
index e5d4d26..0e7f49a 100644
--- a/C/AesOpt.c
+++ b/C/AesOpt.c
@@ -1,12 +1,12 @@
/* AesOpt.c -- Intel's AES
-2013-11-12 : Igor Pavlov : Public domain */
+2017-06-08 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "CpuArch.h"
#ifdef MY_CPU_X86_OR_AMD64
-#if _MSC_VER >= 1500
+#if (_MSC_VER > 1500) || (_MSC_FULL_VER >= 150030729)
#define USE_INTEL_AES
#endif
#endif
diff --git a/C/Alloc.c b/C/Alloc.c
index 9f1d036..30b499e 100644
--- a/C/Alloc.c
+++ b/C/Alloc.c
@@ -1,8 +1,10 @@
/* Alloc.c -- Memory allocation functions
-2015-02-21 : Igor Pavlov : Public domain */
+2018-04-27 : Igor Pavlov : Public domain */
#include "Precomp.h"
+#include <stdio.h>
+
#ifdef _WIN32
#include <windows.h>
#endif
@@ -14,20 +16,127 @@
/* 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,31 +200,36 @@ 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);
}
@@ -127,10 +237,219 @@ void BigFree(void *address)
#endif
-static void *SzAlloc(void *p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
-static void SzFree(void *p, void *address) { UNUSED_VAR(p); MyFree(address); }
-ISzAlloc g_Alloc = { SzAlloc, SzFree };
+static void *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;
-static void *SzBigAlloc(void *p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); }
-static void SzBigFree(void *p, void *address) { UNUSED_VAR(p); BigFree(address); }
-ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
+ 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;
+}
diff --git a/C/Alloc.h b/C/Alloc.h
index 73b282a..3d796e5 100644
--- a/C/Alloc.h
+++ b/C/Alloc.h
@@ -1,5 +1,5 @@
/* Alloc.h -- Memory allocation functions
-2015-02-21 : Igor Pavlov : Public domain */
+2018-02-19 : Igor Pavlov : Public domain */
#ifndef __COMMON_ALLOC_H
#define __COMMON_ALLOC_H
@@ -29,8 +29,22 @@ void BigFree(void *address);
#endif
-extern ISzAlloc g_Alloc;
-extern ISzAlloc g_BigAlloc;
+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
diff --git a/C/Android.bp b/C/Android.bp
index 434c924..d3585f3 100644
--- a/C/Android.bp
+++ b/C/Android.bp
@@ -16,6 +16,7 @@ cc_library {
"-Wall",
"-Werror",
"-Wno-empty-body",
+ "-Wno-enum-conversion",
],
clang_cflags: ["-Wno-self-assign", "-Werror"],
@@ -71,7 +72,9 @@ cc_library {
"Bcj2Enc.c",
"DllSecur.c",
"LzFindMt.c",
+ "Lzma2DecMt.c",
"MtCoder.c",
+ "MtDec.c",
"Threads.c",
],
},
diff --git a/C/Bcj2.c b/C/Bcj2.c
index 707362a..da93985 100644
--- a/C/Bcj2.c
+++ b/C/Bcj2.c
@@ -1,5 +1,5 @@
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
-2015-08-01 : Igor Pavlov : Public domain */
+2018-04-28 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -61,7 +61,8 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
Byte *dest = p->dest;
if (dest == p->destLim)
return SZ_OK;
- *dest = p->temp[p->state++ - BCJ2_DEC_STATE_ORIG_0];
+ *dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0];
+ p->state++;
p->dest = dest + 1;
}
}
@@ -231,10 +232,10 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
if (rem < 4)
{
- SizeT i;
- SetUi32(p->temp, val);
- for (i = 0; i < rem; i++)
- dest[i] = p->temp[i];
+ 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;
diff --git a/C/Bcj2Enc.c b/C/Bcj2Enc.c
index 6a21015..b0bc759 100644
--- a/C/Bcj2Enc.c
+++ b/C/Bcj2Enc.c
@@ -1,5 +1,5 @@
/* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code)
-2014-11-10 : Igor Pavlov : Public domain */
+2017-04-28 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -12,7 +12,6 @@
#define PRF(x)
#endif
-#include <windows.h>
#include <string.h>
#include "Bcj2.h"
@@ -271,7 +270,7 @@ void Bcj2Enc_Encode(CBcj2Enc *p)
unsigned i;
p->tempPos = tempPos;
for (i = 0; i < tempPos; i++)
- p->temp[i] = p->temp[i + num];
+ p->temp[i] = p->temp[(size_t)i + num];
p->src = src;
p->srcLim = srcLim;
diff --git a/C/Bra.c b/C/Bra.c
index 976810c..cbdcb29 100644
--- a/C/Bra.c
+++ b/C/Bra.c
@@ -1,135 +1,230 @@
/* Bra.c -- Converters for RISC code
-2010-04-16 : 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;
+ 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));
+ */
- 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;
+ 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)
+ Byte *p;
+ const Byte *lim;
+ size &= ~(size_t)3;
+ ip -= 4;
+ p = data;
+ lim = data + size;
+
+ for (;;)
{
- if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
- (data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
+ for (;;)
{
- 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 (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)
- dest = ip + i + src;
+ v += ip + (UInt32)(p - data);
else
- dest = src - (ip + i);
- dest >>= 2;
+ v -= ip + (UInt32)(p - data);
- dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
-
- data[i + 0] = (Byte)(dest >> 24);
- data[i + 1] = (Byte)(dest >> 16);
- data[i + 2] = (Byte)(dest >> 8);
- data[i + 3] = (Byte)dest;
+ v &= 0x01FFFFFF;
+ v -= (UInt32)1 << 24;
+ v ^= 0xFF000000;
+ v >>= 2;
+ v |= 0x40000000;
+ SetBe32(p - 4, v);
}
}
- return i;
}
diff --git a/C/Bra86.c b/C/Bra86.c
index 8dd3ed4..a6463c6 100644
--- a/C/Bra86.c
+++ b/C/Bra86.c
@@ -1,5 +1,5 @@
/* Bra86.c -- Converter for x86 code (BCJ)
-2013-11-12 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -37,7 +37,7 @@ SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding
else
{
mask >>= (unsigned)d;
- if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1])))
+ if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(size_t)(mask >> 1) + 1])))
{
mask = (mask >> 1) | 4;
pos++;
diff --git a/C/BraIA64.c b/C/BraIA64.c
index 813830c..2656907 100644
--- a/C/BraIA64.c
+++ b/C/BraIA64.c
@@ -1,69 +1,53 @@
/* BraIA64.c -- Converter for IA-64 code
-2013-11-12 : 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;
}
diff --git a/C/Compiler.h b/C/Compiler.h
index de8fab3..c788648 100644
--- a/C/Compiler.h
+++ b/C/Compiler.h
@@ -1,5 +1,5 @@
/* Compiler.h
-2015-08-02 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_COMPILER_H
#define __7Z_COMPILER_H
@@ -21,6 +21,7 @@
#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
diff --git a/C/CpuArch.h b/C/CpuArch.h
index ef6083c..7fb2728 100644
--- a/C/CpuArch.h
+++ b/C/CpuArch.h
@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code
-2016-06-09: Igor Pavlov : Public domain */
+2017-09-04 : Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H
#define __CPU_ARCH_H
@@ -16,48 +16,122 @@ If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of pl
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
*/
-#if defined(_M_X64) \
- || defined(_M_AMD64) \
- || defined(__x86_64__) \
- || defined(__AMD64__) \
- || defined(__amd64__)
+#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
-#if defined(MY_CPU_AMD64) \
- || defined(_M_IA64) \
- || defined(__AARCH64EL__) \
- || defined(__AARCH64EB__)
+
+#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_IX86) || defined(__i386__)
-#define MY_CPU_X86
+
+#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(MY_CPU_X86) || defined(MY_CPU_AMD64)
-#define MY_CPU_X86_OR_AMD64
+
+#if defined(_M_IA64) \
+ || defined(__ia64__)
+ #define MY_CPU_IA64
+ #define MY_CPU_NAME "ia64"
+ #define MY_CPU_64BIT
#endif
-#if defined(MY_CPU_X86) \
- || defined(_M_ARM) \
- || defined(__ARMEL__) \
- || defined(__THUMBEL__) \
- || defined(__ARMEB__) \
- || defined(__THUMBEB__)
+
+#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(_WIN32) && defined(_M_ARM)
-#define MY_CPU_ARM_LE
+
+#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(_WIN32) && defined(_M_IA64)
-#define MY_CPU_IA64_LE
+
+#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__) \
@@ -86,14 +160,37 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
#define MY_CPU_BE
#endif
+
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
-Stop_Compiling_Bad_Endian
+ #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(__AARCH64EL__) */
+ || defined(MY_CPU_ARM64) \
+ || defined(__ARM_FEATURE_UNALIGNED)
#define MY_CPU_LE_UNALIGN
#endif
#endif
@@ -139,6 +236,11 @@ Stop_Compiling_Bad_Endian
#endif
+#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)
@@ -146,15 +248,21 @@ Stop_Compiling_Bad_Endian
#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))
+#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))
@@ -179,10 +287,14 @@ Stop_Compiling_Bad_Endian
#endif
+#ifndef GetBe16
+
#define GetBe16(p) ( (UInt16) ( \
((UInt16)((const Byte *)(p))[0] << 8) | \
((const Byte *)(p))[1] ))
+#endif
+
#ifdef MY_CPU_X86_OR_AMD64
diff --git a/C/LzFind.c b/C/LzFind.c
index c335d36..6ea82a9 100644
--- a/C/LzFind.c
+++ b/C/LzFind.c
@@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms
-2015-10-15 : Igor Pavlov : Public domain */
+2017-06-10 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -16,18 +16,18 @@
#define kStartMaxLen 3
-static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
+static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc)
{
if (!p->directInput)
{
- alloc->Free(alloc, p->bufferBase);
+ ISzAlloc_Free(alloc, p->bufferBase);
p->bufferBase = NULL;
}
}
/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
-static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
+static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc)
{
UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
if (p->directInput)
@@ -39,7 +39,7 @@ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *a
{
LzInWindow_Free(p, alloc);
p->blockSize = blockSize;
- p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
+ p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, (size_t)blockSize);
}
return (p->bufferBase != NULL);
}
@@ -81,7 +81,7 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
if (size == 0)
return;
- p->result = p->stream->Read(p->stream, dest, &size);
+ p->result = ISeqInStream_Read(p->stream, dest, &size);
if (p->result != SZ_OK)
return;
if (size == 0)
@@ -142,6 +142,7 @@ void MatchFinder_Construct(CMatchFinder *p)
p->bufferBase = NULL;
p->directInput = 0;
p->hash = NULL;
+ p->expectedDataSize = (UInt64)(Int64)-1;
MatchFinder_SetDefaultSettings(p);
for (i = 0; i < 256; i++)
@@ -149,34 +150,34 @@ void MatchFinder_Construct(CMatchFinder *p)
UInt32 r = i;
unsigned j;
for (j = 0; j < 8; j++)
- r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
+ r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
p->crc[i] = r;
}
}
-static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
+static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc)
{
- alloc->Free(alloc, p->hash);
+ ISzAlloc_Free(alloc, p->hash);
p->hash = NULL;
}
-void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
+void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc)
{
MatchFinder_FreeThisClassMemory(p, alloc);
LzInWindow_Free(p, alloc);
}
-static CLzRef* AllocRefs(size_t num, ISzAlloc *alloc)
+static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc)
{
size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
if (sizeInBytes / sizeof(CLzRef) != num)
return NULL;
- return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
+ return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes);
}
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
- ISzAlloc *alloc)
+ ISzAllocPtr alloc)
{
UInt32 sizeReserv;
@@ -208,7 +209,11 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
hs = (1 << 16) - 1;
else
{
- hs = historySize - 1;
+ hs = historySize;
+ if (hs > p->expectedDataSize)
+ hs = (UInt32)p->expectedDataSize;
+ if (hs != 0)
+ hs--;
hs |= (hs >> 1);
hs |= (hs >> 2);
hs |= (hs >> 4);
@@ -292,17 +297,33 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
p->posLimit = p->pos + limit;
}
-void MatchFinder_Init_2(CMatchFinder *p, int readData)
+
+void MatchFinder_Init_LowHash(CMatchFinder *p)
+{
+ size_t i;
+ CLzRef *items = p->hash;
+ size_t numItems = p->fixedHashSize;
+ for (i = 0; i < numItems; i++)
+ items[i] = kEmptyHashValue;
+}
+
+
+void MatchFinder_Init_HighHash(CMatchFinder *p)
+{
+ size_t i;
+ CLzRef *items = p->hash + p->fixedHashSize;
+ size_t numItems = (size_t)p->hashMask + 1;
+ for (i = 0; i < numItems; i++)
+ items[i] = kEmptyHashValue;
+}
+
+
+void MatchFinder_Init_3(CMatchFinder *p, int readData)
{
- UInt32 i;
- UInt32 *hash = p->hash;
- UInt32 num = p->hashSizeSum;
- for (i = 0; i < num; i++)
- hash[i] = kEmptyHashValue;
-
p->cyclicBufferPos = 0;
p->buffer = p->bufferBase;
- p->pos = p->streamPos = p->cyclicBufferSize;
+ p->pos =
+ p->streamPos = p->cyclicBufferSize;
p->result = SZ_OK;
p->streamEndWasReached = 0;
@@ -312,10 +333,14 @@ void MatchFinder_Init_2(CMatchFinder *p, int readData)
MatchFinder_SetLimits(p);
}
+
void MatchFinder_Init(CMatchFinder *p)
{
- MatchFinder_Init_2(p, True);
+ MatchFinder_Init_HighHash(p);
+ MatchFinder_Init_LowHash(p);
+ MatchFinder_Init_3(p, True);
}
+
static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
{
@@ -558,10 +583,10 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
d2 = pos - hash[h2];
- curMatch = hash[kFix3HashSize + hv];
+ curMatch = (hash + kFix3HashSize)[hv];
hash[h2] = pos;
- hash[kFix3HashSize + hv] = pos;
+ (hash + kFix3HashSize)[hv] = pos;
maxLen = 2;
offset = 0;
@@ -594,13 +619,13 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
pos = p->pos;
d2 = pos - hash[ h2];
- d3 = pos - hash[kFix3HashSize + h3];
+ d3 = pos - (hash + kFix3HashSize)[h3];
- curMatch = hash[kFix4HashSize + hv];
+ curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] = pos;
- hash[kFix3HashSize + h3] = pos;
- hash[kFix4HashSize + hv] = pos;
+ (hash + kFix3HashSize)[h3] = pos;
+ (hash + kFix4HashSize)[hv] = pos;
maxLen = 0;
offset = 0;
@@ -615,7 +640,7 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
maxLen = 3;
- distances[offset + 1] = d3 - 1;
+ distances[(size_t)offset + 1] = d3 - 1;
offset += 2;
d2 = d3;
}
@@ -623,7 +648,7 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0)
{
UPDATE_maxLen
- distances[offset - 2] = maxLen;
+ distances[(size_t)offset - 2] = maxLen;
if (maxLen == lenLimit)
{
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
@@ -650,15 +675,15 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
pos = p->pos;
d2 = pos - hash[ h2];
- d3 = pos - hash[kFix3HashSize + h3];
- d4 = pos - hash[kFix4HashSize + h4];
+ d3 = pos - (hash + kFix3HashSize)[h3];
+ d4 = pos - (hash + kFix4HashSize)[h4];
- curMatch = hash[kFix5HashSize + hv];
+ curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] = pos;
- hash[kFix3HashSize + h3] = pos;
- hash[kFix4HashSize + h4] = pos;
- hash[kFix5HashSize + hv] = pos;
+ (hash + kFix3HashSize)[h3] = pos;
+ (hash + kFix4HashSize)[h4] = pos;
+ (hash + kFix5HashSize)[hv] = pos;
maxLen = 0;
offset = 0;
@@ -691,7 +716,7 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
&& *(cur - d4 + 3) == *(cur + 3))
{
maxLen = 4;
- distances[offset + 1] = d4 - 1;
+ distances[(size_t)offset + 1] = d4 - 1;
offset += 2;
d2 = d4;
}
@@ -699,7 +724,7 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0)
{
UPDATE_maxLen
- distances[offset - 2] = maxLen;
+ distances[(size_t)offset - 2] = maxLen;
if (maxLen == lenLimit)
{
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
@@ -726,13 +751,13 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
pos = p->pos;
d2 = pos - hash[ h2];
- d3 = pos - hash[kFix3HashSize + h3];
+ d3 = pos - (hash + kFix3HashSize)[h3];
- curMatch = hash[kFix4HashSize + hv];
+ curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] = pos;
- hash[kFix3HashSize + h3] = pos;
- hash[kFix4HashSize + hv] = pos;
+ (hash + kFix3HashSize)[h3] = pos;
+ (hash + kFix4HashSize)[hv] = pos;
maxLen = 0;
offset = 0;
@@ -747,7 +772,7 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
maxLen = 3;
- distances[offset + 1] = d3 - 1;
+ distances[(size_t)offset + 1] = d3 - 1;
offset += 2;
d2 = d3;
}
@@ -755,7 +780,7 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0)
{
UPDATE_maxLen
- distances[offset - 2] = maxLen;
+ distances[(size_t)offset - 2] = maxLen;
if (maxLen == lenLimit)
{
p->son[p->cyclicBufferPos] = curMatch;
@@ -784,15 +809,15 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
pos = p->pos;
d2 = pos - hash[ h2];
- d3 = pos - hash[kFix3HashSize + h3];
- d4 = pos - hash[kFix4HashSize + h4];
+ d3 = pos - (hash + kFix3HashSize)[h3];
+ d4 = pos - (hash + kFix4HashSize)[h4];
- curMatch = hash[kFix5HashSize + hv];
+ curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] = pos;
- hash[kFix3HashSize + h3] = pos;
- hash[kFix4HashSize + h4] = pos;
- hash[kFix5HashSize + hv] = pos;
+ (hash + kFix3HashSize)[h3] = pos;
+ (hash + kFix4HashSize)[h4] = pos;
+ (hash + kFix5HashSize)[hv] = pos;
maxLen = 0;
offset = 0;
@@ -825,7 +850,7 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
&& *(cur - d4 + 3) == *(cur + 3))
{
maxLen = 4;
- distances[offset + 1] = d4 - 1;
+ distances[(size_t)offset + 1] = d4 - 1;
offset += 2;
d2 = d4;
}
@@ -833,7 +858,7 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0)
{
UPDATE_maxLen
- distances[offset - 2] = maxLen;
+ distances[(size_t)offset - 2] = maxLen;
if (maxLen == lenLimit)
{
p->son[p->cyclicBufferPos] = curMatch;
@@ -897,9 +922,9 @@ static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_HEADER(3)
HASH3_CALC;
hash = p->hash;
- curMatch = hash[kFix3HashSize + hv];
+ curMatch = (hash + kFix3HashSize)[hv];
hash[h2] =
- hash[kFix3HashSize + hv] = p->pos;
+ (hash + kFix3HashSize)[hv] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
@@ -914,10 +939,10 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_HEADER(4)
HASH4_CALC;
hash = p->hash;
- curMatch = hash[kFix4HashSize + hv];
+ curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] =
- hash[kFix3HashSize + h3] =
- hash[kFix4HashSize + hv] = p->pos;
+ (hash + kFix3HashSize)[h3] =
+ (hash + kFix4HashSize)[hv] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
@@ -933,11 +958,11 @@ static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_HEADER(5)
HASH5_CALC;
hash = p->hash;
- curMatch = hash[kFix5HashSize + hv];
+ curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] =
- hash[kFix3HashSize + h3] =
- hash[kFix4HashSize + h4] =
- hash[kFix5HashSize + hv] = p->pos;
+ (hash + kFix3HashSize)[h3] =
+ (hash + kFix4HashSize)[h4] =
+ (hash + kFix5HashSize)[hv] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
@@ -953,10 +978,10 @@ static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_HEADER(4)
HASH4_CALC;
hash = p->hash;
- curMatch = hash[kFix4HashSize + hv];
+ curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] =
- hash[kFix3HashSize + h3] =
- hash[kFix4HashSize + hv] = p->pos;
+ (hash + kFix3HashSize)[h3] =
+ (hash + kFix4HashSize)[hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS
}
@@ -973,11 +998,11 @@ static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_HEADER(5)
HASH5_CALC;
hash = p->hash;
- curMatch = p->hash[kFix5HashSize + hv];
+ curMatch = hash + kFix5HashSize)[hv];
hash[ h2] =
- hash[kFix3HashSize + h3] =
- hash[kFix4HashSize + h4] =
- hash[kFix5HashSize + hv] = p->pos;
+ (hash + kFix3HashSize)[h3] =
+ (hash + kFix4HashSize)[h4] =
+ (hash + kFix5HashSize)[hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS
}
diff --git a/C/LzFind.h b/C/LzFind.h
index 2ff6673..c77adde 100644
--- a/C/LzFind.h
+++ b/C/LzFind.h
@@ -1,5 +1,5 @@
/* LzFind.h -- Match finder for LZ algorithms
-2015-10-15 : Igor Pavlov : Public domain */
+2017-06-10 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_H
#define __LZ_FIND_H
@@ -47,6 +47,8 @@ typedef struct _CMatchFinder
SRes result;
UInt32 crc[256];
size_t numRefs;
+
+ UInt64 expectedDataSize;
} CMatchFinder;
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
@@ -71,8 +73,8 @@ 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);
+ 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);
@@ -103,7 +105,9 @@ typedef struct _IMatchFinder
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
-void MatchFinder_Init_2(CMatchFinder *p, int readData);
+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);
diff --git a/C/LzFindMt.c b/C/LzFindMt.c
index cb61e09..2563824 100644
--- a/C/LzFindMt.c
+++ b/C/LzFindMt.c
@@ -1,5 +1,5 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
-2015-10-15 : Igor Pavlov : Public domain */
+2017-06-10 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -33,6 +33,8 @@ static void MtSync_GetNextBlock(CMtSync *p)
Event_Set(&p->canStart);
Event_Wait(&p->wasStarted);
+
+ // if (mt) MatchFinder_Init_LowHash(mt->MatchFinder);
}
else
{
@@ -155,6 +157,9 @@ static void HashThreadFunc(CMatchFinderMt *mt)
UInt32 numProcessedBlocks = 0;
Event_Wait(&p->canStart);
Event_Set(&p->wasStarted);
+
+ MatchFinder_Init_HighHash(mt->MatchFinder);
+
for (;;)
{
if (p->exit)
@@ -205,7 +210,7 @@ static 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;
@@ -443,13 +448,13 @@ void MatchFinderMt_Construct(CMatchFinderMt *p)
MtSync_Construct(&p->btSync);
}
-static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
+static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAllocPtr alloc)
{
- alloc->Free(alloc, p->hashBuf);
+ ISzAlloc_Free(alloc, p->hashBuf);
p->hashBuf = NULL;
}
-void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc)
{
MtSync_Destruct(&p->hashSync);
MtSync_Destruct(&p->btSync);
@@ -472,7 +477,7 @@ static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)
}
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;
@@ -480,7 +485,7 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
return SZ_ERROR_PARAM;
if (!p->hashBuf)
{
- p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
+ p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
if (!p->hashBuf)
return SZ_ERROR_MEM;
p->btBuf = p->hashBuf + kHashBufferSize;
@@ -496,14 +501,18 @@ 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;
+
+ 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_2(mf, False);
+ MatchFinder_Init_3(mf, False);
+ MatchFinder_Init_LowHash(mf);
p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf);
p->btNumAvailBytes = 0;
@@ -591,10 +600,10 @@ static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *dista
MT_HASH3_CALC
curMatch2 = hash[ h2];
- curMatch3 = hash[kFix3HashSize + h3];
+ curMatch3 = (hash + kFix3HashSize)[h3];
hash[ h2] = lzPos;
- hash[kFix3HashSize + h3] = lzPos;
+ (hash + kFix3HashSize)[h3] = lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{
@@ -627,12 +636,12 @@ static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distan
MT_HASH4_CALC
curMatch2 = hash[ h2];
- curMatch3 = hash[kFix3HashSize + h3];
- curMatch4 = hash[kFix4HashSize + h4];
+ curMatch3 = (hash + kFix3HashSize)[h3];
+ curMatch4 = (hash + kFix4HashSize)[h4];
hash[ h2] = lzPos;
- hash[kFix3HashSize + h3] = lzPos;
- hash[kFix4HashSize + h4] = lzPos;
+ (hash + kFix3HashSize)[h3] = lzPos;
+ (hash + kFix4HashSize)[h4] = lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{
@@ -684,8 +693,12 @@ static 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
@@ -712,8 +725,12 @@ static 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));
@@ -746,7 +763,7 @@ static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
SKIP_HEADER_MT(3)
UInt32 h2, h3;
MT_HASH3_CALC
- hash[kFix3HashSize + h3] =
+ (hash + kFix3HashSize)[h3] =
hash[ h2] =
p->lzPos;
SKIP_FOOTER_MT
@@ -758,8 +775,8 @@ static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
SKIP_HEADER_MT(4)
UInt32 h2, h3, h4;
MT_HASH4_CALC
- hash[kFix4HashSize + h4] =
- hash[kFix3HashSize + h3] =
+ (hash + kFix4HashSize)[h4] =
+ (hash + kFix3HashSize)[h3] =
hash[ h2] =
p->lzPos;
SKIP_FOOTER_MT
@@ -777,7 +794,7 @@ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
{
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;
diff --git a/C/LzFindMt.h b/C/LzFindMt.h
index 46b6924..3d86c78 100644
--- a/C/LzFindMt.h
+++ b/C/LzFindMt.h
@@ -1,5 +1,5 @@
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
-2015-05-03 : Igor Pavlov : Public domain */
+2017-04-03 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_MT_H
#define __LZ_FIND_MT_H
@@ -90,9 +90,9 @@ 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);
diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c
index b688457..57e7f34 100644
--- a/C/Lzma2Dec.c
+++ b/C/Lzma2Dec.c
@@ -1,5 +1,5 @@
/* Lzma2Dec.c -- LZMA2 Decoder
-2015-11-09 : Igor Pavlov : Public domain */
+2018-02-19 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */
@@ -14,28 +14,22 @@
#include "Lzma2Dec.h"
/*
-00000000 - EOS
-00000001 U U - Uncompressed Reset Dic
-00000010 U U - Uncompressed No Reset
-100uuuuu U U P P - LZMA no reset
-101uuuuu U U P P - LZMA reset state
-110uuuuu U U P P S - LZMA reset state + new prop
-111uuuuu U U P P S - LZMA reset state + new prop + reset dic
+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_LZMA (1 << 7)
-#define LZMA2_CONTROL_COPY_NO_RESET 2
#define LZMA2_CONTROL_COPY_RESET_DIC 1
-#define LZMA2_CONTROL_EOF 0
-#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
-
-#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
-#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
+#define LZMA2_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))
@@ -74,14 +68,14 @@ static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
return SZ_OK;
}
-SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
+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, ISzAlloc *alloc)
+SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
{
Byte props[LZMA_PROPS_SIZE];
RINOK(Lzma2Dec_GetOldProps(prop, props));
@@ -91,9 +85,11 @@ SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
void Lzma2Dec_Init(CLzma2Dec *p)
{
p->state = LZMA2_STATE_CONTROL;
- p->needInitDic = True;
- p->needInitState = True;
- p->needInitProp = True;
+ 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);
}
@@ -102,19 +98,26 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
switch (p->state)
{
case LZMA2_STATE_CONTROL:
+ p->isExtraMode = False;
p->control = b;
- PRF(printf("\n %4X ", (unsigned)p->decoder.dicPos));
- PRF(printf(" %2X", (unsigned)b));
- if (p->control == 0)
+ 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 ((p->control & 0x7F) > 2)
+ if (b == LZMA2_CONTROL_COPY_RESET_DIC)
+ p->needInitLevel = 0xC0;
+ else if (b > 2 || p->needInitLevel == 0xE0)
return LZMA2_STATE_ERROR;
- p->unpackSize = 0;
}
else
- p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
+ {
+ 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:
@@ -124,8 +127,8 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
case LZMA2_STATE_UNPACK1:
p->unpackSize |= (UInt32)b;
p->unpackSize++;
- PRF(printf(" %8u", (unsigned)p->unpackSize));
- return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
+ 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;
@@ -134,9 +137,9 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
case LZMA2_STATE_PACK1:
p->packSize |= (UInt32)b;
p->packSize++;
- PRF(printf(" %8u", (unsigned)p->packSize));
- return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
- (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
+ // 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:
{
@@ -145,13 +148,12 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
return LZMA2_STATE_ERROR;
lc = b % 9;
b /= 9;
- p->decoder.prop.pb = b / 5;
+ p->decoder.prop.pb = (Byte)(b / 5);
lp = b % 5;
if (lc + lp > LZMA2_LCLP_MAX)
return LZMA2_STATE_ERROR;
- p->decoder.prop.lc = lc;
- p->decoder.prop.lp = lp;
- p->needInitProp = False;
+ p->decoder.prop.lc = (Byte)lc;
+ p->decoder.prop.lp = (Byte)lp;
return LZMA2_STATE_DATA;
}
}
@@ -169,6 +171,7 @@ static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT s
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
+
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
@@ -176,12 +179,17 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
*srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED;
- while (p->state != LZMA2_STATE_FINISHED)
+ while (p->state != LZMA2_STATE_ERROR)
{
- SizeT dicPos = p->decoder.dicPos;
+ SizeT dicPos;
+
+ if (p->state == LZMA2_STATE_FINISHED)
+ {
+ *status = LZMA_STATUS_FINISHED_WITH_MARK;
+ return SZ_OK;
+ }
- if (p->state == LZMA2_STATE_ERROR)
- return SZ_ERROR_DATA;
+ dicPos = p->decoder.dicPos;
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
{
@@ -198,29 +206,25 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
}
(*srcLen)++;
p->state = Lzma2Dec_UpdateState(p, *src++);
-
if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
- {
- p->state = LZMA2_STATE_ERROR;
- return SZ_ERROR_DATA;
- }
+ break;
continue;
}
{
- SizeT destSizeCur = dicLimit - dicPos;
- SizeT srcSizeCur = inSize - *srcLen;
+ SizeT inCur = inSize - *srcLen;
+ SizeT outCur = dicLimit - dicPos;
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
- if (p->unpackSize <= destSizeCur)
+ if (outCur >= p->unpackSize)
{
- destSizeCur = (SizeT)p->unpackSize;
+ outCur = (SizeT)p->unpackSize;
curFinishMode = LZMA_FINISH_END;
}
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{
- if (*srcLen == inSize)
+ if (inCur == 0)
{
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
@@ -229,134 +233,240 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
if (p->state == LZMA2_STATE_DATA)
{
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
- if (initDic)
- p->needInitProp = p->needInitState = True;
- else if (p->needInitDic)
- {
- p->state = LZMA2_STATE_ERROR;
- return SZ_ERROR_DATA;
- }
- p->needInitDic = False;
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
}
- if (srcSizeCur > destSizeCur)
- srcSizeCur = destSizeCur;
-
- if (srcSizeCur == 0)
- {
- p->state = LZMA2_STATE_ERROR;
- return SZ_ERROR_DATA;
- }
+ if (inCur > outCur)
+ inCur = outCur;
+ if (inCur == 0)
+ break;
- LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
+ LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
- src += srcSizeCur;
- *srcLen += srcSizeCur;
- p->unpackSize -= (UInt32)srcSizeCur;
+ src += inCur;
+ *srcLen += inCur;
+ p->unpackSize -= (UInt32)inCur;
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
}
else
{
- SizeT outSizeProcessed;
SRes res;
if (p->state == LZMA2_STATE_DATA)
{
- unsigned mode = LZMA2_GET_LZMA_MODE(p);
- Bool initDic = (mode == 3);
- Bool initState = (mode != 0);
- if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
- {
- p->state = LZMA2_STATE_ERROR;
- return SZ_ERROR_DATA;
- }
-
+ Bool initDic = (p->control >= 0xE0);
+ Bool initState = (p->control >= 0xA0);
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
- p->needInitDic = False;
- p->needInitState = False;
p->state = LZMA2_STATE_DATA_CONT;
}
- if (srcSizeCur > p->packSize)
- srcSizeCur = (SizeT)p->packSize;
-
- res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
+ if (inCur > p->packSize)
+ inCur = (SizeT)p->packSize;
- src += srcSizeCur;
- *srcLen += srcSizeCur;
- p->packSize -= (UInt32)srcSizeCur;
+ res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
- outSizeProcessed = p->decoder.dicPos - dicPos;
- p->unpackSize -= (UInt32)outSizeProcessed;
+ src += inCur;
+ *srcLen += inCur;
+ p->packSize -= (UInt32)inCur;
+ outCur = p->decoder.dicPos - dicPos;
+ p->unpackSize -= (UInt32)outCur;
- RINOK(res);
+ if (res != 0)
+ break;
+
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
- return res;
+ {
+ if (p->packSize == 0)
+ break;
+ return SZ_OK;
+ }
- if (srcSizeCur == 0 && outSizeProcessed == 0)
+ if (inCur == 0 && outCur == 0)
{
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|| p->unpackSize != 0
|| p->packSize != 0)
- {
- p->state = LZMA2_STATE_ERROR;
- return SZ_ERROR_DATA;
- }
+ break;
p->state = LZMA2_STATE_CONTROL;
}
- if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
- *status = LZMA_STATUS_NOT_FINISHED;
+ *status = LZMA_STATUS_NOT_SPECIFIED;
}
}
}
- *status = LZMA_STATUS_FINISHED_WITH_MARK;
- return SZ_OK;
+ *status = LZMA_STATUS_NOT_SPECIFIED;
+ p->state = LZMA2_STATE_ERROR;
+ return SZ_ERROR_DATA;
}
+
+
+
+ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
+ SizeT outSize,
+ const Byte *src, SizeT *srcLen,
+ int checkFinishBlock)
+{
+ SizeT inSize = *srcLen;
+ *srcLen = 0;
+
+ while (p->state != LZMA2_STATE_ERROR)
+ {
+ if (p->state == LZMA2_STATE_FINISHED)
+ return LZMA_STATUS_FINISHED_WITH_MARK;
+
+ if (outSize == 0 && !checkFinishBlock)
+ return LZMA_STATUS_NOT_FINISHED;
+
+ if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
+ {
+ if (*srcLen == inSize)
+ return LZMA_STATUS_NEEDS_MORE_INPUT;
+ (*srcLen)++;
+
+ p->state = Lzma2Dec_UpdateState(p, *src++);
+
+ if (p->state == LZMA2_STATE_UNPACK0)
+ {
+ // if (p->decoder.dicPos != 0)
+ if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
+ return LZMA2_PARSE_STATUS_NEW_BLOCK;
+ // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
+ }
+
+ // The following code can be commented.
+ // It's not big problem, if we read additional input bytes.
+ // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
+
+ if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
+ {
+ // checkFinishBlock is true. So we expect that block must be finished,
+ // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
+ // break;
+ return LZMA_STATUS_NOT_FINISHED;
+ }
+
+ if (p->state == LZMA2_STATE_DATA)
+ return LZMA2_PARSE_STATUS_NEW_CHUNK;
+
+ continue;
+ }
+
+ if (outSize == 0)
+ return LZMA_STATUS_NOT_FINISHED;
+
+ {
+ SizeT inCur = inSize - *srcLen;
+
+ if (LZMA2_IS_UNCOMPRESSED_STATE(p))
+ {
+ if (inCur == 0)
+ return LZMA_STATUS_NEEDS_MORE_INPUT;
+ if (inCur > p->unpackSize)
+ inCur = p->unpackSize;
+ if (inCur > outSize)
+ inCur = outSize;
+ p->decoder.dicPos += inCur;
+ src += inCur;
+ *srcLen += inCur;
+ outSize -= inCur;
+ p->unpackSize -= (UInt32)inCur;
+ p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
+ }
+ else
+ {
+ p->isExtraMode = True;
+
+ if (inCur == 0)
+ {
+ if (p->packSize != 0)
+ return LZMA_STATUS_NEEDS_MORE_INPUT;
+ }
+ else if (p->state == LZMA2_STATE_DATA)
+ {
+ p->state = LZMA2_STATE_DATA_CONT;
+ if (*src != 0)
+ {
+ // first byte of lzma chunk must be Zero
+ *srcLen += 1;
+ p->packSize--;
+ break;
+ }
+ }
+
+ if (inCur > p->packSize)
+ inCur = (SizeT)p->packSize;
+
+ src += inCur;
+ *srcLen += inCur;
+ p->packSize -= (UInt32)inCur;
+
+ if (p->packSize == 0)
+ {
+ SizeT rem = outSize;
+ if (rem > p->unpackSize)
+ rem = p->unpackSize;
+ p->decoder.dicPos += rem;
+ p->unpackSize -= (UInt32)rem;
+ outSize -= rem;
+ if (p->unpackSize == 0)
+ p->state = LZMA2_STATE_CONTROL;
+ }
+ }
+ }
+ }
+
+ p->state = LZMA2_STATE_ERROR;
+ return LZMA_STATUS_NOT_SPECIFIED;
+}
+
+
+
+
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT outSize = *destLen, inSize = *srcLen;
*srcLen = *destLen = 0;
+
for (;;)
{
- SizeT srcSizeCur = inSize, outSizeCur, dicPos;
+ SizeT inCur = inSize, outCur, dicPos;
ELzmaFinishMode curFinishMode;
SRes res;
+
if (p->decoder.dicPos == p->decoder.dicBufSize)
p->decoder.dicPos = 0;
dicPos = p->decoder.dicPos;
- if (outSize > p->decoder.dicBufSize - dicPos)
- {
- outSizeCur = p->decoder.dicBufSize;
- curFinishMode = LZMA_FINISH_ANY;
- }
- else
+ curFinishMode = LZMA_FINISH_ANY;
+ outCur = p->decoder.dicBufSize - dicPos;
+
+ if (outCur >= outSize)
{
- outSizeCur = dicPos + outSize;
+ outCur = outSize;
curFinishMode = finishMode;
}
- res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
- src += srcSizeCur;
- inSize -= srcSizeCur;
- *srcLen += srcSizeCur;
- outSizeCur = p->decoder.dicPos - dicPos;
- memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
- dest += outSizeCur;
- outSize -= outSizeCur;
- *destLen += outSizeCur;
+ 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 (outSizeCur == 0 || outSize == 0)
+ 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, ISzAlloc *alloc)
+ Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
{
CLzma2Dec p;
SRes res;
diff --git a/C/Lzma2Dec.h b/C/Lzma2Dec.h
index 026cdef..da50387 100644
--- a/C/Lzma2Dec.h
+++ b/C/Lzma2Dec.h
@@ -1,5 +1,5 @@
/* Lzma2Dec.h -- LZMA2 Decoder
-2015-05-13 : Igor Pavlov : Public domain */
+2018-02-19 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_H
#define __LZMA2_DEC_H
@@ -12,25 +12,24 @@ EXTERN_C_BEGIN
typedef struct
{
- CLzmaDec decoder;
- UInt32 packSize;
- UInt32 unpackSize;
unsigned state;
Byte control;
- Bool needInitDic;
- Bool needInitState;
- Bool needInitProp;
+ 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);
+#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc)
+#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc)
-SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
-SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
+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).
@@ -53,6 +52,47 @@ 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 ---------- */
/*
@@ -73,7 +113,7 @@ Returns:
*/
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
- Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
+ Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc);
EXTERN_C_END
diff --git a/C/Lzma2DecMt.c b/C/Lzma2DecMt.c
new file mode 100644
index 0000000..be698cb
--- /dev/null
+++ b/C/Lzma2DecMt.c
@@ -0,0 +1,1082 @@
+/* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread
+2018-03-02 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+// #define SHOW_DEBUG_INFO
+
+#ifdef SHOW_DEBUG_INFO
+#include <stdio.h>
+#endif
+
+#ifdef SHOW_DEBUG_INFO
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+#define PRF_STR(s) PRF(printf("\n" s "\n"))
+#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
+#define PRF_STR_INT_2(s, d1, d2) PRF(printf("\n" s " %d %d\n", (unsigned)d1, (unsigned)d2))
+
+// #define _7ZIP_ST
+
+#include "Alloc.h"
+
+#include "Lzma2Dec.h"
+#include "Lzma2DecMt.h"
+
+#ifndef _7ZIP_ST
+#include "MtDec.h"
+#endif
+
+
+#define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28)
+
+void Lzma2DecMtProps_Init(CLzma2DecMtProps *p)
+{
+ p->inBufSize_ST = 1 << 20;
+ p->outStep_ST = 1 << 20;
+
+ #ifndef _7ZIP_ST
+ p->numThreads = 1;
+ p->inBufSize_MT = 1 << 18;
+ p->outBlockMax = LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT;
+ p->inBlockMax = p->outBlockMax + p->outBlockMax / 16;
+ #endif
+}
+
+
+
+#ifndef _7ZIP_ST
+
+/* ---------- CLzma2DecMtThread ---------- */
+
+typedef struct
+{
+ CLzma2Dec dec;
+ Byte dec_created;
+ Byte needInit;
+
+ Byte *outBuf;
+ size_t outBufSize;
+
+ EMtDecParseState state;
+ ELzma2ParseStatus parseStatus;
+
+ size_t inPreSize;
+ size_t outPreSize;
+
+ size_t inCodeSize;
+ size_t outCodeSize;
+ SRes codeRes;
+
+ CAlignOffsetAlloc alloc;
+
+ Byte mtPad[1 << 7];
+} CLzma2DecMtThread;
+
+#endif
+
+
+/* ---------- CLzma2DecMt ---------- */
+
+typedef struct
+{
+ // ISzAllocPtr alloc;
+ ISzAllocPtr allocMid;
+
+ CAlignOffsetAlloc alignOffsetAlloc;
+ CLzma2DecMtProps props;
+ Byte prop;
+
+ ISeqInStream *inStream;
+ ISeqOutStream *outStream;
+ ICompressProgress *progress;
+
+ Bool finishMode;
+ Bool outSize_Defined;
+ UInt64 outSize;
+
+ UInt64 outProcessed;
+ UInt64 inProcessed;
+ Bool readWasFinished;
+ SRes readRes;
+
+ Byte *inBuf;
+ size_t inBufSize;
+ Byte dec_created;
+ CLzma2Dec dec;
+
+ size_t inPos;
+ size_t inLim;
+
+ #ifndef _7ZIP_ST
+ UInt64 outProcessed_Parse;
+ Bool mtc_WasConstructed;
+ CMtDec mtc;
+ CLzma2DecMtThread coders[MTDEC__THREADS_MAX];
+ #endif
+
+} CLzma2DecMt;
+
+
+
+CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
+{
+ CLzma2DecMt *p = (CLzma2DecMt *)ISzAlloc_Alloc(alloc, sizeof(CLzma2DecMt));
+ if (!p)
+ return NULL;
+
+ // p->alloc = alloc;
+ p->allocMid = allocMid;
+
+ AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
+ p->alignOffsetAlloc.numAlignBits = 7;
+ p->alignOffsetAlloc.offset = 0;
+ p->alignOffsetAlloc.baseAlloc = alloc;
+
+ p->inBuf = NULL;
+ p->inBufSize = 0;
+ p->dec_created = False;
+
+ // Lzma2DecMtProps_Init(&p->props);
+
+ #ifndef _7ZIP_ST
+ p->mtc_WasConstructed = False;
+ {
+ unsigned i;
+ for (i = 0; i < MTDEC__THREADS_MAX; i++)
+ {
+ CLzma2DecMtThread *t = &p->coders[i];
+ t->dec_created = False;
+ t->outBuf = NULL;
+ t->outBufSize = 0;
+ }
+ }
+ #endif
+
+ return p;
+}
+
+
+#ifndef _7ZIP_ST
+
+static void Lzma2DecMt_FreeOutBufs(CLzma2DecMt *p)
+{
+ unsigned i;
+ for (i = 0; i < MTDEC__THREADS_MAX; i++)
+ {
+ CLzma2DecMtThread *t = &p->coders[i];
+ if (t->outBuf)
+ {
+ ISzAlloc_Free(p->allocMid, t->outBuf);
+ t->outBuf = NULL;
+ t->outBufSize = 0;
+ }
+ }
+}
+
+#endif
+
+
+static void Lzma2DecMt_FreeSt(CLzma2DecMt *p)
+{
+ if (p->dec_created)
+ {
+ Lzma2Dec_Free(&p->dec, &p->alignOffsetAlloc.vt);
+ p->dec_created = False;
+ }
+ if (p->inBuf)
+ {
+ ISzAlloc_Free(p->allocMid, p->inBuf);
+ p->inBuf = NULL;
+ }
+ p->inBufSize = 0;
+}
+
+
+void Lzma2DecMt_Destroy(CLzma2DecMtHandle pp)
+{
+ CLzma2DecMt *p = (CLzma2DecMt *)pp;
+
+ Lzma2DecMt_FreeSt(p);
+
+ #ifndef _7ZIP_ST
+
+ if (p->mtc_WasConstructed)
+ {
+ MtDec_Destruct(&p->mtc);
+ p->mtc_WasConstructed = False;
+ }
+ {
+ unsigned i;
+ for (i = 0; i < MTDEC__THREADS_MAX; i++)
+ {
+ CLzma2DecMtThread *t = &p->coders[i];
+ if (t->dec_created)
+ {
+ // we don't need to free dict here
+ Lzma2Dec_FreeProbs(&t->dec, &t->alloc.vt); // p->alloc !!!
+ t->dec_created = False;
+ }
+ }
+ }
+ Lzma2DecMt_FreeOutBufs(p);
+
+ #endif
+
+ ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
+}
+
+
+
+#ifndef _7ZIP_ST
+
+static void Lzma2DecMt_MtCallback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
+{
+ CLzma2DecMt *me = (CLzma2DecMt *)obj;
+ CLzma2DecMtThread *t = &me->coders[coderIndex];
+
+ PRF_STR_INT_2("Parse", coderIndex, cc->srcSize);
+
+ cc->state = MTDEC_PARSE_CONTINUE;
+
+ if (cc->startCall)
+ {
+ if (!t->dec_created)
+ {
+ Lzma2Dec_Construct(&t->dec);
+ t->dec_created = True;
+ AlignOffsetAlloc_CreateVTable(&t->alloc);
+ {
+ /* (1 << 12) is expected size of one way in data cache.
+ We optimize alignment for cache line size of 128 bytes and smaller */
+ const unsigned kNumAlignBits = 12;
+ const unsigned kNumCacheLineBits = 7; /* <= kNumAlignBits */
+ t->alloc.numAlignBits = kNumAlignBits;
+ t->alloc.offset = ((UInt32)coderIndex * ((1 << 11) + (1 << 8) + (1 << 6))) & ((1 << kNumAlignBits) - (1 << kNumCacheLineBits));
+ t->alloc.baseAlloc = me->alignOffsetAlloc.baseAlloc;
+ }
+ }
+ Lzma2Dec_Init(&t->dec);
+
+ t->inPreSize = 0;
+ t->outPreSize = 0;
+ // t->blockWasFinished = False;
+ // t->finishedWithMark = False;
+ t->parseStatus = LZMA_STATUS_NOT_SPECIFIED;
+ t->state = MTDEC_PARSE_CONTINUE;
+
+ t->inCodeSize = 0;
+ t->outCodeSize = 0;
+ t->codeRes = SZ_OK;
+
+ // (cc->srcSize == 0) is allowed
+ }
+
+ {
+ ELzma2ParseStatus status;
+ Bool overflow;
+ UInt32 unpackRem = 0;
+
+ int checkFinishBlock = True;
+ size_t limit = me->props.outBlockMax;
+ if (me->outSize_Defined)
+ {
+ UInt64 rem = me->outSize - me->outProcessed_Parse;
+ if (limit >= rem)
+ {
+ limit = (size_t)rem;
+ if (!me->finishMode)
+ checkFinishBlock = False;
+ }
+ }
+
+ // checkFinishBlock = False, if we want to decode partial data
+ // that must be finished at position <= outBlockMax.
+
+ {
+ const SizeT srcOrig = cc->srcSize;
+ SizeT srcSize_Point = 0;
+ SizeT dicPos_Point = 0;
+
+ cc->srcSize = 0;
+ overflow = False;
+
+ for (;;)
+ {
+ SizeT srcCur = srcOrig - cc->srcSize;
+
+ status = Lzma2Dec_Parse(&t->dec,
+ limit - t->dec.decoder.dicPos,
+ cc->src + cc->srcSize, &srcCur,
+ checkFinishBlock);
+
+ cc->srcSize += srcCur;
+
+ if (status == LZMA2_PARSE_STATUS_NEW_CHUNK)
+ {
+ if (t->dec.unpackSize > me->props.outBlockMax - t->dec.decoder.dicPos)
+ {
+ overflow = True;
+ break;
+ }
+ continue;
+ }
+
+ if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)
+ {
+ if (t->dec.decoder.dicPos == 0)
+ continue;
+ // we decode small blocks in one thread
+ if (t->dec.decoder.dicPos >= (1 << 14))
+ break;
+ dicPos_Point = t->dec.decoder.dicPos;
+ srcSize_Point = cc->srcSize;
+ continue;
+ }
+
+ if ((int)status == LZMA_STATUS_NOT_FINISHED && checkFinishBlock
+ // && limit == t->dec.decoder.dicPos
+ // && limit == me->props.outBlockMax
+ )
+ {
+ overflow = True;
+ break;
+ }
+
+ unpackRem = Lzma2Dec_GetUnpackExtra(&t->dec);
+ break;
+ }
+
+ if (dicPos_Point != 0
+ && (int)status != LZMA2_PARSE_STATUS_NEW_BLOCK
+ && (int)status != LZMA_STATUS_FINISHED_WITH_MARK
+ && (int)status != LZMA_STATUS_NOT_SPECIFIED)
+ {
+ // we revert to latest newBlock state
+ status = LZMA2_PARSE_STATUS_NEW_BLOCK;
+ unpackRem = 0;
+ t->dec.decoder.dicPos = dicPos_Point;
+ cc->srcSize = srcSize_Point;
+ overflow = False;
+ }
+ }
+
+ t->inPreSize += cc->srcSize;
+ t->parseStatus = status;
+
+ if (overflow)
+ cc->state = MTDEC_PARSE_OVERFLOW;
+ else
+ {
+ size_t dicPos = t->dec.decoder.dicPos;
+
+ if ((int)status != LZMA_STATUS_NEEDS_MORE_INPUT)
+ {
+ if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)
+ {
+ cc->state = MTDEC_PARSE_NEW;
+ cc->srcSize--; // we don't need control byte of next block
+ t->inPreSize--;
+ }
+ else
+ {
+ cc->state = MTDEC_PARSE_END;
+ if ((int)status != LZMA_STATUS_FINISHED_WITH_MARK)
+ {
+ // (status == LZMA_STATUS_NOT_SPECIFIED)
+ // (status == LZMA_STATUS_NOT_FINISHED)
+ if (unpackRem != 0)
+ {
+ /* we also reserve space for max possible number of output bytes of current LZMA chunk */
+ SizeT rem = limit - dicPos;
+ if (rem > unpackRem)
+ rem = unpackRem;
+ dicPos += rem;
+ }
+ }
+ }
+
+ me->outProcessed_Parse += dicPos;
+ }
+
+ cc->outPos = dicPos;
+ t->outPreSize = (size_t)dicPos;
+ }
+
+ t->state = cc->state;
+ return;
+ }
+}
+
+
+static SRes Lzma2DecMt_MtCallback_PreCode(void *pp, unsigned coderIndex)
+{
+ CLzma2DecMt *me = (CLzma2DecMt *)pp;
+ CLzma2DecMtThread *t = &me->coders[coderIndex];
+ Byte *dest = t->outBuf;
+
+ if (t->inPreSize == 0)
+ {
+ t->codeRes = SZ_ERROR_DATA;
+ return t->codeRes;
+ }
+
+ if (!dest || t->outBufSize < t->outPreSize)
+ {
+ if (dest)
+ {
+ ISzAlloc_Free(me->allocMid, dest);
+ t->outBuf = NULL;
+ t->outBufSize = 0;
+ }
+
+ dest = (Byte *)ISzAlloc_Alloc(me->allocMid, t->outPreSize
+ // + (1 << 28)
+ );
+ // Sleep(200);
+ if (!dest)
+ return SZ_ERROR_MEM;
+ t->outBuf = dest;
+ t->outBufSize = t->outPreSize;
+ }
+
+ t->dec.decoder.dic = dest;
+ t->dec.decoder.dicBufSize = t->outPreSize;
+
+ t->needInit = True;
+
+ return Lzma2Dec_AllocateProbs(&t->dec, me->prop, &t->alloc.vt); // alloc.vt
+}
+
+
+static SRes Lzma2DecMt_MtCallback_Code(void *pp, unsigned coderIndex,
+ const Byte *src, size_t srcSize, int srcFinished,
+ // int finished, int blockFinished,
+ UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
+{
+ CLzma2DecMt *me = (CLzma2DecMt *)pp;
+ CLzma2DecMtThread *t = &me->coders[coderIndex];
+
+ UNUSED_VAR(srcFinished)
+
+ PRF_STR_INT_2("Code", coderIndex, srcSize);
+
+ *inCodePos = t->inCodeSize;
+ *outCodePos = 0;
+ *stop = True;
+
+ if (t->needInit)
+ {
+ Lzma2Dec_Init(&t->dec);
+ t->needInit = False;
+ }
+
+ {
+ ELzmaStatus status;
+ size_t srcProcessed = srcSize;
+ Bool blockWasFinished =
+ ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
+ || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK);
+
+ SRes res = Lzma2Dec_DecodeToDic(&t->dec,
+ t->outPreSize,
+ src, &srcProcessed,
+ blockWasFinished ? LZMA_FINISH_END : LZMA_FINISH_ANY,
+ &status);
+
+ t->codeRes = res;
+
+ t->inCodeSize += srcProcessed;
+ *inCodePos = t->inCodeSize;
+ t->outCodeSize = t->dec.decoder.dicPos;
+ *outCodePos = t->dec.decoder.dicPos;
+
+ if (res != SZ_OK)
+ return res;
+
+ if (srcProcessed == srcSize)
+ *stop = False;
+
+ if (blockWasFinished)
+ {
+ if (srcSize != srcProcessed)
+ return SZ_ERROR_FAIL;
+
+ if (t->inPreSize == t->inCodeSize)
+ {
+ if (t->outPreSize != t->outCodeSize)
+ return SZ_ERROR_FAIL;
+ *stop = True;
+ }
+ }
+ else
+ {
+ if (t->outPreSize == t->outCodeSize)
+ *stop = True;
+ }
+
+ return SZ_OK;
+ }
+}
+
+
+#define LZMA2DECMT_STREAM_WRITE_STEP (1 << 24)
+
+static SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex,
+ Bool needWriteToStream,
+ const Byte *src, size_t srcSize,
+ Bool *needContinue, Bool *canRecode)
+{
+ CLzma2DecMt *me = (CLzma2DecMt *)pp;
+ const CLzma2DecMtThread *t = &me->coders[coderIndex];
+ size_t size = t->outCodeSize;
+ const Byte *data = t->outBuf;
+ Bool needContinue2 = True;
+
+ PRF_STR_INT_2("Write", coderIndex, srcSize);
+
+ *needContinue = False;
+ *canRecode = True;
+ UNUSED_VAR(src)
+ UNUSED_VAR(srcSize)
+
+ if (
+ // t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
+ t->state == MTDEC_PARSE_OVERFLOW
+ || t->state == MTDEC_PARSE_END)
+ needContinue2 = False;
+
+
+ if (!needWriteToStream)
+ return SZ_OK;
+
+ me->mtc.inProcessed += t->inCodeSize;
+
+ if (t->codeRes == SZ_OK)
+ if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
+ || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK)
+ if (t->outPreSize != t->outCodeSize
+ || t->inPreSize != t->inCodeSize)
+ return SZ_ERROR_FAIL;
+
+ *canRecode = False;
+
+ if (me->outStream)
+ {
+ for (;;)
+ {
+ size_t cur = size;
+ size_t written;
+ if (cur > LZMA2DECMT_STREAM_WRITE_STEP)
+ cur = LZMA2DECMT_STREAM_WRITE_STEP;
+
+ written = ISeqOutStream_Write(me->outStream, data, cur);
+
+ me->outProcessed += written;
+ // me->mtc.writtenTotal += written;
+ if (written != cur)
+ return SZ_ERROR_WRITE;
+ data += cur;
+ size -= cur;
+ if (size == 0)
+ {
+ *needContinue = needContinue2;
+ return SZ_OK;
+ }
+ RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0));
+ }
+ }
+
+ return SZ_ERROR_FAIL;
+ /*
+ if (size > me->outBufSize)
+ return SZ_ERROR_OUTPUT_EOF;
+ memcpy(me->outBuf, data, size);
+ me->outBufSize -= size;
+ me->outBuf += size;
+ *needContinue = needContinue2;
+ return SZ_OK;
+ */
+}
+
+#endif
+
+
+static SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p)
+{
+ if (!p->dec_created)
+ {
+ Lzma2Dec_Construct(&p->dec);
+ p->dec_created = True;
+ }
+
+ RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt));
+
+ if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
+ {
+ ISzAlloc_Free(p->allocMid, p->inBuf);
+ p->inBufSize = 0;
+ p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
+ if (!p->inBuf)
+ return SZ_ERROR_MEM;
+ p->inBufSize = p->props.inBufSize_ST;
+ }
+
+ Lzma2Dec_Init(&p->dec);
+
+ return SZ_OK;
+}
+
+
+static SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p
+ #ifndef _7ZIP_ST
+ , Bool tMode
+ #endif
+ )
+{
+ SizeT wrPos;
+ size_t inPos, inLim;
+ const Byte *inData;
+ UInt64 inPrev, outPrev;
+
+ CLzma2Dec *dec;
+
+ #ifndef _7ZIP_ST
+ if (tMode)
+ {
+ Lzma2DecMt_FreeOutBufs(p);
+ tMode = MtDec_PrepareRead(&p->mtc);
+ }
+ #endif
+
+ RINOK(Lzma2Dec_Prepare_ST(p));
+
+ dec = &p->dec;
+
+ inPrev = p->inProcessed;
+ outPrev = p->outProcessed;
+
+ inPos = 0;
+ inLim = 0;
+ inData = NULL;
+ wrPos = dec->decoder.dicPos;
+
+ for (;;)
+ {
+ SizeT dicPos;
+ SizeT size;
+ ELzmaFinishMode finishMode;
+ SizeT inProcessed;
+ ELzmaStatus status;
+ SRes res;
+
+ SizeT outProcessed;
+ Bool outFinished;
+ Bool needStop;
+
+ if (inPos == inLim)
+ {
+ #ifndef _7ZIP_ST
+ if (tMode)
+ {
+ inData = MtDec_Read(&p->mtc, &inLim);
+ inPos = 0;
+ if (inData)
+ continue;
+ tMode = False;
+ inLim = 0;
+ }
+ #endif
+
+ if (!p->readWasFinished)
+ {
+ inPos = 0;
+ inLim = p->inBufSize;
+ inData = p->inBuf;
+ p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
+ // p->readProcessed += inLim;
+ // inLim -= 5; p->readWasFinished = True; // for test
+ if (inLim == 0 || p->readRes != SZ_OK)
+ p->readWasFinished = True;
+ }
+ }
+
+ dicPos = dec->decoder.dicPos;
+ {
+ SizeT next = dec->decoder.dicBufSize;
+ if (next - wrPos > p->props.outStep_ST)
+ next = wrPos + p->props.outStep_ST;
+ size = next - dicPos;
+ }
+
+ finishMode = LZMA_FINISH_ANY;
+ if (p->outSize_Defined)
+ {
+ const UInt64 rem = p->outSize - p->outProcessed;
+ if (size >= rem)
+ {
+ size = (SizeT)rem;
+ if (p->finishMode)
+ finishMode = LZMA_FINISH_END;
+ }
+ }
+
+ inProcessed = inLim - inPos;
+
+ res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status);
+
+ inPos += inProcessed;
+ p->inProcessed += inProcessed;
+ outProcessed = dec->decoder.dicPos - dicPos;
+ p->outProcessed += outProcessed;
+
+ outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed);
+
+ needStop = (res != SZ_OK
+ || (inProcessed == 0 && outProcessed == 0)
+ || status == LZMA_STATUS_FINISHED_WITH_MARK
+ || (!p->finishMode && outFinished));
+
+ if (needStop || outProcessed >= size)
+ {
+ SRes res2;
+ {
+ size_t writeSize = dec->decoder.dicPos - wrPos;
+ size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize);
+ res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE;
+ }
+
+ if (dec->decoder.dicPos == dec->decoder.dicBufSize)
+ dec->decoder.dicPos = 0;
+ wrPos = dec->decoder.dicPos;
+
+ RINOK(res2);
+
+ if (needStop)
+ {
+ if (res != SZ_OK)
+ return res;
+
+ if (status == LZMA_STATUS_FINISHED_WITH_MARK)
+ {
+ if (p->finishMode)
+ {
+ if (p->outSize_Defined && p->outSize != p->outProcessed)
+ return SZ_ERROR_DATA;
+ }
+ return SZ_OK;
+ }
+
+ if (!p->finishMode && outFinished)
+ return SZ_OK;
+
+ if (status == LZMA_STATUS_NEEDS_MORE_INPUT)
+ return SZ_ERROR_INPUT_EOF;
+
+ return SZ_ERROR_DATA;
+ }
+ }
+
+ if (p->progress)
+ {
+ UInt64 inDelta = p->inProcessed - inPrev;
+ UInt64 outDelta = p->outProcessed - outPrev;
+ if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
+ {
+ RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed));
+ inPrev = p->inProcessed;
+ outPrev = p->outProcessed;
+ }
+ }
+ }
+}
+
+
+
+SRes Lzma2DecMt_Decode(CLzma2DecMtHandle pp,
+ Byte prop,
+ const CLzma2DecMtProps *props,
+ ISeqOutStream *outStream, const UInt64 *outDataSize, int finishMode,
+ // Byte *outBuf, size_t *outBufSize,
+ ISeqInStream *inStream,
+ // const Byte *inData, size_t inDataSize,
+ UInt64 *inProcessed,
+ // UInt64 *outProcessed,
+ int *isMT,
+ ICompressProgress *progress)
+{
+ CLzma2DecMt *p = (CLzma2DecMt *)pp;
+ #ifndef _7ZIP_ST
+ Bool tMode;
+ #endif
+
+ *inProcessed = 0;
+
+ if (prop > 40)
+ return SZ_ERROR_UNSUPPORTED;
+
+ p->prop = prop;
+ p->props = *props;
+
+ p->inStream = inStream;
+ p->outStream = outStream;
+ p->progress = progress;
+
+ p->outSize = 0;
+ p->outSize_Defined = False;
+ if (outDataSize)
+ {
+ p->outSize_Defined = True;
+ p->outSize = *outDataSize;
+ }
+ p->finishMode = finishMode;
+
+ p->outProcessed = 0;
+ p->inProcessed = 0;
+
+ p->readWasFinished = False;
+
+ *isMT = False;
+
+
+ #ifndef _7ZIP_ST
+
+ tMode = False;
+
+ // p->mtc.parseRes = SZ_OK;
+
+ // p->mtc.numFilledThreads = 0;
+ // p->mtc.crossStart = 0;
+ // p->mtc.crossEnd = 0;
+ // p->mtc.allocError_for_Read_BlockIndex = 0;
+ // p->mtc.isAllocError = False;
+
+ if (p->props.numThreads > 1)
+ {
+ IMtDecCallback vt;
+
+ Lzma2DecMt_FreeSt(p);
+
+ p->outProcessed_Parse = 0;
+
+ if (!p->mtc_WasConstructed)
+ {
+ p->mtc_WasConstructed = True;
+ MtDec_Construct(&p->mtc);
+ }
+
+ p->mtc.progress = progress;
+ p->mtc.inStream = inStream;
+
+ // p->outBuf = NULL;
+ // p->outBufSize = 0;
+ /*
+ if (!outStream)
+ {
+ // p->outBuf = outBuf;
+ // p->outBufSize = *outBufSize;
+ // *outBufSize = 0;
+ return SZ_ERROR_PARAM;
+ }
+ */
+
+ // p->mtc.inBlockMax = p->props.inBlockMax;
+ p->mtc.alloc = &p->alignOffsetAlloc.vt;
+ // p->alignOffsetAlloc.baseAlloc;
+ // p->mtc.inData = inData;
+ // p->mtc.inDataSize = inDataSize;
+ p->mtc.mtCallback = &vt;
+ p->mtc.mtCallbackObject = p;
+
+ p->mtc.inBufSize = p->props.inBufSize_MT;
+
+ p->mtc.numThreadsMax = p->props.numThreads;
+
+ *isMT = True;
+
+ vt.Parse = Lzma2DecMt_MtCallback_Parse;
+ vt.PreCode = Lzma2DecMt_MtCallback_PreCode;
+ vt.Code = Lzma2DecMt_MtCallback_Code;
+ vt.Write = Lzma2DecMt_MtCallback_Write;
+
+ {
+ Bool needContinue = False;
+
+ SRes res = MtDec_Code(&p->mtc);
+
+ /*
+ if (!outStream)
+ *outBufSize = p->outBuf - outBuf;
+ */
+
+ *inProcessed = p->mtc.inProcessed;
+
+ needContinue = False;
+
+ if (res == SZ_OK)
+ {
+ if (p->mtc.mtProgress.res != SZ_OK)
+ res = p->mtc.mtProgress.res;
+ else
+ needContinue = p->mtc.needContinue;
+ }
+
+ if (!needContinue)
+ {
+ if (res == SZ_OK)
+ return p->mtc.readRes;
+ return res;
+ }
+
+ tMode = True;
+ p->readRes = p->mtc.readRes;
+ p->readWasFinished = p->mtc.readWasFinished;
+ p->inProcessed = p->mtc.inProcessed;
+
+ PRF_STR("----- decoding ST -----");
+ }
+ }
+
+ #endif
+
+
+ *isMT = False;
+
+ {
+ SRes res = Lzma2Dec_Decode_ST(p
+ #ifndef _7ZIP_ST
+ , tMode
+ #endif
+ );
+
+ *inProcessed = p->inProcessed;
+
+ // res = SZ_OK; // for test
+ if (res == SZ_OK && p->readRes != SZ_OK)
+ res = p->readRes;
+
+ /*
+ #ifndef _7ZIP_ST
+ if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK)
+ res = p->mtc.parseRes;
+ #endif
+ */
+
+ return res;
+ }
+}
+
+
+/* ---------- Read from CLzma2DecMtHandle Interface ---------- */
+
+SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,
+ Byte prop,
+ const CLzma2DecMtProps *props,
+ const UInt64 *outDataSize, int finishMode,
+ ISeqInStream *inStream)
+{
+ CLzma2DecMt *p = (CLzma2DecMt *)pp;
+
+ if (prop > 40)
+ return SZ_ERROR_UNSUPPORTED;
+
+ p->prop = prop;
+ p->props = *props;
+
+ p->inStream = inStream;
+
+ p->outSize = 0;
+ p->outSize_Defined = False;
+ if (outDataSize)
+ {
+ p->outSize_Defined = True;
+ p->outSize = *outDataSize;
+ }
+ p->finishMode = finishMode;
+
+ p->outProcessed = 0;
+ p->inProcessed = 0;
+
+ p->inPos = 0;
+ p->inLim = 0;
+
+ return Lzma2Dec_Prepare_ST(p);
+}
+
+
+SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,
+ Byte *data, size_t *outSize,
+ UInt64 *inStreamProcessed)
+{
+ CLzma2DecMt *p = (CLzma2DecMt *)pp;
+ ELzmaFinishMode finishMode;
+ SRes readRes;
+ size_t size = *outSize;
+
+ *outSize = 0;
+ *inStreamProcessed = 0;
+
+ finishMode = LZMA_FINISH_ANY;
+ if (p->outSize_Defined)
+ {
+ const UInt64 rem = p->outSize - p->outProcessed;
+ if (size >= rem)
+ {
+ size = (size_t)rem;
+ if (p->finishMode)
+ finishMode = LZMA_FINISH_END;
+ }
+ }
+
+ readRes = SZ_OK;
+
+ for (;;)
+ {
+ SizeT inCur;
+ SizeT outCur;
+ ELzmaStatus status;
+ SRes res;
+
+ if (p->inPos == p->inLim && readRes == SZ_OK)
+ {
+ p->inPos = 0;
+ p->inLim = p->props.inBufSize_ST;
+ readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim);
+ }
+
+ inCur = p->inLim - p->inPos;
+ outCur = size;
+
+ res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur,
+ p->inBuf + p->inPos, &inCur, finishMode, &status);
+
+ p->inPos += inCur;
+ p->inProcessed += inCur;
+ *inStreamProcessed += inCur;
+ p->outProcessed += outCur;
+ *outSize += outCur;
+ size -= outCur;
+ data += outCur;
+
+ if (res != 0)
+ return res;
+
+ /*
+ if (status == LZMA_STATUS_FINISHED_WITH_MARK)
+ return readRes;
+
+ if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
+ {
+ if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize)
+ return SZ_ERROR_DATA;
+ return readRes;
+ }
+ */
+
+ if (inCur == 0 && outCur == 0)
+ return readRes;
+ }
+}
diff --git a/C/Lzma2DecMt.h b/C/Lzma2DecMt.h
new file mode 100644
index 0000000..96f89a3
--- /dev/null
+++ b/C/Lzma2DecMt.h
@@ -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
diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c
index cba0134..5098195 100644
--- a/C/Lzma2Enc.c
+++ b/C/Lzma2Enc.c
@@ -1,9 +1,8 @@
/* Lzma2Enc.c -- LZMA2 Encoder
-2015-10-04 : Igor Pavlov : Public domain */
+2018-04-27 : Igor Pavlov : Public domain */
#include "Precomp.h"
-/* #include <stdio.h> */
#include <string.h>
/* #define _7ZIP_ST */
@@ -13,7 +12,7 @@
#ifndef _7ZIP_ST
#include "MtCoder.h"
#else
-#define NUM_MT_CODER_THREADS_MAX 1
+#define MTCODER__THREADS_MAX 1
#endif
#define LZMA2_CONTROL_LZMA (1 << 7)
@@ -35,34 +34,87 @@
#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;
- Byte props;
- Bool needInitState;
- Bool needInitProp;
} CLzma2EncInt;
-static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props)
+
+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)
{
- Byte propsEncoded[LZMA_PROPS_SIZE];
- SizeT propsSize = LZMA_PROPS_SIZE;
- RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
- RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
p->srcPos = 0;
- p->props = propsEncoded[0];
p->needInitState = True;
p->needInitProp = True;
- return SZ_OK;
}
+
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
- ISzAlloc *alloc, ISzAlloc *allocBig);
+ ISzAllocPtr alloc, ISzAllocPtr allocBig);
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
- UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig);
+ UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
@@ -70,6 +122,9 @@ 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)
@@ -126,7 +181,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
if (outStream)
{
*packSizeRes += destPos;
- if (outStream->Write(outStream, outBuf, destPos) != destPos)
+ if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
return SZ_ERROR_WRITE;
destPos = 0;
}
@@ -154,7 +209,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
outBuf[destPos++] = (Byte)pm;
if (p->needInitProp)
- outBuf[destPos++] = p->props;
+ outBuf[destPos++] = p->propsByte;
p->needInitProp = False;
p->needInitState = False;
@@ -162,7 +217,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
p->srcPos += unpackSize;
if (outStream)
- if (outStream->Write(outStream, outBuf, destPos) != destPos)
+ if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
return SZ_ERROR_WRITE;
*packSizeRes = destPos;
@@ -176,14 +231,16 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
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;
- p->numBlockThreads = -1;
- p->blockSize = 0;
}
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
{
- int t1, t1n, t2, t3;
+ UInt64 fileSize;
+ int t1, t1n, t2, t2r, t3;
{
CLzmaEncProps lzmaProps = p->lzmaProps;
LzmaEncProps_Normalize(&lzmaProps);
@@ -191,11 +248,11 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
}
t1 = p->lzmaProps.numThreads;
- t2 = p->numBlockThreads;
+ t2 = p->numBlockThreads_Max;
t3 = p->numTotalThreads;
- if (t2 > NUM_MT_CODER_THREADS_MAX)
- t2 = NUM_MT_CODER_THREADS_MAX;
+ if (t2 > MTCODER__THREADS_MAX)
+ t2 = MTCODER__THREADS_MAX;
if (t3 <= 0)
{
@@ -211,8 +268,8 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
t1 = 1;
t2 = t3;
}
- if (t2 > NUM_MT_CODER_THREADS_MAX)
- t2 = NUM_MT_CODER_THREADS_MAX;
+ if (t2 > MTCODER__THREADS_MAX)
+ t2 = MTCODER__THREADS_MAX;
}
else if (t1 <= 0)
{
@@ -225,46 +282,71 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
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 == 0)
+ if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID)
{
- UInt32 dictSize = p->lzmaProps.dictSize;
- UInt64 blockSize = (UInt64)dictSize << 2;
- const UInt32 kMinSize = (UInt32)1 << 20;
- const UInt32 kMaxSize = (UInt32)1 << 28;
- if (blockSize < kMinSize) blockSize = kMinSize;
- if (blockSize > kMaxSize) blockSize = kMaxSize;
- if (blockSize < dictSize) blockSize = dictSize;
- p->blockSize = (size_t)blockSize;
+ t2r = t2 = 1;
+ t3 = t1;
}
-
- if (t2 > 1 && p->lzmaProps.reduceSize != (UInt64)(Int64)-1)
+ 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
{
- UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1;
- if (temp > p->lzmaProps.reduceSize)
+ if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO)
{
- UInt64 numBlocks = temp / p->blockSize;
+ 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)
{
- t2 = (unsigned)numBlocks;
- if (t2 == 0)
- t2 = 1;
- t3 = t1 * t2;
+ t2r = (unsigned)numBlocks;
+ if (t2r == 0)
+ t2r = 1;
+ t3 = t1 * t2r;
}
}
}
- p->numBlockThreads = t2;
+ p->numBlockThreads_Max = t2;
+ p->numBlockThreads_Reduced = t2r;
p->numTotalThreads = t3;
}
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
{
- return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
+ return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
}
@@ -274,180 +356,112 @@ typedef struct
{
Byte propEncoded;
CLzma2EncProps props;
+ UInt64 expectedDataSize;
- Byte *outBuf;
+ Byte *tempBufLzma;
- ISzAlloc *alloc;
- ISzAlloc *allocBig;
+ ISzAllocPtr alloc;
+ ISzAllocPtr allocBig;
- CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX];
+ 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];
+ Bool mtCoder_WasConstructed;
CMtCoder mtCoder;
+ Byte *outBufs[MTCODER__BLOCKS_MAX];
+
#endif
} CLzma2Enc;
-/* ---------- Lzma2EncThread ---------- */
-static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
- ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
+CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)
{
- UInt64 packTotal = 0;
- SRes res = SZ_OK;
-
- if (!mainEncoder->outBuf)
+ 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;
{
- mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
- if (!mainEncoder->outBuf)
- return SZ_ERROR_MEM;
+ unsigned i;
+ for (i = 0; i < MTCODER__THREADS_MAX; i++)
+ p->coders[i].enc = NULL;
}
- RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
- RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,
- mainEncoder->alloc, mainEncoder->allocBig));
-
- for (;;)
+ #ifndef _7ZIP_ST
+ p->mtCoder_WasConstructed = False;
{
- size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
- res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream);
- if (res != SZ_OK)
- break;
- packTotal += packSize;
- res = Progress(progress, p->srcPos, packTotal);
- if (res != SZ_OK)
- break;
- if (packSize == 0)
- break;
+ unsigned i;
+ for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
+ p->outBufs[i] = NULL;
+ p->outBufSize = 0;
}
-
- LzmaEnc_Finish(p->enc);
+ #endif
- if (res == SZ_OK)
- {
- Byte b = 0;
- if (outStream->Write(outStream, &b, 1) != 1)
- return SZ_ERROR_WRITE;
- }
-
- return res;
+ return p;
}
#ifndef _7ZIP_ST
-typedef struct
+static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p)
{
- IMtCoderCallback funcTable;
- CLzma2Enc *lzma2Enc;
-} CMtCallbackImp;
-
-static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize,
- const Byte *src, size_t srcSize, int finished)
-{
- CMtCallbackImp *imp = (CMtCallbackImp *)pp;
- CLzma2Enc *mainEncoder = imp->lzma2Enc;
- CLzma2EncInt *p = &mainEncoder->coders[index];
-
- SRes res = SZ_OK;
- {
- size_t destLim = *destSize;
- *destSize = 0;
-
- if (srcSize != 0)
- {
- RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
-
- RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE,
- mainEncoder->alloc, mainEncoder->allocBig));
-
- while (p->srcPos < srcSize)
- {
- size_t packSize = destLim - *destSize;
- res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL);
- if (res != SZ_OK)
- break;
- *destSize += packSize;
-
- if (packSize == 0)
- {
- res = SZ_ERROR_FAIL;
- break;
- }
-
- if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK)
- {
- res = SZ_ERROR_PROGRESS;
- break;
- }
- }
-
- LzmaEnc_Finish(p->enc);
- if (res != SZ_OK)
- return res;
- }
-
- if (finished)
+ unsigned i;
+ for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
+ if (p->outBufs[i])
{
- if (*destSize == destLim)
- return SZ_ERROR_OUTPUT_EOF;
- dest[(*destSize)++] = 0;
+ ISzAlloc_Free(p->alloc, p->outBufs[i]);
+ p->outBufs[i] = NULL;
}
- }
- return res;
+ p->outBufSize = 0;
}
#endif
-/* ---------- Lzma2Enc ---------- */
-
-CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
-{
- CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));
- if (!p)
- return NULL;
- Lzma2EncProps_Init(&p->props);
- Lzma2EncProps_Normalize(&p->props);
- p->outBuf = 0;
- p->alloc = alloc;
- p->allocBig = allocBig;
- {
- unsigned i;
- for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
- p->coders[i].enc = 0;
- }
-
- #ifndef _7ZIP_ST
- MtCoder_Construct(&p->mtCoder);
- #endif
-
- return p;
-}
-
void Lzma2Enc_Destroy(CLzma2EncHandle pp)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
unsigned i;
- for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
+ 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 = 0;
+ t->enc = NULL;
}
}
+
#ifndef _7ZIP_ST
- MtCoder_Destruct(&p->mtCoder);
+ if (p->mtCoder_WasConstructed)
+ {
+ MtCoder_Destruct(&p->mtCoder);
+ p->mtCoder_WasConstructed = False;
+ }
+ Lzma2Enc_FreeOutBufs(p);
#endif
- IAlloc_Free(p->alloc, p->outBuf);
- IAlloc_Free(p->alloc, pp);
+ 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;
@@ -460,6 +474,14 @@ SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *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;
@@ -471,50 +493,311 @@ Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
return (Byte)i;
}
-SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
- ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
+
+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)
{
- CLzma2Enc *p = (CLzma2Enc *)pp;
- int i;
+ UInt64 unpackTotal = 0;
+ UInt64 packTotal = 0;
+ size_t outLim = 0;
+ CLimitedSeqInStream limitedInStream;
+
+ if (outBuf)
+ {
+ outLim = *outBufSize;
+ *outBufSize = 0;
+ }
- for (i = 0; i < p->props.numBlockThreads; i++)
+ if (!p->enc)
{
- CLzma2EncInt *t = &p->coders[(unsigned)i];
- if (!t->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)
{
- t->enc = LzmaEnc_Create(p->alloc);
- if (!t->enc)
+ me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
+ if (!me->tempBufLzma)
return SZ_ERROR_MEM;
}
}
- #ifndef _7ZIP_ST
- if (p->props.numBlockThreads > 1)
+ RINOK(Lzma2EncInt_InitStream(p, &me->props));
+
+ for (;;)
{
- CMtCallbackImp mtCallback;
+ 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;
- mtCallback.funcTable.Code = MtCallbackImp_Code;
- mtCallback.lzma2Enc = p;
+ 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.outStream = outStream;
- p->mtCoder.alloc = p->alloc;
- p->mtCoder.mtCallback = &mtCallback.funcTable;
+ 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 */
- p->mtCoder.blockSize = p->props.blockSize;
- p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;
- if (p->mtCoder.destBlockSize < p->props.blockSize)
{
- p->mtCoder.destBlockSize = (size_t)0 - 1;
- if (p->mtCoder.destBlockSize < p->props.blockSize)
- return SZ_ERROR_FAIL;
+ 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.numThreads = p->props.numBlockThreads;
+
+ p->mtCoder.numThreadsMax = p->props.numBlockThreads_Max;
+ p->mtCoder.expectedDataSize = p->expectedDataSize;
- return MtCoder_Code(&p->mtCoder);
+ {
+ SRes res = MtCoder_Code(&p->mtCoder);
+ if (!outStream)
+ *outBufSize = p->outBuf - outBuf;
+ return res;
+ }
}
+
#endif
- return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
+
+ return Lzma2Enc_EncodeMt1(p,
+ &p->coders[0],
+ outStream, outBuf, outBufSize,
+ inStream, inData, inDataSize,
+ True, /* finished */
+ progress);
}
diff --git a/C/Lzma2Enc.h b/C/Lzma2Enc.h
index 061178a..65f2dd1 100644
--- a/C/Lzma2Enc.h
+++ b/C/Lzma2Enc.h
@@ -1,5 +1,5 @@
/* Lzma2Enc.h -- LZMA2 Encoder
-2013-01-18 : Igor Pavlov : Public domain */
+2017-07-27 : Igor Pavlov : Public domain */
#ifndef __LZMA2_ENC_H
#define __LZMA2_ENC_H
@@ -8,11 +8,15 @@
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;
- size_t blockSize;
- int numBlockThreads;
+ UInt64 blockSize;
+ int numBlockThreads_Reduced;
+ int numBlockThreads_Max;
int numTotalThreads;
} CLzma2EncProps;
@@ -22,40 +26,29 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p);
/* ---------- CLzmaEnc2Handle Interface ---------- */
/* Lzma2Enc_* functions can return the following exit codes:
-Returns:
+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 * CLzma2EncHandle;
-CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig);
+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_Encode(CLzma2EncHandle p,
- ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);
-
-/* ---------- One Call Interface ---------- */
-
-/* Lzma2Encode
-Return code:
- SZ_OK - OK
- SZ_ERROR_MEM - Memory allocation error
- SZ_ERROR_PARAM - Incorrect paramater
- SZ_ERROR_OUTPUT_EOF - output buffer overflow
- SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
-*/
-
-/*
-SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
- const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark,
- ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
-*/
+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
diff --git a/C/LzmaDec.c b/C/LzmaDec.c
index 64f1164..962b94b 100644
--- a/C/LzmaDec.c
+++ b/C/LzmaDec.c
@@ -1,8 +1,9 @@
/* LzmaDec.c -- LZMA Decoder
-2016-05-16 : Igor Pavlov : Public domain */
+2018-02-28 : Igor Pavlov : Public domain */
#include "Precomp.h"
+/* #include "CpuArch.h" */
#include "LzmaDec.h"
#include <string.h>
@@ -24,9 +25,16 @@
#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
{ UPDATE_0(p); i = (i + i); A0; } else \
{ UPDATE_1(p); i = (i + i) + 1; A1; }
-#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
-#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
+#define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); }
+
+#define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \
+ { UPDATE_0(p + i); A0; } else \
+ { UPDATE_1(p + i); A1; }
+#define REV_BIT_VAR( p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; )
+#define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m; , i += m * 2; )
+#define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m , ; )
+
#define TREE_DECODE(probs, limit, i) \
{ i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
@@ -46,12 +54,15 @@
i -= 0x40; }
#endif
-#define NORMAL_LITER_DEC GET_BIT(prob + symbol, symbol)
+#define NORMAL_LITER_DEC TREE_GET_BIT(prob, symbol)
#define MATCHED_LITER_DEC \
- matchByte <<= 1; \
- bit = (matchByte & offs); \
- probLit = prob + offs + bit + symbol; \
- GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
+ matchByte += matchByte; \
+ bit = offs; \
+ offs &= matchByte; \
+ probLit = prob + (offs + bit + symbol); \
+ GET_BIT2(probLit, symbol, offs ^= bit; , ;)
+
+
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
@@ -66,25 +77,28 @@
{ i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
+#define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \
+ { UPDATE_0_CHECK; i += m; m += m; } else \
+ { UPDATE_1_CHECK; m += m; i += m; }
+
+
#define kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax)
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
-#define kLenNumMidBits 3
-#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
-#define LenChoice 0
-#define LenChoice2 (LenChoice + 1)
-#define LenLow (LenChoice2 + 1)
-#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
-#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define LenLow 0
+#define LenHigh (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+#define LenChoice LenLow
+#define LenChoice2 (LenLow + (1 << kLenNumLowBits))
#define kNumStates 12
+#define kNumStates2 16
#define kNumLitStates 7
#define kStartPosModelIndex 4
@@ -98,54 +112,117 @@
#define kAlignTableSize (1 << kNumAlignBits)
#define kMatchMinLen 2
-#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols)
-#define IsMatch 0
-#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+/* External ASM code needs same CLzmaProb array layout. So don't change it. */
+
+/* (probs_1664) is faster and better for code size at some platforms */
+/*
+#ifdef MY_CPU_X86_OR_AMD64
+*/
+#define kStartOffset 1664
+#define GET_PROBS p->probs_1664
+/*
+#define GET_PROBS p->probs + kStartOffset
+#else
+#define kStartOffset 0
+#define GET_PROBS p->probs
+#endif
+*/
+
+#define SpecPos (-kStartOffset)
+#define IsRep0Long (SpecPos + kNumFullDistances)
+#define RepLenCoder (IsRep0Long + (kNumStates2 << kNumPosBitsMax))
+#define LenCoder (RepLenCoder + kNumLenProbs)
+#define IsMatch (LenCoder + kNumLenProbs)
+#define Align (IsMatch + (kNumStates2 << kNumPosBitsMax))
+#define IsRep (Align + kAlignTableSize)
#define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates)
-#define IsRep0Long (IsRepG2 + kNumStates)
-#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
-#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
-#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
-#define LenCoder (Align + kAlignTableSize)
-#define RepLenCoder (LenCoder + kNumLenProbs)
-#define Literal (RepLenCoder + kNumLenProbs)
-
-#define LZMA_BASE_SIZE 1846
-#define LZMA_LIT_SIZE 0x300
+#define PosSlot (IsRepG2 + kNumStates)
+#define Literal (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define NUM_BASE_PROBS (Literal + kStartOffset)
-#if Literal != LZMA_BASE_SIZE
-StopCompilingDueBUG
+#if Align != 0 && kStartOffset != 0
+ #error Stop_Compiling_Bad_LZMA_kAlign
#endif
-#define LzmaProps_GetNumProbs(p) (Literal + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
+#if NUM_BASE_PROBS != 1984
+ #error Stop_Compiling_Bad_LZMA_PROBS
+#endif
+
+
+#define LZMA_LIT_SIZE 0x300
+
+#define LzmaProps_GetNumProbs(p) (NUM_BASE_PROBS + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
+
+
+#define CALC_POS_STATE(processedPos, pbMask) (((processedPos) & (pbMask)) << 4)
+#define COMBINED_PS_STATE (posState + state)
+#define GET_LEN_STATE (posState)
#define LZMA_DIC_MIN (1 << 12)
-/* First LZMA-symbol is always decoded.
-And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
+/*
+p->remainLen : shows status of LZMA decoder:
+ < kMatchSpecLenStart : normal remain
+ = kMatchSpecLenStart : finished
+ = kMatchSpecLenStart + 1 : need init range coder
+ = kMatchSpecLenStart + 2 : need init range coder and state
+*/
+
+/* ---------- LZMA_DECODE_REAL ---------- */
+/*
+LzmaDec_DecodeReal_3() can be implemented in external ASM file.
+3 - is the code compatibility version of that function for check at link time.
+*/
+
+#define LZMA_DECODE_REAL LzmaDec_DecodeReal_3
+
+/*
+LZMA_DECODE_REAL()
+In:
+ RangeCoder is normalized
+ if (p->dicPos == limit)
+ {
+ LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases.
+ So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol
+ is not END_OF_PAYALOAD_MARKER, then function returns error code.
+ }
+
+Processing:
+ first LZMA symbol will be decoded in any case
+ All checks for limits are at the end of main loop,
+ It will decode new LZMA-symbols while (p->buf < bufLimit && dicPos < limit),
+ RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked.
+
Out:
+ RangeCoder is normalized
Result:
SZ_OK - OK
SZ_ERROR_DATA - Error
p->remainLen:
< kMatchSpecLenStart : normal remain
= kMatchSpecLenStart : finished
- = kMatchSpecLenStart + 1 : Flush marker (unused now)
- = kMatchSpecLenStart + 2 : State Init Marker (unused now)
*/
-static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
-{
- CLzmaProb *probs = p->probs;
- unsigned state = p->state;
+#ifdef _LZMA_DEC_OPT
+
+int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit);
+
+#else
+
+static
+int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+ CLzmaProb *probs = GET_PROBS;
+ unsigned state = (unsigned)p->state;
UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
- unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
unsigned lc = p->prop.lc;
+ unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc);
Byte *dic = p->dic;
SizeT dicBufSize = p->dicBufSize;
@@ -164,17 +241,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
CLzmaProb *prob;
UInt32 bound;
unsigned ttt;
- unsigned posState = processedPos & pbMask;
+ unsigned posState = CALC_POS_STATE(processedPos, pbMask);
- prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+ prob = probs + IsMatch + COMBINED_PS_STATE;
IF_BIT_0(prob)
{
unsigned symbol;
UPDATE_0(prob);
prob = probs + Literal;
if (processedPos != 0 || checkDicSize != 0)
- prob += ((UInt32)LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
- (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
+ prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc);
processedPos++;
if (state < kNumLitStates)
@@ -240,13 +316,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
else
{
UPDATE_1(prob);
+ /*
+ // that case was checked before with kBadRepCode
if (checkDicSize == 0 && processedPos == 0)
return SZ_ERROR_DATA;
+ */
prob = probs + IsRepG0 + state;
IF_BIT_0(prob)
{
UPDATE_0(prob);
- prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ prob = probs + IsRep0Long + COMBINED_PS_STATE;
IF_BIT_0(prob)
{
UPDATE_0(prob);
@@ -299,7 +378,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
IF_BIT_0(probLen)
{
UPDATE_0(probLen);
- probLen = prob + LenLow + (posState << kLenNumLowBits);
+ probLen = prob + LenLow + GET_LEN_STATE;
offset = 0;
lim = (1 << kLenNumLowBits);
}
@@ -310,15 +389,15 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
IF_BIT_0(probLen)
{
UPDATE_0(probLen);
- probLen = prob + LenMid + (posState << kLenNumMidBits);
+ probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
offset = kLenNumLowSymbols;
- lim = (1 << kLenNumMidBits);
+ lim = (1 << kLenNumLowBits);
}
else
{
UPDATE_1(probLen);
probLen = prob + LenHigh;
- offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ offset = kLenNumLowSymbols * 2;
lim = (1 << kLenNumHighBits);
}
}
@@ -331,7 +410,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
IF_BIT_0(probLen)
{
UPDATE_0(probLen);
- probLen = prob + LenLow + (posState << kLenNumLowBits);
+ probLen = prob + LenLow + GET_LEN_STATE;
len = 1;
TREE_GET_BIT(probLen, len);
TREE_GET_BIT(probLen, len);
@@ -345,7 +424,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
IF_BIT_0(probLen)
{
UPDATE_0(probLen);
- probLen = prob + LenMid + (posState << kLenNumMidBits);
+ probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
len = 1;
TREE_GET_BIT(probLen, len);
TREE_GET_BIT(probLen, len);
@@ -356,7 +435,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
UPDATE_1(probLen);
probLen = prob + LenHigh;
TREE_DECODE(probLen, (1 << kLenNumHighBits), len);
- len += kLenNumLowSymbols + kLenNumMidSymbols;
+ len += kLenNumLowSymbols * 2;
}
}
}
@@ -376,16 +455,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
if (posSlot < kEndPosModelIndex)
{
distance <<= numDirectBits;
- prob = probs + SpecPos + distance - posSlot - 1;
+ prob = probs + SpecPos;
{
- UInt32 mask = 1;
- unsigned i = 1;
+ UInt32 m = 1;
+ distance++;
do
{
- GET_BIT2(prob + i, i, ; , distance |= mask);
- mask <<= 1;
+ REV_BIT_VAR(prob, distance, m);
}
- while (--numDirectBits != 0);
+ while (--numDirectBits);
+ distance -= m;
}
}
else
@@ -412,19 +491,20 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
}
*/
}
- while (--numDirectBits != 0);
+ while (--numDirectBits);
prob = probs + Align;
distance <<= kNumAlignBits;
{
unsigned i = 1;
- GET_BIT2(prob + i, i, ; , distance |= 1);
- GET_BIT2(prob + i, i, ; , distance |= 2);
- GET_BIT2(prob + i, i, ; , distance |= 4);
- GET_BIT2(prob + i, i, ; , distance |= 8);
+ REV_BIT_CONST(prob, i, 1);
+ REV_BIT_CONST(prob, i, 2);
+ REV_BIT_CONST(prob, i, 4);
+ REV_BIT_LAST (prob, i, 8);
+ distance |= i;
}
if (distance == (UInt32)0xFFFFFFFF)
{
- len += kMatchSpecLenStart;
+ len = kMatchSpecLenStart;
state -= kNumStates;
break;
}
@@ -435,20 +515,12 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
rep2 = rep1;
rep1 = rep0;
rep0 = distance + 1;
- if (checkDicSize == 0)
- {
- if (distance >= processedPos)
- {
- p->dicPos = dicPos;
- return SZ_ERROR_DATA;
- }
- }
- else if (distance >= checkDicSize)
+ state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
+ if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize))
{
p->dicPos = dicPos;
return SZ_ERROR_DATA;
}
- state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
}
len += kMatchMinLen;
@@ -511,6 +583,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
return SZ_OK;
}
+#endif
static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
{
@@ -519,7 +592,7 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
Byte *dic = p->dic;
SizeT dicPos = p->dicPos;
SizeT dicBufSize = p->dicBufSize;
- unsigned len = p->remainLen;
+ unsigned len = (unsigned)p->remainLen;
SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
SizeT rem = limit - dicPos;
if (rem < len)
@@ -540,6 +613,14 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
}
}
+
+#define kRange0 0xFFFFFFFF
+#define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))
+#define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)))
+#if kBadRepCode != (0xC0000000 - 0x400)
+ #error Stop_Compiling_Bad_LZMA_Check
+#endif
+
static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
{
do
@@ -550,9 +631,13 @@ static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte
UInt32 rem = p->prop.dicSize - p->processedPos;
if (limit - p->dicPos > rem)
limit2 = p->dicPos + rem;
+
+ if (p->processedPos == 0)
+ if (p->code >= kBadRepCode)
+ return SZ_ERROR_DATA;
}
-
- RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
+
+ RINOK(LZMA_DECODE_REAL(p, limit2, bufLimit));
if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)
p->checkDicSize = p->prop.dicSize;
@@ -561,9 +646,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte
}
while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
- if (p->remainLen > kMatchSpecLenStart)
- p->remainLen = kMatchSpecLenStart;
-
return 0;
}
@@ -580,17 +662,17 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
UInt32 range = p->range;
UInt32 code = p->code;
const Byte *bufLimit = buf + inSize;
- const CLzmaProb *probs = p->probs;
- unsigned state = p->state;
+ const CLzmaProb *probs = GET_PROBS;
+ unsigned state = (unsigned)p->state;
ELzmaDummy res;
{
const CLzmaProb *prob;
UInt32 bound;
unsigned ttt;
- unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
+ unsigned posState = CALC_POS_STATE(p->processedPos, (1 << p->prop.pb) - 1);
- prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+ prob = probs + IsMatch + COMBINED_PS_STATE;
IF_BIT_0_CHECK(prob)
{
UPDATE_0_CHECK
@@ -618,10 +700,11 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
{
unsigned bit;
const CLzmaProb *probLit;
- matchByte <<= 1;
- bit = (matchByte & offs);
- probLit = prob + offs + bit + symbol;
- GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
+ matchByte += matchByte;
+ bit = offs;
+ offs &= matchByte;
+ probLit = prob + (offs + bit + symbol);
+ GET_BIT2_CHECK(probLit, symbol, offs ^= bit; , ; )
}
while (symbol < 0x100);
}
@@ -648,7 +731,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
IF_BIT_0_CHECK(prob)
{
UPDATE_0_CHECK;
- prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ prob = probs + IsRep0Long + COMBINED_PS_STATE;
IF_BIT_0_CHECK(prob)
{
UPDATE_0_CHECK;
@@ -691,7 +774,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
IF_BIT_0_CHECK(probLen)
{
UPDATE_0_CHECK;
- probLen = prob + LenLow + (posState << kLenNumLowBits);
+ probLen = prob + LenLow + GET_LEN_STATE;
offset = 0;
limit = 1 << kLenNumLowBits;
}
@@ -702,15 +785,15 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
IF_BIT_0_CHECK(probLen)
{
UPDATE_0_CHECK;
- probLen = prob + LenMid + (posState << kLenNumMidBits);
+ probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
offset = kLenNumLowSymbols;
- limit = 1 << kLenNumMidBits;
+ limit = 1 << kLenNumLowBits;
}
else
{
UPDATE_1_CHECK;
probLen = prob + LenHigh;
- offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ offset = kLenNumLowSymbols * 2;
limit = 1 << kLenNumHighBits;
}
}
@@ -722,7 +805,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
{
unsigned posSlot;
prob = probs + PosSlot +
- ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) <<
kNumPosSlotBits);
TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
if (posSlot >= kStartPosModelIndex)
@@ -733,7 +816,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
if (posSlot < kEndPosModelIndex)
{
- prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
+ prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits);
}
else
{
@@ -745,17 +828,18 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
code -= range & (((code - range) >> 31) - 1);
/* if (code >= range) code -= range; */
}
- while (--numDirectBits != 0);
+ while (--numDirectBits);
prob = probs + Align;
numDirectBits = kNumAlignBits;
}
{
unsigned i = 1;
+ unsigned m = 1;
do
{
- GET_BIT_CHECK(prob + i, i);
+ REV_BIT_CHECK(prob, i, m);
}
- while (--numDirectBits != 0);
+ while (--numDirectBits);
}
}
}
@@ -768,18 +852,17 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
{
- p->needFlush = 1;
- p->remainLen = 0;
+ p->remainLen = kMatchSpecLenStart + 1;
p->tempBufSize = 0;
if (initDic)
{
p->processedPos = 0;
p->checkDicSize = 0;
- p->needInitState = 1;
+ p->remainLen = kMatchSpecLenStart + 2;
}
if (initState)
- p->needInitState = 1;
+ p->remainLen = kMatchSpecLenStart + 2;
}
void LzmaDec_Init(CLzmaDec *p)
@@ -788,53 +871,54 @@ void LzmaDec_Init(CLzmaDec *p)
LzmaDec_InitDicAndState(p, True, True);
}
-static void LzmaDec_InitStateReal(CLzmaDec *p)
-{
- SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
- SizeT i;
- CLzmaProb *probs = p->probs;
- for (i = 0; i < numProbs; i++)
- probs[i] = kBitModelTotal >> 1;
- p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
- p->state = 0;
- p->needInitState = 0;
-}
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT inSize = *srcLen;
(*srcLen) = 0;
- LzmaDec_WriteRem(p, dicLimit);
*status = LZMA_STATUS_NOT_SPECIFIED;
- while (p->remainLen != kMatchSpecLenStart)
+ if (p->remainLen > kMatchSpecLenStart)
{
- int checkEndMarkNow;
+ for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
+ p->tempBuf[p->tempBufSize++] = *src++;
+ if (p->tempBufSize != 0 && p->tempBuf[0] != 0)
+ return SZ_ERROR_DATA;
+ if (p->tempBufSize < RC_INIT_SIZE)
+ {
+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
+ p->code =
+ ((UInt32)p->tempBuf[1] << 24)
+ | ((UInt32)p->tempBuf[2] << 16)
+ | ((UInt32)p->tempBuf[3] << 8)
+ | ((UInt32)p->tempBuf[4]);
+ p->range = 0xFFFFFFFF;
+ p->tempBufSize = 0;
+
+ if (p->remainLen > kMatchSpecLenStart + 1)
+ {
+ SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
+ SizeT i;
+ CLzmaProb *probs = p->probs;
+ for (i = 0; i < numProbs; i++)
+ probs[i] = kBitModelTotal >> 1;
+ p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
+ p->state = 0;
+ }
- if (p->needFlush)
- {
- for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
- p->tempBuf[p->tempBufSize++] = *src++;
- if (p->tempBufSize < RC_INIT_SIZE)
- {
- *status = LZMA_STATUS_NEEDS_MORE_INPUT;
- return SZ_OK;
- }
- if (p->tempBuf[0] != 0)
- return SZ_ERROR_DATA;
- p->code =
- ((UInt32)p->tempBuf[1] << 24)
- | ((UInt32)p->tempBuf[2] << 16)
- | ((UInt32)p->tempBuf[3] << 8)
- | ((UInt32)p->tempBuf[4]);
- p->range = 0xFFFFFFFF;
- p->needFlush = 0;
- p->tempBufSize = 0;
- }
+ p->remainLen = 0;
+ }
+
+ LzmaDec_WriteRem(p, dicLimit);
+
+ while (p->remainLen != kMatchSpecLenStart)
+ {
+ int checkEndMarkNow = 0;
- checkEndMarkNow = 0;
if (p->dicPos >= dicLimit)
{
if (p->remainLen == 0 && p->code == 0)
@@ -855,9 +939,6 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
checkEndMarkNow = 1;
}
- if (p->needInitState)
- LzmaDec_InitStateReal(p);
-
if (p->tempBufSize == 0)
{
SizeT processed;
@@ -930,11 +1011,14 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
p->tempBufSize = 0;
}
}
- if (p->code == 0)
- *status = LZMA_STATUS_FINISHED_WITH_MARK;
- return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
+
+ if (p->code != 0)
+ return SZ_ERROR_DATA;
+ *status = LZMA_STATUS_FINISHED_WITH_MARK;
+ return SZ_OK;
}
+
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT outSize = *destLen;
@@ -975,19 +1059,19 @@ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *sr
}
}
-void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc)
{
- alloc->Free(alloc, p->probs);
+ ISzAlloc_Free(alloc, p->probs);
p->probs = NULL;
}
-static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAllocPtr alloc)
{
- alloc->Free(alloc, p->dic);
+ ISzAlloc_Free(alloc, p->dic);
p->dic = NULL;
}
-void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
+void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc)
{
LzmaDec_FreeProbs(p, alloc);
LzmaDec_FreeDict(p, alloc);
@@ -1011,29 +1095,30 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
if (d >= (9 * 5 * 5))
return SZ_ERROR_UNSUPPORTED;
- p->lc = d % 9;
+ p->lc = (Byte)(d % 9);
d /= 9;
- p->pb = d / 5;
- p->lp = d % 5;
+ p->pb = (Byte)(d / 5);
+ p->lp = (Byte)(d % 5);
return SZ_OK;
}
-static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAllocPtr alloc)
{
UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
if (!p->probs || numProbs != p->numProbs)
{
LzmaDec_FreeProbs(p, alloc);
- p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
- p->numProbs = numProbs;
+ p->probs = (CLzmaProb *)ISzAlloc_Alloc(alloc, numProbs * sizeof(CLzmaProb));
if (!p->probs)
return SZ_ERROR_MEM;
+ p->probs_1664 = p->probs + 1664;
+ p->numProbs = numProbs;
}
return SZ_OK;
}
-SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)
{
CLzmaProps propNew;
RINOK(LzmaProps_Decode(&propNew, props, propsSize));
@@ -1042,7 +1127,7 @@ SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, I
return SZ_OK;
}
-SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)
{
CLzmaProps propNew;
SizeT dicBufSize;
@@ -1062,7 +1147,7 @@ SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAll
if (!p->dic || dicBufSize != p->dicBufSize)
{
LzmaDec_FreeDict(p, alloc);
- p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
+ p->dic = (Byte *)ISzAlloc_Alloc(alloc, dicBufSize);
if (!p->dic)
{
LzmaDec_FreeProbs(p, alloc);
@@ -1076,7 +1161,7 @@ SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAll
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)
{
CLzmaDec p;
SRes res;
diff --git a/C/LzmaDec.h b/C/LzmaDec.h
index 2633abe..28ce60c 100644
--- a/C/LzmaDec.h
+++ b/C/LzmaDec.h
@@ -1,5 +1,5 @@
/* LzmaDec.h -- LZMA Decoder
-2013-01-18 : Igor Pavlov : Public domain */
+2018-04-21 : Igor Pavlov : Public domain */
#ifndef __LZMA_DEC_H
#define __LZMA_DEC_H
@@ -12,11 +12,13 @@ EXTERN_C_BEGIN
/* _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 ---------- */
@@ -25,7 +27,10 @@ EXTERN_C_BEGIN
typedef struct _CLzmaProps
{
- unsigned lc, lp, pb;
+ Byte lc;
+ Byte lp;
+ Byte pb;
+ Byte _pad_;
UInt32 dicSize;
} CLzmaProps;
@@ -47,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
{
@@ -129,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 ---------- */
@@ -142,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)
{
@@ -220,7 +227,7 @@ 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
diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c
index 462ca67..bebe664 100644
--- a/C/LzmaEnc.c
+++ b/C/LzmaEnc.c
@@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder
-2016-05-16 : Igor Pavlov : Public domain */
+2018-04-29 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -23,17 +23,8 @@
static unsigned g_STAT_OFFSET = 0;
#endif
-#define kMaxHistorySize ((UInt32)3 << 29)
-/* #define kMaxHistorySize ((UInt32)7 << 29) */
-
-#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
-
-#define kBlockSize (9 << 10)
-#define kUnpackBlockSize (1 << 18)
-#define kMatchArraySize (1 << 21)
-#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
-
-#define kNumMaxDirectBits (31)
+#define kLzmaMaxHistorySize ((UInt32)3 << 29)
+/* #define kLzmaMaxHistorySize ((UInt32)7 << 29) */
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
@@ -62,14 +53,15 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
if (level < 0) level = 5;
p->level = level;
- if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
+ if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level <= 7 ? (1 << 25) : (1 << 26)));
if (p->dictSize > p->reduceSize)
{
unsigned i;
+ UInt32 reduceSize = (UInt32)p->reduceSize;
for (i = 11; i <= 30; i++)
{
- if ((UInt32)p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }
- if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
+ if (reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }
+ if (reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
}
}
@@ -110,9 +102,9 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
#define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); }
-static UInt32 GetPosSlot1(UInt32 pos)
+static unsigned GetPosSlot1(UInt32 pos)
{
- UInt32 res;
+ unsigned res;
BSR2_RET(pos, res);
return res;
}
@@ -145,18 +137,18 @@ static void LzmaEnc_FastPosInit(Byte *g_FastPos)
/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
/*
-#define BSR2_RET(pos, res) { UInt32 zz = 6 + ((kNumLogBits - 1) & \
+#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
(0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
res = p->g_FastPos[pos >> zz] + (zz * 2); }
*/
/*
-#define BSR2_RET(pos, res) { UInt32 zz = 6 + ((kNumLogBits - 1) & \
+#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
(0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
res = p->g_FastPos[pos >> zz] + (zz * 2); }
*/
-#define BSR2_RET(pos, res) { UInt32 zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
+#define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
res = p->g_FastPos[pos >> zz] + (zz * 2); }
/*
@@ -167,32 +159,32 @@ static void LzmaEnc_FastPosInit(Byte *g_FastPos)
#define GetPosSlot1(pos) p->g_FastPos[pos]
#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
-#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); }
#endif
#define LZMA_NUM_REPS 4
-typedef unsigned CState;
+typedef UInt16 CState;
+typedef UInt16 CExtra;
typedef struct
{
UInt32 price;
-
CState state;
- int prev1IsChar;
- int prev2;
-
- UInt32 posPrev2;
- UInt32 backPrev2;
-
- UInt32 posPrev;
- UInt32 backPrev;
- UInt32 backs[LZMA_NUM_REPS];
+ CExtra extra;
+ // 0 : normal
+ // 1 : LIT : MATCH
+ // > 1 : MATCH (extra-1) : LIT : REP0 (len)
+ UInt32 len;
+ UInt32 dist;
+ UInt32 reps[LZMA_NUM_REPS];
} COptimal;
+
#define kNumOpts (1 << 12)
+#define kPackReserve (1 + kNumOpts * 2)
#define kNumLenToPosStates 4
#define kNumPosSlotBits 6
@@ -200,22 +192,21 @@ typedef struct
#define kDicLogSizeMax 32
#define kDistTableSizeMax (kDicLogSizeMax * 2)
-
#define kNumAlignBits 4
#define kAlignTableSize (1 << kNumAlignBits)
#define kAlignMask (kAlignTableSize - 1)
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
-#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
-
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+typedef
#ifdef _LZMA_PROB32
-#define CLzmaProb UInt32
+ UInt32
#else
-#define CLzmaProb UInt16
+ UInt16
#endif
+ CLzmaProb;
#define LZMA_PB_MAX 4
#define LZMA_LC_MAX 8
@@ -223,15 +214,11 @@ typedef struct
#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
-
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
-#define kLenNumMidBits 3
-#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
-
-#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)
#define LZMA_MATCH_LEN_MIN 2
#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
@@ -241,27 +228,23 @@ typedef struct
typedef struct
{
- CLzmaProb choice;
- CLzmaProb choice2;
- CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
- CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
+ CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)];
CLzmaProb high[kLenNumHighSymbols];
} CLenEnc;
typedef struct
{
- CLenEnc p;
- UInt32 tableSize;
+ unsigned tableSize;
+ unsigned counters[LZMA_NUM_PB_STATES_MAX];
UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
- UInt32 counters[LZMA_NUM_PB_STATES_MAX];
} CLenPriceEnc;
typedef struct
{
UInt32 range;
- Byte cache;
+ unsigned cache;
UInt64 low;
UInt64 cacheSize;
Byte *buf;
@@ -277,48 +260,54 @@ typedef struct
{
CLzmaProb *litProbs;
- UInt32 state;
+ unsigned state;
UInt32 reps[LZMA_NUM_REPS];
- CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+ CLzmaProb posAlignEncoder[1 << kNumAlignBits];
CLzmaProb isRep[kNumStates];
CLzmaProb isRepG0[kNumStates];
CLzmaProb isRepG1[kNumStates];
CLzmaProb isRepG2[kNumStates];
+ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
- CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
- CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+ CLzmaProb posEncoders[kNumFullDistances];
- CLenPriceEnc lenEnc;
- CLenPriceEnc repLenEnc;
+ CLenEnc lenProbs;
+ CLenEnc repLenProbs;
+
} CSaveState;
+typedef UInt32 CProbPrice;
+
+
typedef struct
{
void *matchFinderObj;
IMatchFinder matchFinder;
- UInt32 optimumEndIndex;
- UInt32 optimumCurrentIndex;
+ unsigned optCur;
+ unsigned optEnd;
- UInt32 longestMatchLength;
- UInt32 numPairs;
+ unsigned longestMatchLen;
+ unsigned numPairs;
UInt32 numAvail;
- UInt32 numFastBytes;
- UInt32 additionalOffset;
+ unsigned state;
+ unsigned numFastBytes;
+ unsigned additionalOffset;
UInt32 reps[LZMA_NUM_REPS];
- UInt32 state;
+ unsigned lpMask, pbMask;
+ CLzmaProb *litProbs;
+ CRangeEnc rc;
+
+ UInt32 backRes;
unsigned lc, lp, pb;
- unsigned lpMask, pbMask;
unsigned lclp;
- CLzmaProb *litProbs;
-
Bool fastMode;
Bool writeEndMark;
Bool finished;
@@ -327,19 +316,19 @@ typedef struct
UInt64 nowPos64;
- UInt32 matchPriceCount;
- UInt32 alignPriceCount;
+ unsigned matchPriceCount;
+ unsigned alignPriceCount;
- UInt32 distTableSize;
+ unsigned distTableSize;
UInt32 dictSize;
SRes result;
- CRangeEnc rc;
-
#ifndef _7ZIP_ST
Bool mtMode;
+ // begin of CMatchFinderMt is used in LZ thread
CMatchFinderMt matchFinderMt;
+ // end of CMatchFinderMt is used in BT and HASH threads
#endif
CMatchFinder matchFinderBase;
@@ -348,33 +337,37 @@ typedef struct
Byte pad[128];
#endif
- COptimal opt[kNumOpts];
-
- #ifndef LZMA_LOG_BSR
- Byte g_FastPos[1 << kNumLogBits];
- #endif
+ // LZ thread
+ CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
- UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
+ UInt32 alignPrices[kAlignTableSize];
UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
- UInt32 alignPrices[kAlignTableSize];
- CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+ CLzmaProb posAlignEncoder[1 << kNumAlignBits];
CLzmaProb isRep[kNumStates];
CLzmaProb isRepG0[kNumStates];
CLzmaProb isRepG1[kNumStates];
CLzmaProb isRepG2[kNumStates];
+ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
-
CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
- CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
- CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+ CLzmaProb posEncoders[kNumFullDistances];
+ CLenEnc lenProbs;
+ CLenEnc repLenProbs;
+
+ #ifndef LZMA_LOG_BSR
+ Byte g_FastPos[1 << kNumLogBits];
+ #endif
+
CLenPriceEnc lenEnc;
CLenPriceEnc repLenEnc;
+ COptimal opt[kNumOpts];
+
CSaveState saveState;
#ifndef _7ZIP_ST
@@ -383,58 +376,62 @@ typedef struct
} CLzmaEnc;
+
+#define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr));
+
void LzmaEnc_SaveState(CLzmaEncHandle pp)
{
CLzmaEnc *p = (CLzmaEnc *)pp;
CSaveState *dest = &p->saveState;
- int i;
- dest->lenEnc = p->lenEnc;
- dest->repLenEnc = p->repLenEnc;
+
dest->state = p->state;
+
+ dest->lenProbs = p->lenProbs;
+ dest->repLenProbs = p->repLenProbs;
+
+ COPY_ARR(dest, p, reps);
+
+ COPY_ARR(dest, p, posAlignEncoder);
+ COPY_ARR(dest, p, isRep);
+ COPY_ARR(dest, p, isRepG0);
+ COPY_ARR(dest, p, isRepG1);
+ COPY_ARR(dest, p, isRepG2);
+ COPY_ARR(dest, p, isMatch);
+ COPY_ARR(dest, p, isRep0Long);
+ COPY_ARR(dest, p, posSlotEncoder);
+ COPY_ARR(dest, p, posEncoders);
- for (i = 0; i < kNumStates; i++)
- {
- memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
- memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
- }
- for (i = 0; i < kNumLenToPosStates; i++)
- memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
- memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
- memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
- memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
- memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
- memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
- memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
- memcpy(dest->reps, p->reps, sizeof(p->reps));
memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb));
}
+
void LzmaEnc_RestoreState(CLzmaEncHandle pp)
{
CLzmaEnc *dest = (CLzmaEnc *)pp;
const CSaveState *p = &dest->saveState;
- int i;
- dest->lenEnc = p->lenEnc;
- dest->repLenEnc = p->repLenEnc;
+
dest->state = p->state;
- for (i = 0; i < kNumStates; i++)
- {
- memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
- memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
- }
- for (i = 0; i < kNumLenToPosStates; i++)
- memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
- memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
- memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
- memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
- memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
- memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
- memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
- memcpy(dest->reps, p->reps, sizeof(p->reps));
+ dest->lenProbs = p->lenProbs;
+ dest->repLenProbs = p->repLenProbs;
+
+ COPY_ARR(dest, p, reps);
+
+ COPY_ARR(dest, p, posAlignEncoder);
+ COPY_ARR(dest, p, isRep);
+ COPY_ARR(dest, p, isRepG0);
+ COPY_ARR(dest, p, isRepG1);
+ COPY_ARR(dest, p, isRepG2);
+ COPY_ARR(dest, p, isMatch);
+ COPY_ARR(dest, p, isRep0Long);
+ COPY_ARR(dest, p, posSlotEncoder);
+ COPY_ARR(dest, p, posEncoders);
+
memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb));
}
+
+
SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
{
CLzmaEnc *p = (CLzmaEnc *)pp;
@@ -445,7 +442,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
|| props.lp > LZMA_LP_MAX
|| props.pb > LZMA_PB_MAX
|| props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress)
- || props.dictSize > kMaxHistorySize)
+ || props.dictSize > kLzmaMaxHistorySize)
return SZ_ERROR_PARAM;
p->dictSize = props.dictSize;
@@ -463,7 +460,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
p->fastMode = (props.algo == 0);
p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0);
{
- UInt32 numHashBytes = 4;
+ unsigned numHashBytes = 4;
if (props.btMode)
{
if (props.numHashBytes < 2)
@@ -492,13 +489,27 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
return SZ_OK;
}
-static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
-static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
-static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
-static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
-#define IsCharState(s) ((s) < 7)
+void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ p->matchFinderBase.expectedDataSize = expectedDataSiize;
+}
+
+#define kState_Start 0
+#define kState_LitAfterMatch 4
+#define kState_LitAfterRep 5
+#define kState_MatchAfterLit 7
+#define kState_RepAfterLit 8
+
+static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
+static const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+static const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+static const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+#define IsLitState(s) ((s) < 7)
+#define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1)
#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
#define kInfinityPrice (1 << 30)
@@ -509,14 +520,16 @@ static void RangeEnc_Construct(CRangeEnc *p)
p->bufBase = NULL;
}
-#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
+#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
+#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + ((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)
#define RC_BUF_SIZE (1 << 16)
-static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
+
+static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc)
{
if (!p->bufBase)
{
- p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
+ p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE);
if (!p->bufBase)
return 0;
p->bufLim = p->bufBase + RC_BUF_SIZE;
@@ -524,19 +537,19 @@ static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
return 1;
}
-static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
+static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc)
{
- alloc->Free(alloc, p->bufBase);
+ ISzAlloc_Free(alloc, p->bufBase);
p->bufBase = 0;
}
static void RangeEnc_Init(CRangeEnc *p)
{
/* Stream.Init(); */
- p->low = 0;
p->range = 0xFFFFFFFF;
- p->cacheSize = 1;
p->cache = 0;
+ p->low = 0;
+ p->cacheSize = 0;
p->buf = p->bufBase;
@@ -544,37 +557,48 @@ static void RangeEnc_Init(CRangeEnc *p)
p->res = SZ_OK;
}
-static void RangeEnc_FlushStream(CRangeEnc *p)
+MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p)
{
size_t num;
if (p->res != SZ_OK)
return;
num = p->buf - p->bufBase;
- if (num != p->outStream->Write(p->outStream, p->bufBase, num))
+ if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))
p->res = SZ_ERROR_WRITE;
p->processed += num;
p->buf = p->bufBase;
}
-static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
+MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
{
- if ((UInt32)p->low < (UInt32)0xFF000000 || (unsigned)(p->low >> 32) != 0)
+ UInt32 low = (UInt32)p->low;
+ unsigned high = (unsigned)(p->low >> 32);
+ p->low = (UInt32)(low << 8);
+ if (low < (UInt32)0xFF000000 || high != 0)
{
- Byte temp = p->cache;
- do
{
Byte *buf = p->buf;
- *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
+ *buf++ = (Byte)(p->cache + high);
+ p->cache = (unsigned)(low >> 24);
+ p->buf = buf;
+ if (buf == p->bufLim)
+ RangeEnc_FlushStream(p);
+ if (p->cacheSize == 0)
+ return;
+ }
+ high += 0xFF;
+ for (;;)
+ {
+ Byte *buf = p->buf;
+ *buf++ = (Byte)(high);
p->buf = buf;
if (buf == p->bufLim)
RangeEnc_FlushStream(p);
- temp = 0xFF;
+ if (--p->cacheSize == 0)
+ return;
}
- while (--p->cacheSize != 0);
- p->cache = (Byte)((UInt32)p->low >> 24);
}
p->cacheSize++;
- p->low = (UInt32)p->low << 8;
}
static void RangeEnc_FlushData(CRangeEnc *p)
@@ -584,78 +608,121 @@ static void RangeEnc_FlushData(CRangeEnc *p)
RangeEnc_ShiftLow(p);
}
-static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, unsigned numBits)
-{
- do
- {
- p->range >>= 1;
- p->low += p->range & (0 - ((value >> --numBits) & 1));
- if (p->range < kTopValue)
- {
- p->range <<= 8;
- RangeEnc_ShiftLow(p);
- }
- }
- while (numBits != 0);
-}
+#define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); }
-static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
-{
- UInt32 ttt = *prob;
- UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
- if (symbol == 0)
- {
- p->range = newBound;
- ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
- }
- else
- {
- p->low += newBound;
- p->range -= newBound;
- ttt -= ttt >> kNumMoveBits;
+#define RC_BIT_PRE(p, prob) \
+ ttt = *(prob); \
+ newBound = (range >> kNumBitModelTotalBits) * ttt;
+
+// #define _LZMA_ENC_USE_BRANCH
+
+#ifdef _LZMA_ENC_USE_BRANCH
+
+#define RC_BIT(p, prob, symbol) { \
+ RC_BIT_PRE(p, prob) \
+ if (symbol == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \
+ else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \
+ *(prob) = (CLzmaProb)ttt; \
+ RC_NORM(p) \
}
- *prob = (CLzmaProb)ttt;
- if (p->range < kTopValue)
- {
- p->range <<= 8;
- RangeEnc_ShiftLow(p);
+
+#else
+
+#define RC_BIT(p, prob, symbol) { \
+ UInt32 mask; \
+ RC_BIT_PRE(p, prob) \
+ mask = 0 - (UInt32)symbol; \
+ range &= mask; \
+ mask &= newBound; \
+ range -= mask; \
+ (p)->low += mask; \
+ mask = (UInt32)symbol - 1; \
+ range += newBound & mask; \
+ mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \
+ mask += ((1 << kNumMoveBits) - 1); \
+ ttt += (Int32)(mask - ttt) >> kNumMoveBits; \
+ *(prob) = (CLzmaProb)ttt; \
+ RC_NORM(p) \
}
+
+#endif
+
+
+
+
+#define RC_BIT_0_BASE(p, prob) \
+ range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+
+#define RC_BIT_1_BASE(p, prob) \
+ range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \
+
+#define RC_BIT_0(p, prob) \
+ RC_BIT_0_BASE(p, prob) \
+ RC_NORM(p)
+
+#define RC_BIT_1(p, prob) \
+ RC_BIT_1_BASE(p, prob) \
+ RC_NORM(p)
+
+static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob)
+{
+ UInt32 range, ttt, newBound;
+ range = p->range;
+ RC_BIT_PRE(p, prob)
+ RC_BIT_0(p, prob)
+ p->range = range;
}
static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
{
+ UInt32 range = p->range;
symbol |= 0x100;
do
{
- RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
+ UInt32 ttt, newBound;
+ // RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
+ CLzmaProb *prob = probs + (symbol >> 8);
+ UInt32 bit = (symbol >> 7) & 1;
symbol <<= 1;
+ RC_BIT(p, prob, bit);
}
while (symbol < 0x10000);
+ p->range = range;
}
static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
{
+ UInt32 range = p->range;
UInt32 offs = 0x100;
symbol |= 0x100;
do
{
+ UInt32 ttt, newBound;
+ CLzmaProb *prob;
+ UInt32 bit;
matchByte <<= 1;
- RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
+ // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
+ prob = probs + (offs + (matchByte & offs) + (symbol >> 8));
+ bit = (symbol >> 7) & 1;
symbol <<= 1;
offs &= ~(matchByte ^ symbol);
+ RC_BIT(p, prob, bit);
}
while (symbol < 0x10000);
+ p->range = range;
}
-static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
+
+
+static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)
{
UInt32 i;
- for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
+ for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++)
{
- const int kCyclesBits = kNumBitPriceShiftBits;
- UInt32 w = i;
- UInt32 bitCount = 0;
- int j;
+ const unsigned kCyclesBits = kNumBitPriceShiftBits;
+ UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1));
+ unsigned bitCount = 0;
+ unsigned j;
for (j = 0; j < kCyclesBits; j++)
{
w = w * w;
@@ -666,37 +733,41 @@ static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
bitCount++;
}
}
- ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
+ ProbPrices[i] = (CProbPrice)((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
+ // printf("\n%3d: %5d", i, ProbPrices[i]);
}
}
#define GET_PRICE(prob, symbol) \
- p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+ p->ProbPrices[((prob) ^ (unsigned)(((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
#define GET_PRICEa(prob, symbol) \
- ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+ ProbPrices[((prob) ^ (unsigned)((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
-#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
-#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+#define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
+#define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+
-static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const UInt32 *ProbPrices)
+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const CProbPrice *ProbPrices)
{
UInt32 price = 0;
symbol |= 0x100;
do
{
- price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
- symbol <<= 1;
+ unsigned bit = symbol & 1;
+ symbol >>= 1;
+ price += GET_PRICEa(probs[symbol], bit);
}
- while (symbol < 0x10000);
+ while (symbol >= 2);
return price;
}
-static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const UInt32 *ProbPrices)
+
+static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const CProbPrice *ProbPrices)
{
UInt32 price = 0;
UInt32 offs = 0x100;
@@ -713,520 +784,525 @@ static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt
}
-static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
-{
- UInt32 m = 1;
- int i;
- for (i = numBitLevels; i != 0;)
- {
- UInt32 bit;
- i--;
- bit = (symbol >> i) & 1;
- RangeEnc_EncodeBit(rc, probs + m, bit);
- m = (m << 1) | bit;
- }
-}
-
-static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
-{
- UInt32 m = 1;
- int i;
- for (i = 0; i < numBitLevels; i++)
- {
- UInt32 bit = symbol & 1;
- RangeEnc_EncodeBit(rc, probs + m, bit);
- m = (m << 1) | bit;
- symbol >>= 1;
- }
-}
-
-static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)
-{
- UInt32 price = 0;
- symbol |= (1 << numBitLevels);
- while (symbol != 1)
- {
- price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
- symbol >>= 1;
- }
- return price;
-}
-
-static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)
+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, UInt32 symbol)
{
- UInt32 price = 0;
- UInt32 m = 1;
- int i;
- for (i = numBitLevels; i != 0; i--)
+ UInt32 range = rc->range;
+ unsigned m = 1;
+ do
{
- UInt32 bit = symbol & 1;
+ UInt32 ttt, newBound;
+ unsigned bit = symbol & 1;
+ // RangeEnc_EncodeBit(rc, probs + m, bit);
symbol >>= 1;
- price += GET_PRICEa(probs[m], bit);
+ RC_BIT(rc, probs + m, bit);
m = (m << 1) | bit;
}
- return price;
+ while (--numBits);
+ rc->range = range;
}
+
static void LenEnc_Init(CLenEnc *p)
{
unsigned i;
- p->choice = p->choice2 = kProbInitValue;
- for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
+ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++)
p->low[i] = kProbInitValue;
- for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
- p->mid[i] = kProbInitValue;
for (i = 0; i < kLenNumHighSymbols; i++)
p->high[i] = kProbInitValue;
}
-static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned symbol, unsigned posState)
{
- if (symbol < kLenNumLowSymbols)
+ UInt32 range, ttt, newBound;
+ CLzmaProb *probs = p->low;
+ range = rc->range;
+ RC_BIT_PRE(rc, probs);
+ if (symbol >= kLenNumLowSymbols)
{
- RangeEnc_EncodeBit(rc, &p->choice, 0);
- RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
- }
- else
- {
- RangeEnc_EncodeBit(rc, &p->choice, 1);
- if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
- {
- RangeEnc_EncodeBit(rc, &p->choice2, 0);
- RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
- }
- else
+ RC_BIT_1(rc, probs);
+ probs += kLenNumLowSymbols;
+ RC_BIT_PRE(rc, probs);
+ if (symbol >= kLenNumLowSymbols * 2)
{
- RangeEnc_EncodeBit(rc, &p->choice2, 1);
- RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
+ RC_BIT_1(rc, probs);
+ rc->range = range;
+ // RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols * 2);
+ LitEnc_Encode(rc, p->high, symbol - kLenNumLowSymbols * 2);
+ return;
}
+ symbol -= kLenNumLowSymbols;
}
-}
-static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, const UInt32 *ProbPrices)
-{
- UInt32 a0 = GET_PRICE_0a(p->choice);
- UInt32 a1 = GET_PRICE_1a(p->choice);
- UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
- UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
- UInt32 i = 0;
- for (i = 0; i < kLenNumLowSymbols; i++)
- {
- if (i >= numSymbols)
- return;
- prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
- }
- for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
+ // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
{
- if (i >= numSymbols)
- return;
- prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
+ unsigned m;
+ unsigned bit;
+ RC_BIT_0(rc, probs);
+ probs += (posState << (1 + kLenNumLowBits));
+ bit = (symbol >> 2) ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit;
+ bit = (symbol >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit;
+ bit = symbol & 1; RC_BIT(rc, probs + m, bit);
+ rc->range = range;
}
- for (; i < numSymbols; i++)
- prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
}
-static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, const UInt32 *ProbPrices)
+static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices)
{
- LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
- p->counters[posState] = p->tableSize;
+ unsigned i;
+ for (i = 0; i < 8; i += 2)
+ {
+ UInt32 price = startPrice;
+ UInt32 prob;
+ price += GET_PRICEa(probs[1 ], (i >> 2));
+ price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1);
+ prob = probs[4 + (i >> 1)];
+ prices[i ] = price + GET_PRICEa_0(prob);
+ prices[i + 1] = price + GET_PRICEa_1(prob);
+ }
}
-static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, const UInt32 *ProbPrices)
+
+MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTable(
+ CLenPriceEnc *p, unsigned posState,
+ const CLenEnc *enc,
+ const CProbPrice *ProbPrices)
{
- UInt32 posState;
- for (posState = 0; posState < numPosStates; posState++)
- LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+ // int y; for (y = 0; y < 100; y++) {
+ UInt32 a;
+ unsigned i, numSymbols;
+
+ UInt32 *prices = p->prices[posState];
+ {
+ const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));
+ SetPrices_3(probs, GET_PRICEa_0(enc->low[0]), prices, ProbPrices);
+ a = GET_PRICEa_1(enc->low[0]);
+ SetPrices_3(probs + kLenNumLowSymbols, a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]), prices + kLenNumLowSymbols, ProbPrices);
+ a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
+ }
+ numSymbols = p->tableSize;
+ p->counters[posState] = numSymbols;
+ for (i = kLenNumLowSymbols * 2; i < numSymbols; i += 1)
+ {
+ prices[i] = a +
+ // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);
+ LitEnc_GetPrice(enc->high, i - kLenNumLowSymbols * 2, ProbPrices);
+ /*
+ unsigned sym = (i - kLenNumLowSymbols * 2) >> 1;
+ UInt32 price = a + RcTree_GetPrice(enc->high, kLenNumHighBits - 1, sym, ProbPrices);
+ UInt32 prob = enc->high[(1 << 7) + sym];
+ prices[i ] = price + GET_PRICEa_0(prob);
+ prices[i + 1] = price + GET_PRICEa_1(prob);
+ */
+ }
+ // }
}
-static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, const UInt32 *ProbPrices)
+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, unsigned numPosStates,
+ const CLenEnc *enc,
+ const CProbPrice *ProbPrices)
{
- LenEnc_Encode(&p->p, rc, symbol, posState);
- if (updatePrice)
- if (--p->counters[posState] == 0)
- LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+ unsigned posState;
+ for (posState = 0; posState < numPosStates; posState++)
+ LenPriceEnc_UpdateTable(p, posState, enc, ProbPrices);
}
-
-
-static void MovePos(CLzmaEnc *p, UInt32 num)
-{
+/*
#ifdef SHOW_STAT
g_STAT_OFFSET += num;
printf("\n MovePos %u", num);
#endif
+*/
- if (num != 0)
- {
- p->additionalOffset += num;
- p->matchFinder.Skip(p->matchFinderObj, num);
- }
-}
+#define MOVE_POS(p, num) { \
+ p->additionalOffset += (num); \
+ p->matchFinder.Skip(p->matchFinderObj, (num)); }
+
-static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
+static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
{
- UInt32 lenRes = 0, numPairs;
+ unsigned numPairs;
+
+ p->additionalOffset++;
p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
+ *numPairsRes = numPairs;
#ifdef SHOW_STAT
printf("\n i = %u numPairs = %u ", g_STAT_OFFSET, numPairs / 2);
g_STAT_OFFSET++;
{
- UInt32 i;
+ unsigned i;
for (i = 0; i < numPairs; i += 2)
printf("%2u %6u | ", p->matches[i], p->matches[i + 1]);
}
#endif
- if (numPairs > 0)
+ if (numPairs == 0)
+ return 0;
{
- lenRes = p->matches[numPairs - 2];
- if (lenRes == p->numFastBytes)
+ unsigned len = p->matches[(size_t)numPairs - 2];
+ if (len != p->numFastBytes)
+ return len;
{
UInt32 numAvail = p->numAvail;
if (numAvail > LZMA_MATCH_LEN_MAX)
numAvail = LZMA_MATCH_LEN_MAX;
{
- const Byte *pbyCur = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
- const Byte *pby = pbyCur + lenRes;
- ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[numPairs - 1];
- const Byte *pbyLim = pbyCur + numAvail;
- for (; pby != pbyLim && *pby == pby[dif]; pby++);
- lenRes = (UInt32)(pby - pbyCur);
+ const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+ const Byte *p2 = p1 + len;
+ ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[(size_t)numPairs - 1];
+ const Byte *lim = p1 + numAvail;
+ for (; p2 != lim && *p2 == p2[dif]; p2++);
+ return (unsigned)(p2 - p1);
}
}
}
- p->additionalOffset++;
- *numDistancePairsRes = numPairs;
- return lenRes;
}
+#define MARK_LIT ((UInt32)(Int32)-1)
-#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;
-#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;
-#define IsShortRep(p) ((p)->backPrev == 0)
+#define MakeAs_Lit(p) { (p)->dist = MARK_LIT; (p)->extra = 0; }
+#define MakeAs_ShortRep(p) { (p)->dist = 0; (p)->extra = 0; }
+#define IsShortRep(p) ((p)->dist == 0)
-static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
-{
- return
- GET_PRICE_0(p->isRepG0[state]) +
- GET_PRICE_0(p->isRep0Long[state][posState]);
-}
-static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
+#define GetPrice_ShortRep(p, state, posState) \
+ ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]))
+
+#define GetPrice_Rep_0(p, state, posState) ( \
+ GET_PRICE_1(p->isMatch[state][posState]) \
+ + GET_PRICE_1(p->isRep0Long[state][posState])) \
+ + GET_PRICE_1(p->isRep[state]) \
+ + GET_PRICE_0(p->isRepG0[state])
+
+
+static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState)
{
UInt32 price;
+ UInt32 prob = p->isRepG0[state];
if (repIndex == 0)
{
- price = GET_PRICE_0(p->isRepG0[state]);
+ price = GET_PRICE_0(prob);
price += GET_PRICE_1(p->isRep0Long[state][posState]);
}
else
{
- price = GET_PRICE_1(p->isRepG0[state]);
+ price = GET_PRICE_1(prob);
+ prob = p->isRepG1[state];
if (repIndex == 1)
- price += GET_PRICE_0(p->isRepG1[state]);
+ price += GET_PRICE_0(prob);
else
{
- price += GET_PRICE_1(p->isRepG1[state]);
+ price += GET_PRICE_1(prob);
price += GET_PRICE(p->isRepG2[state], repIndex - 2);
}
}
return price;
}
-static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
-{
- return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
- GetPureRepPrice(p, repIndex, state, posState);
-}
-static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
+static unsigned Backward(CLzmaEnc *p, unsigned cur)
{
- UInt32 posMem = p->opt[cur].posPrev;
- UInt32 backMem = p->opt[cur].backPrev;
- p->optimumEndIndex = cur;
- do
+ unsigned wr = cur + 1;
+ p->optEnd = wr;
+
+ for (;;)
{
- if (p->opt[cur].prev1IsChar)
+ UInt32 dist = p->opt[cur].dist;
+ UInt32 len = p->opt[cur].len;
+ UInt32 extra = p->opt[cur].extra;
+ cur -= len;
+
+ if (extra)
{
- MakeAsChar(&p->opt[posMem])
- p->opt[posMem].posPrev = posMem - 1;
- if (p->opt[cur].prev2)
+ wr--;
+ p->opt[wr].len = len;
+ cur -= extra;
+ len = extra;
+ if (extra == 1)
{
- p->opt[posMem - 1].prev1IsChar = False;
- p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
- p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
+ p->opt[wr].dist = dist;
+ dist = MARK_LIT;
+ }
+ else
+ {
+ p->opt[wr].dist = 0;
+ len--;
+ wr--;
+ p->opt[wr].dist = MARK_LIT;
+ p->opt[wr].len = 1;
}
}
+
+ if (cur == 0)
{
- UInt32 posPrev = posMem;
- UInt32 backCur = backMem;
-
- backMem = p->opt[posPrev].backPrev;
- posMem = p->opt[posPrev].posPrev;
-
- p->opt[posPrev].backPrev = backCur;
- p->opt[posPrev].posPrev = cur;
- cur = posPrev;
+ p->backRes = dist;
+ p->optCur = wr;
+ return len;
}
+
+ wr--;
+ p->opt[wr].dist = dist;
+ p->opt[wr].len = len;
}
- while (cur != 0);
- *backRes = p->opt[0].backPrev;
- p->optimumCurrentIndex = p->opt[0].posPrev;
- return p->optimumCurrentIndex;
}
-#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * (UInt32)0x300)
-static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
-{
- UInt32 lenEnd, cur;
- UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];
- UInt32 *matches;
- {
+#define LIT_PROBS(pos, prevByte) \
+ (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc))
- UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, len;
- UInt32 matchPrice, repMatchPrice, normalMatchPrice;
- const Byte *data;
- Byte curByte, matchByte;
- if (p->optimumEndIndex != p->optimumCurrentIndex)
- {
- const COptimal *opt = &p->opt[p->optimumCurrentIndex];
- UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
- *backRes = opt->backPrev;
- p->optimumCurrentIndex = opt->posPrev;
- return lenRes;
- }
- p->optimumCurrentIndex = p->optimumEndIndex = 0;
-
- if (p->additionalOffset == 0)
- mainLen = ReadMatchDistances(p, &numPairs);
- else
- {
- mainLen = p->longestMatchLength;
- numPairs = p->numPairs;
- }
-
- numAvail = p->numAvail;
- if (numAvail < 2)
- {
- *backRes = (UInt32)(-1);
- return 1;
- }
- if (numAvail > LZMA_MATCH_LEN_MAX)
- numAvail = LZMA_MATCH_LEN_MAX;
+static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
+{
+ unsigned last, cur;
+ UInt32 reps[LZMA_NUM_REPS];
+ unsigned repLens[LZMA_NUM_REPS];
+ UInt32 *matches;
- data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
- repMaxIndex = 0;
- for (i = 0; i < LZMA_NUM_REPS; i++)
{
- UInt32 lenTest;
- const Byte *data2;
- reps[i] = p->reps[i];
- data2 = data - reps[i] - 1;
- if (data[0] != data2[0] || data[1] != data2[1])
+ UInt32 numAvail;
+ unsigned numPairs, mainLen, repMaxIndex, i, posState;
+ UInt32 matchPrice, repMatchPrice;
+ const Byte *data;
+ Byte curByte, matchByte;
+
+ p->optCur = p->optEnd = 0;
+
+ if (p->additionalOffset == 0)
+ mainLen = ReadMatchDistances(p, &numPairs);
+ else
{
- repLens[i] = 0;
- continue;
+ mainLen = p->longestMatchLen;
+ numPairs = p->numPairs;
}
- for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
- repLens[i] = lenTest;
- if (lenTest > repLens[repMaxIndex])
- repMaxIndex = i;
- }
- if (repLens[repMaxIndex] >= p->numFastBytes)
- {
- UInt32 lenRes;
- *backRes = repMaxIndex;
- lenRes = repLens[repMaxIndex];
- MovePos(p, lenRes - 1);
- return lenRes;
- }
-
- matches = p->matches;
- if (mainLen >= p->numFastBytes)
- {
- *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
- MovePos(p, mainLen - 1);
- return mainLen;
- }
- curByte = *data;
- matchByte = *(data - (reps[0] + 1));
-
- if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
- {
- *backRes = (UInt32)-1;
- return 1;
- }
-
- p->opt[0].state = (CState)p->state;
-
- posState = (position & p->pbMask);
-
- {
- const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
- p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
- (!IsCharState(p->state) ?
- LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
- LitEnc_GetPrice(probs, curByte, p->ProbPrices));
- }
-
- MakeAsChar(&p->opt[1]);
-
- matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
- repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
-
- if (matchByte == curByte)
- {
- UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
- if (shortRepPrice < p->opt[1].price)
+
+ numAvail = p->numAvail;
+ if (numAvail < 2)
{
- p->opt[1].price = shortRepPrice;
- MakeAsShortRep(&p->opt[1]);
+ p->backRes = MARK_LIT;
+ return 1;
}
- }
- lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);
-
- if (lenEnd < 2)
- {
- *backRes = p->opt[1].backPrev;
- return 1;
- }
-
- p->opt[1].posPrev = 0;
- for (i = 0; i < LZMA_NUM_REPS; i++)
- p->opt[0].backs[i] = reps[i];
-
- len = lenEnd;
- do
- p->opt[len--].price = kInfinityPrice;
- while (len >= 2);
-
- for (i = 0; i < LZMA_NUM_REPS; i++)
- {
- UInt32 repLen = repLens[i];
- UInt32 price;
- if (repLen < 2)
- continue;
- price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
- do
+ if (numAvail > LZMA_MATCH_LEN_MAX)
+ numAvail = LZMA_MATCH_LEN_MAX;
+
+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+ repMaxIndex = 0;
+
+ for (i = 0; i < LZMA_NUM_REPS; i++)
{
- UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
- COptimal *opt = &p->opt[repLen];
- if (curAndLenPrice < opt->price)
+ unsigned len;
+ const Byte *data2;
+ reps[i] = p->reps[i];
+ data2 = data - reps[i];
+ if (data[0] != data2[0] || data[1] != data2[1])
{
- opt->price = curAndLenPrice;
- opt->posPrev = 0;
- opt->backPrev = i;
- opt->prev1IsChar = False;
+ repLens[i] = 0;
+ continue;
}
+ for (len = 2; len < numAvail && data[len] == data2[len]; len++);
+ repLens[i] = len;
+ if (len > repLens[repMaxIndex])
+ repMaxIndex = i;
}
- while (--repLen >= 2);
- }
-
- normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
-
- len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
- if (len <= mainLen)
- {
- UInt32 offs = 0;
- while (len > matches[offs])
- offs += 2;
- for (; ; len++)
+
+ if (repLens[repMaxIndex] >= p->numFastBytes)
{
- COptimal *opt;
- UInt32 distance = matches[offs + 1];
-
- UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
- UInt32 lenToPosState = GetLenToPosState(len);
- if (distance < kNumFullDistances)
- curAndLenPrice += p->distancesPrices[lenToPosState][distance];
- else
+ unsigned len;
+ p->backRes = repMaxIndex;
+ len = repLens[repMaxIndex];
+ MOVE_POS(p, len - 1)
+ return len;
+ }
+
+ matches = p->matches;
+
+ if (mainLen >= p->numFastBytes)
+ {
+ p->backRes = matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;
+ MOVE_POS(p, mainLen - 1)
+ return mainLen;
+ }
+
+ curByte = *data;
+ matchByte = *(data - reps[0]);
+
+ if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
+ {
+ p->backRes = MARK_LIT;
+ return 1;
+ }
+
+ p->opt[0].state = (CState)p->state;
+
+ posState = (position & p->pbMask);
+
+ {
+ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+ p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
+ (!IsLitState(p->state) ?
+ LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
+ LitEnc_GetPrice(probs, curByte, p->ProbPrices));
+ }
+
+ MakeAs_Lit(&p->opt[1]);
+
+ matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
+ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
+
+ if (matchByte == curByte)
+ {
+ UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState);
+ if (shortRepPrice < p->opt[1].price)
{
- UInt32 slot;
- GetPosSlot2(distance, slot);
- curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
+ p->opt[1].price = shortRepPrice;
+ MakeAs_ShortRep(&p->opt[1]);
}
- opt = &p->opt[len];
- if (curAndLenPrice < opt->price)
+ }
+
+ last = (mainLen >= repLens[repMaxIndex] ? mainLen : repLens[repMaxIndex]);
+
+ if (last < 2)
+ {
+ p->backRes = p->opt[1].dist;
+ return 1;
+ }
+
+ p->opt[1].len = 1;
+
+ p->opt[0].reps[0] = reps[0];
+ p->opt[0].reps[1] = reps[1];
+ p->opt[0].reps[2] = reps[2];
+ p->opt[0].reps[3] = reps[3];
+
+ {
+ unsigned len = last;
+ do
+ p->opt[len--].price = kInfinityPrice;
+ while (len >= 2);
+ }
+
+ // ---------- REP ----------
+
+ for (i = 0; i < LZMA_NUM_REPS; i++)
+ {
+ unsigned repLen = repLens[i];
+ UInt32 price;
+ if (repLen < 2)
+ continue;
+ price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState);
+ do
{
- opt->price = curAndLenPrice;
- opt->posPrev = 0;
- opt->backPrev = distance + LZMA_NUM_REPS;
- opt->prev1IsChar = False;
+ UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)repLen - 2];
+ COptimal *opt = &p->opt[repLen];
+ if (price2 < opt->price)
+ {
+ opt->price = price2;
+ opt->len = repLen;
+ opt->dist = i;
+ opt->extra = 0;
+ }
}
- if (len == matches[offs])
+ while (--repLen >= 2);
+ }
+
+
+ // ---------- MATCH ----------
+ {
+ unsigned len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
+ if (len <= mainLen)
{
- offs += 2;
- if (offs == numPairs)
- break;
+ unsigned offs = 0;
+ UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
+
+ while (len > matches[offs])
+ offs += 2;
+
+ for (; ; len++)
+ {
+ COptimal *opt;
+ UInt32 dist = matches[(size_t)offs + 1];
+ UInt32 price2 = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN];
+ unsigned lenToPosState = GetLenToPosState(len);
+
+ if (dist < kNumFullDistances)
+ price2 += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
+ else
+ {
+ unsigned slot;
+ GetPosSlot2(dist, slot);
+ price2 += p->alignPrices[dist & kAlignMask];
+ price2 += p->posSlotPrices[lenToPosState][slot];
+ }
+
+ opt = &p->opt[len];
+
+ if (price2 < opt->price)
+ {
+ opt->price = price2;
+ opt->len = len;
+ opt->dist = dist + LZMA_NUM_REPS;
+ opt->extra = 0;
+ }
+
+ if (len == matches[offs])
+ {
+ offs += 2;
+ if (offs == numPairs)
+ break;
+ }
+ }
}
}
- }
+
- cur = 0;
+ cur = 0;
#ifdef SHOW_STAT2
/* if (position >= 0) */
{
unsigned i;
printf("\n pos = %4X", position);
- for (i = cur; i <= lenEnd; i++)
+ for (i = cur; i <= last; i++)
printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);
}
#endif
-
}
+
+
+ // ---------- Optimal Parsing ----------
+
for (;;)
{
- UInt32 numAvail;
- UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;
- UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;
- Bool nextIsChar;
+ UInt32 numAvail, numAvailFull;
+ unsigned newLen, numPairs, prev, state, posState, startLen;
+ UInt32 curPrice, litPrice, matchPrice, repMatchPrice;
+ Bool nextIsLit;
Byte curByte, matchByte;
const Byte *data;
- COptimal *curOpt;
- COptimal *nextOpt;
+ COptimal *curOpt, *nextOpt;
- cur++;
- if (cur == lenEnd)
- return Backward(p, backRes, cur);
+ if (++cur == last)
+ return Backward(p, cur);
newLen = ReadMatchDistances(p, &numPairs);
+
if (newLen >= p->numFastBytes)
{
p->numPairs = numPairs;
- p->longestMatchLength = newLen;
- return Backward(p, backRes, cur);
+ p->longestMatchLen = newLen;
+ return Backward(p, cur);
}
- position++;
+
curOpt = &p->opt[cur];
- posPrev = curOpt->posPrev;
- if (curOpt->prev1IsChar)
- {
- posPrev--;
- if (curOpt->prev2)
- {
- state = p->opt[curOpt->posPrev2].state;
- if (curOpt->backPrev2 < LZMA_NUM_REPS)
- state = kRepNextStates[state];
- else
- state = kMatchNextStates[state];
- }
- else
- state = p->opt[posPrev].state;
- state = kLiteralNextStates[state];
- }
- else
- state = p->opt[posPrev].state;
- if (posPrev == cur - 1)
+ prev = cur - curOpt->len;
+
+ if (curOpt->len == 1)
{
+ state = p->opt[prev].state;
if (IsShortRep(curOpt))
state = kShortRepNextStates[state];
else
@@ -1234,92 +1310,136 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
}
else
{
- UInt32 pos;
const COptimal *prevOpt;
- if (curOpt->prev1IsChar && curOpt->prev2)
+ UInt32 b0;
+ UInt32 dist = curOpt->dist;
+
+ if (curOpt->extra)
{
- posPrev = curOpt->posPrev2;
- pos = curOpt->backPrev2;
- state = kRepNextStates[state];
+ prev -= curOpt->extra;
+ state = kState_RepAfterLit;
+ if (curOpt->extra == 1)
+ state = (dist < LZMA_NUM_REPS) ? kState_RepAfterLit : kState_MatchAfterLit;
}
else
{
- pos = curOpt->backPrev;
- if (pos < LZMA_NUM_REPS)
+ state = p->opt[prev].state;
+ if (dist < LZMA_NUM_REPS)
state = kRepNextStates[state];
else
state = kMatchNextStates[state];
}
- prevOpt = &p->opt[posPrev];
- if (pos < LZMA_NUM_REPS)
+
+ prevOpt = &p->opt[prev];
+ b0 = prevOpt->reps[0];
+
+ if (dist < LZMA_NUM_REPS)
{
- UInt32 i;
- reps[0] = prevOpt->backs[pos];
- for (i = 1; i <= pos; i++)
- reps[i] = prevOpt->backs[i - 1];
- for (; i < LZMA_NUM_REPS; i++)
- reps[i] = prevOpt->backs[i];
+ if (dist == 0)
+ {
+ reps[0] = b0;
+ reps[1] = prevOpt->reps[1];
+ reps[2] = prevOpt->reps[2];
+ reps[3] = prevOpt->reps[3];
+ }
+ else
+ {
+ reps[1] = b0;
+ b0 = prevOpt->reps[1];
+ if (dist == 1)
+ {
+ reps[0] = b0;
+ reps[2] = prevOpt->reps[2];
+ reps[3] = prevOpt->reps[3];
+ }
+ else
+ {
+ reps[2] = b0;
+ reps[0] = prevOpt->reps[dist];
+ reps[3] = prevOpt->reps[dist ^ 1];
+ }
+ }
}
else
{
- UInt32 i;
- reps[0] = (pos - LZMA_NUM_REPS);
- for (i = 1; i < LZMA_NUM_REPS; i++)
- reps[i] = prevOpt->backs[i - 1];
+ reps[0] = (dist - LZMA_NUM_REPS + 1);
+ reps[1] = b0;
+ reps[2] = prevOpt->reps[1];
+ reps[3] = prevOpt->reps[2];
}
}
+
curOpt->state = (CState)state;
+ curOpt->reps[0] = reps[0];
+ curOpt->reps[1] = reps[1];
+ curOpt->reps[2] = reps[2];
+ curOpt->reps[3] = reps[3];
- curOpt->backs[0] = reps[0];
- curOpt->backs[1] = reps[1];
- curOpt->backs[2] = reps[2];
- curOpt->backs[3] = reps[3];
-
- curPrice = curOpt->price;
- nextIsChar = False;
data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
curByte = *data;
- matchByte = *(data - (reps[0] + 1));
+ matchByte = *(data - reps[0]);
+ position++;
posState = (position & p->pbMask);
- curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
- {
- const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
- curAnd1Price +=
- (!IsCharState(state) ?
- LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
- LitEnc_GetPrice(probs, curByte, p->ProbPrices));
- }
+ /*
+ The order of Price checks:
+ < LIT
+ <= SHORT_REP
+ < LIT : REP_0
+ < REP [ : LIT : REP_0 ]
+ < MATCH [ : LIT : REP_0 ]
+ */
+
+ curPrice = curOpt->price;
+ litPrice = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
- nextOpt = &p->opt[cur + 1];
+ nextOpt = &p->opt[(size_t)cur + 1];
+ nextIsLit = False;
- if (curAnd1Price < nextOpt->price)
+ // if (litPrice >= nextOpt->price) litPrice = 0; else // 18.new
{
- nextOpt->price = curAnd1Price;
- nextOpt->posPrev = cur;
- MakeAsChar(nextOpt);
- nextIsChar = True;
+ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+ litPrice += (!IsLitState(state) ?
+ LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
+ LitEnc_GetPrice(probs, curByte, p->ProbPrices));
+
+ if (litPrice < nextOpt->price)
+ {
+ nextOpt->price = litPrice;
+ nextOpt->len = 1;
+ MakeAs_Lit(nextOpt);
+ nextIsLit = True;
+ }
}
matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
- if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
+ // ---------- SHORT_REP ----------
+ // if (IsLitState(state)) // 18.new
+ if (matchByte == curByte)
+ // if (repMatchPrice < nextOpt->price) // 18.new
+ if (nextOpt->len < 2
+ || (nextOpt->dist != 0
+ && nextOpt->extra <= 1 // 17.old
+ ))
{
- UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
- if (shortRepPrice <= nextOpt->price)
+ UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState);
+ if (shortRepPrice <= nextOpt->price) // 17.old
+ // if (shortRepPrice < nextOpt->price) // 18.new
{
nextOpt->price = shortRepPrice;
- nextOpt->posPrev = cur;
- MakeAsShortRep(nextOpt);
- nextIsChar = True;
+ nextOpt->len = 1;
+ MakeAs_ShortRep(nextOpt);
+ nextIsLit = False;
}
}
+
numAvailFull = p->numAvail;
{
UInt32 temp = kNumOpts - 1 - cur;
- if (temp < numAvailFull)
+ if (numAvailFull > temp)
numAvailFull = temp;
}
@@ -1327,41 +1447,53 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
continue;
numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
- if (!nextIsChar && matchByte != curByte) /* speed optimization */
+ // numAvail <= p->numFastBytes
+
+ // ---------- LIT : REP_0 ----------
+
+ if (
+ // litPrice != 0 && // 18.new
+ !nextIsLit
+ && matchByte != curByte
+ && numAvailFull > 2)
{
- /* try Literal + rep0 */
- UInt32 temp;
- UInt32 lenTest2;
- const Byte *data2 = data - reps[0] - 1;
- UInt32 limit = p->numFastBytes + 1;
- if (limit > numAvailFull)
- limit = numAvailFull;
-
- for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
- lenTest2 = temp - 1;
- if (lenTest2 >= 2)
+ const Byte *data2 = data - reps[0];
+ if (data[1] == data2[1] && data[2] == data2[2])
{
- UInt32 state2 = kLiteralNextStates[state];
- UInt32 posStateNext = (position + 1) & p->pbMask;
- UInt32 nextRepMatchPrice = curAnd1Price +
- GET_PRICE_1(p->isMatch[state2][posStateNext]) +
- GET_PRICE_1(p->isRep[state2]);
- /* for (; lenTest2 >= 2; lenTest2--) */
+ unsigned len;
+ unsigned limit = p->numFastBytes + 1;
+ if (limit > numAvailFull)
+ limit = numAvailFull;
+ for (len = 3; len < limit && data[len] == data2[len]; len++);
+
{
- UInt32 curAndLenPrice;
- COptimal *opt;
- UInt32 offset = cur + 1 + lenTest2;
- while (lenEnd < offset)
- p->opt[++lenEnd].price = kInfinityPrice;
- curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
- opt = &p->opt[offset];
- if (curAndLenPrice < opt->price)
+ unsigned state2 = kLiteralNextStates[state];
+ unsigned posState2 = (position + 1) & p->pbMask;
+ UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2);
{
- opt->price = curAndLenPrice;
- opt->posPrev = cur + 1;
- opt->backPrev = 0;
- opt->prev1IsChar = True;
- opt->prev2 = False;
+ unsigned offset = cur + len;
+ while (last < offset)
+ p->opt[++last].price = kInfinityPrice;
+
+ // do
+ {
+ UInt32 price2;
+ COptimal *opt;
+ len--;
+ // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2);
+ price2 = price + p->repLenEnc.prices[posState2][len - LZMA_MATCH_LEN_MIN];
+
+ opt = &p->opt[offset];
+ // offset--;
+ if (price2 < opt->price)
+ {
+ opt->price = price2;
+ opt->len = len;
+ opt->dist = 0;
+ opt->extra = 1;
+ }
+ }
+ // while (len >= 3);
}
}
}
@@ -1369,87 +1501,105 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
startLen = 2; /* speed optimization */
{
- UInt32 repIndex;
- for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
- {
- UInt32 lenTest;
- UInt32 lenTestTemp;
- UInt32 price;
- const Byte *data2 = data - reps[repIndex] - 1;
- if (data[0] != data2[0] || data[1] != data2[1])
- continue;
- for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
- while (lenEnd < cur + lenTest)
- p->opt[++lenEnd].price = kInfinityPrice;
- lenTestTemp = lenTest;
- price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
- do
+ // ---------- REP ----------
+ unsigned repIndex = 0; // 17.old
+ // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused
+ for (; repIndex < LZMA_NUM_REPS; repIndex++)
{
- UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
- COptimal *opt = &p->opt[cur + lenTest];
- if (curAndLenPrice < opt->price)
+ unsigned len;
+ UInt32 price;
+ const Byte *data2 = data - reps[repIndex];
+ if (data[0] != data2[0] || data[1] != data2[1])
+ continue;
+
+ for (len = 2; len < numAvail && data[len] == data2[len]; len++);
+
+ // if (len < startLen) continue; // 18.new: speed optimization
+
+ while (last < cur + len)
+ p->opt[++last].price = kInfinityPrice;
{
- opt->price = curAndLenPrice;
- opt->posPrev = cur;
- opt->backPrev = repIndex;
- opt->prev1IsChar = False;
+ unsigned len2 = len;
+ price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState);
+ do
+ {
+ UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)len2 - 2];
+ COptimal *opt = &p->opt[cur + len2];
+ if (price2 < opt->price)
+ {
+ opt->price = price2;
+ opt->len = len2;
+ opt->dist = repIndex;
+ opt->extra = 0;
+ }
+ }
+ while (--len2 >= 2);
}
- }
- while (--lenTest >= 2);
- lenTest = lenTestTemp;
-
- if (repIndex == 0)
- startLen = lenTest + 1;
- /* if (_maxMode) */
+ if (repIndex == 0) startLen = len + 1; // 17.old
+ // startLen = len + 1; // 18.new
+
+ /* if (_maxMode) */
{
- UInt32 lenTest2 = lenTest + 1;
- UInt32 limit = lenTest2 + p->numFastBytes;
+ // ---------- REP : LIT : REP_0 ----------
+ // numFastBytes + 1 + numFastBytes
+
+ unsigned len2 = len + 1;
+ unsigned limit = len2 + p->numFastBytes;
if (limit > numAvailFull)
limit = numAvailFull;
- for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
- lenTest2 -= lenTest + 1;
- if (lenTest2 >= 2)
+
+ for (; len2 < limit && data[len2] == data2[len2]; len2++);
+
+ len2 -= len;
+ if (len2 >= 3)
{
- UInt32 nextRepMatchPrice;
- UInt32 state2 = kRepNextStates[state];
- UInt32 posStateNext = (position + lenTest) & p->pbMask;
- UInt32 curAndLenCharPrice =
- price + p->repLenEnc.prices[posState][lenTest - 2] +
- GET_PRICE_0(p->isMatch[state2][posStateNext]) +
- LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
- data[lenTest], data2[lenTest], p->ProbPrices);
- state2 = kLiteralNextStates[state2];
- posStateNext = (position + lenTest + 1) & p->pbMask;
- nextRepMatchPrice = curAndLenCharPrice +
- GET_PRICE_1(p->isMatch[state2][posStateNext]) +
- GET_PRICE_1(p->isRep[state2]);
+ unsigned state2 = kRepNextStates[state];
+ unsigned posState2 = (position + len) & p->pbMask;
+ price +=
+ p->repLenEnc.prices[posState][(size_t)len - 2]
+ + GET_PRICE_0(p->isMatch[state2][posState2])
+ + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
+ data[len], data2[len], p->ProbPrices);
- /* for (; lenTest2 >= 2; lenTest2--) */
+ // state2 = kLiteralNextStates[state2];
+ state2 = kState_LitAfterRep;
+ posState2 = (posState2 + 1) & p->pbMask;
+
+
+ price += GetPrice_Rep_0(p, state2, posState2);
{
- UInt32 curAndLenPrice;
- COptimal *opt;
- UInt32 offset = cur + lenTest + 1 + lenTest2;
- while (lenEnd < offset)
- p->opt[++lenEnd].price = kInfinityPrice;
- curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
- opt = &p->opt[offset];
- if (curAndLenPrice < opt->price)
+ unsigned offset = cur + len + len2;
+ while (last < offset)
+ p->opt[++last].price = kInfinityPrice;
+ // do
{
- opt->price = curAndLenPrice;
- opt->posPrev = cur + lenTest + 1;
- opt->backPrev = 0;
- opt->prev1IsChar = True;
- opt->prev2 = True;
- opt->posPrev2 = cur;
- opt->backPrev2 = repIndex;
+ unsigned price2;
+ COptimal *opt;
+ len2--;
+ // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
+ price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];
+
+ opt = &p->opt[offset];
+ // offset--;
+ if (price2 < opt->price)
+ {
+ opt->price = price2;
+ opt->len = len2;
+ opt->extra = (CExtra)(len + 1);
+ opt->dist = repIndex;
+ }
}
+ // while (len2 >= 3);
}
}
}
+ }
}
- }
- /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
+
+
+ // ---------- MATCH ----------
+ /* for (unsigned len = 2; len <= newLen; len++) */
if (newLen > numAvail)
{
newLen = numAvail;
@@ -1457,134 +1607,148 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
matches[numPairs] = newLen;
numPairs += 2;
}
+
if (newLen >= startLen)
{
UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
- UInt32 offs, curBack, posSlot;
- UInt32 lenTest;
- while (lenEnd < cur + newLen)
- p->opt[++lenEnd].price = kInfinityPrice;
+ UInt32 dist;
+ unsigned offs, posSlot, len;
+ while (last < cur + newLen)
+ p->opt[++last].price = kInfinityPrice;
offs = 0;
while (startLen > matches[offs])
offs += 2;
- curBack = matches[offs + 1];
- GetPosSlot2(curBack, posSlot);
- for (lenTest = /*2*/ startLen; ; lenTest++)
+ dist = matches[(size_t)offs + 1];
+
+ // if (dist >= kNumFullDistances)
+ GetPosSlot2(dist, posSlot);
+
+ for (len = /*2*/ startLen; ; len++)
{
- UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
+ UInt32 price = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN];
{
- UInt32 lenToPosState = GetLenToPosState(lenTest);
- COptimal *opt;
- if (curBack < kNumFullDistances)
- curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
- else
- curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
-
- opt = &p->opt[cur + lenTest];
- if (curAndLenPrice < opt->price)
- {
- opt->price = curAndLenPrice;
- opt->posPrev = cur;
- opt->backPrev = curBack + LZMA_NUM_REPS;
- opt->prev1IsChar = False;
- }
+ COptimal *opt;
+ unsigned lenToPosState = len - 2; lenToPosState = GetLenToPosState2(lenToPosState);
+ if (dist < kNumFullDistances)
+ price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
+ else
+ price += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[dist & kAlignMask];
+
+ opt = &p->opt[cur + len];
+ if (price < opt->price)
+ {
+ opt->price = price;
+ opt->len = len;
+ opt->dist = dist + LZMA_NUM_REPS;
+ opt->extra = 0;
+ }
}
- if (/*_maxMode && */lenTest == matches[offs])
+ if (/*_maxMode && */ len == matches[offs])
{
- /* Try Match + Literal + Rep0 */
- const Byte *data2 = data - curBack - 1;
- UInt32 lenTest2 = lenTest + 1;
- UInt32 limit = lenTest2 + p->numFastBytes;
+ // MATCH : LIT : REP_0
+
+ const Byte *data2 = data - dist - 1;
+ unsigned len2 = len + 1;
+ unsigned limit = len2 + p->numFastBytes;
if (limit > numAvailFull)
limit = numAvailFull;
- for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
- lenTest2 -= lenTest + 1;
- if (lenTest2 >= 2)
+
+ for (; len2 < limit && data[len2] == data2[len2]; len2++);
+
+ len2 -= len;
+
+ if (len2 >= 3)
{
- UInt32 nextRepMatchPrice;
- UInt32 state2 = kMatchNextStates[state];
- UInt32 posStateNext = (position + lenTest) & p->pbMask;
- UInt32 curAndLenCharPrice = curAndLenPrice +
- GET_PRICE_0(p->isMatch[state2][posStateNext]) +
- LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
- data[lenTest], data2[lenTest], p->ProbPrices);
- state2 = kLiteralNextStates[state2];
- posStateNext = (posStateNext + 1) & p->pbMask;
- nextRepMatchPrice = curAndLenCharPrice +
- GET_PRICE_1(p->isMatch[state2][posStateNext]) +
- GET_PRICE_1(p->isRep[state2]);
-
- /* for (; lenTest2 >= 2; lenTest2--) */
+ unsigned state2 = kMatchNextStates[state];
+ unsigned posState2 = (position + len) & p->pbMask;
+ unsigned offset;
+ price += GET_PRICE_0(p->isMatch[state2][posState2]);
+ price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
+ data[len], data2[len], p->ProbPrices);
+
+ // state2 = kLiteralNextStates[state2];
+ state2 = kState_LitAfterMatch;
+
+ posState2 = (posState2 + 1) & p->pbMask;
+ price += GetPrice_Rep_0(p, state2, posState2);
+
+ offset = cur + len + len2;
+ while (last < offset)
+ p->opt[++last].price = kInfinityPrice;
+ // do
{
- UInt32 offset = cur + lenTest + 1 + lenTest2;
- UInt32 curAndLenPrice2;
+ UInt32 price2;
COptimal *opt;
- while (lenEnd < offset)
- p->opt[++lenEnd].price = kInfinityPrice;
- curAndLenPrice2 = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+ len2--;
+ // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
+ price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];
opt = &p->opt[offset];
- if (curAndLenPrice2 < opt->price)
+ // offset--;
+ if (price2 < opt->price)
{
- opt->price = curAndLenPrice2;
- opt->posPrev = cur + lenTest + 1;
- opt->backPrev = 0;
- opt->prev1IsChar = True;
- opt->prev2 = True;
- opt->posPrev2 = cur;
- opt->backPrev2 = curBack + LZMA_NUM_REPS;
+ opt->price = price2;
+ opt->len = len2;
+ opt->extra = (CExtra)(len + 1);
+ opt->dist = dist + LZMA_NUM_REPS;
}
}
+ // while (len2 >= 3);
}
+
offs += 2;
if (offs == numPairs)
break;
- curBack = matches[offs + 1];
- if (curBack >= kNumFullDistances)
- GetPosSlot2(curBack, posSlot);
+ dist = matches[(size_t)offs + 1];
+ // if (dist >= kNumFullDistances)
+ GetPosSlot2(dist, posSlot);
}
}
}
}
}
+
+
#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
-static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
+
+
+static unsigned GetOptimumFast(CLzmaEnc *p)
{
- UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;
+ UInt32 numAvail, mainDist;
+ unsigned mainLen, numPairs, repIndex, repLen, i;
const Byte *data;
- const UInt32 *matches;
if (p->additionalOffset == 0)
mainLen = ReadMatchDistances(p, &numPairs);
else
{
- mainLen = p->longestMatchLength;
+ mainLen = p->longestMatchLen;
numPairs = p->numPairs;
}
numAvail = p->numAvail;
- *backRes = (UInt32)-1;
+ p->backRes = MARK_LIT;
if (numAvail < 2)
return 1;
if (numAvail > LZMA_MATCH_LEN_MAX)
numAvail = LZMA_MATCH_LEN_MAX;
data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
-
repLen = repIndex = 0;
+
for (i = 0; i < LZMA_NUM_REPS; i++)
{
- UInt32 len;
- const Byte *data2 = data - p->reps[i] - 1;
+ unsigned len;
+ const Byte *data2 = data - p->reps[i];
if (data[0] != data2[0] || data[1] != data2[1])
continue;
for (len = 2; len < numAvail && data[len] == data2[len]; len++);
if (len >= p->numFastBytes)
{
- *backRes = i;
- MovePos(p, len - 1);
+ p->backRes = i;
+ MOVE_POS(p, len - 1)
return len;
}
if (len > repLen)
@@ -1594,84 +1758,152 @@ static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
}
}
- matches = p->matches;
if (mainLen >= p->numFastBytes)
{
- *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
- MovePos(p, mainLen - 1);
+ p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;
+ MOVE_POS(p, mainLen - 1)
return mainLen;
}
mainDist = 0; /* for GCC */
+
if (mainLen >= 2)
{
- mainDist = matches[numPairs - 1];
- while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)
+ mainDist = p->matches[(size_t)numPairs - 1];
+ while (numPairs > 2)
{
- if (!ChangePair(matches[numPairs - 3], mainDist))
+ UInt32 dist2;
+ if (mainLen != p->matches[(size_t)numPairs - 4] + 1)
+ break;
+ dist2 = p->matches[(size_t)numPairs - 3];
+ if (!ChangePair(dist2, mainDist))
break;
numPairs -= 2;
- mainLen = matches[numPairs - 2];
- mainDist = matches[numPairs - 1];
+ mainLen--;
+ mainDist = dist2;
}
if (mainLen == 2 && mainDist >= 0x80)
mainLen = 1;
}
- if (repLen >= 2 && (
- (repLen + 1 >= mainLen) ||
- (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||
- (repLen + 3 >= mainLen && mainDist >= (1 << 15))))
+ if (repLen >= 2)
+ if ( repLen + 1 >= mainLen
+ || (repLen + 2 >= mainLen && mainDist >= (1 << 9))
+ || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))
{
- *backRes = repIndex;
- MovePos(p, repLen - 1);
+ p->backRes = repIndex;
+ MOVE_POS(p, repLen - 1)
return repLen;
}
if (mainLen < 2 || numAvail <= 2)
return 1;
- p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);
- if (p->longestMatchLength >= 2)
{
- UInt32 newDistance = matches[p->numPairs - 1];
- if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||
- (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||
- (p->longestMatchLength > mainLen + 1) ||
- (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))
- return 1;
+ unsigned len1 = ReadMatchDistances(p, &p->numPairs);
+ p->longestMatchLen = len1;
+
+ if (len1 >= 2)
+ {
+ UInt32 newDist = p->matches[(size_t)p->numPairs - 1];
+ if ( (len1 >= mainLen && newDist < mainDist)
+ || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist))
+ || (len1 > mainLen + 1)
+ || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist)))
+ return 1;
+ }
}
data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+
for (i = 0; i < LZMA_NUM_REPS; i++)
{
- UInt32 len, limit;
- const Byte *data2 = data - p->reps[i] - 1;
+ unsigned len, limit;
+ const Byte *data2 = data - p->reps[i];
if (data[0] != data2[0] || data[1] != data2[1])
continue;
limit = mainLen - 1;
- for (len = 2; len < limit && data[len] == data2[len]; len++);
- if (len >= limit)
- return 1;
+ for (len = 2;; len++)
+ {
+ if (len >= limit)
+ return 1;
+ if (data[len] != data2[len])
+ break;
+ }
+ }
+
+ p->backRes = mainDist + LZMA_NUM_REPS;
+ if (mainLen != 2)
+ {
+ MOVE_POS(p, mainLen - 2)
}
- *backRes = mainDist + LZMA_NUM_REPS;
- MovePos(p, mainLen - 2);
return mainLen;
}
-static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
+
+
+
+static void WriteEndMarker(CLzmaEnc *p, unsigned posState)
{
- UInt32 len;
- RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
- RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
+ UInt32 range;
+ range = p->rc.range;
+ {
+ UInt32 ttt, newBound;
+ CLzmaProb *prob = &p->isMatch[p->state][posState];
+ RC_BIT_PRE(&p->rc, prob)
+ RC_BIT_1(&p->rc, prob)
+ prob = &p->isRep[p->state];
+ RC_BIT_PRE(&p->rc, prob)
+ RC_BIT_0(&p->rc, prob)
+ }
p->state = kMatchNextStates[p->state];
- len = LZMA_MATCH_LEN_MIN;
- LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
- RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
- RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
- RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
+
+ p->rc.range = range;
+ LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState);
+ range = p->rc.range;
+
+ {
+ // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1);
+ CLzmaProb *probs = p->posSlotEncoder[0];
+ unsigned m = 1;
+ do
+ {
+ UInt32 ttt, newBound;
+ RC_BIT_PRE(p, probs + m)
+ RC_BIT_1(&p->rc, probs + m);
+ m = (m << 1) + 1;
+ }
+ while (m < (1 << kNumPosSlotBits));
+ }
+ {
+ // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits); UInt32 range = p->range;
+ unsigned numBits = 30 - kNumAlignBits;
+ do
+ {
+ range >>= 1;
+ p->rc.low += range;
+ RC_NORM(&p->rc)
+ }
+ while (--numBits);
+ }
+
+ {
+ // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
+ CLzmaProb *probs = p->posAlignEncoder;
+ unsigned m = 1;
+ do
+ {
+ UInt32 ttt, newBound;
+ RC_BIT_PRE(p, probs + m)
+ RC_BIT_1(&p->rc, probs + m);
+ m = (m << 1) + 1;
+ }
+ while (m < kAlignTableSize);
+ }
+ p->rc.range = range;
}
+
static SRes CheckErrors(CLzmaEnc *p)
{
if (p->result != SZ_OK)
@@ -1685,7 +1917,8 @@ static SRes CheckErrors(CLzmaEnc *p)
return p->result;
}
-static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
+
+MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
{
/* ReleaseMFStream(); */
p->finished = True;
@@ -1696,47 +1929,108 @@ static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
return CheckErrors(p);
}
+
+
static void FillAlignPrices(CLzmaEnc *p)
{
- UInt32 i;
- for (i = 0; i < kAlignTableSize; i++)
- p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
+ unsigned i;
+ const CProbPrice *ProbPrices = p->ProbPrices;
+ const CLzmaProb *probs = p->posAlignEncoder;
p->alignPriceCount = 0;
+ for (i = 0; i < kAlignTableSize / 2; i++)
+ {
+ UInt32 price = 0;
+ unsigned symbol = i;
+ unsigned m = 1;
+ unsigned bit;
+ UInt32 prob;
+ bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
+ bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
+ bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
+ prob = probs[m];
+ p->alignPrices[i ] = price + GET_PRICEa_0(prob);
+ p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);
+ // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
+ }
}
+
static void FillDistancesPrices(CLzmaEnc *p)
{
UInt32 tempPrices[kNumFullDistances];
- UInt32 i, lenToPosState;
+ unsigned i, lenToPosState;
+
+ const CProbPrice *ProbPrices = p->ProbPrices;
+ p->matchPriceCount = 0;
+
for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
{
- UInt32 posSlot = GetPosSlot1(i);
- UInt32 footerBits = ((posSlot >> 1) - 1);
- UInt32 base = ((2 | (posSlot & 1)) << footerBits);
- tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
+ unsigned posSlot = GetPosSlot1(i);
+ unsigned footerBits = ((posSlot >> 1) - 1);
+ unsigned base = ((2 | (posSlot & 1)) << footerBits);
+ // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);
+
+ const CLzmaProb *probs = p->posEncoders + base;
+ UInt32 price = 0;
+ unsigned m = 1;
+ unsigned symbol = i - base;
+ do
+ {
+ unsigned bit = symbol & 1;
+ symbol >>= 1;
+ price += GET_PRICEa(probs[m], bit);
+ m = (m << 1) + bit;
+ }
+ while (--footerBits);
+ tempPrices[i] = price;
}
for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
{
- UInt32 posSlot;
+ unsigned posSlot;
const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
- for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
- posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
- for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
- posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
+ unsigned distTableSize = p->distTableSize;
+ const CLzmaProb *probs = encoder;
+ for (posSlot = 0; posSlot < distTableSize; posSlot += 2)
+ {
+ // posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
+ UInt32 price = 0;
+ unsigned bit;
+ unsigned symbol = (posSlot >> 1) + (1 << (kNumPosSlotBits - 1));
+ UInt32 prob;
+ bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
+ bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
+ bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
+ bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
+ bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
+ prob = probs[(posSlot >> 1) + (1 << (kNumPosSlotBits - 1))];
+ posSlotPrices[posSlot ] = price + GET_PRICEa_0(prob);
+ posSlotPrices[posSlot + 1] = price + GET_PRICEa_1(prob);
+ }
+ for (posSlot = kEndPosModelIndex; posSlot < distTableSize; posSlot++)
+ posSlotPrices[posSlot] += ((UInt32)(((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
{
UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
- for (i = 0; i < kStartPosModelIndex; i++)
- distancesPrices[i] = posSlotPrices[i];
- for (; i < kNumFullDistances; i++)
- distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
+ {
+ distancesPrices[0] = posSlotPrices[0];
+ distancesPrices[1] = posSlotPrices[1];
+ distancesPrices[2] = posSlotPrices[2];
+ distancesPrices[3] = posSlotPrices[3];
+ }
+ for (i = 4; i < kNumFullDistances; i += 2)
+ {
+ UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];
+ distancesPrices[i ] = slotPrice + tempPrices[i];
+ distancesPrices[i + 1] = slotPrice + tempPrices[i + 1];
+ }
}
}
- p->matchPriceCount = 0;
}
+
+
void LzmaEnc_Construct(CLzmaEnc *p)
{
RangeEnc_Construct(&p->rc);
@@ -1760,26 +2054,27 @@ void LzmaEnc_Construct(CLzmaEnc *p)
LzmaEnc_InitPriceTables(p->ProbPrices);
p->litProbs = NULL;
p->saveState.litProbs = NULL;
+
}
-CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
+CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)
{
void *p;
- p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
+ p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));
if (p)
LzmaEnc_Construct((CLzmaEnc *)p);
return p;
}
-void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
+void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)
{
- alloc->Free(alloc, p->litProbs);
- alloc->Free(alloc, p->saveState.litProbs);
+ ISzAlloc_Free(alloc, p->litProbs);
+ ISzAlloc_Free(alloc, p->saveState.litProbs);
p->litProbs = NULL;
p->saveState.litProbs = NULL;
}
-void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
+void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
{
#ifndef _7ZIP_ST
MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
@@ -1790,13 +2085,14 @@ void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
RangeEnc_Free(&p->rc, alloc);
}
-void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
{
LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
- alloc->Free(alloc, p);
+ ISzAlloc_Free(alloc, p);
}
-static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
+
+static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize)
{
UInt32 nowPos32, startPos32;
if (p->needInit)
@@ -1814,13 +2110,13 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
if (p->nowPos64 == 0)
{
- UInt32 numPairs;
+ unsigned numPairs;
Byte curByte;
if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
return Flush(p, nowPos32);
ReadMatchDistances(p, &numPairs);
- RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
- p->state = kLiteralNextStates[p->state];
+ RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]);
+ // p->state = kLiteralNextStates[p->state];
curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);
LitEnc_Encode(&p->rc, p->litProbs, curByte);
p->additionalOffset--;
@@ -1828,109 +2124,225 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
}
if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
+
for (;;)
{
- UInt32 pos, len, posState;
-
+ UInt32 dist;
+ unsigned len, posState;
+ UInt32 range, ttt, newBound;
+ CLzmaProb *probs;
+
if (p->fastMode)
- len = GetOptimumFast(p, &pos);
+ len = GetOptimumFast(p);
else
- len = GetOptimum(p, nowPos32, &pos);
+ {
+ unsigned oci = p->optCur;
+ if (p->optEnd == oci)
+ len = GetOptimum(p, nowPos32);
+ else
+ {
+ const COptimal *opt = &p->opt[oci];
+ len = opt->len;
+ p->backRes = opt->dist;
+ p->optCur = oci + 1;
+ }
+ }
+
+ posState = (unsigned)nowPos32 & p->pbMask;
+ range = p->rc.range;
+ probs = &p->isMatch[p->state][posState];
+
+ RC_BIT_PRE(&p->rc, probs)
+
+ dist = p->backRes;
#ifdef SHOW_STAT2
- printf("\n pos = %4X, len = %u pos = %u", nowPos32, len, pos);
+ printf("\n pos = %6X, len = %3u pos = %6u", nowPos32, len, dist);
#endif
- posState = nowPos32 & p->pbMask;
- if (len == 1 && pos == (UInt32)-1)
+ if (dist == MARK_LIT)
{
Byte curByte;
- CLzmaProb *probs;
const Byte *data;
+ unsigned state;
- RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
+ RC_BIT_0(&p->rc, probs);
+ p->rc.range = range;
data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
- curByte = *data;
probs = LIT_PROBS(nowPos32, *(data - 1));
- if (IsCharState(p->state))
+ curByte = *data;
+ state = p->state;
+ p->state = kLiteralNextStates[state];
+ if (IsLitState(state))
LitEnc_Encode(&p->rc, probs, curByte);
else
- LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
- p->state = kLiteralNextStates[p->state];
+ LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0]));
}
else
{
- RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
- if (pos < LZMA_NUM_REPS)
+ RC_BIT_1(&p->rc, probs);
+ probs = &p->isRep[p->state];
+ RC_BIT_PRE(&p->rc, probs)
+
+ if (dist < LZMA_NUM_REPS)
{
- RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
- if (pos == 0)
+ RC_BIT_1(&p->rc, probs);
+ probs = &p->isRepG0[p->state];
+ RC_BIT_PRE(&p->rc, probs)
+ if (dist == 0)
{
- RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
- RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
+ RC_BIT_0(&p->rc, probs);
+ probs = &p->isRep0Long[p->state][posState];
+ RC_BIT_PRE(&p->rc, probs)
+ if (len != 1)
+ {
+ RC_BIT_1_BASE(&p->rc, probs);
+ }
+ else
+ {
+ RC_BIT_0_BASE(&p->rc, probs);
+ p->state = kShortRepNextStates[p->state];
+ }
}
else
{
- UInt32 distance = p->reps[pos];
- RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
- if (pos == 1)
- RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
+ RC_BIT_1(&p->rc, probs);
+ probs = &p->isRepG1[p->state];
+ RC_BIT_PRE(&p->rc, probs)
+ if (dist == 1)
+ {
+ RC_BIT_0_BASE(&p->rc, probs);
+ dist = p->reps[1];
+ }
else
{
- RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
- RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
- if (pos == 3)
+ RC_BIT_1(&p->rc, probs);
+ probs = &p->isRepG2[p->state];
+ RC_BIT_PRE(&p->rc, probs)
+ if (dist == 2)
+ {
+ RC_BIT_0_BASE(&p->rc, probs);
+ dist = p->reps[2];
+ }
+ else
+ {
+ RC_BIT_1_BASE(&p->rc, probs);
+ dist = p->reps[3];
p->reps[3] = p->reps[2];
+ }
p->reps[2] = p->reps[1];
}
p->reps[1] = p->reps[0];
- p->reps[0] = distance;
+ p->reps[0] = dist;
}
- if (len == 1)
- p->state = kShortRepNextStates[p->state];
- else
+
+ RC_NORM(&p->rc)
+
+ p->rc.range = range;
+
+ if (len != 1)
{
- LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+ LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
+ if (!p->fastMode)
+ if (--p->repLenEnc.counters[posState] == 0)
+ LenPriceEnc_UpdateTable(&p->repLenEnc, posState, &p->repLenProbs, p->ProbPrices);
+
p->state = kRepNextStates[p->state];
}
}
else
{
- UInt32 posSlot;
- RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
+ unsigned posSlot;
+ RC_BIT_0(&p->rc, probs);
+ p->rc.range = range;
p->state = kMatchNextStates[p->state];
- LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
- pos -= LZMA_NUM_REPS;
- GetPosSlot(pos, posSlot);
- RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
+
+ LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
+ if (!p->fastMode)
+ if (--p->lenEnc.counters[posState] == 0)
+ LenPriceEnc_UpdateTable(&p->lenEnc, posState, &p->lenProbs, p->ProbPrices);
+
+ dist -= LZMA_NUM_REPS;
+ p->reps[3] = p->reps[2];
+ p->reps[2] = p->reps[1];
+ p->reps[1] = p->reps[0];
+ p->reps[0] = dist + 1;
+
+ p->matchPriceCount++;
+ GetPosSlot(dist, posSlot);
+ // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot);
+ {
+ UInt32 symbol = posSlot + (1 << kNumPosSlotBits);
+ range = p->rc.range;
+ probs = p->posSlotEncoder[GetLenToPosState(len)];
+ do
+ {
+ CLzmaProb *prob = probs + (symbol >> kNumPosSlotBits);
+ UInt32 bit = (symbol >> (kNumPosSlotBits - 1)) & 1;
+ symbol <<= 1;
+ RC_BIT(&p->rc, prob, bit);
+ }
+ while (symbol < (1 << kNumPosSlotBits * 2));
+ p->rc.range = range;
+ }
- if (posSlot >= kStartPosModelIndex)
+ if (dist >= kStartPosModelIndex)
{
- UInt32 footerBits = ((posSlot >> 1) - 1);
- UInt32 base = ((2 | (posSlot & 1)) << footerBits);
- UInt32 posReduced = pos - base;
+ unsigned footerBits = ((posSlot >> 1) - 1);
- if (posSlot < kEndPosModelIndex)
- RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
+ if (dist < kNumFullDistances)
+ {
+ unsigned base = ((2 | (posSlot & 1)) << footerBits);
+ RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, dist - base);
+ }
else
{
- RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
- RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
- p->alignPriceCount++;
+ UInt32 pos2 = (dist | 0xF) << (32 - footerBits);
+ range = p->rc.range;
+ // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
+ /*
+ do
+ {
+ range >>= 1;
+ p->rc.low += range & (0 - ((dist >> --footerBits) & 1));
+ RC_NORM(&p->rc)
+ }
+ while (footerBits > kNumAlignBits);
+ */
+ do
+ {
+ range >>= 1;
+ p->rc.low += range & (0 - (pos2 >> 31));
+ pos2 += pos2;
+ RC_NORM(&p->rc)
+ }
+ while (pos2 != 0xF0000000);
+
+
+ // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
+
+ {
+ unsigned m = 1;
+ unsigned bit;
+ bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
+ bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
+ bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
+ bit = dist & 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit);
+ p->rc.range = range;
+ p->alignPriceCount++;
+ }
}
}
- p->reps[3] = p->reps[2];
- p->reps[2] = p->reps[1];
- p->reps[1] = p->reps[0];
- p->reps[0] = pos;
- p->matchPriceCount++;
}
}
- p->additionalOffset -= len;
+
nowPos32 += len;
+ p->additionalOffset -= len;
+
if (p->additionalOffset == 0)
{
UInt32 processed;
+
if (!p->fastMode)
{
if (p->matchPriceCount >= (1 << 7))
@@ -1938,13 +2350,15 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
if (p->alignPriceCount >= kAlignTableSize)
FillAlignPrices(p);
}
+
if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
break;
processed = nowPos32 - startPos32;
- if (useLimits)
+
+ if (maxPackSize)
{
- if (processed + kNumOpts + 300 >= maxUnpackSize ||
- RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
+ if (processed + kNumOpts + 300 >= maxUnpackSize
+ || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize)
break;
}
else if (processed >= (1 << 17))
@@ -1954,13 +2368,16 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
}
}
}
+
p->nowPos64 += nowPos32 - startPos32;
return Flush(p, nowPos32);
}
+
+
#define kBigHashDicLimit ((UInt32)1 << 24)
-static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
{
UInt32 beforeSize = kNumOpts;
if (!RangeEnc_Alloc(&p->rc, alloc))
@@ -1975,8 +2392,8 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
{
LzmaEnc_FreeLits(p, alloc);
- p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
- p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
+ p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
+ p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
if (!p->litProbs || !p->saveState.litProbs)
{
LzmaEnc_FreeLits(p, alloc);
@@ -1994,8 +2411,13 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
#ifndef _7ZIP_ST
if (p->mtMode)
{
- RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
+ RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes,
+ LZMA_MATCH_LEN_MAX
+ + 1 /* 18.04 */
+ , allocBig));
p->matchFinderObj = &p->matchFinderMt;
+ p->matchFinderBase.bigHash = (Byte)(
+ (p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0);
MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
}
else
@@ -2012,17 +2434,21 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
void LzmaEnc_Init(CLzmaEnc *p)
{
- UInt32 i;
+ unsigned i;
p->state = 0;
- for (i = 0 ; i < LZMA_NUM_REPS; i++)
- p->reps[i] = 0;
+ p->reps[0] =
+ p->reps[1] =
+ p->reps[2] =
+ p->reps[3] = 1;
RangeEnc_Init(&p->rc);
+ for (i = 0; i < (1 << kNumAlignBits); i++)
+ p->posAlignEncoder[i] = kProbInitValue;
for (i = 0; i < kNumStates; i++)
{
- UInt32 j;
+ unsigned j;
for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
{
p->isMatch[i][j] = kProbInitValue;
@@ -2035,38 +2461,37 @@ void LzmaEnc_Init(CLzmaEnc *p)
}
{
- UInt32 num = (UInt32)0x300 << (p->lp + p->lc);
- CLzmaProb *probs = p->litProbs;
- for (i = 0; i < num; i++)
- probs[i] = kProbInitValue;
- }
-
- {
for (i = 0; i < kNumLenToPosStates; i++)
{
CLzmaProb *probs = p->posSlotEncoder[i];
- UInt32 j;
+ unsigned j;
for (j = 0; j < (1 << kNumPosSlotBits); j++)
probs[j] = kProbInitValue;
}
}
{
- for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
+ for (i = 0; i < kNumFullDistances; i++)
p->posEncoders[i] = kProbInitValue;
}
- LenEnc_Init(&p->lenEnc.p);
- LenEnc_Init(&p->repLenEnc.p);
+ {
+ UInt32 num = (UInt32)0x300 << (p->lp + p->lc);
+ UInt32 k;
+ CLzmaProb *probs = p->litProbs;
+ for (k = 0; k < num; k++)
+ probs[k] = kProbInitValue;
+ }
+
- for (i = 0; i < (1 << kNumAlignBits); i++)
- p->posAlignEncoder[i] = kProbInitValue;
+ LenEnc_Init(&p->lenProbs);
+ LenEnc_Init(&p->repLenProbs);
- p->optimumEndIndex = 0;
- p->optimumCurrentIndex = 0;
+ p->optEnd = 0;
+ p->optCur = 0;
p->additionalOffset = 0;
p->pbMask = (1 << p->pb) - 1;
- p->lpMask = (1 << p->lp) - 1;
+ p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);
}
void LzmaEnc_InitPrices(CLzmaEnc *p)
@@ -2080,14 +2505,14 @@ void LzmaEnc_InitPrices(CLzmaEnc *p)
p->lenEnc.tableSize =
p->repLenEnc.tableSize =
p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
- LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
- LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
+ LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
+ LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);
}
-static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
{
- UInt32 i;
- for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
+ unsigned i;
+ for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++)
if (p->dictSize <= ((UInt32)1 << i))
break;
p->distTableSize = i * 2;
@@ -2102,7 +2527,7 @@ static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *a
}
static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
- ISzAlloc *alloc, ISzAlloc *allocBig)
+ ISzAllocPtr alloc, ISzAllocPtr allocBig)
{
CLzmaEnc *p = (CLzmaEnc *)pp;
p->matchFinderBase.stream = inStream;
@@ -2113,7 +2538,7 @@ static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInS
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
ISeqInStream *inStream, UInt32 keepWindowSize,
- ISzAlloc *alloc, ISzAlloc *allocBig)
+ ISzAllocPtr alloc, ISzAllocPtr allocBig)
{
CLzmaEnc *p = (CLzmaEnc *)pp;
p->matchFinderBase.stream = inStream;
@@ -2129,12 +2554,13 @@ static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
}
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
- UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+ UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
{
CLzmaEnc *p = (CLzmaEnc *)pp;
LzmaEnc_SetInputBuf(p, src, srcLen);
p->needInit = 1;
+ LzmaEnc_SetDataSize(pp, srcLen);
return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
}
@@ -2152,15 +2578,15 @@ void LzmaEnc_Finish(CLzmaEncHandle pp)
typedef struct
{
- ISeqOutStream funcTable;
+ ISeqOutStream vt;
Byte *data;
SizeT rem;
Bool overflow;
-} CSeqOutStreamBuf;
+} CLzmaEnc_SeqOutStreamBuf;
-static size_t MyWrite(void *pp, const void *data, size_t size)
+static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size)
{
- CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
+ CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt);
if (p->rem < size)
{
size = p->rem;
@@ -2193,9 +2619,9 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
CLzmaEnc *p = (CLzmaEnc *)pp;
UInt64 nowPos64;
SRes res;
- CSeqOutStreamBuf outStream;
+ CLzmaEnc_SeqOutStreamBuf outStream;
- outStream.funcTable.Write = MyWrite;
+ outStream.vt.Write = SeqOutStreamBuf_Write;
outStream.data = dest;
outStream.rem = *destLen;
outStream.overflow = False;
@@ -2207,11 +2633,15 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
if (reInit)
LzmaEnc_Init(p);
LzmaEnc_InitPrices(p);
+
nowPos64 = p->nowPos64;
RangeEnc_Init(&p->rc);
- p->rc.outStream = &outStream.funcTable;
+ p->rc.outStream = &outStream.vt;
+
+ if (desiredPackSize == 0)
+ return SZ_ERROR_OUTPUT_EOF;
- res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);
+ res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize);
*unpackSize = (UInt32)(p->nowPos64 - nowPos64);
*destLen -= outStream.rem;
@@ -2234,12 +2664,12 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
for (;;)
{
- res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
+ res = LzmaEnc_CodeOneBlock(p, 0, 0);
if (res != SZ_OK || p->finished)
break;
if (progress)
{
- res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
+ res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
if (res != SZ_OK)
{
res = SZ_ERROR_PROGRESS;
@@ -2251,7 +2681,7 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
LzmaEnc_Finish(p);
/*
- if (res == S_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))
+ if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))
res = SZ_ERROR_FAIL;
}
*/
@@ -2261,7 +2691,7 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
- ISzAlloc *alloc, ISzAlloc *allocBig)
+ ISzAllocPtr alloc, ISzAllocPtr allocBig)
{
RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
@@ -2296,21 +2726,27 @@ SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
}
+unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp)
+{
+ return ((CLzmaEnc *)pp)->writeEndMark;
+}
+
+
SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, 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)
{
SRes res;
CLzmaEnc *p = (CLzmaEnc *)pp;
- CSeqOutStreamBuf outStream;
+ CLzmaEnc_SeqOutStreamBuf outStream;
- outStream.funcTable.Write = MyWrite;
+ outStream.vt.Write = SeqOutStreamBuf_Write;
outStream.data = dest;
outStream.rem = *destLen;
outStream.overflow = False;
p->writeEndMark = writeEndMark;
- p->rc.outStream = &outStream.funcTable;
+ p->rc.outStream = &outStream.vt;
res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
@@ -2330,7 +2766,7 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
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)
{
CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
SRes res;
diff --git a/C/LzmaEnc.h b/C/LzmaEnc.h
index c2806b4..c9938f0 100644
--- a/C/LzmaEnc.h
+++ b/C/LzmaEnc.h
@@ -1,5 +1,5 @@
/* LzmaEnc.h -- LZMA Encoder
-2013-01-18 : Igor Pavlov : Public domain */
+2017-07-27 : Igor Pavlov : Public domain */
#ifndef __LZMA_ENC_H
#define __LZMA_ENC_H
@@ -12,12 +12,10 @@ EXTERN_C_BEGIN
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) */
- UInt64 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF.
- Encoder uses this value to reduce dictionary size */
+ (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 */
@@ -25,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);
@@ -37,41 +38,38 @@ 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)
-*/
+/* ---------- One Call Interface ---------- */
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
diff --git a/C/MtCoder.c b/C/MtCoder.c
index 8c0d9b3..ddc7c02 100644
--- a/C/MtCoder.c
+++ b/C/MtCoder.c
@@ -1,168 +1,89 @@
/* MtCoder.c -- Multi-thread Coder
-2015-10-13 : Igor Pavlov : Public domain */
+2018-02-21 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "MtCoder.h"
-void LoopThread_Construct(CLoopThread *p)
-{
- Thread_Construct(&p->thread);
- Event_Construct(&p->startEvent);
- Event_Construct(&p->finishedEvent);
-}
-
-void LoopThread_Close(CLoopThread *p)
-{
- Thread_Close(&p->thread);
- Event_Close(&p->startEvent);
- Event_Close(&p->finishedEvent);
-}
+#ifndef _7ZIP_ST
-static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)
+SRes MtProgressThunk_Progress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize)
{
- CLoopThread *p = (CLoopThread *)pp;
- for (;;)
+ CMtProgressThunk *thunk = CONTAINER_FROM_VTBL(pp, CMtProgressThunk, vt);
+ UInt64 inSize2 = 0;
+ UInt64 outSize2 = 0;
+ if (inSize != (UInt64)(Int64)-1)
{
- if (Event_Wait(&p->startEvent) != 0)
- return SZ_ERROR_THREAD;
- if (p->stop)
- return 0;
- p->res = p->func(p->param);
- if (Event_Set(&p->finishedEvent) != 0)
- return SZ_ERROR_THREAD;
+ 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);
}
-WRes LoopThread_Create(CLoopThread *p)
-{
- p->stop = 0;
- RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent));
- RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent));
- return Thread_Create(&p->thread, LoopThreadFunc, p);
-}
-WRes LoopThread_StopAndWait(CLoopThread *p)
+void MtProgressThunk_CreateVTable(CMtProgressThunk *p)
{
- p->stop = 1;
- if (Event_Set(&p->startEvent) != 0)
- return SZ_ERROR_THREAD;
- return Thread_Wait(&p->thread);
+ p->vt.Progress = MtProgressThunk_Progress;
}
-WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); }
-WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); }
-
-static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
-{
- return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
-}
-static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)
-{
- unsigned i;
- for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
- p->inSizes[i] = p->outSizes[i] = 0;
- p->totalInSize = p->totalOutSize = 0;
- p->progress = progress;
- p->res = SZ_OK;
-}
-static void MtProgress_Reinit(CMtProgress *p, unsigned index)
-{
- p->inSizes[index] = 0;
- p->outSizes[index] = 0;
-}
+#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
-#define UPDATE_PROGRESS(size, prev, total) \
- if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; }
-SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize)
+static WRes ArEvent_OptCreate_And_Reset(CEvent *p)
{
- SRes res;
- CriticalSection_Enter(&p->cs);
- UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize)
- UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize)
- if (p->res == SZ_OK)
- p->res = Progress(p->progress, p->totalInSize, p->totalOutSize);
- res = p->res;
- CriticalSection_Leave(&p->cs);
- return res;
+ if (Event_IsCreated(p))
+ return Event_Reset(p);
+ return AutoResetEvent_CreateNotSignaled(p);
}
-static void MtProgress_SetError(CMtProgress *p, SRes res)
-{
- CriticalSection_Enter(&p->cs);
- if (p->res == SZ_OK)
- p->res = res;
- CriticalSection_Leave(&p->cs);
-}
-static void MtCoder_SetError(CMtCoder* p, SRes res)
-{
- CriticalSection_Enter(&p->cs);
- if (p->res == SZ_OK)
- p->res = res;
- CriticalSection_Leave(&p->cs);
-}
+static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp);
-/* ---------- MtThread ---------- */
-void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)
+static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t)
{
- p->mtCoder = mtCoder;
- p->outBuf = 0;
- p->inBuf = 0;
- Event_Construct(&p->canRead);
- Event_Construct(&p->canWrite);
- LoopThread_Construct(&p->thread);
+ 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);
}
-#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
-static void CMtThread_CloseEvents(CMtThread *p)
+static void MtCoderThread_Destruct(CMtCoderThread *t)
{
- Event_Close(&p->canRead);
- Event_Close(&p->canWrite);
-}
-
-static void CMtThread_Destruct(CMtThread *p)
-{
- CMtThread_CloseEvents(p);
-
- if (Thread_WasCreated(&p->thread.thread))
+ if (Thread_WasCreated(&t->thread))
{
- LoopThread_StopAndWait(&p->thread);
- LoopThread_Close(&p->thread);
+ t->stop = 1;
+ Event_Set(&t->startEvent);
+ Thread_Wait(&t->thread);
+ Thread_Close(&t->thread);
}
- if (p->mtCoder->alloc)
- IAlloc_Free(p->mtCoder->alloc, p->outBuf);
- p->outBuf = 0;
+ Event_Close(&t->startEvent);
- if (p->mtCoder->alloc)
- IAlloc_Free(p->mtCoder->alloc, p->inBuf);
- p->inBuf = 0;
+ if (t->inBuf)
+ {
+ ISzAlloc_Free(t->mtCoder->allocBig, t->inBuf);
+ t->inBuf = NULL;
+ }
}
-#define MY_BUF_ALLOC(buf, size, newSize) \
- if (buf == 0 || size != newSize) \
- { IAlloc_Free(p->mtCoder->alloc, buf); \
- size = newSize; buf = (Byte *)IAlloc_Alloc(p->mtCoder->alloc, size); \
- if (buf == 0) return SZ_ERROR_MEM; }
-
-static SRes CMtThread_Prepare(CMtThread *p)
-{
- MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize)
- MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize)
-
- p->stopReading = False;
- p->stopWriting = False;
- RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead));
- RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite));
- return SZ_OK;
-}
static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
{
@@ -170,158 +91,511 @@ static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
*processedSize = 0;
while (size != 0)
{
- size_t curSize = size;
- SRes res = stream->Read(stream, data, &curSize);
- *processedSize += curSize;
- data += curSize;
- size -= curSize;
+ size_t cur = size;
+ SRes res = ISeqInStream_Read(stream, data, &cur);
+ *processedSize += cur;
+ data += cur;
+ size -= cur;
RINOK(res);
- if (curSize == 0)
+ if (cur == 0)
return SZ_OK;
}
return SZ_OK;
}
-#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads - 1 ? 0 : p->index + 1]
-static SRes MtThread_Process(CMtThread *p, Bool *stop)
+/*
+ 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)
{
- CMtThread *next;
- *stop = True;
- if (Event_Wait(&p->canRead) != 0)
- return SZ_ERROR_THREAD;
-
- next = GET_NEXT_THREAD(p);
-
- if (p->stopReading)
- {
- next->stopReading = True;
- return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD;
- }
+ CMtCoder *mtc = t->mtCoder;
+ for (;;)
{
- size_t size = p->mtCoder->blockSize;
- size_t destSize = p->outBufSize;
+ unsigned bi;
+ SRes res;
+ SRes res2;
+ Bool finished;
+ unsigned bufIndex;
+ size_t size;
+ const Byte *inData;
+ UInt64 readProcessed = 0;
+
+ RINOK_THREAD(Event_Wait(&mtc->readEvent))
+
+ /* after Event_Wait(&mtc->readEvent) we must call Event_Set(&mtc->readEvent) in any case to unlock another threads */
+
+ if (mtc->stopReading)
+ {
+ return Event_Set(&mtc->readEvent) == 0 ? SZ_OK : SZ_ERROR_THREAD;
+ }
- RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size));
- next->stopReading = *stop = (size != p->mtCoder->blockSize);
- if (Event_Set(&next->canRead) != 0)
- return SZ_ERROR_THREAD;
+ res = MtProgress_GetError(&mtc->mtProgress);
+
+ size = 0;
+ inData = NULL;
+ finished = True;
- RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index,
- p->outBuf, &destSize, p->inBuf, size, *stop));
+ 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);
+ }
+ }
- MtProgress_Reinit(&p->mtCoder->mtProgress, p->index);
+ /* we must get some block from blocksSemaphore before Event_Set(&mtc->readEvent) */
- if (Event_Wait(&p->canWrite) != 0)
- return SZ_ERROR_THREAD;
- if (p->stopWriting)
- return SZ_ERROR_FAIL;
- if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize)
- return SZ_ERROR_WRITE;
- return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD;
+ res2 = SZ_OK;
+
+ if (Semaphore_Wait(&mtc->blocksSemaphore) != 0)
+ {
+ res2 = SZ_ERROR_THREAD;
+ if (res == SZ_OK)
+ {
+ res = res2;
+ // MtProgress_SetError(&mtc->mtProgress, res);
+ }
+ }
+
+ bi = mtc->blockIndex;
+
+ if (++mtc->blockIndex >= mtc->numBlocksMax)
+ mtc->blockIndex = 0;
+
+ bufIndex = (unsigned)(int)-1;
+
+ if (res == SZ_OK)
+ res = MtProgress_GetError(&mtc->mtProgress);
+
+ if (res != SZ_OK)
+ finished = True;
+
+ if (!finished)
+ {
+ if (mtc->numStartedThreads < mtc->numStartedThreadsLimit
+ && mtc->expectedDataSize != readProcessed)
+ {
+ res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]);
+ if (res == SZ_OK)
+ mtc->numStartedThreads++;
+ else
+ {
+ MtProgress_SetError(&mtc->mtProgress, res);
+ finished = True;
+ }
+ }
+ }
+
+ if (finished)
+ mtc->stopReading = True;
+
+ RINOK_THREAD(Event_Set(&mtc->readEvent))
+
+ if (res2 != SZ_OK)
+ return res2;
+
+ if (res == SZ_OK)
+ {
+ CriticalSection_Enter(&mtc->cs);
+ bufIndex = mtc->freeBlockHead;
+ mtc->freeBlockHead = mtc->freeBlockList[bufIndex];
+ CriticalSection_Leave(&mtc->cs);
+
+ res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex,
+ mtc->inStream ? t->inBuf : inData, size, finished);
+
+ // MtProgress_Reinit(&mtc->mtProgress, t->index);
+
+ if (res != SZ_OK)
+ MtProgress_SetError(&mtc->mtProgress, res);
+ }
+
+ {
+ CMtCoderBlock *block = &mtc->blocks[bi];
+ block->res = res;
+ block->bufIndex = bufIndex;
+ block->finished = finished;
+ }
+
+ #ifdef MTCODER__USE_WRITE_THREAD
+ RINOK_THREAD(Event_Set(&mtc->writeEvents[bi]))
+ #else
+ {
+ unsigned wi;
+ {
+ CriticalSection_Enter(&mtc->cs);
+ wi = mtc->writeIndex;
+ if (wi == bi)
+ mtc->writeIndex = (unsigned)(int)-1;
+ else
+ mtc->ReadyBlocks[bi] = True;
+ CriticalSection_Leave(&mtc->cs);
+ }
+
+ if (wi != bi)
+ {
+ if (res != SZ_OK || finished)
+ return 0;
+ continue;
+ }
+
+ if (mtc->writeRes != SZ_OK)
+ res = mtc->writeRes;
+
+ for (;;)
+ {
+ if (res == SZ_OK && bufIndex != (unsigned)(int)-1)
+ {
+ res = mtc->mtCallback->Write(mtc->mtCallbackObject, bufIndex);
+ if (res != SZ_OK)
+ {
+ mtc->writeRes = res;
+ MtProgress_SetError(&mtc->mtProgress, res);
+ }
+ }
+
+ if (++wi >= mtc->numBlocksMax)
+ wi = 0;
+ {
+ Bool isReady;
+
+ CriticalSection_Enter(&mtc->cs);
+
+ if (bufIndex != (unsigned)(int)-1)
+ {
+ mtc->freeBlockList[bufIndex] = mtc->freeBlockHead;
+ mtc->freeBlockHead = bufIndex;
+ }
+
+ isReady = mtc->ReadyBlocks[wi];
+
+ if (isReady)
+ mtc->ReadyBlocks[wi] = False;
+ else
+ mtc->writeIndex = wi;
+
+ CriticalSection_Leave(&mtc->cs);
+
+ RINOK_THREAD(Semaphore_Release1(&mtc->blocksSemaphore))
+
+ if (!isReady)
+ break;
+ }
+
+ {
+ CMtCoderBlock *block = &mtc->blocks[wi];
+ if (res == SZ_OK && block->res != SZ_OK)
+ res = block->res;
+ bufIndex = block->bufIndex;
+ finished = block->finished;
+ }
+ }
+ }
+ #endif
+
+ if (finished || res != SZ_OK)
+ return 0;
}
}
+
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
{
- CMtThread *p = (CMtThread *)pp;
+ CMtCoderThread *t = (CMtCoderThread *)pp;
for (;;)
{
- Bool stop;
- CMtThread *next = GET_NEXT_THREAD(p);
- SRes res = MtThread_Process(p, &stop);
- if (res != SZ_OK)
+ if (Event_Wait(&t->startEvent) != 0)
+ return SZ_ERROR_THREAD;
+ if (t->stop)
+ return 0;
{
- MtCoder_SetError(p->mtCoder, res);
- MtProgress_SetError(&p->mtCoder->mtProgress, res);
- next->stopReading = True;
- next->stopWriting = True;
- Event_Set(&next->canRead);
- Event_Set(&next->canWrite);
- return res;
+ 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
}
- if (stop)
- return 0;
}
}
-void MtCoder_Construct(CMtCoder* p)
+
+
+void MtCoder_Construct(CMtCoder *p)
{
unsigned i;
- p->alloc = 0;
- for (i = 0; i < NUM_MT_CODER_THREADS_MAX; 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++)
{
- CMtThread *t = &p->threads[i];
+ CMtCoderThread *t = &p->threads[i];
+ t->mtCoder = p;
t->index = i;
- CMtThread_Construct(t, p);
+ 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);
}
-void MtCoder_Destruct(CMtCoder* p)
+
+
+
+static void MtCoder_Free(CMtCoder *p)
{
unsigned i;
- for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
- CMtThread_Destruct(&p->threads[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 i, numThreads = p->numThreads;
+ unsigned numThreads = p->numThreadsMax;
+ unsigned numBlocksMax;
+ unsigned i;
SRes res = SZ_OK;
- p->res = SZ_OK;
- MtProgress_Init(&p->mtProgress, p->progress);
+ 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;
- for (i = 0; i < numThreads; i++)
+ if (p->blockSize != p->allocatedBufsSize)
{
- RINOK(CMtThread_Prepare(&p->threads[i]));
+ 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;
}
- for (i = 0; i < numThreads; i++)
- {
- CMtThread *t = &p->threads[i];
- CLoopThread *lt = &t->thread;
+ p->readRes = SZ_OK;
- if (!Thread_WasCreated(&lt->thread))
+ MtProgress_Init(&p->mtProgress, p->progress);
+
+ #ifdef MTCODER__USE_WRITE_THREAD
+ for (i = 0; i < numBlocksMax; i++)
{
- lt->func = ThreadFunc;
- lt->param = t;
+ RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->writeEvents[i]));
+ }
+ #else
+ RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->finishedEvent));
+ #endif
- if (LoopThread_Create(lt) != SZ_OK)
- {
- res = SZ_ERROR_THREAD;
- break;
- }
+ {
+ 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));
}
- if (res == SZ_OK)
+ 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 j;
- for (i = 0; i < numThreads; i++)
+ unsigned bi = 0;
+
+ for (;; bi++)
{
- CMtThread *t = &p->threads[i];
- if (LoopThread_StartSubThread(&t->thread) != SZ_OK)
+ if (bi >= numBlocksMax)
+ bi = 0;
+
+ RINOK_THREAD(Event_Wait(&p->writeEvents[bi]))
+
{
- res = SZ_ERROR_THREAD;
- p->threads[0].stopReading = True;
- break;
+ const CMtCoderBlock *block = &p->blocks[bi];
+ unsigned bufIndex = block->bufIndex;
+ Bool finished = block->finished;
+ if (res == SZ_OK && block->res != SZ_OK)
+ res = block->res;
+
+ if (bufIndex != (unsigned)(int)-1)
+ {
+ if (res == SZ_OK)
+ {
+ res = p->mtCallback->Write(p->mtCallbackObject, bufIndex);
+ if (res != SZ_OK)
+ MtProgress_SetError(&p->mtProgress, res);
+ }
+
+ CriticalSection_Enter(&p->cs);
+ {
+ p->freeBlockList[bufIndex] = p->freeBlockHead;
+ p->freeBlockHead = bufIndex;
+ }
+ CriticalSection_Leave(&p->cs);
+ }
+
+ RINOK_THREAD(Semaphore_Release1(&p->blocksSemaphore))
+
+ if (finished)
+ break;
}
}
+ }
+ #else
+ {
+ WRes wres = Event_Wait(&p->finishedEvent);
+ res = MY_SRes_HRESULT_FROM_WRes(wres);
+ }
+ #endif
+
+ if (res == SZ_OK)
+ res = p->readRes;
- Event_Set(&p->threads[0].canWrite);
- Event_Set(&p->threads[0].canRead);
+ if (res == SZ_OK)
+ res = p->mtProgress.res;
- for (j = 0; j < i; j++)
- LoopThread_WaitSubThread(&p->threads[j].thread);
- }
+ #ifndef MTCODER__USE_WRITE_THREAD
+ if (res == SZ_OK)
+ res = p->writeRes;
+ #endif
- for (i = 0; i < numThreads; i++)
- CMtThread_CloseEvents(&p->threads[i]);
- return (res == SZ_OK) ? p->res : res;
+ if (res != SZ_OK)
+ MtCoder_Free(p);
+ return res;
}
+
+#endif
diff --git a/C/MtCoder.h b/C/MtCoder.h
index 705208e..7982e84 100644
--- a/C/MtCoder.h
+++ b/C/MtCoder.h
@@ -1,98 +1,141 @@
/* MtCoder.h -- Multi-thread Coder
-2009-11-19 : Igor Pavlov : Public domain */
+2018-02-21 : Igor Pavlov : Public domain */
#ifndef __MT_CODER_H
#define __MT_CODER_H
-#include "Threads.h"
+#include "MtDec.h"
EXTERN_C_BEGIN
-typedef struct
-{
- CThread thread;
- CAutoResetEvent startEvent;
- CAutoResetEvent finishedEvent;
- int stop;
-
- THREAD_FUNC_TYPE func;
- LPVOID param;
- THREAD_FUNC_RET_TYPE res;
-} CLoopThread;
-
-void LoopThread_Construct(CLoopThread *p);
-void LoopThread_Close(CLoopThread *p);
-WRes LoopThread_Create(CLoopThread *p);
-WRes LoopThread_StopAndWait(CLoopThread *p);
-WRes LoopThread_StartSubThread(CLoopThread *p);
-WRes LoopThread_WaitSubThread(CLoopThread *p);
+/*
+ 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 NUM_MT_CODER_THREADS_MAX 32
+ #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 NUM_MT_CODER_THREADS_MAX 1
+ #define MTCODER__THREADS_MAX 1
+ #define MTCODER__BLOCKS_MAX 1
#endif
+
+#ifndef _7ZIP_ST
+
+
typedef struct
{
- UInt64 totalInSize;
- UInt64 totalOutSize;
- ICompressProgress *progress;
- SRes res;
- CCriticalSection cs;
- UInt64 inSizes[NUM_MT_CODER_THREADS_MAX];
- UInt64 outSizes[NUM_MT_CODER_THREADS_MAX];
-} CMtProgress;
+ ICompressProgress vt;
+ CMtProgress *mtProgress;
+ UInt64 inSize;
+ UInt64 outSize;
+} CMtProgressThunk;
+
+void MtProgressThunk_CreateVTable(CMtProgressThunk *p);
+
+#define MtProgressThunk_Init(p) { (p)->inSize = 0; (p)->outSize = 0; }
-SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize);
struct _CMtCoder;
+
typedef struct
{
struct _CMtCoder *mtCoder;
- Byte *outBuf;
- size_t outBufSize;
- Byte *inBuf;
- size_t inBufSize;
unsigned index;
- CLoopThread thread;
+ int stop;
+ Byte *inBuf;
+
+ CAutoResetEvent startEvent;
+ CThread thread;
+} CMtCoderThread;
- Bool stopReading;
- Bool stopWriting;
- CAutoResetEvent canRead;
- CAutoResetEvent canWrite;
-} CMtThread;
typedef struct
{
- SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize,
+ SRes (*Code)(void *p, unsigned coderIndex, unsigned outBufIndex,
const Byte *src, size_t srcSize, int finished);
-} IMtCoderCallback;
+ SRes (*Write)(void *p, unsigned outBufIndex);
+} IMtCoderCallback2;
+
+
+typedef struct
+{
+ SRes res;
+ unsigned bufIndex;
+ Bool finished;
+} CMtCoderBlock;
+
typedef struct _CMtCoder
{
- size_t blockSize;
- size_t destBlockSize;
- unsigned numThreads;
+ /* input variables */
+ size_t blockSize; /* size of input block */
+ unsigned numThreadsMax;
+ UInt64 expectedDataSize;
+
ISeqInStream *inStream;
- ISeqOutStream *outStream;
+ const Byte *inData;
+ size_t inDataSize;
+
ICompressProgress *progress;
- ISzAlloc *alloc;
+ ISzAllocPtr allocBig;
+
+ IMtCoderCallback2 *mtCallback;
+ void *mtCallbackObject;
+
+
+ /* internal variables */
+
+ size_t allocatedBufsSize;
+
+ CAutoResetEvent readEvent;
+ CSemaphore blocksSemaphore;
+
+ Bool stopReading;
+ SRes readRes;
+
+ #ifdef MTCODER__USE_WRITE_THREAD
+ CAutoResetEvent writeEvents[MTCODER__BLOCKS_MAX];
+ #else
+ CAutoResetEvent finishedEvent;
+ SRes writeRes;
+ unsigned writeIndex;
+ Byte ReadyBlocks[MTCODER__BLOCKS_MAX];
+ LONG numFinishedThreads;
+ #endif
+
+ unsigned numStartedThreadsLimit;
+ unsigned numStartedThreads;
+
+ unsigned numBlocksMax;
+ unsigned blockIndex;
+ UInt64 readProcessed;
- IMtCoderCallback *mtCallback;
CCriticalSection cs;
- SRes res;
+
+ unsigned freeBlockHead;
+ unsigned freeBlockList[MTCODER__BLOCKS_MAX];
CMtProgress mtProgress;
- CMtThread threads[NUM_MT_CODER_THREADS_MAX];
+ CMtCoderBlock blocks[MTCODER__BLOCKS_MAX];
+ CMtCoderThread threads[MTCODER__THREADS_MAX];
} CMtCoder;
-void MtCoder_Construct(CMtCoder* p);
-void MtCoder_Destruct(CMtCoder* p);
+
+void MtCoder_Construct(CMtCoder *p);
+void MtCoder_Destruct(CMtCoder *p);
SRes MtCoder_Code(CMtCoder *p);
+
+#endif
+
+
EXTERN_C_END
#endif
diff --git a/C/MtDec.c b/C/MtDec.c
new file mode 100644
index 0000000..60d31b0
--- /dev/null
+++ b/C/MtDec.c
@@ -0,0 +1,1137 @@
+/* MtDec.c -- Multi-thread Decoder
+2018-03-02 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+// #define SHOW_DEBUG_INFO
+
+// #include <stdio.h>
+
+#ifdef SHOW_DEBUG_INFO
+#include <stdio.h>
+#endif
+
+#ifdef SHOW_DEBUG_INFO
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
+
+#include "MtDec.h"
+
+#ifndef _7ZIP_ST
+
+void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)
+{
+ p->progress = progress;
+ p->res = SZ_OK;
+ p->totalInSize = 0;
+ p->totalOutSize = 0;
+}
+
+
+SRes MtProgress_Progress_ST(CMtProgress *p)
+{
+ if (p->res == SZ_OK && p->progress)
+ if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK)
+ p->res = SZ_ERROR_PROGRESS;
+ return p->res;
+}
+
+
+SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize)
+{
+ SRes res;
+ CriticalSection_Enter(&p->cs);
+
+ p->totalInSize += inSize;
+ p->totalOutSize += outSize;
+ if (p->res == SZ_OK && p->progress)
+ if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK)
+ p->res = SZ_ERROR_PROGRESS;
+ res = p->res;
+
+ CriticalSection_Leave(&p->cs);
+ return res;
+}
+
+
+SRes MtProgress_GetError(CMtProgress *p)
+{
+ SRes res;
+ CriticalSection_Enter(&p->cs);
+ res = p->res;
+ CriticalSection_Leave(&p->cs);
+ return res;
+}
+
+
+void MtProgress_SetError(CMtProgress *p, SRes res)
+{
+ CriticalSection_Enter(&p->cs);
+ if (p->res == SZ_OK)
+ p->res = res;
+ CriticalSection_Leave(&p->cs);
+}
+
+
+#define RINOK_THREAD(x) RINOK(x)
+
+
+static WRes ArEvent_OptCreate_And_Reset(CEvent *p)
+{
+ if (Event_IsCreated(p))
+ return Event_Reset(p);
+ return AutoResetEvent_CreateNotSignaled(p);
+}
+
+
+
+typedef struct
+{
+ void *next;
+ void *pad[3];
+} CMtDecBufLink;
+
+#define MTDEC__LINK_DATA_OFFSET sizeof(CMtDecBufLink)
+#define MTDEC__DATA_PTR_FROM_LINK(link) ((Byte *)(link) + MTDEC__LINK_DATA_OFFSET)
+
+
+
+static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp);
+
+
+static WRes MtDecThread_CreateEvents(CMtDecThread *t)
+{
+ WRes wres = ArEvent_OptCreate_And_Reset(&t->canWrite);
+ if (wres == 0)
+ {
+ wres = ArEvent_OptCreate_And_Reset(&t->canRead);
+ if (wres == 0)
+ return SZ_OK;
+ }
+ return wres;
+}
+
+
+static SRes MtDecThread_CreateAndStart(CMtDecThread *t)
+{
+ WRes wres = MtDecThread_CreateEvents(t);
+ // wres = 17; // for test
+ if (wres == 0)
+ {
+ if (Thread_WasCreated(&t->thread))
+ return SZ_OK;
+ wres = Thread_Create(&t->thread, ThreadFunc, t);
+ if (wres == 0)
+ return SZ_OK;
+ }
+ return MY_SRes_HRESULT_FROM_WRes(wres);
+}
+
+
+void MtDecThread_FreeInBufs(CMtDecThread *t)
+{
+ if (t->inBuf)
+ {
+ void *link = t->inBuf;
+ t->inBuf = NULL;
+ do
+ {
+ void *next = ((CMtDecBufLink *)link)->next;
+ ISzAlloc_Free(t->mtDec->alloc, link);
+ link = next;
+ }
+ while (link);
+ }
+}
+
+
+static void MtDecThread_CloseThread(CMtDecThread *t)
+{
+ if (Thread_WasCreated(&t->thread))
+ {
+ Event_Set(&t->canWrite); /* we can disable it. There are no threads waiting canWrite in normal cases */
+ Event_Set(&t->canRead);
+ Thread_Wait(&t->thread);
+ Thread_Close(&t->thread);
+ }
+
+ Event_Close(&t->canRead);
+ Event_Close(&t->canWrite);
+}
+
+static void MtDec_CloseThreads(CMtDec *p)
+{
+ unsigned i;
+ for (i = 0; i < MTDEC__THREADS_MAX; i++)
+ MtDecThread_CloseThread(&p->threads[i]);
+}
+
+static void MtDecThread_Destruct(CMtDecThread *t)
+{
+ MtDecThread_CloseThread(t);
+ MtDecThread_FreeInBufs(t);
+}
+
+
+
+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;
+}
+
+
+static SRes MtDec_GetError_Spec(CMtDec *p, UInt64 interruptIndex, Bool *wasInterrupted)
+{
+ SRes res;
+ CriticalSection_Enter(&p->mtProgress.cs);
+ *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex);
+ res = p->mtProgress.res;
+ CriticalSection_Leave(&p->mtProgress.cs);
+ return res;
+}
+
+static SRes MtDec_Progress_GetError_Spec(CMtDec *p, UInt64 inSize, UInt64 outSize, UInt64 interruptIndex, Bool *wasInterrupted)
+{
+ SRes res;
+ CriticalSection_Enter(&p->mtProgress.cs);
+
+ p->mtProgress.totalInSize += inSize;
+ p->mtProgress.totalOutSize += outSize;
+ if (p->mtProgress.res == SZ_OK && p->mtProgress.progress)
+ if (ICompressProgress_Progress(p->mtProgress.progress, p->mtProgress.totalInSize, p->mtProgress.totalOutSize) != SZ_OK)
+ p->mtProgress.res = SZ_ERROR_PROGRESS;
+
+ *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex);
+ res = p->mtProgress.res;
+
+ CriticalSection_Leave(&p->mtProgress.cs);
+
+ return res;
+}
+
+static void MtDec_Interrupt(CMtDec *p, UInt64 interruptIndex)
+{
+ CriticalSection_Enter(&p->mtProgress.cs);
+ if (!p->needInterrupt || interruptIndex < p->interruptIndex)
+ {
+ p->interruptIndex = interruptIndex;
+ p->needInterrupt = True;
+ }
+ CriticalSection_Leave(&p->mtProgress.cs);
+}
+
+Byte *MtDec_GetCrossBuff(CMtDec *p)
+{
+ Byte *cr = p->crossBlock;
+ if (!cr)
+ {
+ cr = (Byte *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize);
+ if (!cr)
+ return NULL;
+ p->crossBlock = cr;
+ }
+ return MTDEC__DATA_PTR_FROM_LINK(cr);
+}
+
+
+/*
+ ThreadFunc2() returns:
+ 0 - in all normal cases (even for stream error or memory allocation error)
+ (!= 0) - WRes error return by system threading function
+*/
+
+// #define MTDEC_ProgessStep (1 << 22)
+#define MTDEC_ProgessStep (1 << 0)
+
+static WRes ThreadFunc2(CMtDecThread *t)
+{
+ CMtDec *p = t->mtDec;
+
+ PRF_STR_INT("ThreadFunc2", t->index);
+
+ // SetThreadAffinityMask(GetCurrentThread(), 1 << t->index);
+
+ for (;;)
+ {
+ SRes res, codeRes;
+ Bool wasInterrupted, isAllocError, overflow, finish;
+ SRes threadingErrorSRes;
+ Bool needCode, needWrite, needContinue;
+
+ size_t inDataSize_Start;
+ UInt64 inDataSize;
+ // UInt64 inDataSize_Full;
+
+ UInt64 blockIndex;
+
+ UInt64 inPrev = 0;
+ UInt64 outPrev = 0;
+ UInt64 inCodePos;
+ UInt64 outCodePos;
+
+ Byte *afterEndData = NULL;
+ size_t afterEndData_Size = 0;
+
+ Bool canCreateNewThread = False;
+ // CMtDecCallbackInfo parse;
+ CMtDecThread *nextThread;
+
+ PRF_STR_INT("Event_Wait(&t->canRead)", t->index);
+
+ RINOK_THREAD(Event_Wait(&t->canRead));
+ if (p->exitThread)
+ return 0;
+
+ PRF_STR_INT("after Event_Wait(&t->canRead)", t->index);
+
+ // if (t->index == 3) return 19; // for test
+
+ blockIndex = p->blockIndex++;
+
+ // PRF(printf("\ncanRead\n"))
+
+ res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted);
+
+ finish = p->readWasFinished;
+ needCode = False;
+ needWrite = False;
+ isAllocError = False;
+ overflow = False;
+
+ inDataSize_Start = 0;
+ inDataSize = 0;
+ // inDataSize_Full = 0;
+
+ if (res == SZ_OK && !wasInterrupted)
+ {
+ // if (p->inStream)
+ {
+ CMtDecBufLink *prev = NULL;
+ CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf;
+ size_t crossSize = p->crossEnd - p->crossStart;
+
+ PRF(printf("\ncrossSize = %d\n", crossSize));
+
+ for (;;)
+ {
+ if (!link)
+ {
+ link = (CMtDecBufLink *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize);
+ if (!link)
+ {
+ finish = True;
+ // p->allocError_for_Read_BlockIndex = blockIndex;
+ isAllocError = True;
+ break;
+ }
+ link->next = NULL;
+ if (prev)
+ {
+ // static unsigned g_num = 0;
+ // printf("\n%6d : %x", ++g_num, (unsigned)(size_t)((Byte *)link - (Byte *)prev));
+ prev->next = link;
+ }
+ else
+ t->inBuf = (void *)link;
+ }
+
+ {
+ Byte *data = MTDEC__DATA_PTR_FROM_LINK(link);
+ Byte *parseData = data;
+ size_t size;
+
+ if (crossSize != 0)
+ {
+ inDataSize = crossSize;
+ // inDataSize_Full = inDataSize;
+ inDataSize_Start = crossSize;
+ size = crossSize;
+ parseData = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart;
+ PRF(printf("\ncross : crossStart = %7d crossEnd = %7d finish = %1d",
+ (int)p->crossStart, (int)p->crossEnd, (int)finish));
+ }
+ else
+ {
+ size = p->inBufSize;
+
+ res = FullRead(p->inStream, data, &size);
+
+ // size = 10; // test
+
+ inDataSize += size;
+ // inDataSize_Full = inDataSize;
+ if (!prev)
+ inDataSize_Start = size;
+
+ p->readProcessed += size;
+ finish = (size != p->inBufSize);
+ if (finish)
+ p->readWasFinished = True;
+
+ // res = E_INVALIDARG; // test
+
+ if (res != SZ_OK)
+ {
+ // PRF(printf("\nRead error = %d\n", res))
+ // we want to decode all data before error
+ p->readRes = res;
+ // p->readError_BlockIndex = blockIndex;
+ p->readWasFinished = True;
+ finish = True;
+ res = SZ_OK;
+ // break;
+ }
+
+ if (inDataSize - inPrev >= MTDEC_ProgessStep)
+ {
+ res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted);
+ if (res != SZ_OK || wasInterrupted)
+ break;
+ inPrev = inDataSize;
+ }
+ }
+
+ {
+ CMtDecCallbackInfo parse;
+
+ parse.startCall = (prev == NULL);
+ parse.src = parseData;
+ parse.srcSize = size;
+ parse.srcFinished = finish;
+ parse.canCreateNewThread = True;
+
+ // PRF(printf("\nParse size = %d\n", (unsigned)size))
+
+ p->mtCallback->Parse(p->mtCallbackObject, t->index, &parse);
+
+ needWrite = True;
+ canCreateNewThread = parse.canCreateNewThread;
+
+ // printf("\n\n%12I64u %12I64u", (UInt64)p->mtProgress.totalInSize, (UInt64)p->mtProgress.totalOutSize);
+
+ if (
+ // parseRes != SZ_OK ||
+ // inDataSize - (size - parse.srcSize) > p->inBlockMax
+ // ||
+ parse.state == MTDEC_PARSE_OVERFLOW
+ // || wasInterrupted
+ )
+ {
+ // Overflow or Parse error - switch from MT decoding to ST decoding
+ finish = True;
+ overflow = True;
+
+ {
+ PRF(printf("\n Overflow"));
+ // PRF(printf("\nisBlockFinished = %d", (unsigned)parse.blockWasFinished));
+ PRF(printf("\n inDataSize = %d", (unsigned)inDataSize));
+ }
+
+ if (crossSize != 0)
+ memcpy(data, parseData, size);
+ p->crossStart = 0;
+ p->crossEnd = 0;
+ break;
+ }
+
+ if (crossSize != 0)
+ {
+ memcpy(data, parseData, parse.srcSize);
+ p->crossStart += parse.srcSize;
+ }
+
+ if (parse.state != MTDEC_PARSE_CONTINUE || finish)
+ {
+ // we don't need to parse in current thread anymore
+
+ if (parse.state == MTDEC_PARSE_END)
+ finish = True;
+
+ needCode = True;
+ // p->crossFinished = finish;
+
+ if (parse.srcSize == size)
+ {
+ // full parsed - no cross transfer
+ p->crossStart = 0;
+ p->crossEnd = 0;
+ break;
+ }
+
+ if (parse.state == MTDEC_PARSE_END)
+ {
+ p->crossStart = 0;
+ p->crossEnd = 0;
+
+ if (crossSize != 0)
+ memcpy(data + parse.srcSize, parseData + parse.srcSize, size - parse.srcSize); // we need all data
+ afterEndData_Size = size - parse.srcSize;
+ afterEndData = parseData + parse.srcSize;
+
+ // we reduce data size to required bytes (parsed only)
+ inDataSize -= (size - parse.srcSize);
+ if (!prev)
+ inDataSize_Start = parse.srcSize;
+ break;
+ }
+
+ {
+ // partial parsed - need cross transfer
+ if (crossSize != 0)
+ inDataSize = parse.srcSize; // it's only parsed now
+ else
+ {
+ // partial parsed - is not in initial cross block - we need to copy new data to cross block
+ Byte *cr = MtDec_GetCrossBuff(p);
+ if (!cr)
+ {
+ {
+ PRF(printf("\ncross alloc error error\n"));
+ // res = SZ_ERROR_MEM;
+ finish = True;
+ // p->allocError_for_Read_BlockIndex = blockIndex;
+ isAllocError = True;
+ break;
+ }
+ }
+
+ {
+ size_t crSize = size - parse.srcSize;
+ inDataSize -= crSize;
+ p->crossEnd = crSize;
+ p->crossStart = 0;
+ memcpy(cr, parseData + parse.srcSize, crSize);
+ }
+ }
+
+ // inDataSize_Full = inDataSize;
+ if (!prev)
+ inDataSize_Start = parse.srcSize; // it's partial size (parsed only)
+
+ finish = False;
+ break;
+ }
+ }
+
+ if (parse.srcSize != size)
+ {
+ res = SZ_ERROR_FAIL;
+ PRF(printf("\nfinished error SZ_ERROR_FAIL = %d\n", res));
+ break;
+ }
+ }
+ }
+
+ prev = link;
+ link = link->next;
+
+ if (crossSize != 0)
+ {
+ crossSize = 0;
+ p->crossStart = 0;
+ p->crossEnd = 0;
+ }
+ }
+ }
+
+ if (res == SZ_OK)
+ res = MtDec_GetError_Spec(p, blockIndex, &wasInterrupted);
+ }
+
+ codeRes = SZ_OK;
+
+ if (res == SZ_OK && needCode && !wasInterrupted)
+ {
+ codeRes = p->mtCallback->PreCode(p->mtCallbackObject, t->index);
+ if (codeRes != SZ_OK)
+ {
+ needCode = False;
+ finish = True;
+ // SZ_ERROR_MEM is expected error here.
+ // if (codeRes == SZ_ERROR_MEM) - we will try single-thread decoding later.
+ // if (codeRes != SZ_ERROR_MEM) - we can stop decoding or try single-thread decoding.
+ }
+ }
+
+ if (res != SZ_OK || wasInterrupted)
+ finish = True;
+
+ nextThread = NULL;
+ threadingErrorSRes = SZ_OK;
+
+ if (!finish)
+ {
+ if (p->numStartedThreads < p->numStartedThreads_Limit && canCreateNewThread)
+ {
+ SRes res2 = MtDecThread_CreateAndStart(&p->threads[p->numStartedThreads]);
+ if (res2 == SZ_OK)
+ {
+ // if (p->numStartedThreads % 1000 == 0) PRF(printf("\n numStartedThreads=%d\n", p->numStartedThreads));
+ p->numStartedThreads++;
+ }
+ else
+ {
+ PRF(printf("\nERROR: numStartedThreads=%d\n", p->numStartedThreads));
+ if (p->numStartedThreads == 1)
+ {
+ // if only one thread is possible, we leave muti-threading code
+ finish = True;
+ needCode = False;
+ threadingErrorSRes = res2;
+ }
+ else
+ p->numStartedThreads_Limit = p->numStartedThreads;
+ }
+ }
+
+ if (!finish)
+ {
+ unsigned nextIndex = t->index + 1;
+ nextThread = &p->threads[nextIndex >= p->numStartedThreads ? 0 : nextIndex];
+ RINOK_THREAD(Event_Set(&nextThread->canRead))
+ // We have started executing for new iteration (with next thread)
+ // And that next thread now is responsible for possible exit from decoding (threading_code)
+ }
+ }
+
+ // each call of Event_Set(&nextThread->canRead) must be followed by call of Event_Set(&nextThread->canWrite)
+ // if ( !finish ) we must call Event_Set(&nextThread->canWrite) in any case
+ // if ( finish ) we switch to single-thread mode and there are 2 ways at the end of current iteration (current block):
+ // - if (needContinue) after Write(&needContinue), we restore decoding with new iteration
+ // - otherwise we stop decoding and exit from ThreadFunc2()
+
+ // Don't change (finish) variable in the further code
+
+
+ // ---------- CODE ----------
+
+ inPrev = 0;
+ outPrev = 0;
+ inCodePos = 0;
+ outCodePos = 0;
+
+ if (res == SZ_OK && needCode && codeRes == SZ_OK)
+ {
+ Bool isStartBlock = True;
+ CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf;
+
+ for (;;)
+ {
+ size_t inSize;
+ int stop;
+
+ if (isStartBlock)
+ inSize = inDataSize_Start;
+ else
+ {
+ UInt64 rem = inDataSize - inCodePos;
+ inSize = p->inBufSize;
+ if (inSize > rem)
+ inSize = (size_t)rem;
+ }
+
+ inCodePos += inSize;
+ stop = True;
+
+ codeRes = p->mtCallback->Code(p->mtCallbackObject, t->index,
+ (const Byte *)MTDEC__DATA_PTR_FROM_LINK(link), inSize,
+ (inCodePos == inDataSize), // srcFinished
+ &inCodePos, &outCodePos, &stop);
+
+ if (codeRes != SZ_OK)
+ {
+ PRF(printf("\nCode Interrupt error = %x\n", codeRes));
+ // we interrupt only later blocks
+ MtDec_Interrupt(p, blockIndex);
+ break;
+ }
+
+ if (stop || inCodePos == inDataSize)
+ break;
+
+ {
+ const UInt64 inDelta = inCodePos - inPrev;
+ const UInt64 outDelta = outCodePos - outPrev;
+ if (inDelta >= MTDEC_ProgessStep || outDelta >= MTDEC_ProgessStep)
+ {
+ // Sleep(1);
+ res = MtDec_Progress_GetError_Spec(p, inDelta, outDelta, blockIndex, &wasInterrupted);
+ if (res != SZ_OK || wasInterrupted)
+ break;
+ inPrev = inCodePos;
+ outPrev = outCodePos;
+ }
+ }
+
+ link = link->next;
+ isStartBlock = False;
+ }
+ }
+
+
+ // ---------- WRITE ----------
+
+ RINOK_THREAD(Event_Wait(&t->canWrite));
+
+ {
+ Bool isErrorMode = False;
+ Bool canRecode = True;
+ Bool needWriteToStream = needWrite;
+
+ if (p->exitThread) return 0; // it's never executed in normal cases
+
+ if (p->wasInterrupted)
+ wasInterrupted = True;
+ else
+ {
+ if (codeRes != SZ_OK) // || !needCode // check it !!!
+ {
+ p->wasInterrupted = True;
+ p->codeRes = codeRes;
+ if (codeRes == SZ_ERROR_MEM)
+ isAllocError = True;
+ }
+
+ if (threadingErrorSRes)
+ {
+ p->wasInterrupted = True;
+ p->threadingErrorSRes = threadingErrorSRes;
+ needWriteToStream = False;
+ }
+ if (isAllocError)
+ {
+ p->wasInterrupted = True;
+ p->isAllocError = True;
+ needWriteToStream = False;
+ }
+ if (overflow)
+ {
+ p->wasInterrupted = True;
+ p->overflow = True;
+ needWriteToStream = False;
+ }
+ }
+
+ if (needCode)
+ {
+ if (wasInterrupted)
+ {
+ inCodePos = 0;
+ outCodePos = 0;
+ }
+ {
+ const UInt64 inDelta = inCodePos - inPrev;
+ const UInt64 outDelta = outCodePos - outPrev;
+ // if (inDelta != 0 || outDelta != 0)
+ res = MtProgress_ProgressAdd(&p->mtProgress, inDelta, outDelta);
+ }
+ }
+
+ needContinue = (!finish);
+
+ // if (res == SZ_OK && needWrite && !wasInterrupted)
+ if (needWrite)
+ {
+ // p->inProcessed += inCodePos;
+
+ res = p->mtCallback->Write(p->mtCallbackObject, t->index,
+ res == SZ_OK && needWriteToStream && !wasInterrupted, // needWrite
+ afterEndData, afterEndData_Size,
+ &needContinue,
+ &canRecode);
+
+ // res= E_INVALIDARG; // for test
+
+ PRF(printf("\nAfter Write needContinue = %d\n", (unsigned)needContinue));
+ PRF(printf("\nprocessed = %d\n", (unsigned)p->inProcessed));
+
+ if (res != SZ_OK)
+ {
+ PRF(printf("\nWrite error = %d\n", res));
+ isErrorMode = True;
+ p->wasInterrupted = True;
+ }
+ if (res != SZ_OK
+ || (!needContinue && !finish))
+ {
+ PRF(printf("\nWrite Interrupt error = %x\n", res));
+ MtDec_Interrupt(p, blockIndex);
+ }
+ }
+
+ if (canRecode)
+ if (!needCode
+ || res != SZ_OK
+ || p->wasInterrupted
+ || codeRes != SZ_OK
+ || wasInterrupted
+ || p->numFilledThreads != 0
+ || isErrorMode)
+ {
+ if (p->numFilledThreads == 0)
+ p->filledThreadStart = t->index;
+ if (inDataSize != 0 || !finish)
+ {
+ t->inDataSize_Start = inDataSize_Start;
+ t->inDataSize = inDataSize;
+ p->numFilledThreads++;
+ }
+ PRF(printf("\np->numFilledThreads = %d\n", p->numFilledThreads));
+ PRF(printf("p->filledThreadStart = %d\n", p->filledThreadStart));
+ }
+
+ if (!finish)
+ {
+ RINOK_THREAD(Event_Set(&nextThread->canWrite));
+ }
+ else
+ {
+ if (needContinue)
+ {
+ // we restore decoding with new iteration
+ RINOK_THREAD(Event_Set(&p->threads[0].canWrite));
+ }
+ else
+ {
+ // we exit from decoding
+ if (t->index == 0)
+ return SZ_OK;
+ p->exitThread = True;
+ }
+ RINOK_THREAD(Event_Set(&p->threads[0].canRead));
+ }
+ }
+ }
+}
+
+#ifdef _WIN32
+#define USE_ALLOCA
+#endif
+
+#ifdef USE_ALLOCA
+#ifdef _WIN32
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+#endif
+
+
+static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc1(void *pp)
+{
+ WRes res;
+
+ CMtDecThread *t = (CMtDecThread *)pp;
+ CMtDec *p;
+
+ // fprintf(stdout, "\n%d = %p\n", t->index, &t);
+
+ res = ThreadFunc2(t);
+ p = t->mtDec;
+ if (res == 0)
+ return p->exitThreadWRes;
+ {
+ // it's unexpected situation for some threading function error
+ if (p->exitThreadWRes == 0)
+ p->exitThreadWRes = res;
+ PRF(printf("\nthread exit error = %d\n", res));
+ p->exitThread = True;
+ Event_Set(&p->threads[0].canRead);
+ Event_Set(&p->threads[0].canWrite);
+ MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res));
+ }
+ return res;
+}
+
+static MY_NO_INLINE THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
+{
+ CMtDecThread *t = (CMtDecThread *)pp;
+
+ // fprintf(stderr, "\n%d = %p - before", t->index, &t);
+ #ifdef USE_ALLOCA
+ t->allocaPtr = alloca(t->index * 128);
+ #endif
+ return ThreadFunc1(pp);
+}
+
+
+int MtDec_PrepareRead(CMtDec *p)
+{
+ if (p->crossBlock && p->crossStart == p->crossEnd)
+ {
+ ISzAlloc_Free(p->alloc, p->crossBlock);
+ p->crossBlock = NULL;
+ }
+
+ {
+ unsigned i;
+ for (i = 0; i < MTDEC__THREADS_MAX; i++)
+ if (i > p->numStartedThreads
+ || p->numFilledThreads <=
+ (i >= p->filledThreadStart ?
+ i - p->filledThreadStart :
+ i + p->numStartedThreads - p->filledThreadStart))
+ MtDecThread_FreeInBufs(&p->threads[i]);
+ }
+
+ return (p->numFilledThreads != 0) || (p->crossStart != p->crossEnd);
+}
+
+
+const Byte *MtDec_Read(CMtDec *p, size_t *inLim)
+{
+ while (p->numFilledThreads != 0)
+ {
+ CMtDecThread *t = &p->threads[p->filledThreadStart];
+
+ if (*inLim != 0)
+ {
+ {
+ void *link = t->inBuf;
+ void *next = ((CMtDecBufLink *)link)->next;
+ ISzAlloc_Free(p->alloc, link);
+ t->inBuf = next;
+ }
+
+ if (t->inDataSize == 0)
+ {
+ MtDecThread_FreeInBufs(t);
+ if (--p->numFilledThreads == 0)
+ break;
+ if (++p->filledThreadStart == p->numStartedThreads)
+ p->filledThreadStart = 0;
+ t = &p->threads[p->filledThreadStart];
+ }
+ }
+
+ {
+ size_t lim = t->inDataSize_Start;
+ if (lim != 0)
+ t->inDataSize_Start = 0;
+ else
+ {
+ UInt64 rem = t->inDataSize;
+ lim = p->inBufSize;
+ if (lim > rem)
+ lim = (size_t)rem;
+ }
+ t->inDataSize -= lim;
+ *inLim = lim;
+ return (const Byte *)MTDEC__DATA_PTR_FROM_LINK(t->inBuf);
+ }
+ }
+
+ {
+ size_t crossSize = p->crossEnd - p->crossStart;
+ if (crossSize != 0)
+ {
+ const Byte *data = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart;
+ *inLim = crossSize;
+ p->crossStart = 0;
+ p->crossEnd = 0;
+ return data;
+ }
+ *inLim = 0;
+ if (p->crossBlock)
+ {
+ ISzAlloc_Free(p->alloc, p->crossBlock);
+ p->crossBlock = NULL;
+ }
+ return NULL;
+ }
+}
+
+
+void MtDec_Construct(CMtDec *p)
+{
+ unsigned i;
+
+ p->inBufSize = (size_t)1 << 18;
+
+ p->numThreadsMax = 0;
+
+ p->inStream = NULL;
+
+ // p->inData = NULL;
+ // p->inDataSize = 0;
+
+ p->crossBlock = NULL;
+ p->crossStart = 0;
+ p->crossEnd = 0;
+
+ p->numFilledThreads = 0;
+
+ p->progress = NULL;
+ p->alloc = NULL;
+
+ p->mtCallback = NULL;
+ p->mtCallbackObject = NULL;
+
+ p->allocatedBufsSize = 0;
+
+ for (i = 0; i < MTDEC__THREADS_MAX; i++)
+ {
+ CMtDecThread *t = &p->threads[i];
+ t->mtDec = p;
+ t->index = i;
+ t->inBuf = NULL;
+ Event_Construct(&t->canRead);
+ Event_Construct(&t->canWrite);
+ Thread_Construct(&t->thread);
+ }
+
+ // Event_Construct(&p->finishedEvent);
+
+ CriticalSection_Init(&p->mtProgress.cs);
+}
+
+
+static void MtDec_Free(CMtDec *p)
+{
+ unsigned i;
+
+ p->exitThread = True;
+
+ for (i = 0; i < MTDEC__THREADS_MAX; i++)
+ MtDecThread_Destruct(&p->threads[i]);
+
+ // Event_Close(&p->finishedEvent);
+
+ if (p->crossBlock)
+ {
+ ISzAlloc_Free(p->alloc, p->crossBlock);
+ p->crossBlock = NULL;
+ }
+}
+
+
+void MtDec_Destruct(CMtDec *p)
+{
+ MtDec_Free(p);
+
+ CriticalSection_Delete(&p->mtProgress.cs);
+}
+
+
+SRes MtDec_Code(CMtDec *p)
+{
+ unsigned i;
+
+ p->inProcessed = 0;
+
+ p->blockIndex = 1; // it must be larger than not_defined index (0)
+ p->isAllocError = False;
+ p->overflow = False;
+ p->threadingErrorSRes = SZ_OK;
+
+ p->needContinue = True;
+
+ p->readWasFinished = False;
+ p->needInterrupt = False;
+ p->interruptIndex = (UInt64)(Int64)-1;
+
+ p->readProcessed = 0;
+ p->readRes = SZ_OK;
+ p->codeRes = SZ_OK;
+ p->wasInterrupted = False;
+
+ p->crossStart = 0;
+ p->crossEnd = 0;
+
+ p->filledThreadStart = 0;
+ p->numFilledThreads = 0;
+
+ {
+ unsigned numThreads = p->numThreadsMax;
+ if (numThreads > MTDEC__THREADS_MAX)
+ numThreads = MTDEC__THREADS_MAX;
+ p->numStartedThreads_Limit = numThreads;
+ p->numStartedThreads = 0;
+ }
+
+ if (p->inBufSize != p->allocatedBufsSize)
+ {
+ for (i = 0; i < MTDEC__THREADS_MAX; i++)
+ {
+ CMtDecThread *t = &p->threads[i];
+ if (t->inBuf)
+ MtDecThread_FreeInBufs(t);
+ }
+ if (p->crossBlock)
+ {
+ ISzAlloc_Free(p->alloc, p->crossBlock);
+ p->crossBlock = NULL;
+ }
+
+ p->allocatedBufsSize = p->inBufSize;
+ }
+
+ MtProgress_Init(&p->mtProgress, p->progress);
+
+ // RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->finishedEvent));
+ p->exitThread = False;
+ p->exitThreadWRes = 0;
+
+ {
+ WRes wres;
+ WRes sres;
+ CMtDecThread *nextThread = &p->threads[p->numStartedThreads++];
+ // wres = MtDecThread_CreateAndStart(nextThread);
+ wres = MtDecThread_CreateEvents(nextThread);
+ if (wres == 0) { wres = Event_Set(&nextThread->canWrite);
+ if (wres == 0) { wres = Event_Set(&nextThread->canRead);
+ if (wres == 0) { wres = ThreadFunc(nextThread);
+ if (wres != 0)
+ {
+ p->needContinue = False;
+ MtDec_CloseThreads(p);
+ }}}}
+
+ // wres = 17; // for test
+ // wres = Event_Wait(&p->finishedEvent);
+
+ sres = MY_SRes_HRESULT_FROM_WRes(wres);
+
+ if (sres != 0)
+ p->threadingErrorSRes = sres;
+
+ if (
+ // wres == 0
+ // wres != 0
+ // || p->mtc.codeRes == SZ_ERROR_MEM
+ p->isAllocError
+ || p->threadingErrorSRes != SZ_OK
+ || p->overflow)
+ {
+ // p->needContinue = True;
+ }
+ else
+ p->needContinue = False;
+
+ if (p->needContinue)
+ return SZ_OK;
+
+ // if (sres != SZ_OK)
+ return sres;
+ // return E_FAIL;
+ }
+}
+
+#endif
diff --git a/C/MtDec.h b/C/MtDec.h
new file mode 100644
index 0000000..b445bc9
--- /dev/null
+++ b/C/MtDec.h
@@ -0,0 +1,201 @@
+/* MtDec.h -- Multi-thread Decoder
+2018-03-02 : Igor Pavlov : Public domain */
+
+#ifndef __MT_DEC_H
+#define __MT_DEC_H
+
+#include "7zTypes.h"
+
+#ifndef _7ZIP_ST
+#include "Threads.h"
+#endif
+
+EXTERN_C_BEGIN
+
+#ifndef _7ZIP_ST
+
+#ifndef _7ZIP_ST
+ #define MTDEC__THREADS_MAX 32
+#else
+ #define MTDEC__THREADS_MAX 1
+#endif
+
+
+typedef struct
+{
+ ICompressProgress *progress;
+ SRes res;
+ UInt64 totalInSize;
+ UInt64 totalOutSize;
+ CCriticalSection cs;
+} CMtProgress;
+
+void MtProgress_Init(CMtProgress *p, ICompressProgress *progress);
+SRes MtProgress_Progress_ST(CMtProgress *p);
+SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize);
+SRes MtProgress_GetError(CMtProgress *p);
+void MtProgress_SetError(CMtProgress *p, SRes res);
+
+struct _CMtDec;
+
+typedef struct
+{
+ struct _CMtDec *mtDec;
+ unsigned index;
+ void *inBuf;
+
+ size_t inDataSize_Start; // size of input data in start block
+ UInt64 inDataSize; // total size of input data in all blocks
+
+ CThread thread;
+ CAutoResetEvent canRead;
+ CAutoResetEvent canWrite;
+ void *allocaPtr;
+} CMtDecThread;
+
+void MtDecThread_FreeInBufs(CMtDecThread *t);
+
+
+typedef enum
+{
+ MTDEC_PARSE_CONTINUE, // continue this block with more input data
+ MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread
+ MTDEC_PARSE_NEW, // new block
+ MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue)
+} EMtDecParseState;
+
+typedef struct
+{
+ // in
+ int startCall;
+ const Byte *src;
+ size_t srcSize;
+ // in : (srcSize == 0) is allowed
+ // out : it's allowed to return less that actually was used ?
+ int srcFinished;
+
+ // out
+ EMtDecParseState state;
+ Bool canCreateNewThread;
+ UInt64 outPos; // check it (size_t)
+} CMtDecCallbackInfo;
+
+
+typedef struct
+{
+ void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci);
+
+ // PreCode() and Code():
+ // (SRes_return_result != SZ_OK) means stop decoding, no need another blocks
+ SRes (*PreCode)(void *p, unsigned coderIndex);
+ SRes (*Code)(void *p, unsigned coderIndex,
+ const Byte *src, size_t srcSize, int srcFinished,
+ UInt64 *inCodePos, UInt64 *outCodePos, int *stop);
+ // stop - means stop another Code calls
+
+
+ /* Write() must be called, if Parse() was called
+ set (needWrite) if
+ {
+ && (was not interrupted by progress)
+ && (was not interrupted in previous block)
+ }
+
+ out:
+ if (*needContinue), decoder still need to continue decoding with new iteration,
+ even after MTDEC_PARSE_END
+ if (*canRecode), we didn't flush current block data, so we still can decode current block later.
+ */
+ SRes (*Write)(void *p, unsigned coderIndex,
+ Bool needWriteToStream,
+ const Byte *src, size_t srcSize,
+ // int srcFinished,
+ Bool *needContinue,
+ Bool *canRecode);
+} IMtDecCallback;
+
+
+
+typedef struct _CMtDec
+{
+ /* input variables */
+
+ size_t inBufSize; /* size of input block */
+ unsigned numThreadsMax;
+ // size_t inBlockMax;
+ unsigned numThreadsMax_2;
+
+ ISeqInStream *inStream;
+ // const Byte *inData;
+ // size_t inDataSize;
+
+ ICompressProgress *progress;
+ ISzAllocPtr alloc;
+
+ IMtDecCallback *mtCallback;
+ void *mtCallbackObject;
+
+
+ /* internal variables */
+
+ size_t allocatedBufsSize;
+
+ Bool exitThread;
+ WRes exitThreadWRes;
+
+ UInt64 blockIndex;
+ Bool isAllocError;
+ Bool overflow;
+ SRes threadingErrorSRes;
+
+ Bool needContinue;
+
+ // CAutoResetEvent finishedEvent;
+
+ SRes readRes;
+ SRes codeRes;
+
+ Bool wasInterrupted;
+
+ unsigned numStartedThreads_Limit;
+ unsigned numStartedThreads;
+
+ Byte *crossBlock;
+ size_t crossStart;
+ size_t crossEnd;
+ UInt64 readProcessed;
+ Bool readWasFinished;
+ UInt64 inProcessed;
+
+ unsigned filledThreadStart;
+ unsigned numFilledThreads;
+
+ #ifndef _7ZIP_ST
+ Bool needInterrupt;
+ UInt64 interruptIndex;
+ CMtProgress mtProgress;
+ CMtDecThread threads[MTDEC__THREADS_MAX];
+ #endif
+} CMtDec;
+
+
+void MtDec_Construct(CMtDec *p);
+void MtDec_Destruct(CMtDec *p);
+
+/*
+MtDec_Code() returns:
+ SZ_OK - in most cases
+ MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function
+*/
+
+SRes MtDec_Code(CMtDec *p);
+Byte *MtDec_GetCrossBuff(CMtDec *p);
+
+int MtDec_PrepareRead(CMtDec *p);
+const Byte *MtDec_Read(CMtDec *p, size_t *inLim);
+
+#endif
+
+EXTERN_C_END
+
+#endif
diff --git a/C/Ppmd.h b/C/Ppmd.h
index e807ca1..4b99415 100644
--- a/C/Ppmd.h
+++ b/C/Ppmd.h
@@ -1,5 +1,5 @@
/* Ppmd.h -- PPMD codec common code
-2016-05-16 : Igor Pavlov : Public domain
+2017-04-03 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#ifndef __PPMD_H
@@ -77,7 +77,7 @@ typedef
CPpmd_Byte_Ref;
#define PPMD_SetAllBitsIn256Bytes(p) \
- { unsigned z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \
+ { 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
diff --git a/C/Ppmd7.c b/C/Ppmd7.c
index ba5d329..ef93cb2 100644
--- a/C/Ppmd7.c
+++ b/C/Ppmd7.c
@@ -1,5 +1,5 @@
/* Ppmd7.c -- PPMdH codec
-2016-05-21 : Igor Pavlov : Public domain
+2017-04-03 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h"
@@ -15,7 +15,7 @@ static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x
#define UNIT_SIZE 12
#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
-#define U2I(nu) (p->Units2Indx[(nu) - 1])
+#define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1])
#define I2U(indx) (p->Indx2Units[indx])
#ifdef PPMD_32BIT
@@ -88,29 +88,31 @@ void Ppmd7_Construct(CPpmd7 *p)
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
}
-void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
+void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc)
{
- alloc->Free(alloc, p->Base);
+ ISzAlloc_Free(alloc, p->Base);
p->Size = 0;
p->Base = 0;
}
-Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
+Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc)
{
- if (p->Base == 0 || p->Size != size)
+ 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 *)alloc->Alloc(alloc, p->AlignOffset + size
- #ifndef PPMD_32BIT
- + UNIT_SIZE
- #endif
- )) == 0)
+ if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size + size2)) == 0)
return False;
p->Size = size;
}
@@ -513,7 +515,7 @@ static void UpdateModel(CPpmd7 *p)
/* Expand for one UNIT */
unsigned oldNU = ns1 >> 1;
unsigned i = U2I(oldNU);
- if (i != U2I(oldNU + 1))
+ if (i != U2I((size_t)oldNU + 1))
{
void *ptr = AllocUnits(p, i + 1);
void *oldPtr;
@@ -639,7 +641,7 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
unsigned nonMasked = p->MinContext->NumStats - numMasked;
if (p->MinContext->NumStats != 256)
{
- see = p->See[(unsigned)p->NS2Indx[nonMasked - 1]] +
+ 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) +
diff --git a/C/Ppmd7.h b/C/Ppmd7.h
index 1c7870c..ee2c035 100644
--- a/C/Ppmd7.h
+++ b/C/Ppmd7.h
@@ -1,5 +1,5 @@
/* Ppmd7.h -- PPMdH compression codec
-2016-05-21 : Igor Pavlov : Public domain
+2017-04-03 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
/* This code supports virtual RangeDecoder and includes the implementation
@@ -60,8 +60,8 @@ typedef struct
} CPpmd7;
void Ppmd7_Construct(CPpmd7 *p);
-Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
-void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc);
+Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc);
+void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc);
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
@@ -86,8 +86,8 @@ void Ppmd7_Update2(CPpmd7 *p);
void Ppmd7_UpdateBin(CPpmd7 *p);
#define Ppmd7_GetBinSumm(p) \
- &p->BinSumm[(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
- p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
+ &p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
+ p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
(p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
2 * p->HB2Flag[(unsigned)Ppmd7Context_OneState(p->MinContext)->Symbol] + \
((p->RunLength >> 26) & 0x20)]
@@ -97,16 +97,18 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
/* ---------- Decode ---------- */
-typedef struct
+typedef struct IPpmd7_RangeDec IPpmd7_RangeDec;
+
+struct IPpmd7_RangeDec
{
- UInt32 (*GetThreshold)(void *p, UInt32 total);
- void (*Decode)(void *p, UInt32 start, UInt32 size);
- UInt32 (*DecodeBit)(void *p, UInt32 size0);
-} IPpmd7_RangeDec;
+ UInt32 (*GetThreshold)(const IPpmd7_RangeDec *p, UInt32 total);
+ void (*Decode)(const IPpmd7_RangeDec *p, UInt32 start, UInt32 size);
+ UInt32 (*DecodeBit)(const IPpmd7_RangeDec *p, UInt32 size0);
+};
typedef struct
{
- IPpmd7_RangeDec p;
+ IPpmd7_RangeDec vt;
UInt32 Range;
UInt32 Code;
IByteIn *Stream;
@@ -116,7 +118,7 @@ void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
-int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc);
+int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc);
/* ---------- Encode ---------- */
diff --git a/C/Ppmd7Dec.c b/C/Ppmd7Dec.c
index 3d01d76..3023b67 100644
--- a/C/Ppmd7Dec.c
+++ b/C/Ppmd7Dec.c
@@ -1,5 +1,5 @@
/* Ppmd7Dec.c -- PPMdH Decoder
-2010-03-12 : Igor Pavlov : Public domain
+2017-04-03 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h"
@@ -13,44 +13,46 @@ Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
unsigned i;
p->Code = 0;
p->Range = 0xFFFFFFFF;
- if (p->Stream->Read((void *)p->Stream) != 0)
+ if (IByteIn_Read(p->Stream) != 0)
return False;
for (i = 0; i < 4; i++)
- p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
+ p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
return (p->Code < 0xFFFFFFFF);
}
-static UInt32 Range_GetThreshold(void *pp, UInt32 total)
+#define GET_Ppmd7z_RangeDec CPpmd7z_RangeDec *p = CONTAINER_FROM_VTBL(pp, CPpmd7z_RangeDec, vt);
+
+static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total)
{
- CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
- return (p->Code) / (p->Range /= total);
+ GET_Ppmd7z_RangeDec
+ return p->Code / (p->Range /= total);
}
static void Range_Normalize(CPpmd7z_RangeDec *p)
{
if (p->Range < kTopValue)
{
- p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
+ p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
p->Range <<= 8;
if (p->Range < kTopValue)
{
- p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
+ p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
p->Range <<= 8;
}
}
}
-static void Range_Decode(void *pp, UInt32 start, UInt32 size)
+static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size)
{
- CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
+ GET_Ppmd7z_RangeDec
p->Code -= start * p->Range;
p->Range *= size;
Range_Normalize(p);
}
-static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
+static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0)
{
- CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
+ GET_Ppmd7z_RangeDec
UInt32 newBound = (p->Range >> 14) * size0;
UInt32 symbol;
if (p->Code < newBound)
@@ -70,15 +72,15 @@ static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
{
- p->p.GetThreshold = Range_GetThreshold;
- p->p.Decode = Range_Decode;
- p->p.DecodeBit = Range_DecodeBit;
+ p->vt.GetThreshold = Range_GetThreshold;
+ p->vt.Decode = Range_Decode;
+ p->vt.DecodeBit = Range_DecodeBit;
}
#define MASK(sym) ((signed char *)charMask)[sym]
-int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
+int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc)
{
size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 1)
diff --git a/C/Ppmd7Enc.c b/C/Ppmd7Enc.c
index 9b49e5d..a74d300 100644
--- a/C/Ppmd7Enc.c
+++ b/C/Ppmd7Enc.c
@@ -1,5 +1,5 @@
/* Ppmd7Enc.c -- PPMdH Encoder
-2015-09-28 : Igor Pavlov : Public domain
+2017-04-03 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h"
@@ -23,7 +23,7 @@ static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
Byte temp = p->Cache;
do
{
- p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
+ IByteOut_Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
temp = 0xFF;
}
while (--p->CacheSize != 0);
diff --git a/C/Sha256.c b/C/Sha256.c
index 47e2f42..90994e5 100644
--- a/C/Sha256.c
+++ b/C/Sha256.c
@@ -1,5 +1,5 @@
/* Crypto/Sha256.c -- SHA-256 Hash
-2015-11-14 : Igor Pavlov : Public domain
+2017-04-03 : Igor Pavlov : Public domain
This code is based on public domain code from Wei Dai's Crypto++ library. */
#include "Precomp.h"
@@ -45,7 +45,7 @@ void Sha256_Init(CSha256 *p)
#ifdef _SHA256_UNROLL2
#define R(a,b,c,d,e,f,g,h, i) \
- h += S1(e) + Ch(e,f,g) + K[(i)+(j)] + (j ? blk2(i) : blk0(i)); \
+ h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + (j ? blk2(i) : blk0(i)); \
d += h; \
h += S0(a) + Maj(a, b, c)
@@ -73,7 +73,7 @@ void Sha256_Init(CSha256 *p)
#define h(i) T[(7-(i))&7]
#define R(i) \
- h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[(i)+(j)] + (j ? blk2(i) : blk0(i)); \
+ h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[(i)+(size_t)(j)] + (j ? blk2(i) : blk0(i)); \
d(i) += h(i); \
h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) \
diff --git a/C/Threads.c b/C/Threads.c
index ece07e6..8fd86f2 100644
--- a/C/Threads.c
+++ b/C/Threads.c
@@ -1,5 +1,5 @@
/* Threads.c -- multithreading library
-2014-09-21 : Igor Pavlov : Public domain */
+2017-06-26 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -12,18 +12,20 @@
static WRes GetError()
{
DWORD res = GetLastError();
- return (res) ? (WRes)(res) : 1;
+ return res ? (WRes)res : 1;
}
-WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }
-WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
+static WRes HandleToWRes(HANDLE h) { return (h != NULL) ? 0 : GetError(); }
+static WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
WRes HandlePtr_Close(HANDLE *p)
{
if (*p != NULL)
+ {
if (!CloseHandle(*p))
return GetError();
- *p = NULL;
+ *p = NULL;
+ }
return 0;
}
@@ -49,7 +51,7 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
return HandleToWRes(*p);
}
-WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
+static WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
{
*p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
return HandleToWRes(*p);
diff --git a/C/Threads.h b/C/Threads.h
index e927208..f913241 100644
--- a/C/Threads.h
+++ b/C/Threads.h
@@ -1,5 +1,5 @@
/* Threads.h -- multithreading library
-2013-11-12 : Igor Pavlov : Public domain */
+2017-06-18 : Igor Pavlov : Public domain */
#ifndef __7Z_THREADS_H
#define __7Z_THREADS_H
@@ -49,7 +49,8 @@ WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
typedef HANDLE CSemaphore;
-#define Semaphore_Construct(p) (*p) = NULL
+#define Semaphore_Construct(p) *(p) = NULL
+#define Semaphore_IsCreated(p) (*(p) != NULL)
#define Semaphore_Close(p) HandlePtr_Close(p)
#define Semaphore_Wait(p) Handle_WaitObject(*(p))
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
diff --git a/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c
index 92bce0a..82aac89 100644
--- a/C/Util/7z/7zMain.c
+++ b/C/Util/7z/7zMain.c
@@ -1,11 +1,13 @@
/* 7zMain.c - Test application for 7z Decoder
-2016-05-16 : Igor Pavlov : Public domain */
+2018-04-19 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include <stdio.h>
#include <string.h>
+#include "../../CpuArch.h"
+
#include "../../7z.h"
#include "../../7zAlloc.h"
#include "../../7zBuf.h"
@@ -23,7 +25,17 @@
#endif
#endif
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+#define kInputBufSize ((size_t)1 << 18)
+
+static const ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+
+static void Print(const char *s)
+{
+ fputs(s, stdout);
+}
+
static int Buf_EnsureSize(CBuf *dest, size_t size)
{
@@ -227,6 +239,7 @@ static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name)
#endif
}
+
static SRes PrintString(const UInt16 *s)
{
CBuf buf;
@@ -238,12 +251,12 @@ static SRes PrintString(const UInt16 *s)
#endif
);
if (res == SZ_OK)
- fputs((const char *)buf.data, stdout);
+ Print((const char *)buf.data);
Buf_Free(&buf, &g_Alloc);
return res;
}
-static void UInt64ToStr(UInt64 value, char *s)
+static void UInt64ToStr(UInt64 value, char *s, int numDigits)
{
char temp[32];
int pos = 0;
@@ -253,6 +266,10 @@ static void UInt64ToStr(UInt64 value, char *s)
value /= 10;
}
while (value != 0);
+
+ for (numDigits -= pos; numDigits > 0; numDigits--)
+ *s++ = ' ';
+
do
*s++ = temp[--pos];
while (pos);
@@ -266,8 +283,10 @@ static char *UIntToStr(char *s, unsigned value, int numDigits)
do
temp[pos++] = (char)('0' + (value % 10));
while (value /= 10);
+
for (numDigits -= pos; numDigits > 0; numDigits--)
*s++ = '0';
+
do
*s++ = temp[--pos];
while (pos);
@@ -323,9 +342,16 @@ static void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s)
UIntToStr_2(s, sec); s[2] = 0;
}
-void PrintError(char *sz)
+static void PrintLF()
{
- printf("\nERROR: %s\n", sz);
+ Print("\n");
+}
+
+static void PrintError(char *s)
+{
+ Print("\nERROR: ");
+ Print(s);
+ PrintLF();
}
static void GetAttribString(UInt32 wa, Bool isDir, char *s)
@@ -343,25 +369,27 @@ static void GetAttribString(UInt32 wa, Bool isDir, char *s)
#endif
}
+
// #define NUM_PARENTS_MAX 128
int MY_CDECL main(int numargs, char *args[])
{
+ ISzAlloc allocImp;
+ ISzAlloc allocTempImp;
+
CFileInStream archiveStream;
- CLookToRead lookStream;
+ CLookToRead2 lookStream;
CSzArEx db;
SRes res;
- ISzAlloc allocImp;
- ISzAlloc allocTempImp;
UInt16 *temp = NULL;
size_t tempSize = 0;
// UInt32 parents[NUM_PARENTS_MAX];
- printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");
+ Print("\n7z Decoder " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n");
if (numargs == 1)
{
- printf(
+ Print(
"Usage: 7zDec <command> <archive_name>\n\n"
"<Commands>\n"
" e: Extract files from archive (without using directory names)\n"
@@ -370,7 +398,7 @@ int MY_CDECL main(int numargs, char *args[])
" x: eXtract files with full paths\n");
return 0;
}
-
+
if (numargs < 3)
{
PrintError("incorrect command");
@@ -381,11 +409,9 @@ int MY_CDECL main(int numargs, char *args[])
g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
#endif
- allocImp.Alloc = SzAlloc;
- allocImp.Free = SzFree;
- allocTempImp.Alloc = SzAllocTemp;
- allocTempImp.Free = SzFreeTemp;
+ allocImp = g_Alloc;
+ allocTempImp = g_Alloc;
#ifdef UNDER_CE
if (InFile_OpenW(&archiveStream.file, L"\test.7z"))
@@ -398,16 +424,31 @@ int MY_CDECL main(int numargs, char *args[])
}
FileInStream_CreateVTable(&archiveStream);
- LookToRead_CreateVTable(&lookStream, False);
-
- lookStream.realStream = &archiveStream.s;
- LookToRead_Init(&lookStream);
+ LookToRead2_CreateVTable(&lookStream, False);
+ lookStream.buf = NULL;
- CrcGenerateTable();
+ res = SZ_OK;
+ {
+ lookStream.buf = ISzAlloc_Alloc(&allocImp, kInputBufSize);
+ if (!lookStream.buf)
+ res = SZ_ERROR_MEM;
+ else
+ {
+ lookStream.bufSize = kInputBufSize;
+ lookStream.realStream = &archiveStream.vt;
+ LookToRead2_Init(&lookStream);
+ }
+ }
+
+ CrcGenerateTable();
+
SzArEx_Init(&db);
-
- res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
+
+ if (res == SZ_OK)
+ {
+ res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp);
+ }
if (res == SZ_OK)
{
@@ -477,7 +518,7 @@ int MY_CDECL main(int numargs, char *args[])
GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr);
fileSize = SzArEx_GetFileSize(&db, i);
- UInt64ToStr(fileSize, s);
+ UInt64ToStr(fileSize, s, 10);
if (SzBitWithVals_Check(&db.MTime, i))
ConvertFileTimeToString(&db.MTime.Vals[i], t);
@@ -489,29 +530,33 @@ int MY_CDECL main(int numargs, char *args[])
t[j] = '\0';
}
- printf("%s %s %10s ", t, attr, s);
+ Print(t);
+ Print(" ");
+ Print(attr);
+ Print(" ");
+ Print(s);
+ Print(" ");
res = PrintString(temp);
if (res != SZ_OK)
break;
if (isDir)
- printf("/");
- printf("\n");
+ Print("/");
+ PrintLF();
continue;
}
- fputs(testCommand ?
+ Print(testCommand ?
"Testing ":
- "Extracting ",
- stdout);
+ "Extracting ");
res = PrintString(temp);
if (res != SZ_OK)
break;
if (isDir)
- printf("/");
+ Print("/");
else
{
- res = SzArEx_Extract(&db, &lookStream.s, i,
+ res = SzArEx_Extract(&db, &lookStream.vt, i,
&blockIndex, &outBuffer, &outBufferSize,
&offset, &outSizeProcessed,
&allocImp, &allocTempImp);
@@ -543,7 +588,7 @@ int MY_CDECL main(int numargs, char *args[])
if (isDir)
{
MyCreateDir(destPath);
- printf("\n");
+ PrintLF();
continue;
}
else if (OutFile_OpenUtf16(&outFile, destPath))
@@ -561,6 +606,31 @@ int MY_CDECL main(int numargs, char *args[])
res = SZ_ERROR_FAIL;
break;
}
+
+ #ifdef USE_WINDOWS_FILE
+ {
+ FILETIME mtime, ctime;
+ FILETIME *mtimePtr = NULL;
+ FILETIME *ctimePtr = NULL;
+
+ if (SzBitWithVals_Check(&db.MTime, i))
+ {
+ const CNtfsFileTime *t = &db.MTime.Vals[i];
+ mtime.dwLowDateTime = (DWORD)(t->Low);
+ mtime.dwHighDateTime = (DWORD)(t->High);
+ mtimePtr = &mtime;
+ }
+ if (SzBitWithVals_Check(&db.CTime, i))
+ {
+ const CNtfsFileTime *t = &db.CTime.Vals[i];
+ ctime.dwLowDateTime = (DWORD)(t->Low);
+ ctime.dwHighDateTime = (DWORD)(t->High);
+ ctimePtr = &ctime;
+ }
+ if (mtimePtr || ctimePtr)
+ SetFileTime(outFile.handle, ctimePtr, NULL, mtimePtr);
+ }
+ #endif
if (File_Close(&outFile))
{
@@ -571,23 +641,31 @@ int MY_CDECL main(int numargs, char *args[])
#ifdef USE_WINDOWS_FILE
if (SzBitWithVals_Check(&db.Attribs, i))
- SetFileAttributesW(destPath, db.Attribs.Vals[i]);
+ {
+ UInt32 attrib = db.Attribs.Vals[i];
+ /* p7zip stores posix attributes in high 16 bits and adds 0x8000 as marker.
+ We remove posix bits, if we detect posix mode field */
+ if ((attrib & 0xF0000000) != 0)
+ attrib &= 0x7FFF;
+ SetFileAttributesW(destPath, attrib);
+ }
#endif
}
- printf("\n");
+ PrintLF();
}
- IAlloc_Free(&allocImp, outBuffer);
+ ISzAlloc_Free(&allocImp, outBuffer);
}
}
- SzArEx_Free(&db, &allocImp);
SzFree(NULL, temp);
+ SzArEx_Free(&db, &allocImp);
+ ISzAlloc_Free(&allocImp, lookStream.buf);
File_Close(&archiveStream.file);
if (res == SZ_OK)
{
- printf("\nEverything is Ok\n");
+ Print("\nEverything is Ok\n");
return 0;
}
@@ -598,7 +676,11 @@ int MY_CDECL main(int numargs, char *args[])
else if (res == SZ_ERROR_CRC)
PrintError("CRC error");
else
- printf("\nERROR #%d\n", res);
+ {
+ char s[32];
+ UInt64ToStr(res, s, 0);
+ PrintError(s);
+ }
return 1;
}
diff --git a/C/Util/Lzma/LzmaUtil.c b/C/Util/Lzma/LzmaUtil.c
index 98331b4..cf88c77 100644
--- a/C/Util/Lzma/LzmaUtil.c
+++ b/C/Util/Lzma/LzmaUtil.c
@@ -1,5 +1,5 @@
/* LzmaUtil.c -- Test application for LZMA compression
-2015-11-08 : Igor Pavlov : Public domain */
+2017-04-27 : Igor Pavlov : Public domain */
#include "../../Precomp.h"
@@ -7,26 +7,29 @@
#include <stdlib.h>
#include <string.h>
+#include "../../CpuArch.h"
+
#include "../../Alloc.h"
#include "../../7zFile.h"
#include "../../7zVersion.h"
#include "../../LzmaDec.h"
#include "../../LzmaEnc.h"
-const char *kCantReadMessage = "Can not read input file";
-const char *kCantWriteMessage = "Can not write output file";
-const char *kCantAllocateMessage = "Can not allocate memory";
-const char *kDataErrorMessage = "Data error";
+static const char * const kCantReadMessage = "Can not read input file";
+static const char * const kCantWriteMessage = "Can not write output file";
+static const char * const kCantAllocateMessage = "Can not allocate memory";
+static const char * const kDataErrorMessage = "Data error";
-void PrintHelp(char *buffer)
+static void PrintHelp(char *buffer)
{
- strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"
- "\nUsage: lzma <e|d> inputFile outputFile\n"
- " e: encode file\n"
- " d: decode file\n");
+ strcat(buffer,
+ "\nLZMA-C " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"
+ "Usage: lzma <e|d> inputFile outputFile\n"
+ " e: encode file\n"
+ " d: decode file\n");
}
-int PrintError(char *buffer, const char *message)
+static int PrintError(char *buffer, const char *message)
{
strcat(buffer, "\nError: ");
strcat(buffer, message);
@@ -34,20 +37,22 @@ int PrintError(char *buffer, const char *message)
return 1;
}
-int PrintErrorNumber(char *buffer, SRes val)
+static int PrintErrorNumber(char *buffer, SRes val)
{
sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
return 1;
}
-int PrintUserError(char *buffer)
+static int PrintUserError(char *buffer)
{
return PrintError(buffer, "Incorrect command");
}
+
#define IN_BUF_SIZE (1 << 16)
#define OUT_BUF_SIZE (1 << 16)
+
static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
UInt64 unpackSize)
{
@@ -101,6 +106,7 @@ static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inS
}
}
+
static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
{
UInt64 unpackSize;
@@ -163,7 +169,8 @@ static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 file
return res;
}
-int main2(int numArgs, const char *args[], char *rs)
+
+static int main2(int numArgs, const char *args[], char *rs)
{
CFileSeqInStream inStream;
CFileOutStream outStream;
@@ -215,11 +222,11 @@ int main2(int numArgs, const char *args[], char *rs)
{
UInt64 fileSize;
File_GetLength(&inStream.file, &fileSize);
- res = Encode(&outStream.s, &inStream.s, fileSize, rs);
+ res = Encode(&outStream.vt, &inStream.vt, fileSize, rs);
}
else
{
- res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL);
+ res = Decode(&outStream.vt, useOutFile ? &inStream.vt : NULL);
}
if (useOutFile)
@@ -241,6 +248,7 @@ int main2(int numArgs, const char *args[], char *rs)
return 0;
}
+
int MY_CDECL main(int numArgs, const char *args[])
{
char rs[800] = { 0 };
diff --git a/C/Util/Lzma/LzmaUtil.dsp b/C/Util/Lzma/LzmaUtil.dsp
index df1f0cb..eedde07 100644
--- a/C/Util/Lzma/LzmaUtil.dsp
+++ b/C/Util/Lzma/LzmaUtil.dsp
@@ -98,6 +98,10 @@ SOURCE=..\..\7zStream.c
# End Source File
# Begin Source File
+SOURCE=..\..\7zTypes.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\7zVersion.h
# End Source File
# Begin Source File
@@ -160,9 +164,5 @@ SOURCE=..\..\Threads.c
SOURCE=..\..\Threads.h
# End Source File
-# Begin Source File
-
-SOURCE=..\..\Types.h
-# End Source File
# End Target
# End Project
diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c
index 50e57ae..bfbf430 100644
--- a/C/Util/SfxSetup/SfxSetup.c
+++ b/C/Util/SfxSetup/SfxSetup.c
@@ -1,5 +1,5 @@
/* SfxSetup.c - 7z SFX Setup
-2016-05-16 : Igor Pavlov : Public domain */
+2017-04-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -24,6 +24,8 @@
#define k_EXE_ExtIndex 2
+#define kInputBufSize ((size_t)1 << 18)
+
static const char * const kExts[] =
{
"bat"
@@ -238,7 +240,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
#endif
{
CFileInStream archiveStream;
- CLookToRead lookStream;
+ CLookToRead2 lookStream;
CSzArEx db;
SRes res = SZ_OK;
ISzAlloc allocImp;
@@ -275,7 +277,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
allocTempImp.Free = SzFreeTemp;
FileInStream_CreateVTable(&archiveStream);
- LookToRead_CreateVTable(&lookStream, False);
+ LookToRead2_CreateVTable(&lookStream, False);
+ lookStream.buf = NULL;
winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH);
if (winRes == 0 || winRes > MAX_PATH)
@@ -376,14 +379,22 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
if (res == SZ_OK)
{
- lookStream.realStream = &archiveStream.s;
- LookToRead_Init(&lookStream);
+ lookStream.buf = ISzAlloc_Alloc(&allocImp, kInputBufSize);
+ if (!lookStream.buf)
+ res = SZ_ERROR_MEM;
+ else
+ {
+ lookStream.bufSize = kInputBufSize;
+ lookStream.realStream = &archiveStream.vt;
+ LookToRead2_Init(&lookStream);
+ }
}
SzArEx_Init(&db);
+
if (res == SZ_OK)
{
- res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
+ res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp);
}
if (res == SZ_OK)
@@ -411,7 +422,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
SzArEx_GetFileNameUtf16(&db, i, temp);
{
- res = SzArEx_Extract(&db, &lookStream.s, i,
+ res = SzArEx_Extract(&db, &lookStream.vt, i,
&blockIndex, &outBuffer, &outBufferSize,
&offset, &outSizeProcessed,
&allocImp, &allocTempImp);
@@ -522,10 +533,13 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
temp[j] = CHAR_PATH_SEPARATOR;
}
}
- IAlloc_Free(&allocImp, outBuffer);
+ ISzAlloc_Free(&allocImp, outBuffer);
}
+
SzArEx_Free(&db, &allocImp);
+ ISzAlloc_Free(&allocImp, lookStream.buf);
+
File_Close(&archiveStream.file);
if (res == SZ_OK)
diff --git a/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile
index 6985944..c9f59cc 100644
--- a/C/Util/SfxSetup/makefile
+++ b/C/Util/SfxSetup/makefile
@@ -1,4 +1,5 @@
PROG = 7zS2.sfx
+MY_FIXED = 1
C_OBJS = \
$O\7zAlloc.obj \
diff --git a/C/Util/SfxSetup/makefile_con b/C/Util/SfxSetup/makefile_con
index cb2c1a4..6f604ed 100644
--- a/C/Util/SfxSetup/makefile_con
+++ b/C/Util/SfxSetup/makefile_con
@@ -1,4 +1,5 @@
PROG = 7zS2con.sfx
+MY_FIXED = 1
CFLAGS = $(CFLAGS) -D_CONSOLE
C_OBJS = \
diff --git a/C/Xz.c b/C/Xz.c
index 92144db..7e061d6 100644
--- a/C/Xz.c
+++ b/C/Xz.c
@@ -1,5 +1,5 @@
/* Xz.c - Xz
-2015-05-01 : Igor Pavlov : Public domain */
+2017-05-12 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -9,7 +9,7 @@
#include "XzCrc64.h"
const Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };
-const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' };
+/* const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' }; */
unsigned Xz_WriteVarInt(Byte *buf, UInt64 v)
{
@@ -20,22 +20,22 @@ unsigned Xz_WriteVarInt(Byte *buf, UInt64 v)
v >>= 7;
}
while (v != 0);
- buf[i - 1] &= 0x7F;
+ buf[(size_t)i - 1] &= 0x7F;
return i;
}
void Xz_Construct(CXzStream *p)
{
- p->numBlocks = p->numBlocksAllocated = 0;
- p->blocks = 0;
+ p->numBlocks = 0;
+ p->blocks = NULL;
p->flags = 0;
}
-void Xz_Free(CXzStream *p, ISzAlloc *alloc)
+void Xz_Free(CXzStream *p, ISzAllocPtr alloc)
{
- alloc->Free(alloc, p->blocks);
- p->numBlocks = p->numBlocksAllocated = 0;
- p->blocks = 0;
+ ISzAlloc_Free(alloc, p->blocks);
+ p->numBlocks = 0;
+ p->blocks = NULL;
}
unsigned XzFlags_GetCheckSize(CXzStreamFlags f)
diff --git a/C/Xz.h b/C/Xz.h
index 6937bea..7b88f51 100644
--- a/C/Xz.h
+++ b/C/Xz.h
@@ -1,5 +1,5 @@
/* Xz.h - Xz interface
-2015-05-01 : Igor Pavlov : Public domain */
+2018-02-28 : Igor Pavlov : Public domain */
#ifndef __XZ_H
#define __XZ_H
@@ -50,6 +50,7 @@ typedef struct
#define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)
#define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0)
#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)
+#define XzBlock_HasUnsupportedFlags(p) (((p)->flags & ~(XZ_BF_NUM_FILTERS_MASK | XZ_BF_PACK_SIZE | XZ_BF_UNPACK_SIZE)) != 0)
SRes XzBlock_Parse(CXzBlock *p, const Byte *header);
SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes);
@@ -60,7 +61,13 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt
#define XZ_FOOTER_SIG_SIZE 2
extern const Byte XZ_SIG[XZ_SIG_SIZE];
+
+/*
extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
+*/
+
+#define XZ_FOOTER_SIG_0 'Y'
+#define XZ_FOOTER_SIG_1 'Z'
#define XZ_STREAM_FLAGS_SIZE 2
#define XZ_STREAM_CRC_SIZE 4
@@ -106,13 +113,12 @@ typedef struct
{
CXzStreamFlags flags;
size_t numBlocks;
- size_t numBlocksAllocated;
CXzBlockSizes *blocks;
UInt64 startOffset;
} CXzStream;
void Xz_Construct(CXzStream *p);
-void Xz_Free(CXzStream *p, ISzAlloc *alloc);
+void Xz_Free(CXzStream *p, ISzAllocPtr alloc);
#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)
@@ -127,12 +133,15 @@ typedef struct
} CXzs;
void Xzs_Construct(CXzs *p);
-void Xzs_Free(CXzs *p, ISzAlloc *alloc);
-SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc);
+void Xzs_Free(CXzs *p, ISzAllocPtr alloc);
+SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAllocPtr alloc);
UInt64 Xzs_GetNumBlocks(const CXzs *p);
UInt64 Xzs_GetUnpackSize(const CXzs *p);
+
+// ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
+
typedef enum
{
CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */
@@ -141,43 +150,55 @@ typedef enum
CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */
} ECoderStatus;
+
+// ECoderFinishMode values are identical to ELzmaFinishMode
+
typedef enum
{
CODER_FINISH_ANY, /* finish at any point */
CODER_FINISH_END /* block must be finished at the end */
} ECoderFinishMode;
+
typedef struct _IStateCoder
{
void *p;
- void (*Free)(void *p, ISzAlloc *alloc);
- SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);
+ void (*Free)(void *p, ISzAllocPtr alloc);
+ SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAllocPtr alloc);
void (*Init)(void *p);
- SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
- int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished);
+ SRes (*Code2)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+ int srcWasFinished, ECoderFinishMode finishMode,
+ // int *wasFinished,
+ ECoderStatus *status);
+ SizeT (*Filter)(void *p, Byte *data, SizeT size);
} IStateCoder;
+
+
#define MIXCODER_NUM_FILTERS_MAX 4
typedef struct
{
- ISzAlloc *alloc;
+ ISzAllocPtr alloc;
Byte *buf;
unsigned numCoders;
+
+ Byte *outBuf;
+ size_t outBufSize;
+ size_t outWritten; // is equal to lzmaDecoder.dicPos (in outBuf mode)
+ Bool wasFinished;
+ SRes res;
+ ECoderStatus status;
+ // Bool SingleBufMode;
+
int finished[MIXCODER_NUM_FILTERS_MAX - 1];
size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];
size_t size[MIXCODER_NUM_FILTERS_MAX - 1];
UInt64 ids[MIXCODER_NUM_FILTERS_MAX];
+ SRes results[MIXCODER_NUM_FILTERS_MAX];
IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];
} CMixCoder;
-void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);
-void MixCoder_Free(CMixCoder *p);
-void MixCoder_Init(CMixCoder *p);
-SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId);
-SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
- const Byte *src, SizeT *srcLen, int srcWasFinished,
- ECoderFinishMode finishMode, ECoderStatus *status);
typedef enum
{
@@ -191,6 +212,7 @@ typedef enum
XZ_STATE_BLOCK_FOOTER
} EXzState;
+
typedef struct
{
EXzState state;
@@ -204,7 +226,7 @@ typedef struct
UInt64 packSize;
UInt64 unpackSize;
- UInt64 numBlocks;
+ UInt64 numBlocks; // number of finished blocks in current stream
UInt64 indexSize;
UInt64 indexPos;
UInt64 padSize;
@@ -218,15 +240,66 @@ typedef struct
CXzBlock block;
CXzCheck check;
CSha256 sha;
+
+ Bool parseMode;
+ Bool headerParsedOk;
+ Bool decodeToStreamSignature;
+ unsigned decodeOnlyOneBlock;
+
+ Byte *outBuf;
+ size_t outBufSize;
+ size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked
+
Byte shaDigest[SHA256_DIGEST_SIZE];
Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
} CXzUnpacker;
-void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc);
+/* alloc : aligned for cache line allocation is better */
+void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc);
void XzUnpacker_Init(CXzUnpacker *p);
+void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize);
void XzUnpacker_Free(CXzUnpacker *p);
/*
+ XzUnpacker
+ The sequence for decoding functions:
+ {
+ XzUnpacker_Construct()
+ [Decoding_Calls]
+ XzUnpacker_Free()
+ }
+
+ [Decoding_Calls]
+
+ There are 3 types of interfaces for [Decoding_Calls] calls:
+
+ Interface-1 : Partial output buffers:
+ {
+ XzUnpacker_Init()
+ for()
+ XzUnpacker_Code();
+ }
+
+ Interface-2 : Direct output buffer:
+ Use it, if you know exact size of decoded data, and you need
+ whole xz unpacked data in one output buffer.
+ xz unpacker doesn't allocate additional buffer for lzma2 dictionary in that mode.
+ {
+ XzUnpacker_Init()
+ XzUnpacker_SetOutBufMode(); // to set output buffer and size
+ for()
+ XzUnpacker_Code(); // (dest = NULL) in XzUnpacker_Code()
+ }
+
+ Interface-3 : Direct output buffer : One call full decoding
+ It unpacks whole input buffer to output buffer in one call.
+ It uses Interface-2 internally.
+ {
+ XzUnpacker_CodeFull()
+ }
+*/
+
+/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
CODER_FINISH_ANY - use smallest number of input bytes
@@ -255,20 +328,132 @@ Returns:
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
- const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode,
- ECoderStatus *status);
+ const Byte *src, SizeT *srcLen, int srcFinished,
+ ECoderFinishMode finishMode, ECoderStatus *status);
-Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);
+SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
+ const Byte *src, SizeT *srcLen,
+ ECoderFinishMode finishMode, ECoderStatus *status);
+
+Bool XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p);
/*
-Call XzUnpacker_GetExtraSize after XzUnpacker_Code function to detect real size of
-xz stream in two cases:
-XzUnpacker_Code() returns:
+XzUnpacker_GetExtraSize() returns then number of uncofirmed bytes,
+ if it's in (XZ_STATE_STREAM_HEADER) state or in (XZ_STATE_STREAM_PADDING) state.
+These bytes can be some bytes after xz archive, or
+it can be start of new xz stream.
+
+Call XzUnpacker_GetExtraSize() after XzUnpacker_Code() function to detect real size of
+xz stream in two cases, if XzUnpacker_Code() returns:
res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT
res == SZ_ERROR_NO_ARCHIVE
*/
-UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p);
+UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p);
+
+
+/*
+ for random block decoding:
+ XzUnpacker_Init();
+ set CXzUnpacker::streamFlags
+ XzUnpacker_PrepareToRandomBlockDecoding()
+ loop
+ {
+ XzUnpacker_Code()
+ XzUnpacker_IsBlockFinished()
+ }
+*/
+
+void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p);
+Bool XzUnpacker_IsBlockFinished(const CXzUnpacker *p);
+
+#define XzUnpacker_GetPackSizeForIndex(p) ((p)->packSize + (p)->blockHeaderSize + XzFlags_GetCheckSize((p)->streamFlags))
+
+
+
+/* ---------- Multi Threading Decoding ---------- */
+
+
+typedef struct
+{
+ size_t inBufSize_ST;
+ size_t outStep_ST;
+ Bool ignoreErrors;
+
+ #ifndef _7ZIP_ST
+ unsigned numThreads;
+ size_t inBufSize_MT;
+ size_t memUseMax;
+ #endif
+} CXzDecMtProps;
+
+void XzDecMtProps_Init(CXzDecMtProps *p);
+
+
+typedef void * CXzDecMtHandle;
+
+/*
+ alloc : XzDecMt uses CAlignOffsetAlloc for addresses allocated by (alloc).
+ allocMid : for big allocations, aligned allocation is better
+*/
+
+CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid);
+void XzDecMt_Destroy(CXzDecMtHandle p);
+
+
+typedef struct
+{
+ Byte UnpackSize_Defined;
+ Byte NumStreams_Defined;
+ Byte NumBlocks_Defined;
+
+ Byte DataAfterEnd;
+ Byte DecodingTruncated; // Decoding was Truncated, we need only partial output data
+
+ UInt64 InSize; // pack size processed
+ UInt64 OutSize;
+
+ UInt64 NumStreams;
+ UInt64 NumBlocks;
+
+ SRes DecodeRes;
+ SRes ReadRes;
+ SRes ProgressRes;
+ SRes CombinedRes;
+ SRes CombinedRes_Type;
+
+} CXzStatInfo;
+
+void XzStatInfo_Clear(CXzStatInfo *p);
+
+/*
+XzDecMt_Decode()
+SRes:
+ SZ_OK - OK
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_NO_ARCHIVE - is not xz archive
+ SZ_ERROR_ARCHIVE - Headers error
+ SZ_ERROR_DATA - Data Error
+ SZ_ERROR_CRC - CRC Error
+ SZ_ERROR_INPUT_EOF - it needs more input data
+ SZ_ERROR_WRITE - ISeqOutStream error
+ (SZ_ERROR_READ) - ISeqInStream errors
+ (SZ_ERROR_PROGRESS) - ICompressProgress errors
+ // SZ_ERROR_THREAD - error in multi-threading functions
+ MY_SRes_HRESULT_FROM_WRes(WRes_error) - error in multi-threading function
+*/
+
+SRes XzDecMt_Decode(CXzDecMtHandle p,
+ const CXzDecMtProps *props,
+ const UInt64 *outDataSize, // NULL means undefined
+ int finishMode, // 0 - partial unpacking is allowed, 1 - xz stream(s) must be finished
+ ISeqOutStream *outStream,
+ // Byte *outBuf, size_t *outBufSize,
+ ISeqInStream *inStream,
+ // const Byte *inData, size_t inDataSize,
+ CXzStatInfo *stat,
+ int *isMT, // 0 means that ST (Single-Thread) version was used
+ ICompressProgress *progress);
EXTERN_C_END
diff --git a/C/XzCrc64.c b/C/XzCrc64.c
index bd0cf5a..e9ca9ec 100644
--- a/C/XzCrc64.c
+++ b/C/XzCrc64.c
@@ -1,5 +1,5 @@
/* XzCrc64.c -- CRC64 calculation
-2015-03-01 : Igor Pavlov : Public domain */
+2017-05-23 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -9,9 +9,9 @@
#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42)
#ifdef MY_CPU_LE
- #define CRC_NUM_TABLES 4
+ #define CRC64_NUM_TABLES 4
#else
- #define CRC_NUM_TABLES 5
+ #define CRC64_NUM_TABLES 5
#define CRC_UINT64_SWAP(v) \
((v >> 56) \
| ((v >> 40) & ((UInt64)0xFF << 8)) \
@@ -29,10 +29,10 @@
UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table);
#endif
-typedef UInt64 (MY_FAST_CALL *CRC_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table);
+typedef UInt64 (MY_FAST_CALL *CRC64_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table);
-static CRC_FUNC g_Crc64Update;
-UInt64 g_Crc64Table[256 * CRC_NUM_TABLES];
+static CRC64_FUNC g_Crc64Update;
+UInt64 g_Crc64Table[256 * CRC64_NUM_TABLES];
UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size)
{
@@ -52,12 +52,12 @@ void MY_FAST_CALL Crc64GenerateTable()
UInt64 r = i;
unsigned j;
for (j = 0; j < 8; j++)
- r = (r >> 1) ^ (kCrc64Poly & ~((r & 1) - 1));
+ r = (r >> 1) ^ (kCrc64Poly & ((UInt64)0 - (r & 1)));
g_Crc64Table[i] = r;
}
- for (; i < 256 * CRC_NUM_TABLES; i++)
+ for (i = 256; i < 256 * CRC64_NUM_TABLES; i++)
{
- UInt64 r = g_Crc64Table[i - 256];
+ UInt64 r = g_Crc64Table[(size_t)i - 256];
g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8);
}
@@ -74,9 +74,9 @@ void MY_FAST_CALL Crc64GenerateTable()
else
#endif
{
- for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
+ for (i = 256 * CRC64_NUM_TABLES - 1; i >= 256; i--)
{
- UInt64 x = g_Crc64Table[i - 256];
+ UInt64 x = g_Crc64Table[(size_t)i - 256];
g_Crc64Table[i] = CRC_UINT64_SWAP(x);
}
g_Crc64Update = XzCrc64UpdateT1_BeT4;
diff --git a/C/XzCrc64Opt.c b/C/XzCrc64Opt.c
index 97d086e..9273465 100644
--- a/C/XzCrc64Opt.c
+++ b/C/XzCrc64Opt.c
@@ -1,5 +1,5 @@
/* XzCrc64Opt.c -- CRC64 calculation
-2015-03-01 : Igor Pavlov : Public domain */
+2017-06-30 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -7,24 +7,24 @@
#ifndef MY_CPU_BE
-#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
+#define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table)
{
const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
- v = CRC_UPDATE_BYTE_2(v, *p);
+ v = CRC64_UPDATE_BYTE_2(v, *p);
for (; size >= 4; size -= 4, p += 4)
{
UInt32 d = (UInt32)v ^ *(const UInt32 *)p;
v = (v >> 32)
- ^ table[0x300 + ((d ) & 0xFF)]
- ^ table[0x200 + ((d >> 8) & 0xFF)]
- ^ table[0x100 + ((d >> 16) & 0xFF)]
- ^ table[0x000 + ((d >> 24))];
+ ^ (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);
+ v = CRC64_UPDATE_BYTE_2(v, *p);
return v;
}
@@ -43,7 +43,7 @@ UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, con
| ((v << 40) & ((UInt64)0xFF << 48)) \
| ((v << 56)))
-#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(Byte)((crc) >> 56) ^ (b)] ^ ((crc) << 8))
+#define CRC64_UPDATE_BYTE_2_BE(crc, b) (table[(Byte)((crc) >> 56) ^ (b)] ^ ((crc) << 8))
UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table)
{
@@ -51,18 +51,18 @@ UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size
table += 0x100;
v = CRC_UINT64_SWAP(v);
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
- v = CRC_UPDATE_BYTE_2_BE(v, *p);
+ v = CRC64_UPDATE_BYTE_2_BE(v, *p);
for (; size >= 4; size -= 4, p += 4)
{
UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)p;
v = (v << 32)
- ^ table[0x000 + ((d ) & 0xFF)]
- ^ table[0x100 + ((d >> 8) & 0xFF)]
- ^ table[0x200 + ((d >> 16) & 0xFF)]
- ^ table[0x300 + ((d >> 24))];
+ ^ (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);
+ v = CRC64_UPDATE_BYTE_2_BE(v, *p);
return CRC_UINT64_SWAP(v);
}
diff --git a/C/XzDec.c b/C/XzDec.c
index 29831b0..ebf1983 100644
--- a/C/XzDec.c
+++ b/C/XzDec.c
@@ -1,14 +1,33 @@
/* XzDec.c -- Xz Decode
-2015-11-09 : Igor Pavlov : Public domain */
+2018-04-24 : Igor Pavlov : Public domain */
#include "Precomp.h"
+// #include <stdio.h>
+
+// #define XZ_DUMP
+
/* #define XZ_DUMP */
#ifdef XZ_DUMP
#include <stdio.h>
#endif
+// #define SHOW_DEBUG_INFO
+
+#ifdef SHOW_DEBUG_INFO
+#include <stdio.h>
+#endif
+
+#ifdef SHOW_DEBUG_INFO
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+#define PRF_STR(s) PRF(printf("\n" s "\n"))
+#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
+
#include <stdlib.h>
#include <string.h>
@@ -19,16 +38,18 @@
#include "Delta.h"
#include "Lzma2Dec.h"
+// #define USE_SUBBLOCK
+
#ifdef USE_SUBBLOCK
#include "Bcj3Dec.c"
-#include "SbDec.c"
+#include "SbDec.h"
#endif
#include "Xz.h"
#define XZ_CHECK_SIZE_MAX 64
-#define CODER_BUF_SIZE (1 << 17)
+#define CODER_BUF_SIZE ((size_t)1 << 17)
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
{
@@ -56,8 +77,9 @@ typedef struct
size_t bufConv;
size_t bufTotal;
- UInt32 methodId;
int encodeMode;
+
+ UInt32 methodId;
UInt32 delta;
UInt32 ip;
UInt32 x86State;
@@ -66,12 +88,12 @@ typedef struct
Byte buf[BRA_BUF_SIZE];
} CBraState;
-static void BraState_Free(void *pp, ISzAlloc *alloc)
+static void BraState_Free(void *pp, ISzAllocPtr alloc)
{
- alloc->Free(alloc, pp);
+ ISzAlloc_Free(alloc, pp);
}
-static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
+static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
{
CBraState *p = ((CBraState *)pp);
UNUSED_VAR(alloc);
@@ -121,69 +143,84 @@ static void BraState_Init(void *pp)
Delta_Init(p->deltaState);
}
-#define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break;
-static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
- int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
+#define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: size = isa ## _Convert(data, size, p->ip, p->encodeMode); break;
+
+static SizeT BraState_Filter(void *pp, Byte *data, SizeT size)
{
CBraState *p = ((CBraState *)pp);
- SizeT destLenOrig = *destLen;
- SizeT srcLenOrig = *srcLen;
+ switch (p->methodId)
+ {
+ case XZ_ID_Delta:
+ if (p->encodeMode)
+ Delta_Encode(p->deltaState, p->delta, data, size);
+ else
+ Delta_Decode(p->deltaState, p->delta, data, size);
+ break;
+ case XZ_ID_X86:
+ size = x86_Convert(data, size, p->ip, &p->x86State, p->encodeMode);
+ break;
+ CASE_BRA_CONV(PPC)
+ CASE_BRA_CONV(IA64)
+ CASE_BRA_CONV(ARM)
+ CASE_BRA_CONV(ARMT)
+ CASE_BRA_CONV(SPARC)
+ }
+ p->ip += (UInt32)size;
+ return size;
+}
+
+
+static SRes BraState_Code2(void *pp,
+ Byte *dest, SizeT *destLen,
+ const Byte *src, SizeT *srcLen, int srcWasFinished,
+ ECoderFinishMode finishMode,
+ // int *wasFinished
+ ECoderStatus *status)
+{
+ CBraState *p = ((CBraState *)pp);
+ SizeT destRem = *destLen;
+ SizeT srcRem = *srcLen;
UNUSED_VAR(finishMode);
+
*destLen = 0;
*srcLen = 0;
- *wasFinished = 0;
- while (destLenOrig > 0)
+ // *wasFinished = False;
+ *status = CODER_STATUS_NOT_FINISHED;
+
+ while (destRem > 0)
{
if (p->bufPos != p->bufConv)
{
- size_t curSize = p->bufConv - p->bufPos;
- if (curSize > destLenOrig)
- curSize = destLenOrig;
- memcpy(dest, p->buf + p->bufPos, curSize);
- p->bufPos += curSize;
- *destLen += curSize;
- dest += curSize;
- destLenOrig -= curSize;
+ size_t size = p->bufConv - p->bufPos;
+ if (size > destRem)
+ size = destRem;
+ memcpy(dest, p->buf + p->bufPos, size);
+ p->bufPos += size;
+ *destLen += size;
+ dest += size;
+ destRem -= size;
continue;
}
+
p->bufTotal -= p->bufPos;
memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
p->bufPos = 0;
p->bufConv = 0;
{
- size_t curSize = BRA_BUF_SIZE - p->bufTotal;
- if (curSize > srcLenOrig)
- curSize = srcLenOrig;
- memcpy(p->buf + p->bufTotal, src, curSize);
- *srcLen += curSize;
- src += curSize;
- srcLenOrig -= curSize;
- p->bufTotal += curSize;
+ size_t size = BRA_BUF_SIZE - p->bufTotal;
+ if (size > srcRem)
+ size = srcRem;
+ memcpy(p->buf + p->bufTotal, src, size);
+ *srcLen += size;
+ src += size;
+ srcRem -= size;
+ p->bufTotal += size;
}
if (p->bufTotal == 0)
break;
- switch (p->methodId)
- {
- case XZ_ID_Delta:
- if (p->encodeMode)
- Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal);
- else
- Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal);
- p->bufConv = p->bufTotal;
- break;
- case XZ_ID_X86:
- p->bufConv = x86_Convert(p->buf, p->bufTotal, p->ip, &p->x86State, p->encodeMode);
- break;
- CASE_BRA_CONV(PPC)
- CASE_BRA_CONV(IA64)
- CASE_BRA_CONV(ARM)
- CASE_BRA_CONV(ARMT)
- CASE_BRA_CONV(SPARC)
- default:
- return SZ_ERROR_UNSUPPORTED;
- }
- p->ip += (UInt32)p->bufConv;
+
+ p->bufConv = BraState_Filter(pp, p->buf, p->bufTotal);
if (p->bufConv == 0)
{
@@ -192,48 +229,54 @@ static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src,
p->bufConv = p->bufTotal;
}
}
- if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished)
- *wasFinished = 1;
+
+ if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished)
+ {
+ *status = CODER_STATUS_FINISHED_WITH_MARK;
+ // *wasFinished = 1;
+ }
+
return SZ_OK;
}
-SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc)
+
+SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc)
{
CBraState *decoder;
- if (id != XZ_ID_Delta &&
- id != XZ_ID_X86 &&
- id != XZ_ID_PPC &&
- id != XZ_ID_IA64 &&
- id != XZ_ID_ARM &&
- id != XZ_ID_ARMT &&
- id != XZ_ID_SPARC)
+ if (id < XZ_ID_Delta || id > XZ_ID_SPARC)
return SZ_ERROR_UNSUPPORTED;
- p->p = 0;
- decoder = (CBraState *)alloc->Alloc(alloc, sizeof(CBraState));
- if (decoder == 0)
- return SZ_ERROR_MEM;
+ decoder = p->p;
+ if (!decoder)
+ {
+ decoder = (CBraState *)ISzAlloc_Alloc(alloc, sizeof(CBraState));
+ if (!decoder)
+ return SZ_ERROR_MEM;
+ p->p = decoder;
+ p->Free = BraState_Free;
+ p->SetProps = BraState_SetProps;
+ p->Init = BraState_Init;
+ p->Code2 = BraState_Code2;
+ p->Filter = BraState_Filter;
+ }
decoder->methodId = (UInt32)id;
decoder->encodeMode = encodeMode;
- p->p = decoder;
- p->Free = BraState_Free;
- p->SetProps = BraState_SetProps;
- p->Init = BraState_Init;
- p->Code = BraState_Code;
return SZ_OK;
}
+
+
/* ---------- SbState ---------- */
#ifdef USE_SUBBLOCK
-static void SbState_Free(void *pp, ISzAlloc *alloc)
+static void SbState_Free(void *pp, ISzAllocPtr alloc)
{
CSbDec *p = (CSbDec *)pp;
SbDec_Free(p);
- alloc->Free(alloc, pp);
+ ISzAlloc_Free(alloc, pp);
}
-static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
+static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
{
UNUSED_VAR(pp);
UNUSED_VAR(props);
@@ -246,8 +289,10 @@ static void SbState_Init(void *pp)
SbDec_Init((CSbDec *)pp);
}
-static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
- int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
+static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+ int srcWasFinished, ECoderFinishMode finishMode,
+ // int *wasFinished
+ ECoderStatus *status)
{
CSbDec *p = (CSbDec *)pp;
SRes res;
@@ -260,102 +305,185 @@ static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src,
res = SbDec_Decode((CSbDec *)pp);
*destLen -= p->destLen;
*srcLen -= p->srcLen;
- *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
+ // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
+ *status = (*destLen == 0 && *srcLen == 0) ?
+ CODER_STATUS_FINISHED_WITH_MARK :
+ CODER_STATUS_NOT_FINISHED;
return res;
}
-SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
+static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc)
{
- CSbDec *decoder;
- p->p = 0;
- decoder = alloc->Alloc(alloc, sizeof(CSbDec));
- if (decoder == 0)
- return SZ_ERROR_MEM;
- p->p = decoder;
- p->Free = SbState_Free;
- p->SetProps = SbState_SetProps;
- p->Init = SbState_Init;
- p->Code = SbState_Code;
+ CSbDec *decoder = (CSbDec *)p->p;
+ if (!decoder)
+ {
+ decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec));
+ if (!decoder)
+ return SZ_ERROR_MEM;
+ p->p = decoder;
+ p->Free = SbState_Free;
+ p->SetProps = SbState_SetProps;
+ p->Init = SbState_Init;
+ p->Code2 = SbState_Code2;
+ p->Filter = NULL;
+ }
SbDec_Construct(decoder);
SbDec_SetAlloc(decoder, alloc);
return SZ_OK;
}
+
#endif
-/* ---------- Lzma2State ---------- */
-static void Lzma2State_Free(void *pp, ISzAlloc *alloc)
+
+/* ---------- Lzma2 ---------- */
+
+typedef struct
+{
+ CLzma2Dec decoder;
+ Bool outBufMode;
+} CLzma2Dec_Spec;
+
+
+static void Lzma2State_Free(void *pp, ISzAllocPtr alloc)
{
- Lzma2Dec_Free((CLzma2Dec *)pp, alloc);
- alloc->Free(alloc, pp);
+ CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
+ if (p->outBufMode)
+ Lzma2Dec_FreeProbs(&p->decoder, alloc);
+ else
+ Lzma2Dec_Free(&p->decoder, alloc);
+ ISzAlloc_Free(alloc, pp);
}
-static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
+static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
{
if (propSize != 1)
return SZ_ERROR_UNSUPPORTED;
- return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc);
+ {
+ CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
+ if (p->outBufMode)
+ return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc);
+ else
+ return Lzma2Dec_Allocate(&p->decoder, props[0], alloc);
+ }
}
static void Lzma2State_Init(void *pp)
{
- Lzma2Dec_Init((CLzma2Dec *)pp);
+ Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder);
}
-static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
- int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
+
+/*
+ if (outBufMode), then (dest) is not used. Use NULL.
+ Data is unpacked to (spec->decoder.decoder.dic) output buffer.
+*/
+
+static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+ int srcWasFinished, ECoderFinishMode finishMode,
+ // int *wasFinished,
+ ECoderStatus *status)
{
- ELzmaStatus status;
+ CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp;
+ ELzmaStatus status2;
/* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
- SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status);
+ SRes res;
UNUSED_VAR(srcWasFinished);
- *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
+ if (spec->outBufMode)
+ {
+ SizeT dicPos = spec->decoder.decoder.dicPos;
+ SizeT dicLimit = dicPos + *destLen;
+ res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
+ *destLen = spec->decoder.decoder.dicPos - dicPos;
+ }
+ else
+ res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
+ // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK);
+ // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
+ *status = status2;
return res;
}
-static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
+
+static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)
+{
+ CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
+ if (!spec)
+ {
+ spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec));
+ if (!spec)
+ return SZ_ERROR_MEM;
+ p->p = spec;
+ p->Free = Lzma2State_Free;
+ p->SetProps = Lzma2State_SetProps;
+ p->Init = Lzma2State_Init;
+ p->Code2 = Lzma2State_Code2;
+ p->Filter = NULL;
+ Lzma2Dec_Construct(&spec->decoder);
+ }
+ spec->outBufMode = False;
+ if (outBuf)
+ {
+ spec->outBufMode = True;
+ spec->decoder.decoder.dic = outBuf;
+ spec->decoder.decoder.dicBufSize = outBufSize;
+ }
+ return SZ_OK;
+}
+
+
+static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize)
{
- CLzma2Dec *decoder = (CLzma2Dec *)alloc->Alloc(alloc, sizeof(CLzma2Dec));
- p->p = decoder;
- if (decoder == 0)
- return SZ_ERROR_MEM;
- p->Free = Lzma2State_Free;
- p->SetProps = Lzma2State_SetProps;
- p->Init = Lzma2State_Init;
- p->Code = Lzma2State_Code;
- Lzma2Dec_Construct(decoder);
+ CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
+ if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf))
+ return SZ_ERROR_FAIL;
+ if (outBuf)
+ {
+ spec->decoder.decoder.dic = outBuf;
+ spec->decoder.decoder.dicBufSize = outBufSize;
+ }
return SZ_OK;
}
-void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)
+
+static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc)
{
unsigned i;
p->alloc = alloc;
p->buf = NULL;
p->numCoders = 0;
+
+ p->outBufSize = 0;
+ p->outBuf = NULL;
+ // p->SingleBufMode = False;
+
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
p->coders[i].p = NULL;
}
-void MixCoder_Free(CMixCoder *p)
+
+static void MixCoder_Free(CMixCoder *p)
{
unsigned i;
- for (i = 0; i < p->numCoders; i++)
+ p->numCoders = 0;
+ for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
{
IStateCoder *sc = &p->coders[i];
- if (p->alloc && sc->p)
+ if (sc->p)
+ {
sc->Free(sc->p, p->alloc);
+ sc->p = NULL;
+ }
}
- p->numCoders = 0;
if (p->buf)
{
- p->alloc->Free(p->alloc, p->buf);
+ ISzAlloc_Free(p->alloc, p->buf);
p->buf = NULL; /* 9.31: the BUG was fixed */
}
}
-void MixCoder_Init(CMixCoder *p)
+static void MixCoder_Init(CMixCoder *p)
{
unsigned i;
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
@@ -368,16 +496,22 @@ void MixCoder_Init(CMixCoder *p)
{
IStateCoder *coder = &p->coders[i];
coder->Init(coder->p);
+ p->results[i] = SZ_OK;
}
+ p->outWritten = 0;
+ p->wasFinished = False;
+ p->res = SZ_OK;
+ p->status = CODER_STATUS_NOT_SPECIFIED;
}
-SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId)
+
+static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
{
IStateCoder *sc = &p->coders[coderIndex];
p->ids[coderIndex] = methodId;
switch (methodId)
{
- case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);
+ case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);
#ifdef USE_SUBBLOCK
case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);
#endif
@@ -387,31 +521,128 @@ SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId)
return BraState_SetFromMethod(sc, methodId, 0, p->alloc);
}
-SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
+
+static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
+{
+ IStateCoder *sc = &p->coders[coderIndex];
+ switch (methodId)
+ {
+ case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
+ }
+ return SZ_ERROR_UNSUPPORTED;
+}
+
+
+
+/*
+ if (destFinish) - then unpack data block is finished at (*destLen) position,
+ and we can return data that were not processed by filter
+
+output (status) can be :
+ CODER_STATUS_NOT_FINISHED
+ CODER_STATUS_FINISHED_WITH_MARK
+ CODER_STATUS_NEEDS_MORE_INPUT - not implemented still
+*/
+
+static SRes MixCoder_Code(CMixCoder *p,
+ Byte *dest, SizeT *destLen, int destFinish,
const Byte *src, SizeT *srcLen, int srcWasFinished,
- ECoderFinishMode finishMode, ECoderStatus *status)
+ ECoderFinishMode finishMode)
{
SizeT destLenOrig = *destLen;
SizeT srcLenOrig = *srcLen;
- Bool allFinished = True;
+
*destLen = 0;
*srcLen = 0;
- *status = CODER_STATUS_NOT_FINISHED;
- if (!p->buf)
+ if (p->wasFinished)
+ return p->res;
+
+ p->status = CODER_STATUS_NOT_FINISHED;
+
+ // if (p->SingleBufMode)
+ if (p->outBuf)
{
- p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
- if (!p->buf)
- return SZ_ERROR_MEM;
+ SRes res;
+ SizeT destLen2, srcLen2;
+ int wasFinished;
+
+ PRF_STR("------- MixCoder Single ----------");
+
+ srcLen2 = srcLenOrig;
+ destLen2 = destLenOrig;
+
+ {
+ IStateCoder *coder = &p->coders[0];
+ res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode,
+ // &wasFinished,
+ &p->status);
+ wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK);
+ }
+
+ p->res = res;
+
+ /*
+ if (wasFinished)
+ p->status = CODER_STATUS_FINISHED_WITH_MARK;
+ else
+ {
+ if (res == SZ_OK)
+ if (destLen2 != destLenOrig)
+ p->status = CODER_STATUS_NEEDS_MORE_INPUT;
+ }
+ */
+
+
+ *srcLen = srcLen2;
+ src += srcLen2;
+ p->outWritten += destLen2;
+
+ if (res != SZ_OK || srcWasFinished || wasFinished)
+ p->wasFinished = True;
+
+ if (p->numCoders == 1)
+ *destLen = destLen2;
+ else if (p->wasFinished)
+ {
+ unsigned i;
+ size_t processed = p->outWritten;
+
+ for (i = 1; i < p->numCoders; i++)
+ {
+ IStateCoder *coder = &p->coders[i];
+ processed = coder->Filter(coder->p, p->outBuf, processed);
+ if (wasFinished || (destFinish && p->outWritten == destLenOrig))
+ processed = p->outWritten;
+ PRF_STR_INT("filter", i);
+ }
+ *destLen = processed;
+ }
+ return res;
}
+ PRF_STR("standard mix");
+
if (p->numCoders != 1)
+ {
+ if (!p->buf)
+ {
+ p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
+ if (!p->buf)
+ return SZ_ERROR_MEM;
+ }
+
finishMode = CODER_FINISH_ANY;
+ }
for (;;)
{
Bool processed = False;
+ Bool allFinished = True;
+ SRes resMain = SZ_OK;
unsigned i;
+
+ p->status = CODER_STATUS_NOT_FINISHED;
/*
if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
break;
@@ -421,79 +652,106 @@ SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
{
SRes res;
IStateCoder *coder = &p->coders[i];
- Byte *destCur;
- SizeT destLenCur, srcLenCur;
- const Byte *srcCur;
- int srcFinishedCur;
+ Byte *dest2;
+ SizeT destLen2, srcLen2; // destLen2_Orig;
+ const Byte *src2;
+ int srcFinished2;
int encodingWasFinished;
+ ECoderStatus status2;
if (i == 0)
{
- srcCur = src;
- srcLenCur = srcLenOrig - *srcLen;
- srcFinishedCur = srcWasFinished;
+ src2 = src;
+ srcLen2 = srcLenOrig - *srcLen;
+ srcFinished2 = srcWasFinished;
}
else
{
- srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1];
- srcLenCur = p->size[i - 1] - p->pos[i - 1];
- srcFinishedCur = p->finished[i - 1];
+ size_t k = i - 1;
+ src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k];
+ srcLen2 = p->size[k] - p->pos[k];
+ srcFinished2 = p->finished[k];
}
if (i == p->numCoders - 1)
{
- destCur = dest;
- destLenCur = destLenOrig - *destLen;
+ dest2 = dest;
+ destLen2 = destLenOrig - *destLen;
}
else
{
if (p->pos[i] != p->size[i])
continue;
- destCur = p->buf + (CODER_BUF_SIZE * i);
- destLenCur = CODER_BUF_SIZE;
+ dest2 = p->buf + (CODER_BUF_SIZE * i);
+ destLen2 = CODER_BUF_SIZE;
}
- res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished);
+ // destLen2_Orig = destLen2;
+
+ if (p->results[i] != SZ_OK)
+ {
+ if (resMain == SZ_OK)
+ resMain = p->results[i];
+ continue;
+ }
+
+ res = coder->Code2(coder->p,
+ dest2, &destLen2,
+ src2, &srcLen2, srcFinished2,
+ finishMode,
+ // &encodingWasFinished,
+ &status2);
+ if (res != SZ_OK)
+ {
+ p->results[i] = res;
+ if (resMain == SZ_OK)
+ resMain = res;
+ }
+
+ encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK);
+
if (!encodingWasFinished)
+ {
allFinished = False;
+ if (p->numCoders == 1 && res == SZ_OK)
+ p->status = status2;
+ }
if (i == 0)
{
- *srcLen += srcLenCur;
- src += srcLenCur;
+ *srcLen += srcLen2;
+ src += srcLen2;
}
else
- {
- p->pos[i - 1] += srcLenCur;
- }
+ p->pos[(size_t)i - 1] += srcLen2;
if (i == p->numCoders - 1)
{
- *destLen += destLenCur;
- dest += destLenCur;
+ *destLen += destLen2;
+ dest += destLen2;
}
else
{
- p->size[i] = destLenCur;
+ p->size[i] = destLen2;
p->pos[i] = 0;
p->finished[i] = encodingWasFinished;
}
- if (res != SZ_OK)
- return res;
-
- if (destLenCur != 0 || srcLenCur != 0)
+ if (destLen2 != 0 || srcLen2 != 0)
processed = True;
}
+
if (!processed)
- break;
+ {
+ if (allFinished)
+ p->status = CODER_STATUS_FINISHED_WITH_MARK;
+ return resMain;
+ }
}
- if (allFinished)
- *status = CODER_STATUS_FINISHED_WITH_MARK;
- return SZ_OK;
}
+
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
{
*p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
@@ -505,11 +763,11 @@ SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
{
- return
- indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) &&
- (GetUi32(buf) == CrcCalc(buf + 4, 6) &&
- flags == GetBe16(buf + 8) &&
- memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0);
+ return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2)
+ && GetUi32(buf) == CrcCalc(buf + 4, 6)
+ && flags == GetBe16(buf + 8)
+ && buf[10] == XZ_FOOTER_SIG_0
+ && buf[11] == XZ_FOOTER_SIG_1;
}
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
@@ -517,20 +775,48 @@ static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *b
if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
+static Bool XzBlock_AreSupportedFilters(const CXzBlock *p)
+{
+ unsigned numFilters = XzBlock_GetNumFilters(p) - 1;
+ unsigned i;
+ {
+ const CXzFilter *f = &p->filters[numFilters];
+ if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40)
+ return False;
+ }
+
+ for (i = 0; i < numFilters; i++)
+ {
+ const CXzFilter *f = &p->filters[i];
+ if (f->id == XZ_ID_Delta)
+ {
+ if (f->propsSize != 1)
+ return False;
+ }
+ else if (f->id < XZ_ID_Delta
+ || f->id > XZ_ID_SPARC
+ || (f->propsSize != 0 && f->propsSize != 4))
+ return False;
+ }
+ return True;
+}
+
+
SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
{
unsigned pos;
unsigned numFilters, i;
unsigned headerSize = (unsigned)header[0] << 2;
+ /* (headerSize != 0) : another code checks */
+
if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
return SZ_ERROR_ARCHIVE;
pos = 1;
- if (pos == headerSize)
- return SZ_ERROR_ARCHIVE;
p->flags = header[pos++];
+ p->packSize = (UInt64)(Int64)-1;
if (XzBlock_HasPackSize(p))
{
READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);
@@ -538,6 +824,7 @@ SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
return SZ_ERROR_ARCHIVE;
}
+ p->unpackSize = (UInt64)(Int64)-1;
if (XzBlock_HasUnpackSize(p))
READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
@@ -564,37 +851,56 @@ SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
#endif
}
+ if (XzBlock_HasUnsupportedFlags(p))
+ return SZ_ERROR_UNSUPPORTED;
+
while (pos < headerSize)
if (header[pos++] != 0)
return SZ_ERROR_ARCHIVE;
return SZ_OK;
}
-SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
+
+
+
+static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
{
unsigned i;
Bool needReInit = True;
unsigned numFilters = XzBlock_GetNumFilters(block);
-
- if (numFilters == p->numCoders)
+
+ if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf)))
{
+ needReInit = False;
for (i = 0; i < numFilters; i++)
if (p->ids[i] != block->filters[numFilters - 1 - i].id)
+ {
+ needReInit = True;
break;
- needReInit = (i != numFilters);
+ }
}
+
+ // p->SingleBufMode = (outBuf != NULL);
+ p->outBuf = outBuf;
+ p->outBufSize = outBufSize;
+
+ // p->SingleBufMode = False;
+ // outBuf = NULL;
if (needReInit)
{
MixCoder_Free(p);
- p->numCoders = numFilters;
for (i = 0; i < numFilters; i++)
{
- const CXzFilter *f = &block->filters[numFilters - 1 - i];
- RINOK(MixCoder_SetFromMethod(p, i, f->id));
+ RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize));
}
+ p->numCoders = numFilters;
}
-
+ else
+ {
+ RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize));
+ }
+
for (i = 0; i < numFilters; i++)
{
const CXzFilter *f = &block->filters[numFilters - 1 - i];
@@ -606,6 +912,8 @@ SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
return SZ_OK;
}
+
+
void XzUnpacker_Init(CXzUnpacker *p)
{
p->state = XZ_STATE_STREAM_HEADER;
@@ -614,75 +922,171 @@ void XzUnpacker_Init(CXzUnpacker *p)
p->numFinishedStreams = 0;
p->numTotalBlocks = 0;
p->padSize = 0;
+ p->decodeOnlyOneBlock = 0;
+
+ p->parseMode = False;
+ p->decodeToStreamSignature = False;
+
+ // p->outBuf = NULL;
+ // p->outBufSize = 0;
+ p->outDataWritten = 0;
+}
+
+
+void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
+{
+ p->outBuf = outBuf;
+ p->outBufSize = outBufSize;
}
-void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc)
+
+void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)
{
MixCoder_Construct(&p->decoder, alloc);
+ p->outBuf = NULL;
+ p->outBufSize = 0;
XzUnpacker_Init(p);
}
+
void XzUnpacker_Free(CXzUnpacker *p)
{
MixCoder_Free(&p->decoder);
}
+
+void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p)
+{
+ p->indexSize = 0;
+ p->numBlocks = 0;
+ Sha256_Init(&p->sha);
+ p->state = XZ_STATE_BLOCK_HEADER;
+ p->pos = 0;
+ p->decodeOnlyOneBlock = 1;
+}
+
+
+static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize)
+{
+ Byte temp[32];
+ unsigned num = Xz_WriteVarInt(temp, packSize);
+ num += Xz_WriteVarInt(temp + num, unpackSize);
+ Sha256_Update(&p->sha, temp, num);
+ p->indexSize += num;
+ p->numBlocks++;
+}
+
+
+
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
- const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status)
+ const Byte *src, SizeT *srcLen, int srcFinished,
+ ECoderFinishMode finishMode, ECoderStatus *status)
{
SizeT destLenOrig = *destLen;
SizeT srcLenOrig = *srcLen;
*destLen = 0;
*srcLen = 0;
*status = CODER_STATUS_NOT_SPECIFIED;
+
for (;;)
{
- SizeT srcRem = srcLenOrig - *srcLen;
+ SizeT srcRem;
if (p->state == XZ_STATE_BLOCK)
{
SizeT destLen2 = destLenOrig - *destLen;
SizeT srcLen2 = srcLenOrig - *srcLen;
SRes res;
+
+ ECoderFinishMode finishMode2 = finishMode;
+ Bool srcFinished2 = srcFinished;
+ Bool destFinish = False;
+
+ if (p->block.packSize != (UInt64)(Int64)-1)
+ {
+ UInt64 rem = p->block.packSize - p->packSize;
+ if (srcLen2 >= rem)
+ {
+ srcFinished2 = True;
+ srcLen2 = (SizeT)rem;
+ }
+ if (rem == 0 && p->block.unpackSize == p->unpackSize)
+ return SZ_ERROR_DATA;
+ }
+
+ if (p->block.unpackSize != (UInt64)(Int64)-1)
+ {
+ UInt64 rem = p->block.unpackSize - p->unpackSize;
+ if (destLen2 >= rem)
+ {
+ destFinish = True;
+ finishMode2 = CODER_FINISH_END;
+ destLen2 = (SizeT)rem;
+ }
+ }
+
+ /*
if (srcLen2 == 0 && destLen2 == 0)
{
*status = CODER_STATUS_NOT_FINISHED;
return SZ_OK;
}
+ */
- res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);
- XzCheck_Update(&p->check, dest, destLen2);
+ {
+ res = MixCoder_Code(&p->decoder,
+ (p->outBuf ? NULL : dest), &destLen2, destFinish,
+ src, &srcLen2, srcFinished2,
+ finishMode2);
+
+ *status = p->decoder.status;
+ XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2);
+ if (!p->outBuf)
+ dest += destLen2;
+ p->outDataWritten += destLen2;
+ }
(*srcLen) += srcLen2;
src += srcLen2;
p->packSize += srcLen2;
-
(*destLen) += destLen2;
- dest += destLen2;
p->unpackSize += destLen2;
-
+
RINOK(res);
-
- if (*status == CODER_STATUS_FINISHED_WITH_MARK)
- {
- Byte temp[32];
- unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));
- num += Xz_WriteVarInt(temp + num, p->unpackSize);
- Sha256_Update(&p->sha, temp, num);
- p->indexSize += num;
- p->numBlocks++;
+
+ if (*status != CODER_STATUS_FINISHED_WITH_MARK)
+ {
+ if (p->block.packSize == p->packSize
+ && *status == CODER_STATUS_NEEDS_MORE_INPUT)
+ {
+ PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT");
+ *status = CODER_STATUS_NOT_SPECIFIED;
+ return SZ_ERROR_DATA;
+ }
+ return SZ_OK;
+ }
+ {
+ XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize);
p->state = XZ_STATE_BLOCK_FOOTER;
p->pos = 0;
p->alignPos = 0;
+ *status = CODER_STATUS_NOT_SPECIFIED;
+
+ if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize)
+ || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize))
+ {
+ PRF_STR("ERROR: block.size mismatch");
+ return SZ_ERROR_DATA;
+ }
}
- else if (srcLen2 == 0 && destLen2 == 0)
- return SZ_OK;
-
- continue;
+ // continue;
}
- if (srcRem == 0)
+ srcRem = srcLenOrig - *srcLen;
+
+ // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes
+ if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER)
{
*status = CODER_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
@@ -696,6 +1100,8 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
{
if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
return SZ_ERROR_NO_ARCHIVE;
+ if (p->decodeToStreamSignature)
+ return SZ_OK;
p->buf[p->pos++] = *src++;
(*srcLen)++;
}
@@ -703,10 +1109,10 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
{
RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
p->numStartedStreams++;
- p->state = XZ_STATE_BLOCK_HEADER;
- Sha256_Init(&p->sha);
p->indexSize = 0;
p->numBlocks = 0;
+ Sha256_Init(&p->sha);
+ p->state = XZ_STATE_BLOCK_HEADER;
p->pos = 0;
}
break;
@@ -720,6 +1126,8 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
(*srcLen)++;
if (p->buf[0] == 0)
{
+ if (p->decodeOnlyOneBlock)
+ return SZ_ERROR_DATA;
p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
p->indexPos = p->indexPreSize;
p->indexSize += p->indexPreSize;
@@ -727,10 +1135,13 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
Sha256_Init(&p->sha);
p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
p->state = XZ_STATE_STREAM_INDEX;
+ break;
}
p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
+ break;
}
- else if (p->pos != p->blockHeaderSize)
+
+ if (p->pos != p->blockHeaderSize)
{
UInt32 cur = p->blockHeaderSize - p->pos;
if (cur > srcRem)
@@ -743,20 +1154,32 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
else
{
RINOK(XzBlock_Parse(&p->block, p->buf));
+ if (!XzBlock_AreSupportedFilters(&p->block))
+ return SZ_ERROR_UNSUPPORTED;
p->numTotalBlocks++;
p->state = XZ_STATE_BLOCK;
p->packSize = 0;
p->unpackSize = 0;
XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
- RINOK(XzDec_Init(&p->decoder, &p->block));
+ if (p->parseMode)
+ {
+ p->headerParsedOk = True;
+ return SZ_OK;
+ }
+ RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize));
}
break;
}
case XZ_STATE_BLOCK_FOOTER:
{
- if (((p->packSize + p->alignPos) & 3) != 0)
+ if ((((unsigned)p->packSize + p->alignPos) & 3) != 0)
{
+ if (srcRem == 0)
+ {
+ *status = CODER_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
(*srcLen)++;
p->alignPos++;
if (*src++ != 0)
@@ -768,20 +1191,31 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
UInt32 cur = checkSize - p->pos;
if (cur != 0)
{
+ if (srcRem == 0)
+ {
+ *status = CODER_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
if (cur > srcRem)
cur = (UInt32)srcRem;
memcpy(p->buf + p->pos, src, cur);
p->pos += cur;
(*srcLen) += cur;
src += cur;
+ if (checkSize != p->pos)
+ break;
}
- else
{
Byte digest[XZ_CHECK_SIZE_MAX];
p->state = XZ_STATE_BLOCK_HEADER;
p->pos = 0;
if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
return SZ_ERROR_CRC;
+ if (p->decodeOnlyOneBlock)
+ {
+ *status = CODER_STATUS_FINISHED_WITH_MARK;
+ return SZ_OK;
+ }
}
}
break;
@@ -897,17 +1331,1443 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
*/
}
-Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)
+
+SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
+ const Byte *src, SizeT *srcLen,
+ ECoderFinishMode finishMode, ECoderStatus *status)
+{
+ XzUnpacker_Init(p);
+ XzUnpacker_SetOutBuf(p, dest, *destLen);
+
+ return XzUnpacker_Code(p,
+ NULL, destLen,
+ src, srcLen, True,
+ finishMode, status);
+}
+
+
+Bool XzUnpacker_IsBlockFinished(const CXzUnpacker *p)
+{
+ return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);
+}
+
+Bool XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)
{
return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
}
-UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p)
+UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)
{
UInt64 num = 0;
if (p->state == XZ_STATE_STREAM_PADDING)
- num += p->padSize;
+ num = p->padSize;
else if (p->state == XZ_STATE_STREAM_HEADER)
- num += p->padSize + p->pos;
+ num = p->padSize + p->pos;
return num;
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#ifndef _7ZIP_ST
+#include "MtDec.h"
+#endif
+
+
+void XzDecMtProps_Init(CXzDecMtProps *p)
+{
+ p->inBufSize_ST = 1 << 18;
+ p->outStep_ST = 1 << 20;
+ p->ignoreErrors = False;
+
+ #ifndef _7ZIP_ST
+ p->numThreads = 1;
+ p->inBufSize_MT = 1 << 18;
+ p->memUseMax = sizeof(size_t) << 28;
+ #endif
+}
+
+
+
+#ifndef _7ZIP_ST
+
+/* ---------- CXzDecMtThread ---------- */
+
+typedef struct
+{
+ Byte *outBuf;
+ size_t outBufSize;
+ size_t outPreSize;
+ size_t inPreSize;
+ size_t inPreHeaderSize;
+ size_t blockPackSize_for_Index; // including block header and checksum.
+ size_t blockPackTotal; // including stream header, block header and checksum.
+ size_t inCodeSize;
+ size_t outCodeSize;
+ ECoderStatus status;
+ SRes codeRes;
+ Bool skipMode;
+ // Bool finishedWithMark;
+ EMtDecParseState parseState;
+ Bool parsing_Truncated;
+ Bool atBlockHeader;
+ CXzStreamFlags streamFlags;
+ // UInt64 numFinishedStreams
+ UInt64 numStreams;
+ UInt64 numTotalBlocks;
+ UInt64 numBlocks;
+
+ Bool dec_created;
+ CXzUnpacker dec;
+
+ Byte mtPad[1 << 7];
+} CXzDecMtThread;
+
+#endif
+
+
+/* ---------- CXzDecMt ---------- */
+
+typedef struct
+{
+ CAlignOffsetAlloc alignOffsetAlloc;
+ ISzAllocPtr allocMid;
+
+ CXzDecMtProps props;
+ size_t unpackBlockMaxSize;
+
+ ISeqInStream *inStream;
+ ISeqOutStream *outStream;
+ ICompressProgress *progress;
+ // CXzStatInfo *stat;
+
+ Bool finishMode;
+ Bool outSize_Defined;
+ UInt64 outSize;
+
+ UInt64 outProcessed;
+ UInt64 inProcessed;
+ UInt64 readProcessed;
+ Bool readWasFinished;
+ SRes readRes;
+ SRes writeRes;
+
+ Byte *outBuf;
+ size_t outBufSize;
+ Byte *inBuf;
+ size_t inBufSize;
+ Bool dec_created;
+ CXzUnpacker dec;
+
+ ECoderStatus status;
+ SRes codeRes;
+
+ #ifndef _7ZIP_ST
+ Bool mainDecoderWasCalled;
+ // int statErrorDefined;
+ int finishedDecoderIndex;
+
+ // global values that are used in Parse stage
+ CXzStreamFlags streamFlags;
+ // UInt64 numFinishedStreams
+ UInt64 numStreams;
+ UInt64 numTotalBlocks;
+ UInt64 numBlocks;
+
+ // UInt64 numBadBlocks;
+ SRes mainErrorCode;
+
+ Bool isBlockHeaderState_Parse;
+ Bool isBlockHeaderState_Write;
+ UInt64 outProcessed_Parse;
+ Bool parsing_Truncated;
+
+ Bool mtc_WasConstructed;
+ CMtDec mtc;
+ CXzDecMtThread coders[MTDEC__THREADS_MAX];
+ #endif
+
+} CXzDecMt;
+
+
+
+CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
+{
+ CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt));
+ if (!p)
+ return NULL;
+
+ AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
+ p->alignOffsetAlloc.baseAlloc = alloc;
+ p->alignOffsetAlloc.numAlignBits = 7;
+ p->alignOffsetAlloc.offset = 0;
+
+ p->allocMid = allocMid;
+
+ p->outBuf = NULL;
+ p->outBufSize = 0;
+ p->inBuf = NULL;
+ p->inBufSize = 0;
+ p->dec_created = False;
+
+ p->unpackBlockMaxSize = 0;
+
+ XzDecMtProps_Init(&p->props);
+
+ #ifndef _7ZIP_ST
+ p->mtc_WasConstructed = False;
+ {
+ unsigned i;
+ for (i = 0; i < MTDEC__THREADS_MAX; i++)
+ {
+ CXzDecMtThread *coder = &p->coders[i];
+ coder->dec_created = False;
+ coder->outBuf = NULL;
+ coder->outBufSize = 0;
+ }
+ }
+ #endif
+
+ return p;
+}
+
+
+#ifndef _7ZIP_ST
+
+static void XzDecMt_FreeOutBufs(CXzDecMt *p)
+{
+ unsigned i;
+ for (i = 0; i < MTDEC__THREADS_MAX; i++)
+ {
+ CXzDecMtThread *coder = &p->coders[i];
+ if (coder->outBuf)
+ {
+ ISzAlloc_Free(p->allocMid, coder->outBuf);
+ coder->outBuf = NULL;
+ coder->outBufSize = 0;
+ }
+ }
+ p->unpackBlockMaxSize = 0;
+}
+
+#endif
+
+
+
+static void XzDecMt_FreeSt(CXzDecMt *p)
+{
+ if (p->dec_created)
+ {
+ XzUnpacker_Free(&p->dec);
+ p->dec_created = False;
+ }
+
+ if (p->outBuf)
+ {
+ ISzAlloc_Free(p->allocMid, p->outBuf);
+ p->outBuf = NULL;
+ }
+ p->outBufSize = 0;
+
+ if (p->inBuf)
+ {
+ ISzAlloc_Free(p->allocMid, p->inBuf);
+ p->inBuf = NULL;
+ }
+ p->inBufSize = 0;
+}
+
+
+void XzDecMt_Destroy(CXzDecMtHandle pp)
+{
+ CXzDecMt *p = (CXzDecMt *)pp;
+
+ XzDecMt_FreeSt(p);
+
+ #ifndef _7ZIP_ST
+
+ if (p->mtc_WasConstructed)
+ {
+ MtDec_Destruct(&p->mtc);
+ p->mtc_WasConstructed = False;
+ }
+ {
+ unsigned i;
+ for (i = 0; i < MTDEC__THREADS_MAX; i++)
+ {
+ CXzDecMtThread *t = &p->coders[i];
+ if (t->dec_created)
+ {
+ // we don't need to free dict here
+ XzUnpacker_Free(&t->dec);
+ t->dec_created = False;
+ }
+ }
+ }
+ XzDecMt_FreeOutBufs(p);
+
+ #endif
+
+ ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
+}
+
+
+
+#ifndef _7ZIP_ST
+
+static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
+{
+ CXzDecMt *me = (CXzDecMt *)obj;
+ CXzDecMtThread *coder = &me->coders[coderIndex];
+ size_t srcSize = cc->srcSize;
+
+ cc->srcSize = 0;
+ cc->outPos = 0;
+ cc->state = MTDEC_PARSE_CONTINUE;
+
+ cc->canCreateNewThread = True;
+
+ if (cc->startCall)
+ {
+ coder->outPreSize = 0;
+ coder->inPreSize = 0;
+ coder->inPreHeaderSize = 0;
+ coder->parseState = MTDEC_PARSE_CONTINUE;
+ coder->parsing_Truncated = False;
+ coder->skipMode = False;
+ coder->codeRes = SZ_OK;
+ coder->status = CODER_STATUS_NOT_SPECIFIED;
+ coder->inCodeSize = 0;
+ coder->outCodeSize = 0;
+
+ coder->numStreams = me->numStreams;
+ coder->numTotalBlocks = me->numTotalBlocks;
+ coder->numBlocks = me->numBlocks;
+
+ if (!coder->dec_created)
+ {
+ XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt);
+ coder->dec_created = True;
+ }
+
+ XzUnpacker_Init(&coder->dec);
+
+ if (me->isBlockHeaderState_Parse)
+ {
+ coder->dec.streamFlags = me->streamFlags;
+ coder->atBlockHeader = True;
+ XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec);
+ }
+ else
+ {
+ coder->atBlockHeader = False;
+ me->isBlockHeaderState_Parse = True;
+ }
+
+ coder->dec.numStartedStreams = me->numStreams;
+ coder->dec.numTotalBlocks = me->numTotalBlocks;
+ coder->dec.numBlocks = me->numBlocks;
+ }
+
+ while (!coder->skipMode)
+ {
+ ECoderStatus status;
+ SRes res;
+ size_t srcSize2 = srcSize;
+ size_t destSize = (size_t)0 - 1;
+
+ coder->dec.parseMode = True;
+ coder->dec.headerParsedOk = False;
+
+ PRF_STR_INT("Parse", srcSize2);
+
+ res = XzUnpacker_Code(&coder->dec,
+ NULL, &destSize,
+ cc->src, &srcSize2, cc->srcFinished,
+ CODER_FINISH_END, &status);
+
+ // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2));
+
+ coder->codeRes = res;
+ coder->status = status;
+ cc->srcSize += srcSize2;
+ srcSize -= srcSize2;
+ coder->inPreHeaderSize += srcSize2;
+ coder->inPreSize = coder->inPreHeaderSize;
+
+ if (res != SZ_OK)
+ {
+ cc->state =
+ coder->parseState = MTDEC_PARSE_END;
+ /*
+ if (res == SZ_ERROR_MEM)
+ return res;
+ return SZ_OK;
+ */
+ return; // res;
+ }
+
+ if (coder->dec.headerParsedOk)
+ {
+ const CXzBlock *block = &coder->dec.block;
+ if (XzBlock_HasUnpackSize(block)
+ // && block->unpackSize <= me->props.outBlockMax
+ && XzBlock_HasPackSize(block))
+ {
+ {
+ if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)
+ {
+ cc->state = MTDEC_PARSE_OVERFLOW;
+ return; // SZ_OK;
+ }
+ }
+ {
+ UInt64 packSize = block->packSize;
+ UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
+ UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);
+ UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;
+ // if (blockPackSum <= me->props.inBlockMax)
+ // unpackBlockMaxSize
+ {
+ coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize);
+ coder->blockPackTotal = (size_t)blockPackSum;
+ coder->outPreSize = (size_t)block->unpackSize;
+ coder->streamFlags = coder->dec.streamFlags;
+ me->streamFlags = coder->dec.streamFlags;
+ coder->skipMode = True;
+ break;
+ }
+ }
+ }
+ }
+ else
+ // if (coder->inPreSize <= me->props.inBlockMax)
+ {
+ if (!cc->srcFinished)
+ return; // SZ_OK;
+ cc->state =
+ coder->parseState = MTDEC_PARSE_END;
+ return; // SZ_OK;
+ }
+ cc->state = MTDEC_PARSE_OVERFLOW;
+ return; // SZ_OK;
+ }
+
+ // ---------- skipMode ----------
+ {
+ UInt64 rem = coder->blockPackTotal - coder->inPreSize;
+ size_t cur = srcSize;
+ if (cur > rem)
+ cur = (size_t)rem;
+ cc->srcSize += cur;
+ coder->inPreSize += cur;
+ srcSize -= cur;
+
+ if (coder->inPreSize == coder->blockPackTotal)
+ {
+ if (srcSize == 0)
+ {
+ if (!cc->srcFinished)
+ return; // SZ_OK;
+ cc->state = MTDEC_PARSE_END;
+ }
+ else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block
+ cc->state = MTDEC_PARSE_END;
+ else
+ {
+ cc->state = MTDEC_PARSE_NEW;
+
+ {
+ size_t blockMax = me->unpackBlockMaxSize;
+ if (blockMax < coder->outPreSize)
+ blockMax = coder->outPreSize;
+ {
+ UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2;
+ if (me->props.memUseMax < required)
+ cc->canCreateNewThread = False;
+ }
+ }
+
+ if (me->outSize_Defined)
+ {
+ // next block can be zero size
+ const UInt64 rem2 = me->outSize - me->outProcessed_Parse;
+ if (rem2 < coder->outPreSize)
+ {
+ coder->parsing_Truncated = True;
+ cc->state = MTDEC_PARSE_END;
+ }
+ me->outProcessed_Parse += coder->outPreSize;
+ }
+ }
+ }
+ else if (cc->srcFinished)
+ cc->state = MTDEC_PARSE_END;
+ else
+ return; // SZ_OK;
+
+ coder->parseState = cc->state;
+ cc->outPos = coder->outPreSize;
+
+ me->numStreams = coder->dec.numStartedStreams;
+ me->numTotalBlocks = coder->dec.numTotalBlocks;
+ me->numBlocks = coder->dec.numBlocks + 1;
+ return; // SZ_OK;
+ }
+}
+
+
+static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex)
+{
+ CXzDecMt *me = (CXzDecMt *)pp;
+ CXzDecMtThread *coder = &me->coders[coderIndex];
+ Byte *dest;
+
+ if (!coder->dec.headerParsedOk)
+ return SZ_OK;
+
+ dest = coder->outBuf;
+
+ if (!dest || coder->outBufSize < coder->outPreSize)
+ {
+ if (dest)
+ {
+ ISzAlloc_Free(me->allocMid, dest);
+ coder->outBuf = NULL;
+ coder->outBufSize = 0;
+ }
+ {
+ size_t outPreSize = coder->outPreSize;
+ if (outPreSize == 0)
+ outPreSize = 1;
+ dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize);
+ }
+ if (!dest)
+ return SZ_ERROR_MEM;
+ coder->outBuf = dest;
+ coder->outBufSize = coder->outPreSize;
+
+ if (coder->outBufSize > me->unpackBlockMaxSize)
+ me->unpackBlockMaxSize = coder->outBufSize;
+ }
+
+ // return SZ_ERROR_MEM;
+
+ XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);
+
+ {
+ SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize);
+ // res = SZ_ERROR_UNSUPPORTED; // to test
+ coder->codeRes = res;
+ if (res != SZ_OK)
+ {
+ // if (res == SZ_ERROR_MEM) return res;
+ if (me->props.ignoreErrors && res != SZ_ERROR_MEM)
+ return S_OK;
+ return res;
+ }
+ }
+
+ return SZ_OK;
+}
+
+
+static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex,
+ const Byte *src, size_t srcSize, int srcFinished,
+ // int finished, int blockFinished,
+ UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
+{
+ CXzDecMt *me = (CXzDecMt *)pp;
+ CXzDecMtThread *coder = &me->coders[coderIndex];
+
+ *inCodePos = coder->inCodeSize;
+ *outCodePos = coder->outCodeSize;
+ *stop = True;
+
+ if (coder->inCodeSize < coder->inPreHeaderSize)
+ {
+ UInt64 rem = coder->inPreHeaderSize - coder->inCodeSize;
+ size_t step = srcSize;
+ if (step > rem)
+ step = (size_t)rem;
+ src += step;
+ srcSize -= step;
+ coder->inCodeSize += step;
+ if (coder->inCodeSize < coder->inPreHeaderSize)
+ {
+ *stop = False;
+ return SZ_OK;
+ }
+ }
+
+ if (!coder->dec.headerParsedOk)
+ return SZ_OK;
+ if (!coder->outBuf)
+ return SZ_OK;
+
+ if (coder->codeRes == SZ_OK)
+ {
+ ECoderStatus status;
+ SRes res;
+ size_t srcProcessed = srcSize;
+ size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;
+
+ // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur));
+
+ res = XzUnpacker_Code(&coder->dec,
+ NULL, &outSizeCur,
+ src, &srcProcessed, srcFinished,
+ // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,
+ CODER_FINISH_END,
+ &status);
+
+ // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur));
+
+ coder->codeRes = res;
+ coder->status = status;
+ coder->inCodeSize += srcProcessed;
+ coder->outCodeSize = coder->dec.outDataWritten;
+ *inCodePos = coder->inCodeSize;
+ *outCodePos = coder->outCodeSize;
+
+ if (res == SZ_OK)
+ {
+ if (srcProcessed == srcSize)
+ *stop = False;
+ return SZ_OK;
+ }
+ }
+
+ if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)
+ {
+ *inCodePos = coder->inPreSize;
+ *outCodePos = coder->outPreSize;
+ return S_OK;
+ }
+ return coder->codeRes;
+}
+
+
+#define XZDECMT_STREAM_WRITE_STEP (1 << 24)
+
+static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,
+ Bool needWriteToStream,
+ const Byte *src, size_t srcSize,
+ // int srcFinished,
+ Bool *needContinue,
+ Bool *canRecode)
+{
+ CXzDecMt *me = (CXzDecMt *)pp;
+ const CXzDecMtThread *coder = &me->coders[coderIndex];
+
+ // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));
+
+ *needContinue = False;
+ *canRecode = True;
+
+ if (!needWriteToStream)
+ return SZ_OK;
+
+ if (!coder->dec.headerParsedOk || !coder->outBuf)
+ {
+ if (me->finishedDecoderIndex < 0)
+ me->finishedDecoderIndex = coderIndex;
+ return SZ_OK;
+ }
+
+ if (me->finishedDecoderIndex >= 0)
+ return SZ_OK;
+
+ me->mtc.inProcessed += coder->inCodeSize;
+
+ *canRecode = False;
+
+ {
+ SRes res;
+ size_t size = coder->outCodeSize;
+ Byte *data = coder->outBuf;
+
+ // we use in me->dec: sha, numBlocks, indexSize
+
+ if (!me->isBlockHeaderState_Write)
+ {
+ XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);
+ me->dec.decodeOnlyOneBlock = False;
+ me->dec.numStartedStreams = coder->dec.numStartedStreams;
+ me->dec.streamFlags = coder->streamFlags;
+
+ me->isBlockHeaderState_Write = True;
+ }
+
+ me->dec.numTotalBlocks = coder->dec.numTotalBlocks;
+ XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);
+
+ if (coder->outPreSize != size)
+ {
+ if (me->props.ignoreErrors)
+ {
+ memset(data + size, 0, coder->outPreSize - size);
+ size = coder->outPreSize;
+ }
+ // me->numBadBlocks++;
+ if (me->mainErrorCode == SZ_OK)
+ {
+ if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)
+ me->mainErrorCode = SZ_ERROR_INPUT_EOF;
+ else
+ me->mainErrorCode = SZ_ERROR_DATA;
+ }
+ }
+
+ if (me->writeRes != SZ_OK)
+ return me->writeRes;
+
+ res = SZ_OK;
+ {
+ if (me->outSize_Defined)
+ {
+ const UInt64 rem = me->outSize - me->outProcessed;
+ if (size > rem)
+ size = (SizeT)rem;
+ }
+
+ for (;;)
+ {
+ size_t cur = size;
+ size_t written;
+ if (cur > XZDECMT_STREAM_WRITE_STEP)
+ cur = XZDECMT_STREAM_WRITE_STEP;
+
+ written = ISeqOutStream_Write(me->outStream, data, cur);
+
+ // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written));
+
+ me->outProcessed += written;
+ if (written != cur)
+ {
+ me->writeRes = SZ_ERROR_WRITE;
+ res = me->writeRes;
+ break;
+ }
+ data += cur;
+ size -= cur;
+ // PRF_STR_INT("Written size =", size);
+ if (size == 0)
+ break;
+ res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);
+ if (res != SZ_OK)
+ break;
+ }
+ }
+
+ if (coder->codeRes != SZ_OK)
+ if (!me->props.ignoreErrors)
+ {
+ me->finishedDecoderIndex = coderIndex;
+ return res;
+ }
+
+ RINOK(res);
+
+ if (coder->inPreSize != coder->inCodeSize
+ || coder->blockPackTotal != coder->inCodeSize)
+ {
+ me->finishedDecoderIndex = coderIndex;
+ return SZ_OK;
+ }
+
+ if (coder->parseState != MTDEC_PARSE_END)
+ {
+ *needContinue = True;
+ return SZ_OK;
+ }
+ }
+
+ // (coder->state == MTDEC_PARSE_END) means that there are no other working threads
+ // so we can use mtc variables without lock
+
+ PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed);
+
+ me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
+ {
+ CXzUnpacker *dec = &me->dec;
+
+ PRF_STR_INT("PostSingle", srcSize);
+
+ {
+ size_t srcProcessed = srcSize;
+ ECoderStatus status;
+ size_t outSizeCur = 0;
+ SRes res;
+
+ // dec->decodeOnlyOneBlock = False;
+ dec->decodeToStreamSignature = True;
+
+ me->mainDecoderWasCalled = True;
+
+ if (coder->parsing_Truncated)
+ {
+ me->parsing_Truncated = True;
+ return SZ_OK;
+ }
+
+ res = XzUnpacker_Code(dec,
+ NULL, &outSizeCur,
+ src, &srcProcessed,
+ me->mtc.readWasFinished, // srcFinished
+ CODER_FINISH_END, // CODER_FINISH_ANY,
+ &status);
+
+ me->status = status;
+ me->codeRes = res;
+
+ me->mtc.inProcessed += srcProcessed;
+ me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
+
+ if (res != SZ_OK)
+ {
+ return S_OK;
+ // return res;
+ }
+
+ if (dec->state == XZ_STATE_STREAM_HEADER)
+ {
+ *needContinue = True;
+ me->isBlockHeaderState_Parse = False;
+ me->isBlockHeaderState_Write = False;
+ {
+ Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
+ if (!crossBuf)
+ return SZ_ERROR_MEM;
+ memcpy(crossBuf, src + srcProcessed, srcSize - srcProcessed);
+ }
+ me->mtc.crossStart = 0;
+ me->mtc.crossEnd = srcSize - srcProcessed;
+ return SZ_OK;
+ }
+
+ if (status != CODER_STATUS_NEEDS_MORE_INPUT)
+ {
+ return E_FAIL;
+ }
+
+ if (me->mtc.readWasFinished)
+ {
+ return SZ_OK;
+ }
+ }
+
+ {
+ size_t inPos;
+ size_t inLim;
+ const Byte *inData;
+ UInt64 inProgressPrev = me->mtc.inProcessed;
+
+ // XzDecMt_Prepare_InBuf_ST(p);
+ Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
+ if (!crossBuf)
+ return SZ_ERROR_MEM;
+
+ inPos = 0;
+ inLim = 0;
+ // outProcessed = 0;
+
+ inData = crossBuf;
+
+ for (;;)
+ {
+ SizeT inProcessed;
+ SizeT outProcessed;
+ ECoderStatus status;
+ SRes res;
+
+ if (inPos == inLim)
+ {
+ if (!me->mtc.readWasFinished)
+ {
+ inPos = 0;
+ inLim = me->mtc.inBufSize;
+ me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)inData, &inLim);
+ me->mtc.readProcessed += inLim;
+ if (inLim == 0 || me->mtc.readRes != SZ_OK)
+ me->mtc.readWasFinished = True;
+ }
+ }
+
+ inProcessed = inLim - inPos;
+ outProcessed = 0;
+
+ res = XzUnpacker_Code(dec,
+ NULL, &outProcessed,
+ inData + inPos, &inProcessed,
+ (inProcessed == 0), // srcFinished
+ CODER_FINISH_END, &status);
+
+ me->codeRes = res;
+ me->status = status;
+ inPos += inProcessed;
+ me->mtc.inProcessed += inProcessed;
+ me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
+
+ if (res != SZ_OK)
+ {
+ return S_OK;
+ // return res;
+ }
+
+ if (dec->state == XZ_STATE_STREAM_HEADER)
+ {
+ *needContinue = True;
+ me->mtc.crossStart = inPos;
+ me->mtc.crossEnd = inLim;
+ me->isBlockHeaderState_Parse = False;
+ me->isBlockHeaderState_Write = False;
+ return SZ_OK;
+ }
+
+ if (status != CODER_STATUS_NEEDS_MORE_INPUT)
+ return E_FAIL;
+
+ if (me->mtc.progress)
+ {
+ UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;
+ if (inDelta >= (1 << 22))
+ {
+ RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress));
+ inProgressPrev = me->mtc.inProcessed;
+ }
+ }
+ if (me->mtc.readWasFinished)
+ return SZ_OK;
+ }
+ }
+ }
+}
+
+
+#endif
+
+
+
+void XzStatInfo_Clear(CXzStatInfo *p)
+{
+ p->InSize = 0;
+ p->OutSize = 0;
+
+ p->NumStreams = 0;
+ p->NumBlocks = 0;
+
+ p->UnpackSize_Defined = False;
+
+ p->NumStreams_Defined = False;
+ p->NumBlocks_Defined = False;
+
+ // p->IsArc = False;
+ // p->UnexpectedEnd = False;
+ // p->Unsupported = False;
+ // p->HeadersError = False;
+ // p->DataError = False;
+ // p->CrcError = False;
+
+ p->DataAfterEnd = False;
+ p->DecodingTruncated = False;
+
+ p->DecodeRes = SZ_OK;
+ p->ReadRes = SZ_OK;
+ p->ProgressRes = SZ_OK;
+
+ p->CombinedRes = SZ_OK;
+ p->CombinedRes_Type = SZ_OK;
+}
+
+
+
+
+static SRes XzDecMt_Decode_ST(CXzDecMt *p
+ #ifndef _7ZIP_ST
+ , Bool tMode
+ #endif
+ , CXzStatInfo *stat)
+{
+ size_t outPos;
+ size_t inPos, inLim;
+ const Byte *inData;
+ UInt64 inPrev, outPrev;
+
+ CXzUnpacker *dec;
+
+ #ifndef _7ZIP_ST
+ if (tMode)
+ {
+ XzDecMt_FreeOutBufs(p);
+ tMode = MtDec_PrepareRead(&p->mtc);
+ }
+ #endif
+
+ if (!p->outBuf || p->outBufSize != p->props.outStep_ST)
+ {
+ ISzAlloc_Free(p->allocMid, p->outBuf);
+ p->outBufSize = 0;
+ p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);
+ if (!p->outBuf)
+ return SZ_ERROR_MEM;
+ p->outBufSize = p->props.outStep_ST;
+ }
+
+ if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
+ {
+ ISzAlloc_Free(p->allocMid, p->inBuf);
+ p->inBufSize = 0;
+ p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
+ if (!p->inBuf)
+ return SZ_ERROR_MEM;
+ p->inBufSize = p->props.inBufSize_ST;
+ }
+
+ dec = &p->dec;
+ dec->decodeToStreamSignature = False;
+ // dec->decodeOnlyOneBlock = False;
+
+ XzUnpacker_SetOutBuf(dec, NULL, 0);
+
+ inPrev = p->inProcessed;
+ outPrev = p->outProcessed;
+
+ inPos = 0;
+ inLim = 0;
+ inData = NULL;
+ outPos = 0;
+
+ for (;;)
+ {
+ SizeT outSize;
+ Bool finished;
+ ECoderFinishMode finishMode;
+ SizeT inProcessed;
+ ECoderStatus status;
+ SRes res;
+
+ SizeT outProcessed;
+
+
+
+ if (inPos == inLim)
+ {
+ #ifndef _7ZIP_ST
+ if (tMode)
+ {
+ inData = MtDec_Read(&p->mtc, &inLim);
+ inPos = 0;
+ if (inData)
+ continue;
+ tMode = False;
+ inLim = 0;
+ }
+ #endif
+
+ if (!p->readWasFinished)
+ {
+ inPos = 0;
+ inLim = p->inBufSize;
+ inData = p->inBuf;
+ p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
+ p->readProcessed += inLim;
+ if (inLim == 0 || p->readRes != SZ_OK)
+ p->readWasFinished = True;
+ }
+ }
+
+ outSize = p->props.outStep_ST - outPos;
+
+ finishMode = CODER_FINISH_ANY;
+ if (p->outSize_Defined)
+ {
+ const UInt64 rem = p->outSize - p->outProcessed;
+ if (outSize >= rem)
+ {
+ outSize = (SizeT)rem;
+ if (p->finishMode)
+ finishMode = CODER_FINISH_END;
+ }
+ }
+
+ inProcessed = inLim - inPos;
+ outProcessed = outSize;
+
+ res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,
+ inData + inPos, &inProcessed,
+ (inPos == inLim), // srcFinished
+ finishMode, &status);
+
+ p->codeRes = res;
+ p->status = status;
+
+ inPos += inProcessed;
+ outPos += outProcessed;
+ p->inProcessed += inProcessed;
+ p->outProcessed += outProcessed;
+
+ finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);
+
+ if (finished || outProcessed >= outSize)
+ if (outPos != 0)
+ {
+ size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);
+ p->outProcessed += written;
+ if (written != outPos)
+ {
+ stat->CombinedRes_Type = SZ_ERROR_WRITE;
+ return SZ_ERROR_WRITE;
+ }
+ outPos = 0;
+ }
+
+ if (p->progress && res == SZ_OK)
+ {
+ UInt64 inDelta = p->inProcessed - inPrev;
+ UInt64 outDelta = p->outProcessed - outPrev;
+ if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
+ {
+ res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);
+ if (res != SZ_OK)
+ {
+ stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
+ stat->ProgressRes = res;
+ return res;
+ }
+ inPrev = p->inProcessed;
+ outPrev = p->outProcessed;
+ }
+ }
+
+ if (finished)
+ return res;
+ }
+}
+
+static SRes XzStatInfo_SetStat(const CXzUnpacker *dec,
+ int finishMode,
+ UInt64 readProcessed, UInt64 inProcessed,
+ SRes res, ECoderStatus status,
+ Bool decodingTruncated,
+ CXzStatInfo *stat)
+{
+ UInt64 extraSize;
+
+ stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);
+ stat->InSize = inProcessed;
+ stat->NumStreams = dec->numStartedStreams;
+ stat->NumBlocks = dec->numTotalBlocks;
+
+ stat->UnpackSize_Defined = True;
+ stat->NumStreams_Defined = True;
+ stat->NumBlocks_Defined = True;
+
+ extraSize = XzUnpacker_GetExtraSize(dec);
+
+ if (res == SZ_OK)
+ {
+ if (status == CODER_STATUS_NEEDS_MORE_INPUT)
+ {
+ // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
+ extraSize = 0;
+ if (!XzUnpacker_IsStreamWasFinished(dec))
+ res = SZ_ERROR_INPUT_EOF;
+ }
+ else if (!decodingTruncated || finishMode) // (status == CODER_STATUS_NOT_FINISHED)
+ res = SZ_ERROR_DATA;
+ }
+ else if (res == SZ_ERROR_NO_ARCHIVE)
+ {
+ /*
+ SZ_ERROR_NO_ARCHIVE is possible for 2 states:
+ XZ_STATE_STREAM_HEADER - if bad signature or bad CRC
+ XZ_STATE_STREAM_PADDING - if non-zero padding data
+ extraSize / inProcessed don't include "bad" byte
+ */
+ if (inProcessed != extraSize) // if good streams before error
+ if (extraSize != 0 || readProcessed != inProcessed)
+ {
+ stat->DataAfterEnd = True;
+ // there is some good xz stream before. So we set SZ_OK
+ res = SZ_OK;
+ }
+ }
+
+ stat->DecodeRes = res;
+
+ stat->InSize -= extraSize;
+ return res;
+}
+
+
+SRes XzDecMt_Decode(CXzDecMtHandle pp,
+ const CXzDecMtProps *props,
+ const UInt64 *outDataSize, int finishMode,
+ ISeqOutStream *outStream,
+ // Byte *outBuf, size_t *outBufSize,
+ ISeqInStream *inStream,
+ // const Byte *inData, size_t inDataSize,
+ CXzStatInfo *stat,
+ int *isMT,
+ ICompressProgress *progress)
+{
+ CXzDecMt *p = (CXzDecMt *)pp;
+ #ifndef _7ZIP_ST
+ Bool tMode;
+ #endif
+
+ XzStatInfo_Clear(stat);
+
+ p->props = *props;
+
+ p->inStream = inStream;
+ p->outStream = outStream;
+ p->progress = progress;
+ // p->stat = stat;
+
+ p->outSize = 0;
+ p->outSize_Defined = False;
+ if (outDataSize)
+ {
+ p->outSize_Defined = True;
+ p->outSize = *outDataSize;
+ }
+
+ p->finishMode = finishMode;
+
+ // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
+
+ p->writeRes = SZ_OK;
+ p->outProcessed = 0;
+ p->inProcessed = 0;
+ p->readProcessed = 0;
+ p->readWasFinished = False;
+
+ p->codeRes = 0;
+ p->status = CODER_STATUS_NOT_SPECIFIED;
+
+ if (!p->dec_created)
+ {
+ XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);
+ p->dec_created = True;
+ }
+ XzUnpacker_Init(&p->dec);
+
+
+ *isMT = False;
+
+ /*
+ p->outBuf = NULL;
+ p->outBufSize = 0;
+ if (!outStream)
+ {
+ p->outBuf = outBuf;
+ p->outBufSize = *outBufSize;
+ *outBufSize = 0;
+ }
+ */
+
+
+ #ifndef _7ZIP_ST
+
+ p->isBlockHeaderState_Parse = False;
+ p->isBlockHeaderState_Write = False;
+ // p->numBadBlocks = 0;
+ p->mainErrorCode = SZ_OK;
+ p->mainDecoderWasCalled = False;
+
+ tMode = False;
+
+ if (p->props.numThreads > 1)
+ {
+ IMtDecCallback vt;
+
+ XzDecMt_FreeSt(p);
+
+ p->outProcessed_Parse = 0;
+ p->parsing_Truncated = False;
+
+ p->numStreams = 0;
+ p->numTotalBlocks = 0;
+ p->numBlocks = 0;
+ p->finishedDecoderIndex = -1;
+
+ if (!p->mtc_WasConstructed)
+ {
+ p->mtc_WasConstructed = True;
+ MtDec_Construct(&p->mtc);
+ }
+
+ p->mtc.mtCallback = &vt;
+ p->mtc.mtCallbackObject = p;
+
+ p->mtc.progress = progress;
+ p->mtc.inStream = inStream;
+ p->mtc.alloc = &p->alignOffsetAlloc.vt;
+ // p->mtc.inData = inData;
+ // p->mtc.inDataSize = inDataSize;
+ p->mtc.inBufSize = p->props.inBufSize_MT;
+ // p->mtc.inBlockMax = p->props.inBlockMax;
+ p->mtc.numThreadsMax = p->props.numThreads;
+
+ *isMT = True;
+
+ vt.Parse = XzDecMt_Callback_Parse;
+ vt.PreCode = XzDecMt_Callback_PreCode;
+ vt.Code = XzDecMt_Callback_Code;
+ vt.Write = XzDecMt_Callback_Write;
+
+ {
+ Bool needContinue;
+
+ SRes res = MtDec_Code(&p->mtc);
+
+ stat->InSize = p->mtc.inProcessed;
+
+ p->inProcessed = p->mtc.inProcessed;
+ p->readRes = p->mtc.readRes;
+ p->readWasFinished = p->mtc.readWasFinished;
+ p->readProcessed = p->mtc.readProcessed;
+
+ tMode = True;
+ needContinue = False;
+
+ if (res == SZ_OK)
+ {
+ if (p->mtc.mtProgress.res != SZ_OK)
+ {
+ res = p->mtc.mtProgress.res;
+ stat->ProgressRes = res;
+ stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
+ }
+ else
+ needContinue = p->mtc.needContinue;
+ }
+
+ if (!needContinue)
+ {
+ SRes codeRes;
+ Bool truncated = False;
+ ECoderStatus status;
+ CXzUnpacker *dec;
+
+ stat->OutSize = p->outProcessed;
+
+ if (p->finishedDecoderIndex >= 0)
+ {
+ CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];
+ codeRes = coder->codeRes;
+ dec = &coder->dec;
+ status = coder->status;
+ }
+ else if (p->mainDecoderWasCalled)
+ {
+ codeRes = p->codeRes;
+ dec = &p->dec;
+ status = p->status;
+ truncated = p->parsing_Truncated;
+ }
+ else
+ return E_FAIL;
+
+ XzStatInfo_SetStat(dec, p->finishMode,
+ p->mtc.readProcessed, p->mtc.inProcessed,
+ codeRes, status,
+ truncated,
+ stat);
+
+ if (res == SZ_OK)
+ {
+ if (p->writeRes != SZ_OK)
+ {
+ res = p->writeRes;
+ stat->CombinedRes_Type = SZ_ERROR_WRITE;
+ }
+ else if (p->mtc.readRes != SZ_OK && p->mtc.inProcessed == p->mtc.readProcessed)
+ {
+ res = p->mtc.readRes;
+ stat->ReadRes = res;
+ stat->CombinedRes_Type = SZ_ERROR_READ;
+ }
+ else if (p->mainErrorCode != SZ_OK)
+ {
+ res = p->mainErrorCode;
+ }
+ }
+
+ stat->CombinedRes = res;
+ if (stat->CombinedRes_Type == SZ_OK)
+ stat->CombinedRes_Type = res;
+ return res;
+ }
+
+ PRF_STR("----- decoding ST -----");
+ }
+ }
+
+ #endif
+
+
+ *isMT = False;
+
+ {
+ SRes res = XzDecMt_Decode_ST(p
+ #ifndef _7ZIP_ST
+ , tMode
+ #endif
+ , stat
+ );
+
+ XzStatInfo_SetStat(&p->dec,
+ p->finishMode,
+ p->readProcessed, p->inProcessed,
+ p->codeRes, p->status,
+ False, // truncated
+ stat);
+
+ if (res == SZ_OK)
+ {
+ /*
+ if (p->writeRes != SZ_OK)
+ {
+ res = p->writeRes;
+ stat->CombinedRes_Type = SZ_ERROR_WRITE;
+ }
+ else
+ */
+ if (p->readRes != SZ_OK && p->inProcessed == p->readProcessed)
+ {
+ res = p->readRes;
+ stat->ReadRes = res;
+ stat->CombinedRes_Type = SZ_ERROR_READ;
+ }
+ #ifndef _7ZIP_ST
+ else if (p->mainErrorCode != SZ_OK)
+ res = p->mainErrorCode;
+ #endif
+ }
+
+ stat->CombinedRes = res;
+ if (stat->CombinedRes_Type == SZ_OK)
+ stat->CombinedRes_Type = res;
+ return res;
+ }
+}
diff --git a/C/XzEnc.c b/C/XzEnc.c
index 2e5a003..432cbfe 100644
--- a/C/XzEnc.c
+++ b/C/XzEnc.c
@@ -1,5 +1,5 @@
/* XzEnc.c -- Xz Encode
-2015-09-16 : Igor Pavlov : Public domain */
+2018-04-28 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -7,7 +7,6 @@
#include <string.h>
#include "7zCrc.h"
-#include "Alloc.h"
#include "Bra.h"
#include "CpuArch.h"
@@ -19,22 +18,41 @@
#include "XzEnc.h"
+// #define _7ZIP_ST
+
+#ifndef _7ZIP_ST
+#include "MtCoder.h"
+#else
+#define MTCODER__THREADS_MAX 1
+#define MTCODER__BLOCKS_MAX 1
+#endif
+
+#define XZ_GET_PAD_SIZE(dataSize) ((4 - ((unsigned)(dataSize) & 3)) & 3)
+
+/* max pack size for LZMA2 block + check-64bytrs: */
+#define XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize) ((unpackSize) + ((unpackSize) >> 10) + 16 + 64)
+
+#define XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(unpackSize) (XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize))
+
+
#define XzBlock_ClearFlags(p) (p)->flags = 0;
#define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1);
#define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE;
#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE;
-static SRes WriteBytes(ISeqOutStream *s, const void *buf, UInt32 size)
+
+static SRes WriteBytes(ISeqOutStream *s, const void *buf, size_t size)
{
- return (s->Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE;
+ return (ISeqOutStream_Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE;
}
-static SRes WriteBytesAndCrc(ISeqOutStream *s, const void *buf, UInt32 size, UInt32 *crc)
+static SRes WriteBytesUpdateCrc(ISeqOutStream *s, const void *buf, size_t size, UInt32 *crc)
{
*crc = CrcUpdate(*crc, buf, size);
return WriteBytes(s, buf, size);
}
+
static SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)
{
UInt32 crc;
@@ -78,98 +96,154 @@ static SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
}
-static SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
+
+
+typedef struct
{
- Byte buf[32];
- UInt64 globalPos;
- {
- UInt32 crc = CRC_INIT_VAL;
- unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks);
- size_t i;
+ size_t numBlocks;
+ size_t size;
+ size_t allocated;
+ Byte *blocks;
+} CXzEncIndex;
- globalPos = pos;
- buf[0] = 0;
- RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
- for (i = 0; i < p->numBlocks; i++)
- {
- const CXzBlockSizes *block = &p->blocks[i];
- pos = Xz_WriteVarInt(buf, block->totalSize);
- pos += Xz_WriteVarInt(buf + pos, block->unpackSize);
- globalPos += pos;
- RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
- }
-
- pos = ((unsigned)globalPos & 3);
-
- if (pos != 0)
- {
- buf[0] = buf[1] = buf[2] = 0;
- RINOK(WriteBytesAndCrc(s, buf, 4 - pos, &crc));
- globalPos += 4 - pos;
- }
- {
- SetUi32(buf, CRC_GET_DIGEST(crc));
- RINOK(WriteBytes(s, buf, 4));
- globalPos += 4;
- }
- }
+static void XzEncIndex_Construct(CXzEncIndex *p)
+{
+ p->numBlocks = 0;
+ p->size = 0;
+ p->allocated = 0;
+ p->blocks = NULL;
+}
+static void XzEncIndex_Init(CXzEncIndex *p)
+{
+ p->numBlocks = 0;
+ p->size = 0;
+}
+
+static void XzEncIndex_Free(CXzEncIndex *p, ISzAllocPtr alloc)
+{
+ if (p->blocks)
{
- UInt32 indexSize = (UInt32)((globalPos >> 2) - 1);
- SetUi32(buf + 4, indexSize);
- buf[8] = (Byte)(p->flags >> 8);
- buf[9] = (Byte)(p->flags & 0xFF);
- SetUi32(buf, CrcCalc(buf + 4, 6));
- memcpy(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE);
- return WriteBytes(s, buf, 12);
+ ISzAlloc_Free(alloc, p->blocks);
+ p->blocks = NULL;
}
+ p->numBlocks = 0;
+ p->size = 0;
+ p->allocated = 0;
}
-static SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)
+static SRes XzEncIndex_ReAlloc(CXzEncIndex *p, size_t newSize, ISzAllocPtr alloc)
{
- if (!p->blocks || p->numBlocksAllocated == p->numBlocks)
+ Byte *blocks = (Byte *)ISzAlloc_Alloc(alloc, newSize);
+ if (!blocks)
+ return SZ_ERROR_MEM;
+ if (p->size != 0)
+ memcpy(blocks, p->blocks, p->size);
+ if (p->blocks)
+ ISzAlloc_Free(alloc, p->blocks);
+ p->blocks = blocks;
+ p->allocated = newSize;
+ return SZ_OK;
+}
+
+
+static SRes XzEncIndex_PreAlloc(CXzEncIndex *p, UInt64 numBlocks, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc)
+{
+ UInt64 pos;
{
- size_t num = p->numBlocks * 2 + 1;
- size_t newSize = sizeof(CXzBlockSizes) * num;
- CXzBlockSizes *blocks;
- if (newSize / sizeof(CXzBlockSizes) != num)
- return SZ_ERROR_MEM;
- blocks = (CXzBlockSizes *)alloc->Alloc(alloc, newSize);
- if (!blocks)
+ Byte buf[32];
+ unsigned pos2 = Xz_WriteVarInt(buf, totalSize);
+ pos2 += Xz_WriteVarInt(buf + pos2, unpackSize);
+ pos = numBlocks * pos2;
+ }
+
+ if (pos <= p->allocated - p->size)
+ return SZ_OK;
+ {
+ UInt64 newSize64 = p->size + pos;
+ size_t newSize = (size_t)newSize64;
+ if (newSize != newSize64)
return SZ_ERROR_MEM;
- if (p->numBlocks != 0)
- {
- memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes));
- alloc->Free(alloc, p->blocks);
- }
- p->blocks = blocks;
- p->numBlocksAllocated = num;
+ return XzEncIndex_ReAlloc(p, newSize, alloc);
}
+}
+
+
+static SRes XzEncIndex_AddIndexRecord(CXzEncIndex *p, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc)
+{
+ Byte buf[32];
+ unsigned pos = Xz_WriteVarInt(buf, totalSize);
+ pos += Xz_WriteVarInt(buf + pos, unpackSize);
+
+ if (pos > p->allocated - p->size)
{
- CXzBlockSizes *block = &p->blocks[p->numBlocks++];
- block->unpackSize = unpackSize;
- block->totalSize = totalSize;
+ size_t newSize = p->allocated * 2 + 16 * 2;
+ if (newSize < p->size + pos)
+ return SZ_ERROR_MEM;
+ RINOK(XzEncIndex_ReAlloc(p, newSize, alloc));
}
+ memcpy(p->blocks + p->size, buf, pos);
+ p->size += pos;
+ p->numBlocks++;
return SZ_OK;
}
+static SRes XzEncIndex_WriteFooter(const CXzEncIndex *p, CXzStreamFlags flags, ISeqOutStream *s)
+{
+ Byte buf[32];
+ UInt64 globalPos;
+ UInt32 crc = CRC_INIT_VAL;
+ unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks);
+
+ globalPos = pos;
+ buf[0] = 0;
+ RINOK(WriteBytesUpdateCrc(s, buf, pos, &crc));
+ RINOK(WriteBytesUpdateCrc(s, p->blocks, p->size, &crc));
+ globalPos += p->size;
+
+ pos = XZ_GET_PAD_SIZE(globalPos);
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+ globalPos += pos;
+
+ crc = CrcUpdate(crc, buf + 4 - pos, pos);
+ SetUi32(buf + 4, CRC_GET_DIGEST(crc));
+
+ SetUi32(buf + 8 + 4, (UInt32)(globalPos >> 2));
+ buf[8 + 8] = (Byte)(flags >> 8);
+ buf[8 + 9] = (Byte)(flags & 0xFF);
+ SetUi32(buf + 8, CrcCalc(buf + 8 + 4, 6));
+ buf[8 + 10] = XZ_FOOTER_SIG_0;
+ buf[8 + 11] = XZ_FOOTER_SIG_1;
+
+ return WriteBytes(s, buf + 4 - pos, pos + 4 + 12);
+}
+
+
+
/* ---------- CSeqCheckInStream ---------- */
typedef struct
{
- ISeqInStream p;
+ ISeqInStream vt;
ISeqInStream *realStream;
+ const Byte *data;
+ UInt64 limit;
UInt64 processed;
+ int realStreamFinished;
CXzCheck check;
} CSeqCheckInStream;
-static void SeqCheckInStream_Init(CSeqCheckInStream *p, unsigned mode)
+static void SeqCheckInStream_Init(CSeqCheckInStream *p, unsigned checkMode)
{
+ p->limit = (UInt64)(Int64)-1;
p->processed = 0;
- XzCheck_Init(&p->check, mode);
+ p->realStreamFinished = 0;
+ XzCheck_Init(&p->check, checkMode);
}
static void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)
@@ -177,12 +251,31 @@ static void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)
XzCheck_Final(&p->check, digest);
}
-static SRes SeqCheckInStream_Read(void *pp, void *data, size_t *size)
+static SRes SeqCheckInStream_Read(const ISeqInStream *pp, void *data, size_t *size)
{
- CSeqCheckInStream *p = (CSeqCheckInStream *)pp;
- SRes res = p->realStream->Read(p->realStream, data, size);
- XzCheck_Update(&p->check, data, *size);
- p->processed += *size;
+ CSeqCheckInStream *p = CONTAINER_FROM_VTBL(pp, CSeqCheckInStream, 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)
+ {
+ if (p->realStream)
+ {
+ res = ISeqInStream_Read(p->realStream, data, &size2);
+ p->realStreamFinished = (size2 == 0) ? 1 : 0;
+ }
+ else
+ memcpy(data, p->data + (size_t)p->processed, size2);
+ XzCheck_Update(&p->check, data, size2);
+ p->processed += size2;
+ }
+ *size = size2;
return res;
}
@@ -191,15 +284,24 @@ static SRes SeqCheckInStream_Read(void *pp, void *data, size_t *size)
typedef struct
{
- ISeqOutStream p;
+ ISeqOutStream vt;
ISeqOutStream *realStream;
+ Byte *outBuf;
+ size_t outBufLimit;
UInt64 processed;
} CSeqSizeOutStream;
-static size_t MyWrite(void *pp, const void *data, size_t size)
+static size_t SeqSizeOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size)
{
- CSeqSizeOutStream *p = (CSeqSizeOutStream *)pp;
- size = p->realStream->Write(p->realStream, data, size);
+ CSeqSizeOutStream *p = CONTAINER_FROM_VTBL(pp, CSeqSizeOutStream, vt);
+ if (p->realStream)
+ size = ISeqOutStream_Write(p->realStream, data, size);
+ else
+ {
+ if (size > p->outBufLimit - (size_t)p->processed)
+ return 0;
+ memcpy(p->outBuf + (size_t)p->processed, data, size);
+ }
p->processed += size;
return size;
}
@@ -220,9 +322,29 @@ typedef struct
int srcWasFinished;
} CSeqInFilter;
-static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)
+
+SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc);
+
+static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props, ISzAllocPtr alloc)
{
- CSeqInFilter *p = (CSeqInFilter *)pp;
+ if (!p->buf)
+ {
+ p->buf = (Byte *)ISzAlloc_Alloc(alloc, FILTER_BUF_SIZE);
+ if (!p->buf)
+ return SZ_ERROR_MEM;
+ }
+ p->curPos = p->endPos = 0;
+ p->srcWasFinished = 0;
+ RINOK(BraState_SetFromMethod(&p->StateCoder, props->id, 1, alloc));
+ RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, alloc));
+ p->StateCoder.Init(p->StateCoder.p);
+ return SZ_OK;
+}
+
+
+static SRes SeqInFilter_Read(const ISeqInStream *pp, void *data, size_t *size)
+{
+ CSeqInFilter *p = CONTAINER_FROM_VTBL(pp, CSeqInFilter, p);
size_t sizeOriginal = *size;
if (sizeOriginal == 0)
return SZ_OK;
@@ -234,19 +356,22 @@ static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)
{
p->curPos = 0;
p->endPos = FILTER_BUF_SIZE;
- RINOK(p->realStream->Read(p->realStream, p->buf, &p->endPos));
+ RINOK(ISeqInStream_Read(p->realStream, p->buf, &p->endPos));
if (p->endPos == 0)
p->srcWasFinished = 1;
}
{
SizeT srcLen = p->endPos - p->curPos;
- int wasFinished;
+ ECoderStatus status;
SRes res;
*size = sizeOriginal;
- res = p->StateCoder.Code(p->StateCoder.p, data, size, p->buf + p->curPos, &srcLen,
- p->srcWasFinished, CODER_FINISH_ANY, &wasFinished);
+ res = p->StateCoder.Code2(p->StateCoder.p,
+ data, size,
+ p->buf + p->curPos, &srcLen,
+ p->srcWasFinished, CODER_FINISH_ANY,
+ &status);
p->curPos += srcLen;
- if (*size != 0 || srcLen == 0 || res != 0)
+ if (*size != 0 || srcLen == 0 || res != SZ_OK)
return res;
}
}
@@ -255,34 +380,22 @@ static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)
static void SeqInFilter_Construct(CSeqInFilter *p)
{
p->buf = NULL;
+ p->StateCoder.p = NULL;
p->p.Read = SeqInFilter_Read;
}
-static void SeqInFilter_Free(CSeqInFilter *p)
+static void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc)
{
- if (p->buf)
+ if (p->StateCoder.p)
{
- g_Alloc.Free(&g_Alloc, p->buf);
- p->buf = NULL;
+ p->StateCoder.Free(p->StateCoder.p, alloc);
+ p->StateCoder.p = NULL;
}
-}
-
-SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc);
-
-static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props)
-{
- if (!p->buf)
+ if (p->buf)
{
- p->buf = g_Alloc.Alloc(&g_Alloc, FILTER_BUF_SIZE);
- if (!p->buf)
- return SZ_ERROR_MEM;
+ ISzAlloc_Free(alloc, p->buf);
+ p->buf = NULL;
}
- p->curPos = p->endPos = 0;
- p->srcWasFinished = 0;
- RINOK(BraState_SetFromMethod(&p->StateCoder, props->id, 1, &g_Alloc));
- RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, &g_Alloc));
- p->StateCoder.Init(p->StateCoder.p);
- return SZ_OK;
}
@@ -292,17 +405,17 @@ static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props)
typedef struct
{
- ISeqInStream p;
+ ISeqInStream vt;
ISeqInStream *inStream;
CSbEnc enc;
} CSbEncInStream;
-static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)
+static SRes SbEncInStream_Read(const ISeqInStream *pp, void *data, size_t *size)
{
- CSbEncInStream *p = (CSbEncInStream *)pp;
+ CSbEncInStream *p = CONTAINER_FROM_VTBL(pp, CSbEncInStream, vt);
size_t sizeOriginal = *size;
if (sizeOriginal == 0)
- return S_OK;
+ return SZ_OK;
for (;;)
{
@@ -322,14 +435,14 @@ static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)
*size = sizeOriginal;
RINOK(SbEnc_Read(&p->enc, data, size));
if (*size != 0 || !p->enc.needRead)
- return S_OK;
+ return SZ_OK;
}
}
-void SbEncInStream_Construct(CSbEncInStream *p, ISzAlloc *alloc)
+void SbEncInStream_Construct(CSbEncInStream *p, ISzAllocPtr alloc)
{
SbEnc_Construct(&p->enc, alloc);
- p->p.Read = SbEncInStream_Read;
+ p->vt.Read = SbEncInStream_Read;
}
SRes SbEncInStream_Init(CSbEncInStream *p)
@@ -345,43 +458,233 @@ void SbEncInStream_Free(CSbEncInStream *p)
#endif
+
+/* ---------- CXzProps ---------- */
+
+
+void XzFilterProps_Init(CXzFilterProps *p)
+{
+ p->id = 0;
+ p->delta = 0;
+ p->ip = 0;
+ p->ipDefined = False;
+}
+
+void XzProps_Init(CXzProps *p)
+{
+ p->checkId = XZ_CHECK_CRC32;
+ p->blockSize = XZ_PROPS__BLOCK_SIZE__AUTO;
+ p->numBlockThreads_Reduced = -1;
+ p->numBlockThreads_Max = -1;
+ p->numTotalThreads = -1;
+ p->reduceSize = (UInt64)(Int64)-1;
+ p->forceWriteSizesInHeader = 0;
+ // p->forceWriteSizesInHeader = 1;
+
+ XzFilterProps_Init(&p->filterProps);
+ Lzma2EncProps_Init(&p->lzma2Props);
+}
+
+
+static void XzEncProps_Normalize_Fixed(CXzProps *p)
+{
+ UInt64 fileSize;
+ int t1, t1n, t2, t2r, t3;
+ {
+ CLzma2EncProps tp = p->lzma2Props;
+ if (tp.numTotalThreads <= 0)
+ tp.numTotalThreads = p->numTotalThreads;
+ Lzma2EncProps_Normalize(&tp);
+ t1n = tp.numTotalThreads;
+ }
+
+ t1 = p->lzma2Props.numTotalThreads;
+ 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->lzma2Props.numTotalThreads = t1;
+
+ t2r = t2;
+
+ fileSize = p->reduceSize;
+
+ if ((p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))
+ p->lzma2Props.lzmaProps.reduceSize = p->blockSize;
+
+ Lzma2EncProps_Normalize(&p->lzma2Props);
+
+ t1 = p->lzma2Props.numTotalThreads;
+
+ {
+ 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 void XzProps_Normalize(CXzProps *p)
+{
+ /* we normalize xzProps properties, but we normalize only some of CXzProps::lzma2Props properties.
+ Lzma2Enc_SetProps() will normalize lzma2Props later. */
+
+ if (p->blockSize == XZ_PROPS__BLOCK_SIZE__SOLID)
+ {
+ p->lzma2Props.lzmaProps.reduceSize = p->reduceSize;
+ p->numBlockThreads_Reduced = 1;
+ p->numBlockThreads_Max = 1;
+ if (p->lzma2Props.numTotalThreads <= 0)
+ p->lzma2Props.numTotalThreads = p->numTotalThreads;
+ return;
+ }
+ else
+ {
+ CLzma2EncProps *lzma2 = &p->lzma2Props;
+ if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO)
+ {
+ // xz-auto
+ p->lzma2Props.lzmaProps.reduceSize = p->reduceSize;
+
+ if (lzma2->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID)
+ {
+ // if (xz-auto && lzma2-solid) - we use solid for both
+ p->blockSize = XZ_PROPS__BLOCK_SIZE__SOLID;
+ p->numBlockThreads_Reduced = 1;
+ p->numBlockThreads_Max = 1;
+ if (p->lzma2Props.numTotalThreads <= 0)
+ p->lzma2Props.numTotalThreads = p->numTotalThreads;
+ }
+ else
+ {
+ // if (xz-auto && (lzma2-auto || lzma2-fixed_)
+ // we calculate block size for lzma2 and use that block size for xz, lzma2 uses single-chunk per block
+ CLzma2EncProps tp = p->lzma2Props;
+ if (tp.numTotalThreads <= 0)
+ tp.numTotalThreads = p->numTotalThreads;
+
+ Lzma2EncProps_Normalize(&tp);
+
+ p->blockSize = tp.blockSize; // fixed or solid
+ p->numBlockThreads_Reduced = tp.numBlockThreads_Reduced;
+ p->numBlockThreads_Max = tp.numBlockThreads_Max;
+ if (lzma2->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO)
+ lzma2->blockSize = tp.blockSize; // fixed or solid, LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
+ if (lzma2->lzmaProps.reduceSize > tp.blockSize && tp.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID)
+ lzma2->lzmaProps.reduceSize = tp.blockSize;
+ lzma2->numBlockThreads_Reduced = 1;
+ lzma2->numBlockThreads_Max = 1;
+ return;
+ }
+ }
+ else
+ {
+ // xz-fixed
+ // we can use xz::reduceSize or xz::blockSize as base for lzmaProps::reduceSize
+
+ p->lzma2Props.lzmaProps.reduceSize = p->reduceSize;
+ {
+ UInt64 r = p->reduceSize;
+ if (r > p->blockSize || r == (UInt64)(Int64)-1)
+ r = p->blockSize;
+ lzma2->lzmaProps.reduceSize = r;
+ }
+ if (lzma2->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO)
+ lzma2->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID;
+ else if (lzma2->blockSize > p->blockSize && lzma2->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID)
+ lzma2->blockSize = p->blockSize;
+
+ XzEncProps_Normalize_Fixed(p);
+ }
+ }
+}
+
+
+/* ---------- CLzma2WithFilters ---------- */
+
typedef struct
{
CLzma2EncHandle lzma2;
+ CSeqInFilter filter;
+
#ifdef USE_SUBBLOCK
CSbEncInStream sb;
#endif
- CSeqInFilter filter;
- ISzAlloc *alloc;
- ISzAlloc *bigAlloc;
} CLzma2WithFilters;
-static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, ISzAlloc *bigAlloc)
+static void Lzma2WithFilters_Construct(CLzma2WithFilters *p)
{
- p->alloc = alloc;
- p->bigAlloc = bigAlloc;
p->lzma2 = NULL;
+ SeqInFilter_Construct(&p->filter);
+
#ifdef USE_SUBBLOCK
SbEncInStream_Construct(&p->sb, alloc);
#endif
- SeqInFilter_Construct(&p->filter);
}
-static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)
+
+static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p, ISzAllocPtr alloc, ISzAllocPtr bigAlloc)
{
- p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc);
if (!p->lzma2)
- return SZ_ERROR_MEM;
+ {
+ p->lzma2 = Lzma2Enc_Create(alloc, bigAlloc);
+ if (!p->lzma2)
+ return SZ_ERROR_MEM;
+ }
return SZ_OK;
}
-static void Lzma2WithFilters_Free(CLzma2WithFilters *p)
+
+static void Lzma2WithFilters_Free(CLzma2WithFilters *p, ISzAllocPtr alloc)
{
- SeqInFilter_Free(&p->filter);
#ifdef USE_SUBBLOCK
SbEncInStream_Free(&p->sb);
#endif
+
+ SeqInFilter_Free(&p->filter, alloc);
if (p->lzma2)
{
Lzma2Enc_Destroy(p->lzma2);
@@ -390,137 +693,625 @@ static void Lzma2WithFilters_Free(CLzma2WithFilters *p)
}
-void XzProps_Init(CXzProps *p)
+typedef struct
{
- p->lzma2Props = NULL;
- p->filterProps = NULL;
- p->checkId = XZ_CHECK_CRC32;
+ UInt64 unpackSize;
+ UInt64 totalSize;
+ size_t headerSize;
+} CXzEncBlockInfo;
+
+
+static SRes Xz_CompressBlock(
+ CLzma2WithFilters *lzmaf,
+
+ ISeqOutStream *outStream,
+ Byte *outBufHeader,
+ Byte *outBufData, size_t outBufDataLimit,
+
+ ISeqInStream *inStream,
+ // UInt64 expectedSize,
+ const Byte *inBuf, // used if (!inStream)
+ size_t inBufSize, // used if (!inStream), it's block size, props->blockSize is ignored
+
+ const CXzProps *props,
+ ICompressProgress *progress,
+ int *inStreamFinished, /* only for inStream version */
+ CXzEncBlockInfo *blockSizes,
+ ISzAllocPtr alloc,
+ ISzAllocPtr allocBig)
+{
+ CSeqCheckInStream checkInStream;
+ CSeqSizeOutStream seqSizeOutStream;
+ CXzBlock block;
+ unsigned filterIndex = 0;
+ CXzFilter *filter = NULL;
+ const CXzFilterProps *fp = &props->filterProps;
+ if (fp->id == 0)
+ fp = NULL;
+
+ *inStreamFinished = False;
+
+ RINOK(Lzma2WithFilters_Create(lzmaf, alloc, allocBig));
+
+ RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, &props->lzma2Props));
+
+ XzBlock_ClearFlags(&block);
+ XzBlock_SetNumFilters(&block, 1 + (fp ? 1 : 0));
+
+ if (fp)
+ {
+ filter = &block.filters[filterIndex++];
+ filter->id = fp->id;
+ filter->propsSize = 0;
+
+ if (fp->id == XZ_ID_Delta)
+ {
+ filter->props[0] = (Byte)(fp->delta - 1);
+ filter->propsSize = 1;
+ }
+ else if (fp->ipDefined)
+ {
+ SetUi32(filter->props, fp->ip);
+ filter->propsSize = 4;
+ }
+ }
+
+ {
+ CXzFilter *f = &block.filters[filterIndex++];
+ f->id = XZ_ID_LZMA2;
+ f->propsSize = 1;
+ f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2);
+ }
+
+ seqSizeOutStream.vt.Write = SeqSizeOutStream_Write;
+ seqSizeOutStream.realStream = outStream;
+ seqSizeOutStream.outBuf = outBufData;
+ seqSizeOutStream.outBufLimit = outBufDataLimit;
+ seqSizeOutStream.processed = 0;
+
+ /*
+ if (expectedSize != (UInt64)(Int64)-1)
+ {
+ block.unpackSize = expectedSize;
+ if (props->blockSize != (UInt64)(Int64)-1)
+ if (expectedSize > props->blockSize)
+ block.unpackSize = props->blockSize;
+ XzBlock_SetHasUnpackSize(&block);
+ }
+ */
+
+ if (outStream)
+ {
+ RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt));
+ }
+
+ checkInStream.vt.Read = SeqCheckInStream_Read;
+ SeqCheckInStream_Init(&checkInStream, props->checkId);
+
+ checkInStream.realStream = inStream;
+ checkInStream.data = inBuf;
+ checkInStream.limit = props->blockSize;
+ if (!inStream)
+ checkInStream.limit = inBufSize;
+
+ if (fp)
+ {
+ #ifdef USE_SUBBLOCK
+ if (fp->id == XZ_ID_Subblock)
+ {
+ lzmaf->sb.inStream = &checkInStream.vt;
+ RINOK(SbEncInStream_Init(&lzmaf->sb));
+ }
+ else
+ #endif
+ {
+ lzmaf->filter.realStream = &checkInStream.vt;
+ RINOK(SeqInFilter_Init(&lzmaf->filter, filter, alloc));
+ }
+ }
+
+ {
+ SRes res;
+ Byte *outBuf = NULL;
+ size_t outSize = 0;
+ Bool useStream = (fp || inStream);
+ // useStream = True;
+
+ if (!useStream)
+ {
+ XzCheck_Update(&checkInStream.check, inBuf, inBufSize);
+ checkInStream.processed = inBufSize;
+ }
+
+ if (!outStream)
+ {
+ outBuf = seqSizeOutStream.outBuf; // + (size_t)seqSizeOutStream.processed;
+ outSize = seqSizeOutStream.outBufLimit; // - (size_t)seqSizeOutStream.processed;
+ }
+
+ res = Lzma2Enc_Encode2(lzmaf->lzma2,
+ outBuf ? NULL : &seqSizeOutStream.vt,
+ outBuf,
+ outBuf ? &outSize : NULL,
+
+ useStream ?
+ (fp ?
+ (
+ #ifdef USE_SUBBLOCK
+ (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.vt:
+ #endif
+ &lzmaf->filter.p) :
+ &checkInStream.vt) : NULL,
+
+ useStream ? NULL : inBuf,
+ useStream ? 0 : inBufSize,
+
+ progress);
+
+ if (outBuf)
+ seqSizeOutStream.processed += outSize;
+
+ RINOK(res);
+ blockSizes->unpackSize = checkInStream.processed;
+ }
+ {
+ Byte buf[4 + 64];
+ unsigned padSize = XZ_GET_PAD_SIZE(seqSizeOutStream.processed);
+ UInt64 packSize = seqSizeOutStream.processed;
+
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+
+ SeqCheckInStream_GetDigest(&checkInStream, buf + 4);
+ RINOK(WriteBytes(&seqSizeOutStream.vt, buf + (4 - padSize), padSize + XzFlags_GetCheckSize((CXzStreamFlags)props->checkId)));
+
+ blockSizes->totalSize = seqSizeOutStream.processed - padSize;
+
+ if (!outStream)
+ {
+ seqSizeOutStream.outBuf = outBufHeader;
+ seqSizeOutStream.outBufLimit = XZ_BLOCK_HEADER_SIZE_MAX;
+ seqSizeOutStream.processed = 0;
+
+ block.unpackSize = blockSizes->unpackSize;
+ XzBlock_SetHasUnpackSize(&block);
+
+ block.packSize = packSize;
+ XzBlock_SetHasPackSize(&block);
+
+ RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt));
+
+ blockSizes->headerSize = (size_t)seqSizeOutStream.processed;
+ blockSizes->totalSize += seqSizeOutStream.processed;
+ }
+ }
+
+ if (inStream)
+ *inStreamFinished = checkInStream.realStreamFinished;
+ else
+ {
+ *inStreamFinished = False;
+ if (checkInStream.processed != inBufSize)
+ return SZ_ERROR_FAIL;
+ }
+
+ return SZ_OK;
}
-void XzFilterProps_Init(CXzFilterProps *p)
+
+
+typedef struct
{
- p->id = 0;
- p->delta = 0;
- p->ip = 0;
- p->ipDefined = False;
+ ICompressProgress vt;
+ ICompressProgress *progress;
+ UInt64 inOffset;
+ UInt64 outOffset;
+} CCompressProgress_XzEncOffset;
+
+
+static SRes CompressProgress_XzEncOffset_Progress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize)
+{
+ const CCompressProgress_XzEncOffset *p = CONTAINER_FROM_VTBL(pp, CCompressProgress_XzEncOffset, vt);
+ inSize += p->inOffset;
+ outSize += p->outOffset;
+ return ICompressProgress_Progress(p->progress, inSize, outSize);
}
-static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
- ISeqOutStream *outStream, ISeqInStream *inStream,
- const CXzProps *props, ICompressProgress *progress)
+
+
+typedef struct
{
- xz->flags = (Byte)props->checkId;
+ ISzAllocPtr alloc;
+ ISzAllocPtr allocBig;
+
+ CXzProps xzProps;
+ UInt64 expectedDataSize;
- RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, props->lzma2Props));
- RINOK(Xz_WriteHeader(xz->flags, outStream));
+ CXzEncIndex xzIndex;
+ CLzma2WithFilters lzmaf_Items[MTCODER__THREADS_MAX];
+
+ size_t outBufSize; /* size of allocated outBufs[i] */
+ Byte *outBufs[MTCODER__BLOCKS_MAX];
+
+ #ifndef _7ZIP_ST
+ unsigned checkType;
+ ISeqOutStream *outStream;
+ Bool mtCoder_WasConstructed;
+ CMtCoder mtCoder;
+ CXzEncBlockInfo EncBlocks[MTCODER__BLOCKS_MAX];
+ #endif
+
+} CXzEnc;
+
+
+static void XzEnc_Construct(CXzEnc *p)
+{
+ unsigned i;
+
+ XzEncIndex_Construct(&p->xzIndex);
+
+ for (i = 0; i < MTCODER__THREADS_MAX; i++)
+ Lzma2WithFilters_Construct(&p->lzmaf_Items[i]);
+
+ #ifndef _7ZIP_ST
+ p->mtCoder_WasConstructed = False;
{
- CSeqCheckInStream checkInStream;
- CSeqSizeOutStream seqSizeOutStream;
- CXzBlock block;
- unsigned filterIndex = 0;
- CXzFilter *filter = NULL;
- const CXzFilterProps *fp = props->filterProps;
+ for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
+ p->outBufs[i] = NULL;
+ p->outBufSize = 0;
+ }
+ #endif
+}
+
+
+static void XzEnc_FreeOutBufs(CXzEnc *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;
+}
+
+
+static void XzEnc_Free(CXzEnc *p, ISzAllocPtr alloc)
+{
+ unsigned i;
+
+ XzEncIndex_Free(&p->xzIndex, alloc);
+
+ for (i = 0; i < MTCODER__THREADS_MAX; i++)
+ Lzma2WithFilters_Free(&p->lzmaf_Items[i], alloc);
+
+ #ifndef _7ZIP_ST
+ if (p->mtCoder_WasConstructed)
+ {
+ MtCoder_Destruct(&p->mtCoder);
+ p->mtCoder_WasConstructed = False;
+ }
+ XzEnc_FreeOutBufs(p);
+ #endif
+}
+
+
+CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)
+{
+ CXzEnc *p = (CXzEnc *)ISzAlloc_Alloc(alloc, sizeof(CXzEnc));
+ if (!p)
+ return NULL;
+ XzEnc_Construct(p);
+ XzProps_Init(&p->xzProps);
+ XzProps_Normalize(&p->xzProps);
+ p->expectedDataSize = (UInt64)(Int64)-1;
+ p->alloc = alloc;
+ p->allocBig = allocBig;
+ return p;
+}
+
+
+void XzEnc_Destroy(CXzEncHandle pp)
+{
+ CXzEnc *p = (CXzEnc *)pp;
+ XzEnc_Free(p, p->alloc);
+ ISzAlloc_Free(p->alloc, p);
+}
+
+
+SRes XzEnc_SetProps(CXzEncHandle pp, const CXzProps *props)
+{
+ CXzEnc *p = (CXzEnc *)pp;
+ p->xzProps = *props;
+ XzProps_Normalize(&p->xzProps);
+ return SZ_OK;
+}
+
+
+void XzEnc_SetDataSize(CXzEncHandle pp, UInt64 expectedDataSiize)
+{
+ CXzEnc *p = (CXzEnc *)pp;
+ p->expectedDataSize = expectedDataSiize;
+}
+
+
+
+
+#ifndef _7ZIP_ST
+
+static SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex,
+ const Byte *src, size_t srcSize, int finished)
+{
+ CXzEnc *me = (CXzEnc *)pp;
+ SRes res;
+ CMtProgressThunk progressThunk;
+
+ Byte *dest = me->outBufs[outBufIndex];
+
+ UNUSED_VAR(finished)
+
+ {
+ CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex];
+ bInfo->totalSize = 0;
+ bInfo->unpackSize = 0;
+ bInfo->headerSize = 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;
+ MtProgressThunk_Init(&progressThunk);
+
+ {
+ CXzEncBlockInfo blockSizes;
+ int inStreamFinished;
+
+ res = Xz_CompressBlock(
+ &me->lzmaf_Items[coderIndex],
+
+ NULL,
+ dest,
+ dest + XZ_BLOCK_HEADER_SIZE_MAX, me->outBufSize - XZ_BLOCK_HEADER_SIZE_MAX,
+
+ NULL,
+ // srcSize, // expectedSize
+ src, srcSize,
+
+ &me->xzProps,
+ &progressThunk.vt,
+ &inStreamFinished,
+ &blockSizes,
+ me->alloc,
+ me->allocBig);
- XzBlock_ClearFlags(&block);
- XzBlock_SetNumFilters(&block, 1 + (fp ? 1 : 0));
+ if (res == SZ_OK)
+ me->EncBlocks[outBufIndex] = blockSizes;
+
+ return res;
+ }
+}
+
+
+static SRes XzEnc_MtCallback_Write(void *pp, unsigned outBufIndex)
+{
+ CXzEnc *me = (CXzEnc *)pp;
+
+ const CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex];
+ const Byte *data = me->outBufs[outBufIndex];
+
+ RINOK(WriteBytes(me->outStream, data, bInfo->headerSize));
+
+ {
+ UInt64 totalPackFull = bInfo->totalSize + XZ_GET_PAD_SIZE(bInfo->totalSize);
+ RINOK(WriteBytes(me->outStream, data + XZ_BLOCK_HEADER_SIZE_MAX, (size_t)totalPackFull - bInfo->headerSize));
+ }
+
+ return XzEncIndex_AddIndexRecord(&me->xzIndex, bInfo->unpackSize, bInfo->totalSize, me->alloc);
+}
+
+#endif
+
+
+
+SRes XzEnc_Encode(CXzEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
+{
+ CXzEnc *p = (CXzEnc *)pp;
+
+ const CXzProps *props = &p->xzProps;
+
+ XzEncIndex_Init(&p->xzIndex);
+ {
+ UInt64 numBlocks = 1;
+ UInt64 blockSize = props->blockSize;
- if (fp)
+ if (blockSize != XZ_PROPS__BLOCK_SIZE__SOLID
+ && props->reduceSize != (UInt64)(Int64)-1)
{
- filter = &block.filters[filterIndex++];
- filter->id = fp->id;
- filter->propsSize = 0;
-
- if (fp->id == XZ_ID_Delta)
- {
- filter->props[0] = (Byte)(fp->delta - 1);
- filter->propsSize = 1;
- }
- else if (fp->ipDefined)
- {
- SetUi32(filter->props, fp->ip);
- filter->propsSize = 4;
- }
+ numBlocks = props->reduceSize / blockSize;
+ if (numBlocks * blockSize != props->reduceSize)
+ numBlocks++;
+ }
+ else
+ blockSize = (UInt64)1 << 62;
+
+ RINOK(XzEncIndex_PreAlloc(&p->xzIndex, numBlocks, blockSize, XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(blockSize), p->alloc));
+ }
+
+ RINOK(Xz_WriteHeader((CXzStreamFlags)props->checkId, outStream));
+
+
+ #ifndef _7ZIP_ST
+ if (props->numBlockThreads_Reduced > 1)
+ {
+ IMtCoderCallback2 vt;
+
+ if (!p->mtCoder_WasConstructed)
+ {
+ p->mtCoder_WasConstructed = True;
+ MtCoder_Construct(&p->mtCoder);
}
+ vt.Code = XzEnc_MtCallback_Code;
+ vt.Write = XzEnc_MtCallback_Write;
+
+ p->checkType = props->checkId;
+ p->xzProps = *props;
+
+ p->outStream = outStream;
+
+ p->mtCoder.allocBig = p->allocBig;
+ p->mtCoder.progress = progress;
+ p->mtCoder.inStream = inStream;
+ p->mtCoder.inData = NULL;
+ p->mtCoder.inDataSize = 0;
+ p->mtCoder.mtCallback = &vt;
+ p->mtCoder.mtCallbackObject = p;
+
+ if ( props->blockSize == XZ_PROPS__BLOCK_SIZE__SOLID
+ || props->blockSize == XZ_PROPS__BLOCK_SIZE__AUTO)
+ return SZ_ERROR_FAIL;
+
+ p->mtCoder.blockSize = (size_t)props->blockSize;
+ if (p->mtCoder.blockSize != props->blockSize)
+ return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */
+
{
- CXzFilter *f = &block.filters[filterIndex++];
- f->id = XZ_ID_LZMA2;
- f->propsSize = 1;
- f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2);
+ size_t destBlockSize = XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(p->mtCoder.blockSize);
+ if (destBlockSize < p->mtCoder.blockSize)
+ return SZ_ERROR_PARAM;
+ if (p->outBufSize != destBlockSize)
+ XzEnc_FreeOutBufs(p);
+ p->outBufSize = destBlockSize;
}
- seqSizeOutStream.p.Write = MyWrite;
- seqSizeOutStream.realStream = outStream;
- seqSizeOutStream.processed = 0;
+ p->mtCoder.numThreadsMax = props->numBlockThreads_Max;
+ p->mtCoder.expectedDataSize = p->expectedDataSize;
- RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.p));
+ RINOK(MtCoder_Code(&p->mtCoder));
+ }
+ else
+ #endif
+ {
+ int writeStartSizes;
+ CCompressProgress_XzEncOffset progress2;
+ Byte *bufData = NULL;
+ size_t bufSize = 0;
+
+ progress2.vt.Progress = CompressProgress_XzEncOffset_Progress;
+ progress2.inOffset = 0;
+ progress2.outOffset = 0;
+ progress2.progress = progress;
- checkInStream.p.Read = SeqCheckInStream_Read;
- checkInStream.realStream = inStream;
- SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags));
+ writeStartSizes = 0;
- if (fp)
+ if (props->blockSize != XZ_PROPS__BLOCK_SIZE__SOLID)
{
- #ifdef USE_SUBBLOCK
- if (fp->id == XZ_ID_Subblock)
- {
- lzmaf->sb.inStream = &checkInStream.p;
- RINOK(SbEncInStream_Init(&lzmaf->sb));
- }
- else
- #endif
+ writeStartSizes = (props->forceWriteSizesInHeader > 0);
+
+ if (writeStartSizes)
{
- lzmaf->filter.realStream = &checkInStream.p;
- RINOK(SeqInFilter_Init(&lzmaf->filter, filter));
+ size_t t2;
+ size_t t = (size_t)props->blockSize;
+ if (t != props->blockSize)
+ return SZ_ERROR_PARAM;
+ t = XZ_GET_MAX_BLOCK_PACK_SIZE(t);
+ if (t < props->blockSize)
+ return SZ_ERROR_PARAM;
+ t2 = XZ_BLOCK_HEADER_SIZE_MAX + t;
+ if (!p->outBufs[0] || t2 != p->outBufSize)
+ {
+ XzEnc_FreeOutBufs(p);
+ p->outBufs[0] = (Byte *)ISzAlloc_Alloc(p->alloc, t2);
+ if (!p->outBufs[0])
+ return SZ_ERROR_MEM;
+ p->outBufSize = t2;
+ }
+ bufData = p->outBufs[0] + XZ_BLOCK_HEADER_SIZE_MAX;
+ bufSize = t;
}
}
-
+
+ for (;;)
{
- UInt64 packPos = seqSizeOutStream.processed;
+ CXzEncBlockInfo blockSizes;
+ int inStreamFinished;
- SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,
- fp ?
- #ifdef USE_SUBBLOCK
- (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p:
- #endif
- &lzmaf->filter.p:
- &checkInStream.p,
- progress);
+ /*
+ UInt64 rem = (UInt64)(Int64)-1;
+ if (props->reduceSize != (UInt64)(Int64)-1
+ && props->reduceSize >= progress2.inOffset)
+ rem = props->reduceSize - progress2.inOffset;
+ */
+
+ blockSizes.headerSize = 0; // for GCC
- RINOK(res);
- block.unpackSize = checkInStream.processed;
- block.packSize = seqSizeOutStream.processed - packPos;
- }
+ RINOK(Xz_CompressBlock(
+ &p->lzmaf_Items[0],
+
+ writeStartSizes ? NULL : outStream,
+ writeStartSizes ? p->outBufs[0] : NULL,
+ bufData, bufSize,
+
+ inStream,
+ // rem,
+ NULL, 0,
+
+ props,
+ progress ? &progress2.vt : NULL,
+ &inStreamFinished,
+ &blockSizes,
+ p->alloc,
+ p->allocBig));
- {
- unsigned padSize = 0;
- Byte buf[128];
- while ((((unsigned)block.packSize + padSize) & 3) != 0)
- buf[padSize++] = 0;
- SeqCheckInStream_GetDigest(&checkInStream, buf + padSize);
- RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags)));
- RINOK(Xz_AddIndexRecord(xz, block.unpackSize, seqSizeOutStream.processed - padSize, &g_Alloc));
+ {
+ UInt64 totalPackFull = blockSizes.totalSize + XZ_GET_PAD_SIZE(blockSizes.totalSize);
+
+ if (writeStartSizes)
+ {
+ RINOK(WriteBytes(outStream, p->outBufs[0], blockSizes.headerSize));
+ RINOK(WriteBytes(outStream, bufData, (size_t)totalPackFull - blockSizes.headerSize));
+ }
+
+ RINOK(XzEncIndex_AddIndexRecord(&p->xzIndex, blockSizes.unpackSize, blockSizes.totalSize, p->alloc));
+
+ progress2.inOffset += blockSizes.unpackSize;
+ progress2.outOffset += totalPackFull;
+ }
+
+ if (inStreamFinished)
+ break;
}
}
- return Xz_WriteFooter(xz, outStream);
+
+ return XzEncIndex_WriteFooter(&p->xzIndex, (CXzStreamFlags)props->checkId, outStream);
}
+#include "Alloc.h"
+
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
const CXzProps *props, ICompressProgress *progress)
{
SRes res;
- CXzStream xz;
- CLzma2WithFilters lzmaf;
- Xz_Construct(&xz);
- Lzma2WithFilters_Construct(&lzmaf, &g_Alloc, &g_BigAlloc);
- res = Lzma2WithFilters_Create(&lzmaf);
+ CXzEncHandle xz = XzEnc_Create(&g_Alloc, &g_BigAlloc);
+ if (!xz)
+ return SZ_ERROR_MEM;
+ res = XzEnc_SetProps(xz, props);
if (res == SZ_OK)
- res = Xz_Compress(&xz, &lzmaf, outStream, inStream, props, progress);
- Lzma2WithFilters_Free(&lzmaf);
- Xz_Free(&xz, &g_Alloc);
+ res = XzEnc_Encode(xz, outStream, inStream, progress);
+ XzEnc_Destroy(xz);
return res;
}
@@ -528,11 +1319,11 @@ SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
SRes Xz_EncodeEmpty(ISeqOutStream *outStream)
{
SRes res;
- CXzStream xz;
- Xz_Construct(&xz);
- res = Xz_WriteHeader(xz.flags, outStream);
+ CXzEncIndex xzIndex;
+ XzEncIndex_Construct(&xzIndex);
+ res = Xz_WriteHeader((CXzStreamFlags)0, outStream);
if (res == SZ_OK)
- res = Xz_WriteFooter(&xz, outStream);
- Xz_Free(&xz, &g_Alloc);
+ res = XzEncIndex_WriteFooter(&xzIndex, (CXzStreamFlags)0, outStream);
+ XzEncIndex_Free(&xzIndex, NULL); // g_Alloc
return res;
}
diff --git a/C/XzEnc.h b/C/XzEnc.h
index e9cea34..529ac3f 100644
--- a/C/XzEnc.h
+++ b/C/XzEnc.h
@@ -1,5 +1,5 @@
/* XzEnc.h -- Xz Encode
-2011-02-07 : Igor Pavlov : Public domain */
+2017-06-27 : Igor Pavlov : Public domain */
#ifndef __XZ_ENC_H
#define __XZ_ENC_H
@@ -10,6 +10,11 @@
EXTERN_C_BEGIN
+
+#define XZ_PROPS__BLOCK_SIZE__AUTO LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO
+#define XZ_PROPS__BLOCK_SIZE__SOLID LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
+
+
typedef struct
{
UInt32 id;
@@ -20,15 +25,31 @@ typedef struct
void XzFilterProps_Init(CXzFilterProps *p);
+
typedef struct
{
- const CLzma2EncProps *lzma2Props;
- const CXzFilterProps *filterProps;
+ CLzma2EncProps lzma2Props;
+ CXzFilterProps filterProps;
unsigned checkId;
+ UInt64 blockSize;
+ int numBlockThreads_Reduced;
+ int numBlockThreads_Max;
+ int numTotalThreads;
+ int forceWriteSizesInHeader;
+ UInt64 reduceSize;
} CXzProps;
void XzProps_Init(CXzProps *p);
+
+typedef void * CXzEncHandle;
+
+CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig);
+void XzEnc_Destroy(CXzEncHandle p);
+SRes XzEnc_SetProps(CXzEncHandle p, const CXzProps *props);
+void XzEnc_SetDataSize(CXzEncHandle p, UInt64 expectedDataSiize);
+SRes XzEnc_Encode(CXzEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);
+
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
const CXzProps *props, ICompressProgress *progress);
diff --git a/C/XzIn.c b/C/XzIn.c
index aaa0597..42da1de 100644
--- a/C/XzIn.c
+++ b/C/XzIn.c
@@ -1,5 +1,5 @@
/* XzIn.c - Xz input
-2015-11-08 : Igor Pavlov : Public domain */
+2018-02-02 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -9,6 +9,12 @@
#include "CpuArch.h"
#include "Xz.h"
+/*
+#define XZ_FOOTER_SIG_CHECK(p) (memcmp((p), XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0)
+*/
+#define XZ_FOOTER_SIG_CHECK(p) ((p)[0] == XZ_FOOTER_SIG_0 && (p)[1] == XZ_FOOTER_SIG_1)
+
+
SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream)
{
Byte sig[XZ_STREAM_HEADER_SIZE];
@@ -28,7 +34,7 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt
unsigned headerSize;
*headerSizeRes = 0;
RINOK(SeqInStream_ReadByte(inStream, &header[0]));
- headerSize = ((unsigned)header[0] << 2) + 4;
+ headerSize = (unsigned)header[0];
if (headerSize == 0)
{
*headerSizeRes = 1;
@@ -37,12 +43,13 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt
}
*isIndex = False;
+ headerSize = (headerSize << 2) + 4;
*headerSizeRes = headerSize;
RINOK(SeqInStream_Read(inStream, header + 1, headerSize - 1));
return XzBlock_Parse(p, header);
}
-#define ADD_SIZE_CHECH(size, val) \
+#define ADD_SIZE_CHECK(size, val) \
{ UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; }
UInt64 Xz_GetUnpackSize(const CXzStream *p)
@@ -50,7 +57,7 @@ UInt64 Xz_GetUnpackSize(const CXzStream *p)
UInt64 size = 0;
size_t i;
for (i = 0; i < p->numBlocks; i++)
- ADD_SIZE_CHECH(size, p->blocks[i].unpackSize);
+ ADD_SIZE_CHECK(size, p->blocks[i].unpackSize);
return size;
}
@@ -59,7 +66,7 @@ UInt64 Xz_GetPackSize(const CXzStream *p)
UInt64 size = 0;
size_t i;
for (i = 0; i < p->numBlocks; i++)
- ADD_SIZE_CHECH(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3);
+ ADD_SIZE_CHECK(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3);
return size;
}
@@ -70,7 +77,7 @@ SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStream *inStream)
}
*/
-static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc)
+static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAllocPtr alloc)
{
size_t numBlocks, pos = 1;
UInt32 crc;
@@ -96,9 +103,8 @@ static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *
{
size_t i;
p->numBlocks = numBlocks;
- p->numBlocksAllocated = numBlocks;
- p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);
- if (p->blocks == 0)
+ p->blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);
+ if (!p->blocks)
return SZ_ERROR_MEM;
for (i = 0; i < numBlocks; i++)
{
@@ -115,7 +121,7 @@ static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *
return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
}
-static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize, ISzAlloc *alloc)
+static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize, ISzAllocPtr alloc)
{
SRes res;
size_t size;
@@ -125,13 +131,13 @@ static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize,
size = (size_t)indexSize;
if (size != indexSize)
return SZ_ERROR_UNSUPPORTED;
- buf = alloc->Alloc(alloc, size);
- if (buf == 0)
+ buf = (Byte *)ISzAlloc_Alloc(alloc, size);
+ if (!buf)
return SZ_ERROR_MEM;
res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED);
if (res == SZ_OK)
res = Xz_ReadIndex2(p, buf, size, alloc);
- alloc->Free(alloc, buf);
+ ISzAlloc_Free(alloc, buf);
return res;
}
@@ -142,7 +148,7 @@ static SRes LookInStream_SeekRead_ForArc(ILookInStream *stream, UInt64 offset, v
/* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */
}
-static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc)
+static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAllocPtr alloc)
{
UInt64 indexSize;
Byte buf[XZ_STREAM_FOOTER_SIZE];
@@ -154,7 +160,7 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff
pos -= XZ_STREAM_FOOTER_SIZE;
RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE));
- if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)
+ if (!XZ_FOOTER_SIG_CHECK(buf + 10))
{
UInt32 total = 0;
pos += XZ_STREAM_FOOTER_SIZE;
@@ -187,7 +193,7 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff
return SZ_ERROR_NO_ARCHIVE;
pos -= XZ_STREAM_FOOTER_SIZE;
RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE));
- if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)
+ if (!XZ_FOOTER_SIG_CHECK(buf + 10))
return SZ_ERROR_NO_ARCHIVE;
}
@@ -224,7 +230,7 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff
SecToRead_CreateVTable(&secToRead);
secToRead.realStream = stream;
- RINOK(Xz_ReadHeader(&headerFlags, &secToRead.s));
+ RINOK(Xz_ReadHeader(&headerFlags, &secToRead.vt));
return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE;
}
}
@@ -238,12 +244,12 @@ void Xzs_Construct(CXzs *p)
p->streams = 0;
}
-void Xzs_Free(CXzs *p, ISzAlloc *alloc)
+void Xzs_Free(CXzs *p, ISzAllocPtr alloc)
{
size_t i;
for (i = 0; i < p->num; i++)
Xz_Free(&p->streams[i], alloc);
- alloc->Free(alloc, p->streams);
+ ISzAlloc_Free(alloc, p->streams);
p->num = p->numAllocated = 0;
p->streams = 0;
}
@@ -262,7 +268,7 @@ UInt64 Xzs_GetUnpackSize(const CXzs *p)
UInt64 size = 0;
size_t i;
for (i = 0; i < p->num; i++)
- ADD_SIZE_CHECH(size, Xz_GetUnpackSize(&p->streams[i]));
+ ADD_SIZE_CHECK(size, Xz_GetUnpackSize(&p->streams[i]));
return size;
}
@@ -272,15 +278,15 @@ UInt64 Xzs_GetPackSize(const CXzs *p)
UInt64 size = 0;
size_t i;
for (i = 0; i < p->num; i++)
- ADD_SIZE_CHECH(size, Xz_GetTotalSize(&p->streams[i]));
+ ADD_SIZE_CHECK(size, Xz_GetTotalSize(&p->streams[i]));
return size;
}
*/
-SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc)
+SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAllocPtr alloc)
{
Int64 endOffset = 0;
- RINOK(stream->Seek(stream, &endOffset, SZ_SEEK_END));
+ RINOK(ILookInStream_Seek(stream, &endOffset, SZ_SEEK_END));
*startOffset = endOffset;
for (;;)
{
@@ -293,20 +299,20 @@ SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompr
if (p->num == p->numAllocated)
{
size_t newNum = p->num + p->num / 4 + 1;
- Byte *data = (Byte *)alloc->Alloc(alloc, newNum * sizeof(CXzStream));
- if (data == 0)
+ Byte *data = (Byte *)ISzAlloc_Alloc(alloc, newNum * sizeof(CXzStream));
+ if (!data)
return SZ_ERROR_MEM;
p->numAllocated = newNum;
if (p->num != 0)
memcpy(data, p->streams, p->num * sizeof(CXzStream));
- alloc->Free(alloc, p->streams);
+ ISzAlloc_Free(alloc, p->streams);
p->streams = (CXzStream *)data;
}
p->streams[p->num++] = st;
if (*startOffset == 0)
break;
RINOK(LookInStream_SeekTo(stream, *startOffset));
- if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK)
+ if (progress && ICompressProgress_Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK)
return SZ_ERROR_PROGRESS;
}
return SZ_OK;
diff --git a/CPP/7zip/Aes.mak b/CPP/7zip/Aes.mak
index 7ce28cf..4d5e98b 100644
--- a/CPP/7zip/Aes.mak
+++ b/CPP/7zip/Aes.mak
@@ -1,7 +1,7 @@
C_OBJS = $(C_OBJS) \
$O\Aes.obj
-!IF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM"
+!IF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM" && "$(CPU)" != "ARM64"
ASM_OBJS = $(ASM_OBJS) \
$O\AesOpt.obj
!ENDIF
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
index 80e4154..2360017 100644
--- a/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -13,7 +13,9 @@ struct CMethodFull: public CMethodProps
{
CMethodId Id;
UInt32 NumStreams;
+ int CodecIndex;
+ CMethodFull(): CodecIndex(-1) {}
bool IsSimpleCoder() const { return NumStreams == 1; }
};
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
index 1f709cb..2705ecb 100644
--- a/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -226,19 +226,23 @@ HRESULT CDecoder::Decode(
, ISequentialOutStream *outStream
, ICompressProgressInfo *compressProgress
+
, ISequentialInStream **
+ #ifdef USE_MIXER_ST
+ inStreamMainRes
+ #endif
- #ifdef USE_MIXER_ST
- inStreamMainRes
- #endif
+ , bool &dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS_DECL
- #if !defined(_7ZIP_ST) && !defined(_SFX)
- , bool mtMode, UInt32 numThreads
+ #if !defined(_7ZIP_ST)
+ , bool mtMode, UInt32 numThreads, UInt64 memUsage
#endif
)
{
+ dataAfterEnd_Error = false;
+
const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
CFolderEx folderInfo;
folders.ParseFolderEx(folderIndex, folderInfo);
@@ -308,7 +312,7 @@ HRESULT CDecoder::Decode(
#endif
CCreatedCoder cod;
- RINOK(CreateCoder(
+ RINOK(CreateCoder_Id(
EXTERNAL_CODECS_LOC_VARS
coderInfo.MethodID, false, cod));
@@ -351,11 +355,39 @@ HRESULT CDecoder::Decode(
unsigned i;
+ bool mt_wasUsed = false;
+
for (i = 0; i < folderInfo.Coders.Size(); i++)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
+ #if !defined(_7ZIP_ST)
+ if (!mt_wasUsed)
+ {
+ if (mtMode)
+ {
+ CMyComPtr<ICompressSetCoderMt> setCoderMt;
+ decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
+ if (setCoderMt)
+ {
+ mt_wasUsed = true;
+ RINOK(setCoderMt->SetNumberOfThreads(numThreads));
+ }
+ }
+ // if (memUsage != 0)
+ {
+ CMyComPtr<ICompressSetMemLimit> setMemLimit;
+ decoder->QueryInterface(IID_ICompressSetMemLimit, (void **)&setMemLimit);
+ if (setMemLimit)
+ {
+ mt_wasUsed = true;
+ RINOK(setMemLimit->SetMemLimit(memUsage));
+ }
+ }
+ }
+ #endif
+
{
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
@@ -372,18 +404,6 @@ HRESULT CDecoder::Decode(
}
}
- #if !defined(_7ZIP_ST) && !defined(_SFX)
- if (mtMode)
- {
- CMyComPtr<ICompressSetCoderMt> setCoderMt;
- decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
- if (setCoderMt)
- {
- RINOK(setCoderMt->SetNumberOfThreads(numThreads));
- }
- }
- #endif
-
#ifndef _NO_CRYPTO
{
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
@@ -415,12 +435,14 @@ HRESULT CDecoder::Decode(
}
#endif
+ bool finishMode = false;
{
CMyComPtr<ICompressSetFinishMode> setFinishMode;
decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
if (setFinishMode)
{
- RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));
+ finishMode = fullUnpack;
+ RINOK(setFinishMode->SetFinishMode(BoolToInt(finishMode)));
}
}
@@ -450,7 +472,7 @@ HRESULT CDecoder::Decode(
unpackSize :
&folders.CoderUnpackSizes[unpackStreamIndexStart + i];
- _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);
+ _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers, finishMode);
}
if (outStream)
@@ -530,7 +552,9 @@ HRESULT CDecoder::Decode(
progress2 = new CDecProgress(compressProgress);
ISequentialOutStream *outStreamPointer = outStream;
- return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress);
+ return _mixer->Code(inStreamPointers, &outStreamPointer,
+ progress2 ? (ICompressProgressInfo *)progress2 : compressProgress,
+ dataAfterEnd_Error);
}
#ifdef USE_MIXER_ST
diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h
index 051f843..944f8a3 100644
--- a/CPP/7zip/Archive/7z/7zDecode.h
+++ b/CPP/7zip/Archive/7z/7zDecode.h
@@ -53,12 +53,14 @@ public:
, ISequentialOutStream *outStream
, ICompressProgressInfo *compressProgress
+
, ISequentialInStream **inStreamMainRes
+ , bool &dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS_DECL
- #if !defined(_7ZIP_ST) && !defined(_SFX)
- , bool mtMode, UInt32 numThreads
+ #if !defined(_7ZIP_ST)
+ , bool mtMode, UInt32 numThreads, UInt64 memUsage
#endif
);
};
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
index 7636c60..4c0d221 100644
--- a/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -154,9 +154,18 @@ HRESULT CEncoder::CreateMixerCoder(
CCreatedCoder cod;
- RINOK(CreateCoder(
+ if (methodFull.CodecIndex >= 0)
+ {
+ RINOK(CreateCoder_Index(
+ EXTERNAL_CODECS_LOC_VARS
+ methodFull.CodecIndex, true, cod));
+ }
+ else
+ {
+ RINOK(CreateCoder_Id(
EXTERNAL_CODECS_LOC_VARS
methodFull.Id, true, cod));
+ }
if (cod.NumStreams != methodFull.NumStreams)
return E_FAIL;
@@ -333,7 +342,7 @@ HRESULT CEncoder::Encode(
}
for (i = 0; i < numMethods; i++)
- _mixer->SetCoderInfo(i, NULL, NULL);
+ _mixer->SetCoderInfo(i, NULL, NULL, false);
/* inStreamSize can be used by BCJ2 to set optimal range of conversion.
@@ -370,6 +379,17 @@ HRESULT CEncoder::Encode(
resetInitVector->ResetInitVector();
}
+ {
+ CMyComPtr<ICompressSetCoderPropertiesOpt> optProps;
+ coder->QueryInterface(IID_ICompressSetCoderPropertiesOpt, (void **)&optProps);
+ if (optProps)
+ {
+ PROPID propID = NCoderPropID::kExpectedDataSize;
+ NWindows::NCOM::CPropVariant prop = (UInt64)unpackSize;
+ RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1));
+ }
+ }
+
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
@@ -380,7 +400,7 @@ HRESULT CEncoder::Encode(
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
outStreamSpec->Init();
- writeCoderProperties->WriteCoderProperties(dynOutStream);
+ RINOK(writeCoderProperties->WriteCoderProperties(dynOutStream));
outStreamSpec->CopyToBuffer(props);
}
else
@@ -429,10 +449,12 @@ HRESULT CEncoder::Encode(
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
outStreamPointers.Add(tempBuffers[i - 1]);
+ bool dataAfterEnd_Error;
+
RINOK(_mixer->Code(
&inStreamPointer,
&outStreamPointers.Front(),
- mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress));
+ mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress, dataAfterEnd_Error));
if (_bindInfo.PackStreams.Size() != 0)
packSizes.Add(outStreamSizeCountSpec->GetSize());
diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
index a675797..075644f 100644
--- a/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -152,6 +152,12 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc
if (_fileIsOpen)
{
UInt32 cur = (size < _rem ? size : (UInt32)_rem);
+ if (_calcCrc)
+ {
+ const UInt32 k_Step = (UInt32)1 << 20;
+ if (cur > k_Step)
+ cur = k_Step;
+ }
HRESULT result = S_OK;
if (_stream)
result = _stream->Write(data, cur, &cur);
@@ -348,6 +354,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
#endif
+ bool dataAfterEnd_Error = false;
+
HRESULT result = decoder.Decode(
EXTERNAL_CODECS_VARS
_inStream,
@@ -358,20 +366,27 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStream,
progress,
NULL // *inStreamMainRes
+ , dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS
- #if !defined(_7ZIP_ST) && !defined(_SFX)
- , true, _numThreads
+ #if !defined(_7ZIP_ST)
+ , true, _numThreads, _memUsage
#endif
);
- if (result == S_FALSE || result == E_NOTIMPL)
+ if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error)
{
bool wasFinished = folderOutStream->WasWritingFinished();
-
- int resOp = (result == S_FALSE ?
- NExtract::NOperationResult::kDataError :
- NExtract::NOperationResult::kUnsupportedMethod);
+
+ int resOp = NExtract::NOperationResult::kDataError;
+
+ if (result != S_FALSE)
+ {
+ if (result == E_NOTIMPL)
+ resOp = NExtract::NOperationResult::kUnsupportedMethod;
+ else if (wasFinished && dataAfterEnd_Error)
+ resOp = NExtract::NOperationResult::kDataAfterEnd;
+ }
RINOK(folderOutStream->FlushCorrupted(resOp));
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
index 51a6f68..eee11a0 100644
--- a/CPP/7zip/Archive/7z/7zFolderInStream.cpp
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
@@ -80,14 +80,17 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
{
if (_stream)
{
- UInt32 processed2;
- RINOK(_stream->Read(data, size, &processed2));
- if (processed2 != 0)
+ UInt32 cur = size;
+ const UInt32 kMax = (UInt32)1 << 20;
+ if (cur > kMax)
+ cur = kMax;
+ RINOK(_stream->Read(data, cur, &cur));
+ if (cur != 0)
{
- _crc = CrcUpdate(_crc, data, processed2);
- _pos += processed2;
+ _crc = CrcUpdate(_crc, data, cur);
+ _pos += cur;
if (processedSize)
- *processedSize = processed2;
+ *processedSize = cur;
return S_OK;
}
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
index ce955a6..a3b0bce 100644
--- a/CPP/7zip/Archive/7z/7zHandler.cpp
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -40,7 +40,6 @@ CHandler::CHandler()
_crcSize = 4;
#ifdef __7Z_SET_PROPERTIES
- _numThreads = NSystem::GetNumberOfProcessors();
_useMultiThreadMixer = true;
#endif
@@ -540,7 +539,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
*/
const CFileItem &item = _db.Files[index];
- UInt32 index2 = index;
+ const UInt32 index2 = index;
switch (propID)
{
@@ -575,7 +574,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;
case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;
case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;
- case kpidAttrib: if (item.AttribDefined) PropVarEm_Set_UInt32(value, item.Attrib); break;
+ case kpidAttrib: if (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); break;
case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;
case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;
case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;
@@ -714,8 +713,8 @@ STDMETHODIMP CHandler::Close()
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
- const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
- _numThreads = numProcessors;
+
+ InitCommon();
_useMultiThreadMixer = true;
for (UInt32 i = 0; i < numProps; i++)
@@ -734,13 +733,15 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer));
continue;
}
- if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
- RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));
- continue;
+ HRESULT hres;
+ if (SetCommonProperty(name, value, hres))
+ {
+ RINOK(hres);
+ continue;
+ }
}
- else
- return E_INVALIDARG;
+ return E_INVALIDARG;
}
}
return S_OK;
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
index 00a8e83..7d5a5f0 100644
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -8,16 +8,6 @@
#include "../../Common/CreateCoder.h"
-#ifndef EXTRACT_ONLY
-#include "../Common/HandlerOut.h"
-#endif
-
-#include "7zCompressionMode.h"
-#include "7zIn.h"
-
-namespace NArchive {
-namespace N7z {
-
#ifndef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
@@ -30,6 +20,16 @@ namespace N7z {
#endif
+// #ifdef __7Z_SET_PROPERTIES
+#include "../Common/HandlerOut.h"
+// #endif
+
+#include "7zCompressionMode.h"
+#include "7zIn.h"
+
+namespace NArchive {
+namespace N7z {
+
#ifndef EXTRACT_ONLY
@@ -38,8 +38,6 @@ class COutHandler: public CMultiMethodProps
HRESULT SetSolidFromString(const UString &s);
HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);
public:
- bool _removeSfxBlock;
-
UInt64 _numSolidFiles;
UInt64 _numSolidBytes;
bool _numSolidBytesDefined;
@@ -54,9 +52,12 @@ public:
CBoolPair Write_CTime;
CBoolPair Write_ATime;
CBoolPair Write_MTime;
+ CBoolPair Write_Attrib;
bool _useMultiThreadMixer;
+ bool _removeSfxBlock;
+
// bool _volumeMode;
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
@@ -69,9 +70,10 @@ public:
_numSolidBytesDefined = false;
}
+ void InitProps7z();
void InitProps();
- COutHandler() { InitProps(); }
+ COutHandler() { InitProps7z(); }
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
};
@@ -81,16 +83,23 @@ public:
class CHandler:
public IInArchive,
public IArchiveGetRawProps,
+
#ifdef __7Z_SET_PROPERTIES
public ISetProperties,
#endif
+
#ifndef EXTRACT_ONLY
public IOutArchive,
#endif
+
PUBLIC_ISetCompressCodecsInfo
- public CMyUnknownImp
+
+ public CMyUnknownImp,
+
#ifndef EXTRACT_ONLY
- , public COutHandler
+ public COutHandler
+ #else
+ public CCommonMethodProps
#endif
{
public:
@@ -134,7 +143,6 @@ private:
#ifdef EXTRACT_ONLY
#ifdef __7Z_SET_PROPERTIES
- UInt32 _numThreads;
bool _useMultiThreadMixer;
#endif
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index 2f6a072..f0474bb 100644
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -13,16 +13,19 @@
#include "7zOut.h"
#include "7zUpdate.h"
+#ifndef EXTRACT_ONLY
+
using namespace NWindows;
namespace NArchive {
namespace N7z {
-static const char *k_LZMA_Name = "LZMA";
-static const char *kDefaultMethodName = "LZMA2";
-static const char *k_Copy_Name = "Copy";
+#define k_LZMA_Name "LZMA"
+#define kDefaultMethodName "LZMA2"
+#define k_Copy_Name "Copy"
+
+#define k_MatchFinder_ForHeaders "BT2"
-static const char *k_MatchFinder_ForHeaders = "BT2";
static const UInt32 k_NumFastBytes_ForHeaders = 273;
static const UInt32 k_Level_ForHeaders = 5;
static const UInt32 k_Dictionary_ForHeaders =
@@ -40,9 +43,11 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m)
{
- if (!FindMethod(
+ dest.CodecIndex = FindMethod_Index(
EXTERNAL_CODECS_VARS
- m.MethodName, dest.Id, dest.NumStreams))
+ m.MethodName, true,
+ dest.Id, dest.NumStreams);
+ if (dest.CodecIndex < 0)
return E_INVALIDARG;
(CProps &)dest = (CProps &)m;
return S_OK;
@@ -113,11 +118,11 @@ HRESULT CHandler::SetMainMethod(
FOR_VECTOR (i, methods)
{
COneMethodInfo &oneMethodInfo = methods[i];
- SetGlobalLevelAndThreads(oneMethodInfo
- #ifndef _7ZIP_ST
- , numThreads
- #endif
- );
+
+ SetGlobalLevelTo(oneMethodInfo);
+ #ifndef _7ZIP_ST
+ CMultiMethodProps::SetMethodThreadsTo(oneMethodInfo, numThreads);
+ #endif
CMethodFull &methodFull = methodMode.Methods.AddNew();
RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
@@ -282,15 +287,18 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
bool need_CTime = (Write_CTime.Def && Write_CTime.Val);
bool need_ATime = (Write_ATime.Def && Write_ATime.Val);
bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def);
+ bool need_Attrib = (Write_Attrib.Def && Write_Attrib.Val || !Write_Attrib.Def);
if (db && !db->Files.IsEmpty())
{
if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();
if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();
if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty();
+ if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty();
}
- UString s;
+ // UString s;
+ UString name;
for (UInt32 i = 0; i < numItems; i++)
{
@@ -307,7 +315,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
ui.IsAnti = false;
ui.Size = 0;
- UString name;
+ name.Empty();
// bool isAltStream = false;
if (ui.IndexInArchive != -1)
{
@@ -334,6 +342,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (ui.NewProps)
{
bool folderStatusIsDefined;
+ if (need_Attrib)
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop));
@@ -377,7 +386,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
else
{
- name = NItemName::MakeLegalName(prop.bstrVal);
+ name = prop.bstrVal;
+ NItemName::ReplaceSlashes_OsToUnix(name);
}
}
{
@@ -614,6 +624,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.HeaderOptions.WriteCTime = Write_CTime;
options.HeaderOptions.WriteATime = Write_ATime;
options.HeaderOptions.WriteMTime = Write_MTime;
+ options.HeaderOptions.WriteAttrib = Write_Attrib;
*/
options.NumSolidFiles = _numSolidFiles;
@@ -692,10 +703,8 @@ static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
return S_OK;
}
-void COutHandler::InitProps()
+void COutHandler::InitProps7z()
{
- CMultiMethodProps::Init();
-
_removeSfxBlock = false;
_compressHeaders = true;
_encryptHeadersSpecified = false;
@@ -705,6 +714,7 @@ void COutHandler::InitProps()
Write_CTime.Init();
Write_ATime.Init();
Write_MTime.Init();
+ Write_Attrib.Init();
_useMultiThreadMixer = true;
@@ -714,6 +724,14 @@ void COutHandler::InitProps()
_useTypeSorting = false;
}
+void COutHandler::InitProps()
+{
+ CMultiMethodProps::Init();
+ InitProps7z();
+}
+
+
+
HRESULT COutHandler::SetSolidFromString(const UString &s)
{
UString s2 = s;
@@ -754,6 +772,10 @@ HRESULT COutHandler::SetSolidFromString(const UString &s)
}
_numSolidBytes = (v << numBits);
_numSolidBytesDefined = true;
+ /*
+ if (_numSolidBytes == 0)
+ _numSolidFiles = 1;
+ */
}
}
return S_OK;
@@ -802,7 +824,7 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
return E_INVALIDARG;
return SetSolidFromString(name);
}
-
+
UInt32 number;
int index = ParseStringToUInt32(name, number);
// UString realName = name.Ptr(index);
@@ -830,6 +852,8 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime);
if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime);
+ if (name.IsEqualTo("tr")) return PROPVARIANT_to_BoolPair(value, Write_Attrib);
+
if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
@@ -911,3 +935,5 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
}
}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
index b03bc89..bbc77b0 100644
--- a/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -32,6 +32,21 @@ using namespace NCOM;
namespace NArchive {
namespace N7z {
+unsigned BoolVector_CountSum(const CBoolVector &v)
+{
+ unsigned sum = 0;
+ const unsigned size = v.Size();
+ for (unsigned i = 0; i < size; i++)
+ if (v[i])
+ sum++;
+ return sum;
+}
+
+static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i)
+{
+ return (i < v.Size() ? v[i] : false);
+}
+
static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
{
v.ClearAndSetSize(size);
@@ -40,6 +55,7 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
p[i] = false;
}
+
class CInArchiveException {};
class CUnsupportedFeatureException: public CInArchiveException {};
@@ -566,21 +582,30 @@ void CInArchive::WaitId(UInt64 id)
}
}
-void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
+
+void CInArchive::Read_UInt32_Vector(CUInt32DefVector &v)
{
- ReadBoolVector2(numItems, crcs.Defs);
- crcs.Vals.ClearAndSetSize(numItems);
- UInt32 *p = &crcs.Vals[0];
- const bool *defs = &crcs.Defs[0];
+ unsigned numItems = v.Defs.Size();
+ v.Vals.ClearAndSetSize(numItems);
+ UInt32 *p = &v.Vals[0];
+ const bool *defs = &v.Defs[0];
for (unsigned i = 0; i < numItems; i++)
{
- UInt32 crc = 0;
+ UInt32 a = 0;
if (defs[i])
- crc = ReadUInt32();
- p[i] = crc;
+ a = ReadUInt32();
+ p[i] = a;
}
}
+
+void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
+{
+ ReadBoolVector2(numItems, crcs.Defs);
+ Read_UInt32_Vector(crcs);
+}
+
+
#define k_Scan_NumCoders_MAX 64
#define k_Scan_NumCodersStreams_in_Folder_MAX 64
@@ -1075,6 +1100,8 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
outStreamSpec->Init(data, unpackSize);
+ bool dataAfterEnd_Error = false;
+
HRESULT result = decoder.Decode(
EXTERNAL_CODECS_LOC_VARS
_stream, baseOffset + dataOffset,
@@ -1083,16 +1110,23 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
outStream,
NULL, // *compressProgress
+
NULL // **inStreamMainRes
+ , dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS
- #if !defined(_7ZIP_ST) && !defined(_SFX)
+ #if !defined(_7ZIP_ST)
, false // mtMode
, 1 // numThreads
+ , 0 // memUsage
#endif
);
+
RINOK(result);
+ if (dataAfterEnd_Error)
+ ThereIsHeaderError = true;
+
if (folders.FolderCRCs.ValidAndDefined(i))
if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])
ThrowIncorrect();
@@ -1148,19 +1182,10 @@ HRESULT CInArchive::ReadHeader(
type = ReadID();
}
- db.Files.Clear();
-
if (type == NID::kFilesInfo)
{
const CNum numFiles = ReadNum();
- db.Files.ClearAndSetSize(numFiles);
- /*
- db.Files.Reserve(numFiles);
- CNum i;
- for (i = 0; i < numFiles; i++)
- db.Files.Add(CFileItem());
- */
db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
// if (!db.PackSizes.IsEmpty())
@@ -1169,7 +1194,6 @@ HRESULT CInArchive::ReadHeader(
db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
CBoolVector emptyStreamVector;
- BoolVector_Fill_False(emptyStreamVector, (unsigned)numFiles);
CBoolVector emptyFileVector;
CBoolVector antiFileVector;
CNum numEmptyStreams = 0;
@@ -1197,10 +1221,10 @@ HRESULT CInArchive::ReadHeader(
size_t rem = _inByteBack->GetRem();
db.NamesBuf.Alloc(rem);
ReadBytes(db.NamesBuf, rem);
- db.NameOffsets.Alloc(db.Files.Size() + 1);
+ db.NameOffsets.Alloc(numFiles + 1);
size_t pos = 0;
unsigned i;
- for (i = 0; i < db.Files.Size(); i++)
+ for (i = 0; i < numFiles; i++)
{
size_t curRem = (rem - pos) / 2;
const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos);
@@ -1216,36 +1240,31 @@ HRESULT CInArchive::ReadHeader(
ThereIsHeaderError = true;
break;
}
+
case NID::kWinAttrib:
{
- CBoolVector boolVector;
- ReadBoolVector2(db.Files.Size(), boolVector);
+ ReadBoolVector2(numFiles, db.Attrib.Defs);
CStreamSwitch streamSwitch;
streamSwitch.Set(this, &dataVector);
- for (CNum i = 0; i < numFiles; i++)
- {
- CFileItem &file = db.Files[i];
- file.AttribDefined = boolVector[i];
- if (file.AttribDefined)
- file.Attrib = ReadUInt32();
- }
+ Read_UInt32_Vector(db.Attrib);
break;
}
+
/*
case NID::kIsAux:
{
- ReadBoolVector(db.Files.Size(), db.IsAux);
+ ReadBoolVector(numFiles, db.IsAux);
break;
}
case NID::kParent:
{
db.IsTree = true;
// CBoolVector boolVector;
- // ReadBoolVector2(db.Files.Size(), boolVector);
+ // ReadBoolVector2(numFiles, boolVector);
// CStreamSwitch streamSwitch;
// streamSwitch.Set(this, &dataVector);
CBoolVector boolVector;
- ReadBoolVector2(db.Files.Size(), boolVector);
+ ReadBoolVector2(numFiles, boolVector);
db.ThereAreAltStreams = false;
for (i = 0; i < numFiles; i++)
@@ -1264,14 +1283,9 @@ HRESULT CInArchive::ReadHeader(
case NID::kEmptyStream:
{
ReadBoolVector(numFiles, emptyStreamVector);
- numEmptyStreams = 0;
- for (CNum i = 0; i < (CNum)emptyStreamVector.Size(); i++)
- if (emptyStreamVector[i])
- numEmptyStreams++;
-
- BoolVector_Fill_False(emptyFileVector, numEmptyStreams);
- BoolVector_Fill_False(antiFileVector, numEmptyStreams);
-
+ numEmptyStreams = BoolVector_CountSum(emptyStreamVector);
+ emptyFileVector.Clear();
+ antiFileVector.Clear();
break;
}
case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break;
@@ -1314,7 +1328,7 @@ HRESULT CInArchive::ReadHeader(
ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset);
}
db.SecureIDs.Clear();
- for (unsigned i = 0; i < db.Files.Size(); i++)
+ for (unsigned i = 0; i < numFiles; i++)
{
db.SecureIDs.Add(ReadNum());
// db.SecureIDs.Add(ReadUInt32());
@@ -1359,22 +1373,21 @@ HRESULT CInArchive::ReadHeader(
CNum emptyFileIndex = 0;
CNum sizeIndex = 0;
- CNum numAntiItems = 0;
+ const CNum numAntiItems = BoolVector_CountSum(antiFileVector);
- CNum i;
+ if (numAntiItems != 0)
+ db.IsAnti.ClearAndSetSize(numFiles);
- for (i = 0; i < numEmptyStreams; i++)
- if (antiFileVector[i])
- numAntiItems++;
+ db.Files.ClearAndSetSize(numFiles);
- for (i = 0; i < numFiles; i++)
+ for (CNum i = 0; i < numFiles; i++)
{
CFileItem &file = db.Files[i];
bool isAnti;
- file.HasStream = !emptyStreamVector[i];
file.Crc = 0;
- if (file.HasStream)
+ if (!BoolVector_Item_IsValidAndTrue(emptyStreamVector, i))
{
+ file.HasStream = true;
file.IsDir = false;
isAnti = false;
file.Size = unpackSizes[sizeIndex];
@@ -1385,26 +1398,31 @@ HRESULT CInArchive::ReadHeader(
}
else
{
- file.IsDir = !emptyFileVector[emptyFileIndex];
- isAnti = antiFileVector[emptyFileIndex];
+ file.HasStream = false;
+ file.IsDir = !BoolVector_Item_IsValidAndTrue(emptyFileVector, emptyFileIndex);
+ isAnti = BoolVector_Item_IsValidAndTrue(antiFileVector, emptyFileIndex);
emptyFileIndex++;
file.Size = 0;
file.CrcDefined = false;
}
if (numAntiItems != 0)
- db.IsAnti.Add(isAnti);
+ db.IsAnti[i] = isAnti;
}
+
}
+
db.FillLinks();
- /*
- if (type != NID::kEnd)
- ThrowIncorrect();
- if (_inByteBack->GetRem() != 0)
- ThrowIncorrect();
- */
+
+ if (type != NID::kEnd || _inByteBack->GetRem() != 0)
+ {
+ db.UnsupportedFeatureWarning = true;
+ // ThrowIncorrect();
+ }
+
return S_OK;
}
+
void CDbEx::FillLinks()
{
FolderStartFileIndex.Alloc(NumFolders);
@@ -1466,6 +1484,7 @@ void CDbEx::FillLinks()
}
}
+
HRESULT CInArchive::ReadDatabase2(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
@@ -1610,6 +1629,7 @@ HRESULT CInArchive::ReadDatabase2(
);
}
+
HRESULT CInArchive::ReadDatabase(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
index 260d8f7..c5fb909 100644
--- a/CPP/7zip/Archive/7z/7zIn.h
+++ b/CPP/7zip/Archive/7z/7zIn.h
@@ -115,6 +115,7 @@ struct CDatabase: public CFolders
CUInt64DefVector ATime;
CUInt64DefVector MTime;
CUInt64DefVector StartPos;
+ CUInt32DefVector Attrib;
CBoolVector IsAnti;
/*
CBoolVector IsAux;
@@ -146,6 +147,7 @@ struct CDatabase: public CFolders
ATime.Clear();
MTime.Clear();
StartPos.Clear();
+ Attrib.Clear();
IsAnti.Clear();
// IsAux.Clear();
}
@@ -369,6 +371,8 @@ class CInArchive
void SkipData() { _inByteBack->SkipData(); }
void WaitId(UInt64 id);
+ void Read_UInt32_Vector(CUInt32DefVector &v);
+
void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);
diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h
index 935ee43..90cf98c 100644
--- a/CPP/7zip/Archive/7z/7zItem.h
+++ b/CPP/7zip/Archive/7z/7zItem.h
@@ -26,12 +26,14 @@ struct CCoderInfo
bool IsSimpleCoder() const { return NumStreams == 1; }
};
+
struct CBond
{
UInt32 PackIndex;
UInt32 UnpackIndex;
};
+
struct CFolder
{
CLASS_NO_COPY(CFolder)
@@ -87,6 +89,7 @@ public:
}
};
+
struct CUInt32DefVector
{
CBoolVector Defs;
@@ -110,9 +113,25 @@ struct CUInt32DefVector
Vals.ReserveDown();
}
+ bool GetItem(unsigned index, UInt32 &value) const
+ {
+ if (index < Defs.Size() && Defs[index])
+ {
+ value = Vals[index];
+ return true;
+ }
+ value = 0;
+ return false;
+ }
+
bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; }
+
+ bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
+
+ void SetItem(unsigned index, bool defined, UInt32 value);
};
+
struct CUInt64DefVector
{
CBoolVector Defs;
@@ -141,15 +160,15 @@ struct CUInt64DefVector
return false;
}
- void SetItem(unsigned index, bool defined, UInt64 value);
-
bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
+
+ void SetItem(unsigned index, bool defined, UInt64 value);
};
+
struct CFileItem
{
UInt64 Size;
- UInt32 Attrib;
UInt32 Crc;
/*
int Parent;
@@ -159,23 +178,23 @@ struct CFileItem
// stream in some folder. It can be empty stream
bool IsDir;
bool CrcDefined;
- bool AttribDefined;
+
+ /*
+ void Clear()
+ {
+ HasStream = true;
+ IsDir = false;
+ CrcDefined = false;
+ }
CFileItem():
- /*
- Parent(-1),
- IsAltStream(false),
- */
+ // Parent(-1),
+ // IsAltStream(false),
HasStream(true),
IsDir(false),
CrcDefined(false),
- AttribDefined(false)
{}
- void SetAttrib(UInt32 attrib)
- {
- AttribDefined = true;
- Attrib = attrib;
- }
+ */
};
}}
diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
index 0989978..5bd3a41 100644
--- a/CPP/7zip/Archive/7z/7zOut.cpp
+++ b/CPP/7zip/Archive/7z/7zOut.cpp
@@ -330,13 +330,11 @@ void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)
WriteBoolVector(boolVector);
}
+unsigned BoolVector_CountSum(const CBoolVector &v);
+
void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
{
- unsigned numDefined = 0;
- unsigned i;
- for (i = 0; i < digests.Defs.Size(); i++)
- if (digests.Defs[i])
- numDefined++;
+ const unsigned numDefined = BoolVector_CountSum(digests.Defs);
if (numDefined == 0)
return;
@@ -348,7 +346,8 @@ void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
WriteByte(0);
WriteBoolVector(digests.Defs);
}
- for (i = 0; i < digests.Defs.Size(); i++)
+
+ for (unsigned i = 0; i < digests.Defs.Size(); i++)
if (digests.Defs[i])
WriteUInt32(digests.Vals[i]);
}
@@ -453,10 +452,12 @@ void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders,
// 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.
-void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)
+void COutArchive::SkipToAligned(unsigned pos, unsigned alignShifts)
{
if (!_useAlign)
return;
+
+ const unsigned alignSize = (unsigned)1 << alignShifts;
pos += (unsigned)GetPos();
pos &= (alignSize - 1);
if (pos == 0)
@@ -471,11 +472,11 @@ void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)
WriteByte(0);
}
-void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize)
+void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts)
{
const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);
- const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2;
- SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize);
+ const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2;
+ SkipToAligned(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSizeShifts);
WriteByte(type);
WriteNumber(dataSize);
@@ -486,24 +487,18 @@ void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefin
WriteByte(0);
WriteBoolVector(v);
}
- WriteByte(0);
+ WriteByte(0); // 0 means no switching to external stream
}
void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
{
- unsigned numDefined = 0;
-
- unsigned i;
- for (i = 0; i < v.Defs.Size(); i++)
- if (v.Defs[i])
- numDefined++;
-
+ const unsigned numDefined = BoolVector_CountSum(v.Defs);
if (numDefined == 0)
return;
- WriteAlignedBoolHeader(v.Defs, numDefined, type, 8);
+ WriteAlignedBools(v.Defs, numDefined, type, 3);
- for (i = 0; i < v.Defs.Size(); i++)
+ for (unsigned i = 0; i < v.Defs.Size(); i++)
if (v.Defs[i])
WriteUInt64(v.Vals[i]);
}
@@ -520,7 +515,7 @@ HRESULT COutArchive::EncodeStream(
outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));
// outFolders.NumUnpackStreamsVector.Add(1);
UInt64 dataSize64 = data.Size();
- UInt64 unpackSize;
+ UInt64 unpackSize = data.Size();
RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
stream,
@@ -648,7 +643,7 @@ void COutArchive::WriteHeader(
if (numDefined > 0)
{
namesDataSize++;
- SkipAlign(2 + GetBigNumberSize(namesDataSize), 16);
+ SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4);
WriteByte(NID::kName);
WriteNumber(namesDataSize);
@@ -673,28 +668,15 @@ void COutArchive::WriteHeader(
{
/* ---------- Write Attrib ---------- */
- CBoolVector boolVector;
- boolVector.ClearAndSetSize(db.Files.Size());
- unsigned numDefined = 0;
-
- {
- FOR_VECTOR (i, db.Files)
- {
- bool defined = db.Files[i].AttribDefined;
- boolVector[i] = defined;
- if (defined)
- numDefined++;
- }
- }
+ const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs);
if (numDefined != 0)
{
- WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4);
- FOR_VECTOR (i, db.Files)
+ WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2);
+ FOR_VECTOR (i, db.Attrib.Defs)
{
- const CFileItem &file = db.Files[i];
- if (file.AttribDefined)
- WriteUInt32(file.Attrib);
+ if (db.Attrib.Defs[i])
+ WriteUInt32(db.Attrib.Vals[i]);
}
}
}
@@ -702,18 +684,8 @@ void COutArchive::WriteHeader(
/*
{
// ---------- Write IsAux ----------
- unsigned numAux = 0;
- const CBoolVector &isAux = db.IsAux;
- for (i = 0; i < isAux.Size(); i++)
- if (isAux[i])
- numAux++;
- if (numAux > 0)
- {
- const unsigned bvSize = Bv_GetSizeInBytes(isAux);
- WriteByte(NID::kIsAux);
- WriteNumber(bvSize);
- WriteBoolVector(isAux);
- }
+ if (BoolVector_CountSum(db.IsAux) != 0)
+ WritePropBoolVector(NID::kIsAux, db.IsAux);
}
{
@@ -734,10 +706,10 @@ void COutArchive::WriteHeader(
}
if (numParentLinks > 0)
{
- // WriteAlignedBoolHeader(boolVector, numDefined, NID::kParent, 4);
+ // WriteAlignedBools(boolVector, numDefined, NID::kParent, 2);
const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector);
const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1;
- SkipAlign(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 4);
+ SkipToAligned(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 2);
WriteByte(NID::kParent);
WriteNumber(dataSize);
@@ -765,7 +737,7 @@ void COutArchive::WriteHeader(
// secureDataSize += db.SecureIDs.Size() * 4;
for (i = 0; i < db.SecureIDs.Size(); i++)
secureDataSize += GetBigNumberSize(db.SecureIDs[i]);
- SkipAlign(2 + GetBigNumberSize(secureDataSize), 4);
+ SkipToAligned(2 + GetBigNumberSize(secureDataSize), 2);
WriteByte(NID::kNtSecure);
WriteNumber(secureDataSize);
WriteByte(0);
@@ -888,6 +860,18 @@ HRESULT COutArchive::WriteDatabase(
}
}
+void CUInt32DefVector::SetItem(unsigned index, bool defined, UInt32 value)
+{
+ while (index >= Defs.Size())
+ Defs.Add(false);
+ Defs[index] = defined;
+ if (!defined)
+ return;
+ while (index >= Vals.Size())
+ Vals.Add(0);
+ Vals[index] = value;
+}
+
void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value)
{
while (index >= Defs.Size())
@@ -907,6 +891,7 @@ void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2
ATime.SetItem(index, file2.ATimeDefined, file2.ATime);
MTime.SetItem(index, file2.MTimeDefined, file2.MTime);
StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);
+ Attrib.SetItem(index, file2.AttribDefined, file2.Attrib);
SetItem_Anti(index, file2.IsAnti);
// SetItem_Aux(index, file2.IsAux);
Names.Add(name);
diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h
index 86034f3..12e965f 100644
--- a/CPP/7zip/Archive/7z/7zOut.h
+++ b/CPP/7zip/Archive/7z/7zOut.h
@@ -45,6 +45,7 @@ public:
size_t GetPos() const { return _pos; }
};
+
struct CHeaderOptions
{
bool CompressMainHeader;
@@ -71,24 +72,31 @@ struct CFileItem2
UInt64 ATime;
UInt64 MTime;
UInt64 StartPos;
+ UInt32 Attrib;
+
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
bool StartPosDefined;
+ bool AttribDefined;
bool IsAnti;
// bool IsAux;
+ /*
void Init()
{
CTimeDefined = false;
ATimeDefined = false;
MTimeDefined = false;
StartPosDefined = false;
+ AttribDefined = false;
IsAnti = false;
// IsAux = false;
}
+ */
};
+
struct COutFolders
{
CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
@@ -111,6 +119,7 @@ struct COutFolders
}
};
+
struct CArchiveDatabaseOut: public COutFolders
{
CRecordVector<UInt64> PackSizes;
@@ -123,10 +132,11 @@ struct CArchiveDatabaseOut: public COutFolders
CUInt64DefVector ATime;
CUInt64DefVector MTime;
CUInt64DefVector StartPos;
- CRecordVector<bool> IsAnti;
+ CUInt32DefVector Attrib;
+ CBoolVector IsAnti;
/*
- CRecordVector<bool> IsAux;
+ CBoolVector IsAux;
CByteBuffer SecureBuf;
CRecordVector<UInt32> SecureSizes;
@@ -154,6 +164,7 @@ struct CArchiveDatabaseOut: public COutFolders
ATime.Clear();
MTime.Clear();
StartPos.Clear();
+ Attrib.Clear();
IsAnti.Clear();
/*
@@ -176,6 +187,7 @@ struct CArchiveDatabaseOut: public COutFolders
ATime.ReserveDown();
MTime.ReserveDown();
StartPos.ReserveDown();
+ Attrib.ReserveDown();
IsAnti.ReserveDown();
/*
@@ -196,11 +208,12 @@ struct CArchiveDatabaseOut: public COutFolders
{
unsigned size = Files.Size();
return (
- CTime.CheckSize(size) &&
- ATime.CheckSize(size) &&
- MTime.CheckSize(size) &&
- StartPos.CheckSize(size) &&
- (size == IsAnti.Size() || IsAnti.Size() == 0));
+ CTime.CheckSize(size)
+ && ATime.CheckSize(size)
+ && MTime.CheckSize(size)
+ && StartPos.CheckSize(size)
+ && Attrib.CheckSize(size)
+ && (size == IsAnti.Size() || IsAnti.Size() == 0));
}
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
@@ -224,6 +237,7 @@ struct CArchiveDatabaseOut: public COutFolders
void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name);
};
+
class COutArchive
{
UInt64 _prefixHeaderPos;
@@ -261,8 +275,8 @@ class COutArchive
const CRecordVector<UInt64> &unpackSizes,
const CUInt32DefVector &digests);
- void SkipAlign(unsigned pos, unsigned alignSize);
- void WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize);
+ void SkipToAligned(unsigned pos, unsigned alignShifts);
+ void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts);
void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type);
HRESULT EncodeStream(
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index 509a330..44de9ac 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -1088,18 +1088,23 @@ static HRESULT MakeExeMethod(CCompressionMethodMode &mode,
}
-static void FromUpdateItemToFileItem(const CUpdateItem &ui,
- CFileItem &file, CFileItem2 &file2)
+static void UpdateItem_To_FileItem2(const CUpdateItem &ui, CFileItem2 &file2)
{
- if (ui.AttribDefined)
- file.SetAttrib(ui.Attrib);
-
+ file2.Attrib = ui.Attrib; file2.AttribDefined = ui.AttribDefined;
file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined;
file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined;
file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined;
file2.IsAnti = ui.IsAnti;
// file2.IsAux = false;
file2.StartPosDefined = false;
+ // file2.StartPos = 0;
+}
+
+
+static void UpdateItem_To_FileItem(const CUpdateItem &ui,
+ CFileItem &file, CFileItem2 &file2)
+{
+ UpdateItem_To_FileItem2(ui, file2);
file.Size = ui.Size;
file.IsDir = ui.IsDir;
@@ -1107,6 +1112,8 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui,
// file.IsAltStream = ui.IsAltStream;
}
+
+
class CRepackInStreamWithSizes:
public ISequentialInStream,
public ICompressGetSubStreamSize,
@@ -1437,6 +1444,7 @@ public:
#ifndef _7ZIP_ST
+ bool dataAfterEnd_Error;
HRESULT Result;
CMyComPtr<IInStream> InStream;
@@ -1479,7 +1487,9 @@ void CThreadDecoder::Execute()
bool passwordIsDefined = false;
UString password;
#endif
-
+
+ dataAfterEnd_Error = false;
+
Result = Decoder.Decode(
EXTERNAL_CODECS_LOC_VARS
InStream,
@@ -1491,12 +1501,16 @@ void CThreadDecoder::Execute()
Fos,
NULL, // compressProgress
+
NULL // *inStreamMainRes
+ , dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS
#ifndef _7ZIP_ST
- , MtMode, NumThreads
+ , MtMode, NumThreads,
+ 0 // MemUsage
#endif
+
);
}
catch(...)
@@ -1541,6 +1555,7 @@ static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFil
file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime);
file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime);
file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos);
+ file2.AttribDefined = inDb.Attrib.GetItem(index, file2.Attrib);
file2.IsAnti = inDb.IsItemAnti(index);
// file2.IsAux = inDb.IsItemAux(index);
}
@@ -1682,13 +1697,14 @@ HRESULT Update(
UInt64 inSizeForReduce = 0;
{
+ bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0);
FOR_VECTOR (i, updateItems)
{
const CUpdateItem &ui = updateItems[i];
if (ui.NewData)
{
complexity += ui.Size;
- if (numSolidFiles != 1)
+ if (isSolid)
inSizeForReduce += ui.Size;
else if (inSizeForReduce < ui.Size)
inSizeForReduce = ui.Size;
@@ -1837,7 +1853,7 @@ HRESULT Update(
continue;
secureID = ui.SecureIndex;
if (ui.NewProps)
- FromUpdateItemToFileItem(ui, file, file2);
+ UpdateItem_To_FileItem(ui, file, file2);
else
GetFile(*db, ui.IndexInArchive, file, file2);
}
@@ -1887,7 +1903,8 @@ HRESULT Update(
UString name;
if (ui.NewProps)
{
- FromUpdateItemToFileItem(ui, file, file2);
+ UpdateItem_To_FileItem(ui, file, file2);
+ file.CrcDefined = false;
name = ui.Name;
}
else
@@ -2107,6 +2124,8 @@ HRESULT Update(
#endif
CMyComPtr<ISequentialInStream> decodedStream;
+ bool dataAfterEnd_Error = false;
+
HRESULT res = threadDecoder.Decoder.Decode(
EXTERNAL_CODECS_LOC_VARS
inStream,
@@ -2117,12 +2136,15 @@ HRESULT Update(
NULL, // *outStream
NULL, // *compressProgress
+
&decodedStream
+ , dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS
#ifndef _7ZIP_ST
, false // mtMode
, 1 // numThreads
+ , 0 // memUsage
#endif
);
@@ -2151,6 +2173,7 @@ HRESULT Update(
#endif
}
+ curUnpackSize = sizeToEncode;
HRESULT encodeRes = encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
@@ -2175,16 +2198,19 @@ HRESULT Update(
HRESULT decodeRes = threadDecoder.Result;
// if (res == k_My_HRESULT_CRC_ERROR)
- if (decodeRes == S_FALSE)
+ if (decodeRes == S_FALSE || threadDecoder.dataAfterEnd_Error)
{
if (extractCallback)
{
RINOK(extractCallback->ReportExtractResult(
NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex],
// NEventIndexType::kBlockIndex, (UInt32)folderIndex,
- NExtract::NOperationResult::kDataError));
+ (decodeRes != S_OK ?
+ NExtract::NOperationResult::kDataError :
+ NExtract::NOperationResult::kDataAfterEnd)));
}
- return E_FAIL;
+ if (decodeRes != S_OK)
+ return E_FAIL;
}
RINOK(decodeRes);
if (encodeRes == S_OK)
@@ -2224,12 +2250,7 @@ HRESULT Update(
CNum indexInFolder = 0;
for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
{
- CFileItem file;
- CFileItem2 file2;
- GetFile(*db, fi, file, file2);
- UString name;
- db->GetPath(fi, name);
- if (file.HasStream)
+ if (db->Files[fi].HasStream)
{
indexInFolder++;
int updateIndex = fileIndexToUpdateIndexMap[fi];
@@ -2238,17 +2259,21 @@ HRESULT Update(
const CUpdateItem &ui = updateItems[updateIndex];
if (ui.NewData)
continue;
+
+ UString name;
+ CFileItem file;
+ CFileItem2 file2;
+ GetFile(*db, fi, file, file2);
+
if (ui.NewProps)
{
- CFileItem uf;
- FromUpdateItemToFileItem(ui, uf, file2);
- uf.Size = file.Size;
- uf.Crc = file.Crc;
- uf.CrcDefined = file.CrcDefined;
- uf.HasStream = file.HasStream;
- file = uf;
+ UpdateItem_To_FileItem2(ui, file2);
+ file.IsDir = ui.IsDir;
name = ui.Name;
}
+ else
+ db->GetPath(fi, name);
+
/*
file.Parent = ui.ParentFolderIndex;
if (ui.TreeFolderIndex >= 0)
@@ -2270,7 +2295,8 @@ HRESULT Update(
continue;
CRecordVector<CRefItem> refItems;
refItems.ClearAndSetSize(numFiles);
- bool sortByType = (options.UseTypeSorting && numSolidFiles > 1);
+ // bool sortByType = (options.UseTypeSorting && isSoid); // numSolidFiles > 1
+ bool sortByType = options.UseTypeSorting;
unsigned i;
@@ -2292,7 +2318,7 @@ HRESULT Update(
const CUpdateItem &ui = updateItems[index];
CFileItem file;
if (ui.NewProps)
- FromUpdateItemToFileItem(ui, file);
+ UpdateItem_To_FileItem(ui, file);
else
file = db.Files[ui.IndexInArchive];
if (file.IsAnti || file.IsDir)
@@ -2336,7 +2362,9 @@ HRESULT Update(
inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
unsigned startPackIndex = newDatabase.PackSizes.Size();
- UInt64 curFolderUnpackSize;
+ UInt64 curFolderUnpackSize = totalSize;
+ // curFolderUnpackSize = (UInt64)(Int64)-1;
+
RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
solidInStream,
@@ -2367,7 +2395,7 @@ HRESULT Update(
UString name;
if (ui.NewProps)
{
- FromUpdateItemToFileItem(ui, file, file2);
+ UpdateItem_To_FileItem(ui, file, file2);
name = ui.Name;
}
else
@@ -2386,7 +2414,7 @@ HRESULT Update(
{
skippedSize += ui.Size;
continue;
- // file.Name.AddAscii(".locked");
+ // file.Name += ".locked";
}
file.Crc = inStreamSpec->CRCs[subIndex];
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
index aeb1d38..d4d9949 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp
@@ -60,6 +60,62 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
p[i] = false;
}
+
+HRESULT CCoder::CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const
+{
+ if (Coder)
+ {
+ if (PackSizePointers.IsEmpty() || !PackSizePointers[0])
+ return S_OK;
+ CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
+ Coder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize);
+ // if (!getInStreamProcessedSize) return E_FAIL;
+ if (getInStreamProcessedSize)
+ {
+ UInt64 processed;
+ RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed));
+ if (processed != (UInt64)(Int64)-1)
+ {
+ const UInt64 size = PackSizes[0];
+ if (processed < size && Finish)
+ dataAfterEnd_Error = true;
+ if (processed > size)
+ {
+ // InternalPackSizeError = true;
+ // return S_FALSE;
+ }
+ }
+ }
+ }
+ else if (Coder2)
+ {
+ CMyComPtr<ICompressGetInStreamProcessedSize2> getInStreamProcessedSize2;
+ Coder2.QueryInterface(IID_ICompressGetInStreamProcessedSize2, (void **)&getInStreamProcessedSize2);
+ FOR_VECTOR (i, PackSizePointers)
+ {
+ if (!PackSizePointers[i])
+ continue;
+ UInt64 processed;
+ RINOK(getInStreamProcessedSize2->GetInStreamProcessedSize2(i, &processed));
+ if (processed != (UInt64)(Int64)-1)
+ {
+ const UInt64 size = PackSizes[i];
+ if (processed < size && Finish)
+ dataAfterEnd_Error = true;
+ else if (processed > size)
+ {
+ // InternalPackSizeError = true;
+ // return S_FALSE;
+ }
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+
class CBondsChecks
{
CBoolVector _coderUsed;
@@ -151,8 +207,10 @@ bool CBindInfo::CalcMapsAndCheck()
}
-void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes)
+void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
{
+ Finish = finish;
+
if (unpackSize)
{
UnpackSize = *unpackSize;
@@ -640,8 +698,12 @@ void CMixerST::SelectMainCoder(bool useFirst)
HRESULT CMixerST::Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress)
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error)
{
+ // InternalPackSizeError = false;
+ dataAfterEnd_Error = false;
+
_binderStreams.Clear();
unsigned ci = MainCoderIndex;
@@ -742,7 +804,16 @@ HRESULT CMixerST::Code(
if (res == k_My_HRESULT_WritingWasCut)
res = S_OK;
- return res;
+
+ if (res != S_OK)
+ return res;
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */));
+ }
+
+ return S_OK;
}
@@ -988,8 +1059,12 @@ HRESULT CMixerMT::ReturnIfError(HRESULT code)
HRESULT CMixerMT::Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress)
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error)
{
+ // InternalPackSizeError = false;
+ dataAfterEnd_Error = false;
+
Init(inStreams, outStreams);
unsigned i;
@@ -1031,6 +1106,11 @@ HRESULT CMixerMT::Code(
return result;
}
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */));
+ }
+
return S_OK;
}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h
index ce4797f..4bd6418 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2.h
@@ -201,9 +201,13 @@ public:
CRecordVector<UInt64> PackSizes;
CRecordVector<const UInt64 *> PackSizePointers;
- CCoder() {}
+ bool Finish;
- void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes);
+ CCoder(): Finish(false) {}
+
+ void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish);
+
+ HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const;
IUnknown *GetUnknown() const
{
@@ -239,9 +243,12 @@ protected:
public:
unsigned MainCoderIndex;
+ // bool InternalPackSizeError;
+
CMixer(bool encodeMode):
EncodeMode(encodeMode),
MainCoderIndex(0)
+ // , InternalPackSizeError(false)
{}
/*
@@ -273,11 +280,12 @@ public:
virtual CCoder &GetCoder(unsigned index) = 0;
virtual void SelectMainCoder(bool useFirst) = 0;
virtual void ReInit() = 0;
- virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) = 0;
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0;
virtual HRESULT Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress) = 0;
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error) = 0;
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;
bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);
@@ -338,12 +346,13 @@ public:
virtual CCoder &GetCoder(unsigned index);
virtual void SelectMainCoder(bool useFirst);
virtual void ReInit();
- virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
- { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
virtual HRESULT Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress);
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error);
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
HRESULT GetMainUnpackStream(
@@ -419,12 +428,13 @@ public:
virtual CCoder &GetCoder(unsigned index);
virtual void SelectMainCoder(bool useFirst);
virtual void ReInit();
- virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
- { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
virtual HRESULT Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress);
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error);
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
CMixerMT(bool encodeMode): CMixer(encodeMode) {}
diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
index 3200fd2..41762d9 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.cpp
+++ b/CPP/7zip/Archive/Common/HandlerOut.cpp
@@ -2,54 +2,129 @@
#include "StdAfx.h"
-#ifndef _7ZIP_ST
-#include "../../../Windows/System.h"
-#endif
+#include "../../../Common/StringToInt.h"
#include "../Common/ParseProperties.h"
#include "HandlerOut.h"
-using namespace NWindows;
-
namespace NArchive {
+bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res)
+{
+ if (*s == 0)
+ {
+ switch (prop.vt)
+ {
+ case VT_UI4: res = prop.ulVal; return true;
+ case VT_UI8: res = prop.uhVal.QuadPart; return true;
+ case VT_BSTR:
+ s = prop.bstrVal;
+ break;
+ default: return false;
+ }
+ }
+ else if (prop.vt != VT_EMPTY)
+ return false;
+
+ const wchar_t *end;
+ UInt64 v = ConvertStringToUInt64(s, &end);
+ if (s == end)
+ return false;
+ wchar_t c = *end;
+ if (c == 0)
+ {
+ res = v;
+ return true;
+ }
+ if (end[1] != 0)
+ return false;
+
+ if (c == '%')
+ {
+ res = percentsBase / 100 * v;
+ return true;
+ }
+
+ unsigned numBits;
+ switch (MyCharLower_Ascii(c))
+ {
+ case 'b': numBits = 0; break;
+ case 'k': numBits = 10; break;
+ case 'm': numBits = 20; break;
+ case 'g': numBits = 30; break;
+ case 't': numBits = 40; break;
+ default: return false;
+ }
+ UInt64 val2 = v << numBits;
+ if ((val2 >> numBits) != v)
+ return false;
+ res = val2;
+ return true;
+}
+
+bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres)
+{
+ hres = S_OK;
+
+ if (name.IsPrefixedBy_Ascii_NoCase("mt"))
+ {
+ #ifndef _7ZIP_ST
+ hres = ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads);
+ #endif
+ return true;
+ }
+
+ if (name.IsPrefixedBy_Ascii_NoCase("memuse"))
+ {
+ if (!ParseSizeString(name.Ptr(6), value, _memAvail, _memUsage))
+ hres = E_INVALIDARG;
+ return true;
+ }
+
+ return false;
+}
+
+
+#ifndef EXTRACT_ONLY
+
static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value)
{
if (m.FindProp(propID) < 0)
m.AddProp32(propID, value);
}
-void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
- #ifndef _7ZIP_ST
- , UInt32 numThreads
- #endif
- )
+void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const
{
UInt32 level = _level;
if (level != (UInt32)(Int32)-1)
SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
-
- #ifndef _7ZIP_ST
+}
+
+#ifndef _7ZIP_ST
+void CMultiMethodProps::SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads)
+{
SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
- #endif
}
+#endif
-void CMultiMethodProps::Init()
+void CMultiMethodProps::InitMulti()
{
- #ifndef _7ZIP_ST
- _numProcessors = _numThreads = NSystem::GetNumberOfProcessors();
- #endif
-
_level = (UInt32)(Int32)-1;
_analysisLevel = -1;
-
- _autoFilter = true;
_crcSize = 4;
- _filterMethod.Clear();
+ _autoFilter = true;
+}
+
+void CMultiMethodProps::Init()
+{
+ InitCommon();
+ InitMulti();
_methods.Clear();
+ _filterMethod.Clear();
}
+
HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
{
UString name = nameSpec;
@@ -73,26 +148,24 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
return S_OK;
}
- if (name.IsEqualTo("crc"))
+ if (name.IsPrefixedBy_Ascii_NoCase("crc"))
{
name.Delete(0, 3);
_crcSize = 4;
return ParsePropToUInt32(name, value, _crcSize);
}
+
+ {
+ HRESULT hres;
+ if (SetCommonProperty(name, value, hres))
+ return hres;
+ }
UInt32 number;
unsigned index = ParseStringToUInt32(name, number);
UString realName = name.Ptr(index);
if (index == 0)
{
- if (name.IsPrefixedBy_Ascii_NoCase("mt"))
- {
- #ifndef _7ZIP_ST
- RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
- #endif
-
- return S_OK;
- }
if (name.IsEqualTo("f"))
{
HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);
@@ -111,20 +184,20 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
return _methods[number].ParseMethodFromPROPVARIANT(realName, value);
}
+
+
void CSingleMethodProps::Init()
{
+ InitCommon();
+ InitSingle();
Clear();
- _level = (UInt32)(Int32)-1;
-
- #ifndef _7ZIP_ST
- _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
- AddProp_NumThreads(_numThreads);
- #endif
}
+
HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
Init();
+
for (UInt32 i = 0; i < numProps; i++)
{
UString name = names[i];
@@ -138,20 +211,22 @@ HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PR
RINOK(ParsePropToUInt32(name.Ptr(1), value, a));
_level = a;
AddProp_Level(a);
+ continue;
}
- else if (name.IsPrefixedBy_Ascii_NoCase("mt"))
- {
- #ifndef _7ZIP_ST
- RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
- AddProp_NumThreads(_numThreads);
- #endif
- }
- else
{
- RINOK(ParseMethodFromPROPVARIANT(names[i], value));
+ HRESULT hres;
+ if (SetCommonProperty(name, value, hres))
+ {
+ RINOK(hres)
+ continue;
+ }
}
+ RINOK(ParseMethodFromPROPVARIANT(names[i], value));
}
+
return S_OK;
}
+#endif
+
}
diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h
index 44dee09..90b000a 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.h
+++ b/CPP/7zip/Archive/Common/HandlerOut.h
@@ -3,30 +3,69 @@
#ifndef __HANDLER_OUT_H
#define __HANDLER_OUT_H
+#include "../../../Windows/System.h"
+
#include "../../Common/MethodProps.h"
namespace NArchive {
-class CMultiMethodProps
+bool ParseSizeString(const wchar_t *name, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res);
+
+class CCommonMethodProps
{
- UInt32 _level;
- int _analysisLevel;
+protected:
+ void InitCommon()
+ {
+ #ifndef _7ZIP_ST
+ _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
+ #endif
+
+ UInt64 memAvail = (UInt64)(sizeof(size_t)) << 28;
+ _memAvail = memAvail;
+ _memUsage = memAvail;
+ if (NWindows::NSystem::GetRamSize(memAvail))
+ {
+ _memAvail = memAvail;
+ _memUsage = memAvail / 32 * 17;
+ }
+ }
+
public:
#ifndef _7ZIP_ST
UInt32 _numThreads;
UInt32 _numProcessors;
#endif
+ UInt64 _memUsage;
+ UInt64 _memAvail;
+
+ bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres);
+
+ CCommonMethodProps() { InitCommon(); }
+};
+
+
+#ifndef EXTRACT_ONLY
+
+class CMultiMethodProps: public CCommonMethodProps
+{
+ UInt32 _level;
+ int _analysisLevel;
+
+ void InitMulti();
+public:
UInt32 _crcSize;
CObjectVector<COneMethodInfo> _methods;
COneMethodInfo _filterMethod;
bool _autoFilter;
- void SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
- #ifndef _7ZIP_ST
- , UInt32 numThreads
- #endif
- );
+
+ void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const;
+
+ #ifndef _7ZIP_ST
+ static void SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads);
+ #endif
+
unsigned GetNumEmptyMethods() const
{
@@ -41,27 +80,31 @@ public:
int GetAnalysisLevel() const { return _analysisLevel; }
void Init();
+ CMultiMethodProps() { InitMulti(); }
- CMultiMethodProps() { Init(); }
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
};
-class CSingleMethodProps: public COneMethodInfo
+
+class CSingleMethodProps: public COneMethodInfo, public CCommonMethodProps
{
UInt32 _level;
-
-public:
- #ifndef _7ZIP_ST
- UInt32 _numThreads;
- UInt32 _numProcessors;
- #endif
+ void InitSingle()
+ {
+ _level = (UInt32)(Int32)-1;
+ }
+
+public:
void Init();
- CSingleMethodProps() { Init(); }
+ CSingleMethodProps() { InitSingle(); }
+
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
};
+#endif
+
}
#endif
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
index 1608949..e0c35a9 100644
--- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp
+++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
@@ -7,58 +7,57 @@
namespace NArchive {
namespace NItemName {
-static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR;
-static const wchar_t kDirDelimiter = L'/';
+static const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR;
+static const wchar_t kUnixPathSepar = L'/';
-void ReplaceToOsPathSeparator(wchar_t *s)
-{
- #ifdef _WIN32
- for (;;)
+void ReplaceSlashes_OsToUnix
+#if WCHAR_PATH_SEPARATOR != L'/'
+ (UString &name)
{
- wchar_t c = *s;
- if (c == 0)
- break;
- if (c == kDirDelimiter)
- *s = kOSDirDelimiter;
- s++;
+ name.Replace(kOsPathSepar, kUnixPathSepar);
}
- #endif
-}
+#else
+ (UString &) {}
+#endif
-UString MakeLegalName(const UString &name)
-{
- UString zipName = name;
- zipName.Replace(kOSDirDelimiter, kDirDelimiter);
- return zipName;
-}
-UString GetOSName(const UString &name)
+UString GetOsPath(const UString &name)
{
- UString newName = name;
- newName.Replace(kDirDelimiter, kOSDirDelimiter);
- return newName;
+ #if WCHAR_PATH_SEPARATOR != L'/'
+ UString newName = name;
+ newName.Replace(kUnixPathSepar, kOsPathSepar);
+ return newName;
+ #else
+ return name;
+ #endif
}
-UString GetOSName2(const UString &name)
+
+UString GetOsPath_Remove_TailSlash(const UString &name)
{
if (name.IsEmpty())
return UString();
- UString newName = GetOSName(name);
- if (newName.Back() == kOSDirDelimiter)
+ UString newName = GetOsPath(name);
+ if (newName.Back() == kOsPathSepar)
newName.DeleteBack();
return newName;
}
-void ConvertToOSName2(UString &name)
+
+void ReplaceToOsSlashes_Remove_TailSlash(UString &name)
{
if (!name.IsEmpty())
{
- name.Replace(kDirDelimiter, kOSDirDelimiter);
- if (name.Back() == kOSDirDelimiter)
+ #if WCHAR_PATH_SEPARATOR != L'/'
+ name.Replace(kUnixPathSepar, kOsPathSepar);
+ #endif
+
+ if (name.Back() == kOsPathSepar)
name.DeleteBack();
}
}
+
bool HasTailSlash(const AString &name, UINT
#if defined(_WIN32) && !defined(UNDER_CE)
codePage
@@ -67,20 +66,21 @@ bool HasTailSlash(const AString &name, UINT
{
if (name.IsEmpty())
return false;
- LPCSTR prev =
- #if defined(_WIN32) && !defined(UNDER_CE)
- CharPrevExA((WORD)codePage, name, &name[name.Len()], 0);
- #else
- (LPCSTR)(name) + (name.Len() - 1);
- #endif
- return (*prev == '/');
+ char c =
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0);
+ #else
+ name.Back();
+ #endif
+ return (c == '/');
}
+
#ifndef _WIN32
-UString WinNameToOSName(const UString &name)
+UString WinPathToOsPath(const UString &name)
{
UString newName = name;
- newName.Replace(L'\\', kOSDirDelimiter);
+ newName.Replace(L'\\', WCHAR_PATH_SEPARATOR);
return newName;
}
#endif
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h
index 8ee2d0f..404fce4 100644
--- a/CPP/7zip/Archive/Common/ItemNameUtils.h
+++ b/CPP/7zip/Archive/Common/ItemNameUtils.h
@@ -8,19 +8,20 @@
namespace NArchive {
namespace NItemName {
- void ReplaceToOsPathSeparator(wchar_t *s);
-
- UString MakeLegalName(const UString &name);
- UString GetOSName(const UString &name);
- UString GetOSName2(const UString &name);
- void ConvertToOSName2(UString &name);
- bool HasTailSlash(const AString &name, UINT codePage);
-
- #ifdef _WIN32
- inline UString WinNameToOSName(const UString &name) { return name; }
- #else
- UString WinNameToOSName(const UString &name);
- #endif
+void ReplaceSlashes_OsToUnix(UString &name);
+
+UString GetOsPath(const UString &name);
+UString GetOsPath_Remove_TailSlash(const UString &name);
+
+void ReplaceToOsSlashes_Remove_TailSlash(UString &name);
+
+bool HasTailSlash(const AString &name, UINT codePage);
+
+#ifdef _WIN32
+ inline UString WinPathToOsPath(const UString &name) { return name; }
+#else
+ UString WinPathToOsPath(const UString &name);
+#endif
}}
diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h
index 5c0957e..96451a6 100644
--- a/CPP/7zip/Archive/IArchive.h
+++ b/CPP/7zip/Archive/IArchive.h
@@ -488,6 +488,16 @@ ARCHIVE_INTERFACE(IOutArchive, 0xA0)
};
+/*
+ISetProperties::SetProperties()
+ PROPVARIANT values[i].vt:
+ VT_EMPTY
+ VT_BOOL
+ VT_UI4 - if 32-bit number
+ VT_UI8 - if 64-bit number
+ VT_BSTR
+*/
+
ARCHIVE_INTERFACE(ISetProperties, 0x03)
{
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) PURE;
diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp
index cd9e89a..28079df 100644
--- a/CPP/7zip/Archive/LzmaHandler.cpp
+++ b/CPP/7zip/Archive/LzmaHandler.cpp
@@ -44,7 +44,8 @@ static const Byte kProps[] =
static const Byte kArcProps[] =
{
- kpidNumStreams
+ kpidNumStreams,
+ kpidMethod
};
struct CHeader
@@ -53,6 +54,7 @@ struct CHeader
Byte FilterID;
Byte LzmaProps[5];
+ Byte GetProp() const { return LzmaProps[0]; }
UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); }
bool HasSize() const { return (Size != (UInt64)(Int64)-1); }
bool Parse(const Byte *buf, bool isThereFilter);
@@ -197,6 +199,8 @@ class CHandler:
UInt64 _unpackSize;
UInt64 _numStreams;
+ void GetMethod(NCOM::CPropVariant &prop);
+
public:
MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
@@ -220,6 +224,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;
case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;
case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;
+ case kpidMethod: GetMethod(prop); break;
case kpidErrorFlags:
{
UInt32 v = 0;
@@ -229,6 +234,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
if (_dataError) v |= kpv_ErrorFlags_DataError;
prop = v;
+ break;
}
}
prop.Detach(value);
@@ -241,23 +247,60 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK;
}
-static void DictSizeToString(UInt32 value, char *s)
+
+static void DictSizeToString(UInt32 val, char *s)
{
- for (int i = 0; i <= 31; i++)
- if (((UInt32)1 << i) == value)
+ for (unsigned i = 0; i <= 31; i++)
+ if (((UInt32)1 << i) == val)
{
::ConvertUInt32ToString(i, s);
return;
}
char c = 'b';
- if ((value & ((1 << 20) - 1)) == 0) { value >>= 20; c = 'm'; }
- else if ((value & ((1 << 10) - 1)) == 0) { value >>= 10; c = 'k'; }
- ::ConvertUInt32ToString(value, s);
+ if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
+ else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
+ ::ConvertUInt32ToString(val, s);
s += MyStringLen(s);
*s++ = c;
*s = 0;
}
+static char *AddProp32(char *s, const char *name, UInt32 v)
+{
+ *s++ = ':';
+ s = MyStpCpy(s, name);
+ ::ConvertUInt32ToString(v, s);
+ return s + MyStringLen(s);
+}
+
+void CHandler::GetMethod(NCOM::CPropVariant &prop)
+{
+ if (!_stream)
+ return;
+
+ char sz[64];
+ char *s = sz;
+ if (_header.FilterID != 0)
+ s = MyStpCpy(s, "BCJ ");
+ s = MyStpCpy(s, "LZMA:");
+ DictSizeToString(_header.GetDicSize(), s);
+ s += strlen(s);
+
+ UInt32 d = _header.GetProp();
+ // if (d != 0x5D)
+ {
+ UInt32 lc = d % 9;
+ d /= 9;
+ UInt32 pb = d / 5;
+ UInt32 lp = d % 5;
+ if (lc != 3) s = AddProp32(s, "lc", lc);
+ if (lp != 0) s = AddProp32(s, "lp", lp);
+ if (pb != 2) s = AddProp32(s, "pb", pb);
+ }
+ prop = sz;
+}
+
+
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
@@ -265,18 +308,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
{
case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break;
case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;
- case kpidMethod:
- if (_stream)
- {
- char sz[64];
- char *s = sz;
- if (_header.FilterID != 0)
- s = MyStpCpy(s, "BCJ ");
- s = MyStpCpy(s, "LZMA:");
- DictSizeToString(_header.GetDicSize(), s);
- prop = sz;
- }
- break;
+ case kpidMethod: GetMethod(prop); break;
}
prop.Detach(value);
return S_OK;
@@ -396,9 +428,9 @@ STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const
{
if (Callback)
{
- UInt64 files = 0;
- UInt64 value = Offset + *inSize;
- return Callback->SetCompleted(&files, &value);
+ const UInt64 files = 0;
+ const UInt64 val = Offset + *inSize;
+ return Callback->SetCompleted(&files, &val);
}
return S_OK;
}
@@ -510,7 +542,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
if (dataAfterEnd)
_dataAfterEnd = true;
- else if (decoder._lzmaDecoderSpec->NeedMoreInput)
+ else if (decoder._lzmaDecoderSpec->NeedsMoreInput())
_needMoreInput = true;
_packSize = packSize;
diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp
index f20680d..ffb0e33 100644
--- a/CPP/7zip/Archive/SplitHandler.cpp
+++ b/CPP/7zip/Archive/SplitHandler.cpp
@@ -181,7 +181,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
seqName._splitStyle = splitStyle;
if (prefix.Len() < 1)
- _subName.SetFromAscii("file");
+ _subName = "file";
else
_subName.SetFrom(prefix, prefix.Len() - 1);
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
index 5616aa1..74cbca9 100644
--- a/CPP/7zip/Archive/XzHandler.cpp
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -3,16 +3,15 @@
#include "StdAfx.h"
#include "../../../C/Alloc.h"
-#include "../../../C/XzCrc64.h"
-#include "../../../C/XzEnc.h"
#include "../../Common/ComTry.h"
#include "../../Common/Defs.h"
#include "../../Common/IntToString.h"
+#include "../../Common/MyBuffer.h"
+#include "../../Common/StringToInt.h"
#include "../../Windows/PropVariant.h"
-
-#include "../ICoder.h"
+#include "../../Windows/System.h"
#include "../Common/CWrappers.h"
#include "../Common/ProgressUtils.h"
@@ -20,72 +19,55 @@
#include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h"
+#include "../Compress/XzDecoder.h"
+#include "../Compress/XzEncoder.h"
#include "IArchive.h"
-#ifndef EXTRACT_ONLY
#include "Common/HandlerOut.h"
-#endif
-
-#include "XzHandler.h"
using namespace NWindows;
-namespace NCompress {
-namespace NLzma2 {
-
-HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);
-
-}}
-
namespace NArchive {
namespace NXz {
-struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;
+#define k_LZMA2_Name "LZMA2"
-static const char *k_LZMA2_Name = "LZMA2";
-void CStatInfo::Clear()
+struct CBlockInfo
{
- InSize = 0;
- OutSize = 0;
- PhySize = 0;
-
- NumStreams = 0;
- NumBlocks = 0;
-
- UnpackSize_Defined = false;
-
- NumStreams_Defined = false;
- NumBlocks_Defined = false;
-
- IsArc = false;
- UnexpectedEnd = false;
- DataAfterEnd = false;
- Unsupported = false;
- HeadersError = false;
- DataError = false;
- CrcError = false;
-}
+ unsigned StreamFlags;
+ UInt64 PackPos;
+ UInt64 PackSize; // pure value from Index record, it doesn't include pad zeros
+ UInt64 UnpackPos;
+};
+
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
+ public IInArchiveGetStream,
+ public ISetProperties,
+
#ifndef EXTRACT_ONLY
public IOutArchive,
- public ISetProperties,
- public CMultiMethodProps,
#endif
- public CMyUnknownImp
+
+ public CMyUnknownImp,
+
+ #ifndef EXTRACT_ONLY
+ public CMultiMethodProps
+ #else
+ public CCommonMethodProps
+ #endif
{
- CStatInfo _stat;
+ CXzStatInfo _stat;
+ SRes MainDecodeSRes;
bool _isArc;
bool _needSeekToStart;
bool _phySize_Defined;
-
- CMyComPtr<IInStream> _stream;
- CMyComPtr<ISequentialInStream> _seqStream;
+ bool _firstBlockWasRead;
AString _methodsString;
@@ -93,21 +75,50 @@ class CHandler:
UInt32 _filterId;
- void Init()
+ UInt64 _numSolidBytes;
+
+ void InitXz()
{
_filterId = 0;
- CMultiMethodProps::Init();
+ _numSolidBytes = XZ_PROPS__BLOCK_SIZE__AUTO;
}
-
+
#endif
+ void Init()
+ {
+ #ifndef EXTRACT_ONLY
+ InitXz();
+ CMultiMethodProps::Init();
+ #else
+ CCommonMethodProps::InitCommon();
+ #endif
+ }
+
+ HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
+
HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback);
- HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
- CDecoder &decoder, ICompressProgressInfo *progress)
+ HRESULT Decode(NCompress::NXz::CDecoder &decoder,
+ ISequentialInStream *seqInStream,
+ ISequentialOutStream *outStream,
+ ICompressProgressInfo *progress)
{
- RINOK(decoder.Decode(seqInStream, outStream, progress));
- _stat = decoder;
+ #ifndef _7ZIP_ST
+ decoder._numThreads = _numThreads;
+ #endif
+ decoder._memUsage = _memUsage;
+
+ MainDecodeSRes = SZ_OK;
+
+ RINOK(decoder.Decode(seqInStream, outStream,
+ NULL, // *outSizeLimit
+ true, // finishStream
+ progress));
+
+ _stat = decoder.Stat;
+ MainDecodeSRes = decoder.MainDecodeSRes;
+
_phySize_Defined = true;
return S_OK;
}
@@ -115,31 +126,55 @@ class CHandler:
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)
+ MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
+ MY_QUERYINTERFACE_ENTRY(ISetProperties)
#ifndef EXTRACT_ONLY
MY_QUERYINTERFACE_ENTRY(IOutArchive)
- MY_QUERYINTERFACE_ENTRY(ISetProperties)
#endif
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IInArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
#ifndef EXTRACT_ONLY
INTERFACE_IOutArchive(;)
- STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
#endif
+ size_t _blocksArraySize;
+ CBlockInfo *_blocks;
+ UInt64 _maxBlocksSize;
+ CMyComPtr<IInStream> _stream;
+ CMyComPtr<ISequentialInStream> _seqStream;
+
+ CXzBlock _firstBlock;
+
CHandler();
+ ~CHandler();
+
+ HRESULT SeekToPackPos(UInt64 pos)
+ {
+ return _stream->Seek(pos, STREAM_SEEK_SET, NULL);
+ }
};
-CHandler::CHandler()
+
+CHandler::CHandler():
+ _blocks(NULL),
+ _blocksArraySize(0)
{
#ifndef EXTRACT_ONLY
- Init();
+ InitXz();
#endif
}
+CHandler::~CHandler()
+{
+ MyFree(_blocks);
+}
+
static const Byte kProps[] =
{
@@ -152,7 +187,9 @@ static const Byte kArcProps[] =
{
kpidMethod,
kpidNumStreams,
- kpidNumBlocks
+ kpidNumBlocks,
+ kpidClusterSize,
+ kpidCharacts
};
IMP_IInArchive_Props
@@ -169,13 +206,6 @@ static inline void AddHexToString(AString &s, Byte value)
s += GetHex(value & 0xF);
}
-static void AddUInt32ToString(AString &s, UInt32 value)
-{
- char temp[16];
- ConvertUInt32ToString(value, temp);
- s += temp;
-}
-
static void Lzma2PropToString(AString &s, unsigned prop)
{
char c = 0;
@@ -192,7 +222,7 @@ static void Lzma2PropToString(AString &s, unsigned prop)
c = 'm';
}
}
- AddUInt32ToString(s, size);
+ s.Add_UInt32(size);
if (c != 0)
s += c;
}
@@ -216,7 +246,7 @@ static const CMethodNamePair g_NamePairs[] =
{ XZ_ID_LZMA2, "LZMA2" }
};
-static AString GetMethodString(const CXzFilter &f)
+static void AddMethodString(AString &s, const CXzFilter &f)
{
const char *p = NULL;
for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++)
@@ -232,7 +262,7 @@ static AString GetMethodString(const CXzFilter &f)
p = temp;
}
- AString s = p;
+ s += p;
if (f.propsSize > 0)
{
@@ -240,7 +270,7 @@ static AString GetMethodString(const CXzFilter &f)
if (f.id == XZ_ID_LZMA2 && f.propsSize == 1)
Lzma2PropToString(s, f.props[0]);
else if (f.id == XZ_ID_Delta && f.propsSize == 1)
- AddUInt32ToString(s, (UInt32)f.props[0] + 1);
+ s.Add_UInt32((UInt32)f.props[0] + 1);
else
{
s += '[';
@@ -249,13 +279,6 @@ static AString GetMethodString(const CXzFilter &f)
s += ']';
}
}
- return s;
-}
-
-static void AddString(AString &dest, const AString &src)
-{
- dest.Add_Space_if_NotEmpty();
- dest += src;
}
static const char * const kChecks[] =
@@ -278,27 +301,24 @@ static const char * const kChecks[] =
, NULL
};
-static AString GetCheckString(const CXzs &xzs)
+static void AddCheckString(AString &s, const CXzs &xzs)
{
size_t i;
UInt32 mask = 0;
for (i = 0; i < xzs.num; i++)
mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags));
- AString s;
for (i = 0; i <= XZ_CHECK_MASK; i++)
if (((mask >> i) & 1) != 0)
{
- AString s2;
+ s.Add_Space_if_NotEmpty();
if (kChecks[i])
- s2 = kChecks[i];
+ s += kChecks[i];
else
{
- s2 = "Check-";
- AddUInt32ToString(s2, (UInt32)i);
+ s += "Check-";
+ s.Add_UInt32((UInt32)i);
}
- AddString(s, s2);
}
- return s;
}
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
@@ -307,22 +327,47 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
NCOM::CPropVariant prop;
switch (propID)
{
- case kpidPhySize: if (_phySize_Defined) prop = _stat.PhySize; break;
+ case kpidPhySize: if (_phySize_Defined) prop = _stat.InSize; break;
case kpidNumStreams: if (_stat.NumStreams_Defined) prop = _stat.NumStreams; break;
case kpidNumBlocks: if (_stat.NumBlocks_Defined) prop = _stat.NumBlocks; break;
case kpidUnpackSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break;
+ case kpidClusterSize: if (_stat.NumBlocks_Defined && _stat.NumBlocks > 1) prop = _maxBlocksSize; break;
+ case kpidCharacts:
+ if (_firstBlockWasRead)
+ {
+ AString s;
+ if (XzBlock_HasPackSize(&_firstBlock))
+ s.Add_OptSpaced("BlockPackSize");
+ if (XzBlock_HasUnpackSize(&_firstBlock))
+ s.Add_OptSpaced("BlockUnpackSize");
+ if (!s.IsEmpty())
+ prop = s;
+ }
+ break;
+
+
case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
case kpidErrorFlags:
{
UInt32 v = 0;
- if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;;
- if (_stat.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
+ SRes sres = MainDecodeSRes; // _stat.DecodeRes2; //
+ if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
+ if (/*_stat.UnexpectedEnd */ sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd;
if (_stat.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
- if (_stat.HeadersError) v |= kpv_ErrorFlags_HeadersError;
- if (_stat.Unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
- if (_stat.DataError) v |= kpv_ErrorFlags_DataError;
- if (_stat.CrcError) v |= kpv_ErrorFlags_CrcError;
- prop = v;
+ if (/* _stat.HeadersError */ sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError;
+ if (/* _stat.Unsupported */ sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod;
+ if (/* _stat.DataError */ sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError;
+ if (/* _stat.CrcError */ sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError;
+ if (v != 0)
+ prop = v;
+ break;
+ }
+
+ case kpidMainSubfile:
+ {
+ // debug only, comment it:
+ // if (_blocks) prop = (UInt32)0;
+ break;
}
}
prop.Detach(value);
@@ -343,7 +388,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value)
switch (propID)
{
case kpidSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break;
- case kpidPackSize: if (_phySize_Defined) prop = _stat.PhySize; break;
+ case kpidPackSize: if (_phySize_Defined) prop = _stat.InSize; break;
case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
}
prop.Detach(value);
@@ -354,27 +399,28 @@ STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value)
struct COpenCallbackWrap
{
- ICompressProgress p;
+ ICompressProgress vt;
IArchiveOpenCallback *OpenCallback;
HRESULT Res;
COpenCallbackWrap(IArchiveOpenCallback *progress);
};
-static SRes OpenCallbackProgress(void *pp, UInt64 inSize, UInt64 /* outSize */)
+static SRes OpenCallbackProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 /* outSize */)
{
- COpenCallbackWrap *p = (COpenCallbackWrap *)pp;
+ COpenCallbackWrap *p = CONTAINER_FROM_VTBL(pp, COpenCallbackWrap, vt);
if (p->OpenCallback)
p->Res = p->OpenCallback->SetCompleted(NULL, &inSize);
- return (SRes)p->Res;
+ return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);
}
COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback)
{
- p.Progress = OpenCallbackProgress;
+ vt.Progress = OpenCallbackProgress;
OpenCallback = callback;
Res = SZ_OK;
}
+
struct CXzsCPP
{
CXzs p;
@@ -382,6 +428,30 @@ struct CXzsCPP
~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }
};
+#define kInputBufSize ((size_t)1 << 10)
+
+struct CLookToRead2_CPP: public CLookToRead2
+{
+ CLookToRead2_CPP()
+ {
+ buf = NULL;
+ LookToRead2_CreateVTable(this,
+ True // Lookahead ?
+ );
+ }
+ void Alloc(size_t allocSize)
+ {
+ buf = (Byte *)MyAlloc(allocSize);
+ if (buf)
+ this->bufSize = allocSize;
+ }
+ ~CLookToRead2_CPP()
+ {
+ MyFree(buf);
+ }
+};
+
+
static HRESULT SRes_to_Open_HRESULT(SRes res)
{
switch (res)
@@ -401,14 +471,18 @@ static HRESULT SRes_to_Open_HRESULT(SRes res)
return S_FALSE;
}
+
+
HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback)
{
_needSeekToStart = true;
{
CXzStreamFlags st;
- CSeqInStreamWrap inStreamWrap(inStream);
- SRes res = Xz_ReadHeader(&st, &inStreamWrap.p);
+ CSeqInStreamWrap inStreamWrap;
+
+ inStreamWrap.Init(inStream);
+ SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt);
if (res != SZ_OK)
return SRes_to_Open_HRESULT(res);
@@ -416,34 +490,47 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
CXzBlock block;
Bool isIndex;
UInt32 headerSizeRes;
- SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes);
+ SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes);
if (res2 == SZ_OK && !isIndex)
{
+ _firstBlockWasRead = true;
+ _firstBlock = block;
+
unsigned numFilters = XzBlock_GetNumFilters(&block);
for (unsigned i = 0; i < numFilters; i++)
- AddString(_methodsString, GetMethodString(block.filters[i]));
+ {
+ _methodsString.Add_Space_if_NotEmpty();
+ AddMethodString(_methodsString, block.filters[i]);
+ }
}
}
}
- RINOK(inStream->Seek(0, STREAM_SEEK_END, &_stat.PhySize));
+ RINOK(inStream->Seek(0, STREAM_SEEK_END, &_stat.InSize));
if (callback)
{
- RINOK(callback->SetTotal(NULL, &_stat.PhySize));
+ RINOK(callback->SetTotal(NULL, &_stat.InSize));
}
- CSeekInStreamWrap inStreamImp(inStream);
+ CSeekInStreamWrap inStreamImp;
+
+ inStreamImp.Init(inStream);
+
+ CLookToRead2_CPP lookStream;
+
+ lookStream.Alloc(kInputBufSize);
+
+ if (!lookStream.buf)
+ return E_OUTOFMEMORY;
- CLookToRead lookStream;
- LookToRead_CreateVTable(&lookStream, True);
- lookStream.realStream = &inStreamImp.p;
- LookToRead_Init(&lookStream);
+ lookStream.realStream = &inStreamImp.vt;
+ LookToRead2_Init(&lookStream);
COpenCallbackWrap openWrap(callback);
CXzsCPP xzs;
Int64 startPosition;
- SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &startPosition, &openWrap.p, &g_Alloc);
+ SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.vt, &startPosition, &openWrap.vt, &g_Alloc);
if (res == SZ_ERROR_PROGRESS)
return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res;
/*
@@ -463,7 +550,64 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
_stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p);
_stat.NumBlocks_Defined = true;
- AddString(_methodsString, GetCheckString(xzs.p));
+ AddCheckString(_methodsString, xzs.p);
+
+ const size_t numBlocks = (size_t)_stat.NumBlocks + 1;
+ const size_t bytesAlloc = numBlocks * sizeof(CBlockInfo);
+
+ if (bytesAlloc / sizeof(CBlockInfo) == _stat.NumBlocks + 1)
+ {
+ _blocks = (CBlockInfo *)MyAlloc(bytesAlloc);
+ if (_blocks)
+ {
+ unsigned blockIndex = 0;
+ UInt64 unpackPos = 0;
+
+ for (size_t si = xzs.p.num; si != 0;)
+ {
+ si--;
+ const CXzStream &str = xzs.p.streams[si];
+ UInt64 packPos = str.startOffset + XZ_STREAM_HEADER_SIZE;
+
+ for (size_t bi = 0; bi < str.numBlocks; bi++)
+ {
+ const CXzBlockSizes &bs = str.blocks[bi];
+ const UInt64 packSizeAligned = bs.totalSize + ((0 - (unsigned)bs.totalSize) & 3);
+
+ if (bs.unpackSize != 0)
+ {
+ if (blockIndex >= _stat.NumBlocks)
+ return E_FAIL;
+
+ CBlockInfo &block = _blocks[blockIndex++];
+ block.StreamFlags = str.flags;
+ block.PackSize = bs.totalSize; // packSizeAligned;
+ block.PackPos = packPos;
+ block.UnpackPos = unpackPos;
+ }
+ packPos += packSizeAligned;
+ unpackPos += bs.unpackSize;
+ if (_maxBlocksSize < bs.unpackSize)
+ _maxBlocksSize = bs.unpackSize;
+ }
+ }
+
+ /*
+ if (blockIndex != _stat.NumBlocks)
+ {
+ // there are Empty blocks;
+ }
+ */
+ if (_stat.OutSize != unpackPos)
+ return E_FAIL;
+ CBlockInfo &block = _blocks[blockIndex++];
+ block.StreamFlags = 0;
+ block.PackSize = 0;
+ block.PackPos = 0;
+ block.UnpackPos = unpackPos;
+ _blocksArraySize = blockIndex;
+ }
+ }
}
else
{
@@ -477,6 +621,8 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
return S_OK;
}
+
+
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)
{
COM_TRY_BEGIN
@@ -498,202 +644,338 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
STDMETHODIMP CHandler::Close()
{
- _stat.Clear();
+ XzStatInfo_Clear(&_stat);
_isArc = false;
_needSeekToStart = false;
-
_phySize_Defined = false;
+ _firstBlockWasRead = false;
_methodsString.Empty();
_stream.Release();
_seqStream.Release();
+
+ MyFree(_blocks);
+ _blocks = NULL;
+ _blocksArraySize = 0;
+ _maxBlocksSize = 0;
+
+ MainDecodeSRes = SZ_OK;
+
return S_OK;
}
-class CSeekToSeqStream:
+
+struct CXzUnpackerCPP2
+{
+ Byte *InBuf;
+ // Byte *OutBuf;
+ CXzUnpacker p;
+
+ CXzUnpackerCPP2();
+ ~CXzUnpackerCPP2();
+};
+
+CXzUnpackerCPP2::CXzUnpackerCPP2(): InBuf(NULL)
+ // , OutBuf(NULL)
+{
+ XzUnpacker_Construct(&p, &g_Alloc);
+}
+
+CXzUnpackerCPP2::~CXzUnpackerCPP2()
+{
+ XzUnpacker_Free(&p);
+ MidFree(InBuf);
+ // MidFree(OutBuf);
+}
+
+
+class CInStream:
public IInStream,
public CMyUnknownImp
{
public:
- CMyComPtr<ISequentialInStream> Stream;
+ UInt64 _virtPos;
+ UInt64 Size;
+ UInt64 _cacheStartPos;
+ size_t _cacheSize;
+ CByteBuffer _cache;
+ // UInt64 _startPos;
+ CXzUnpackerCPP2 xz;
+
+ void InitAndSeek()
+ {
+ _virtPos = 0;
+ _cacheStartPos = 0;
+ _cacheSize = 0;
+ // _startPos = startPos;
+ }
+
+ CHandler *_handlerSpec;
+ CMyComPtr<IUnknown> _handler;
+
MY_UNKNOWN_IMP1(IInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+
+ ~CInStream();
};
-STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+
+CInStream::~CInStream()
{
- return Stream->Read(data, size, processedSize);
+ // _cache.Free();
}
-STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; }
-CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(0), OutBuf(0)
+size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos)
{
- XzUnpacker_Construct(&p, &g_Alloc);
+ size_t left = 0, right = numBlocks;
+ for (;;)
+ {
+ size_t mid = (left + right) / 2;
+ if (mid == left)
+ return left;
+ if (pos < blocks[mid].UnpackPos)
+ right = mid;
+ else
+ left = mid;
+ }
}
-CXzUnpackerCPP::~CXzUnpackerCPP()
-{
- XzUnpacker_Free(&p);
- MyFree(InBuf);
- MyFree(OutBuf);
-}
-HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
-{
- const size_t kInBufSize = 1 << 15;
- const size_t kOutBufSize = 1 << 21;
- Clear();
- DecodeRes = SZ_OK;
+static HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu,
+ ISequentialInStream *seqInStream,
+ unsigned streamFlags,
+ UInt64 packSize, // pure size from Index record, it doesn't include pad zeros
+ size_t unpackSize, Byte *dest
+ // , ICompressProgressInfo *progress
+ )
+{
+ const size_t kInBufSize = (size_t)1 << 16;
XzUnpacker_Init(&xzu.p);
+
if (!xzu.InBuf)
- xzu.InBuf = (Byte *)MyAlloc(kInBufSize);
- if (!xzu.OutBuf)
- xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);
+ {
+ xzu.InBuf = (Byte *)MidAlloc(kInBufSize);
+ if (!xzu.InBuf)
+ return E_OUTOFMEMORY;
+ }
+ xzu.p.streamFlags = (UInt16)streamFlags;
+ XzUnpacker_PrepareToRandomBlockDecoding(&xzu.p);
+
+ XzUnpacker_SetOutBuf(&xzu.p, dest, unpackSize);
+
+ const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
+ UInt64 packRem = packSizeAligned;
+
UInt32 inSize = 0;
SizeT inPos = 0;
SizeT outPos = 0;
+ HRESULT readRes = S_OK;
+
for (;;)
{
- if (inPos == inSize)
+ if (inPos == inSize && readRes == S_OK)
{
- inPos = inSize = 0;
- RINOK(seqInStream->Read(xzu.InBuf, kInBufSize, &inSize));
+ inPos = 0;
+ inSize = 0;
+ UInt32 rem = kInBufSize;
+ if (rem > packRem)
+ rem = (UInt32)packRem;
+ if (rem != 0)
+ readRes = seqInStream->Read(xzu.InBuf, rem, &inSize);
}
SizeT inLen = inSize - inPos;
- SizeT outLen = kOutBufSize - outPos;
- ECoderStatus status;
+ SizeT outLen = unpackSize - outPos;
+ ECoderStatus status;
+
SRes res = XzUnpacker_Code(&xzu.p,
- xzu.OutBuf + outPos, &outLen,
+ // dest + outPos,
+ NULL,
+ &outLen,
xzu.InBuf + inPos, &inLen,
- (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status);
+ (inLen == 0), // srcFinished
+ CODER_FINISH_END, &status);
- inPos += inLen;
- outPos += outLen;
+ // return E_OUTOFMEMORY;
+ // res = SZ_ERROR_CRC;
- InSize += inLen;
- OutSize += outLen;
+ if (res != SZ_OK)
+ {
+ if (res == SZ_ERROR_CRC)
+ return S_FALSE;
+ return SResToHRESULT(res);
+ }
- DecodeRes = res;
+ inPos += inLen;
+ outPos += outLen;
- bool finished = ((inLen == 0 && outLen == 0) || res != SZ_OK);
+ packRem -= inLen;
+
+ Bool blockFinished = XzUnpacker_IsBlockFinished(&xzu.p);
- if (outStream)
+ if ((inLen == 0 && outLen == 0) || blockFinished)
{
- if (outPos == kOutBufSize || finished)
- {
- if (outPos != 0)
- {
- RINOK(WriteStream(outStream, xzu.OutBuf, outPos));
- outPos = 0;
- }
- }
+ if (packRem != 0 || !blockFinished || unpackSize != outPos)
+ return S_FALSE;
+ if (XzUnpacker_GetPackSizeForIndex(&xzu.p) != packSize)
+ return S_FALSE;
+ return S_OK;
}
- else
- outPos = 0;
-
- if (progress)
+ }
+}
+
+
+STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ COM_TRY_BEGIN
+
+ if (processedSize)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+
+ {
+ if (_virtPos >= Size)
+ return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL;
{
- RINOK(progress->SetRatioInfo(&InSize, &OutSize));
+ UInt64 rem = Size - _virtPos;
+ if (size > rem)
+ size = (UInt32)rem;
}
-
- if (finished)
- {
- PhySize = InSize;
- NumStreams = xzu.p.numStartedStreams;
- if (NumStreams > 0)
- IsArc = true;
- NumBlocks = xzu.p.numTotalBlocks;
+ }
- UnpackSize_Defined = true;
- NumStreams_Defined = true;
- NumBlocks_Defined = true;
+ if (size == 0)
+ return S_OK;
- UInt64 extraSize = XzUnpacker_GetExtraSize(&xzu.p);
+ if (_virtPos < _cacheStartPos || _virtPos >= _cacheStartPos + _cacheSize)
+ {
+ size_t bi = FindBlock(_handlerSpec->_blocks, _handlerSpec->_blocksArraySize, _virtPos);
+ const CBlockInfo &block = _handlerSpec->_blocks[bi];
+ const UInt64 unpackSize = _handlerSpec->_blocks[bi + 1].UnpackPos - block.UnpackPos;
+ if (_cache.Size() < unpackSize)
+ return E_FAIL;
- if (res == SZ_OK)
- {
- if (status == CODER_STATUS_NEEDS_MORE_INPUT)
- {
- extraSize = 0;
- if (!XzUnpacker_IsStreamWasFinished(&xzu.p))
- {
- // finished at padding bytes, but padding is not aligned for 4
- UnexpectedEnd = true;
- res = SZ_ERROR_DATA;
- }
- }
- else // status == CODER_STATUS_NOT_FINISHED
- res = SZ_ERROR_DATA;
- }
- else if (res == SZ_ERROR_NO_ARCHIVE)
- {
- if (InSize == extraSize)
- IsArc = false;
- else
- {
- if (extraSize != 0 || inPos != inSize)
- {
- DataAfterEnd = true;
- res = SZ_OK;
- }
- }
- }
+ _cacheSize = 0;
- DecodeRes = res;
- PhySize -= extraSize;
+ RINOK(_handlerSpec->SeekToPackPos(block.PackPos));
+ RINOK(DecodeBlock(xz, _handlerSpec->_seqStream, block.StreamFlags, block.PackSize,
+ (size_t)unpackSize, _cache));
+ _cacheStartPos = block.UnpackPos;
+ _cacheSize = (size_t)unpackSize;
+ }
- switch (res)
- {
- case SZ_OK: break;
- case SZ_ERROR_NO_ARCHIVE: IsArc = false; break;
- case SZ_ERROR_ARCHIVE: HeadersError = true; break;
- case SZ_ERROR_UNSUPPORTED: Unsupported = true; break;
- case SZ_ERROR_CRC: CrcError = true; break;
- case SZ_ERROR_DATA: DataError = true; break;
- default: DataError = true; break;
- }
+ {
+ size_t offset = (size_t)(_virtPos - _cacheStartPos);
+ size_t rem = _cacheSize - offset;
+ if (size > rem)
+ size = (UInt32)rem;
+ memcpy(data, _cache + offset, size);
+ _virtPos += size;
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+ }
- break;
- }
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ switch (seekOrigin)
+ {
+ case STREAM_SEEK_SET: break;
+ case STREAM_SEEK_CUR: offset += _virtPos; break;
+ case STREAM_SEEK_END: offset += Size; break;
+ default: return STG_E_INVALIDFUNCTION;
}
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ _virtPos = offset;
+ if (newPosition)
+ *newPosition = offset;
+ return S_OK;
+}
+
+
+
+static const UInt64 kMaxBlockSize_for_GetStream = (UInt64)1 << 40;
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+ COM_TRY_BEGIN
+
+ *stream = NULL;
+ if (index != 0)
+ return E_INVALIDARG;
+
+ if (!_stat.UnpackSize_Defined
+ || _maxBlocksSize == 0 // 18.02
+ || _maxBlocksSize > kMaxBlockSize_for_GetStream
+ || _maxBlocksSize != (size_t)_maxBlocksSize)
+ return S_FALSE;
+
+ UInt64 memSize;
+ if (!NSystem::GetRamSize(memSize))
+ memSize = (UInt64)(sizeof(size_t)) << 28;
+ {
+ if (_maxBlocksSize > memSize / 4)
+ return S_FALSE;
+ }
+
+ CInStream *spec = new CInStream;
+ CMyComPtr<ISequentialInStream> specStream = spec;
+ spec->_cache.Alloc((size_t)_maxBlocksSize);
+ spec->_handlerSpec = this;
+ spec->_handler = (IInArchive *)this;
+ spec->Size = _stat.OutSize;
+ spec->InitAndSeek();
+
+ *stream = specStream.Detach();
return S_OK;
+
+ COM_TRY_END
}
-Int32 CDecoder::Get_Extract_OperationResult() const
+
+static Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder)
{
Int32 opRes;
- if (!IsArc)
+ SRes sres = decoder.MainDecodeSRes; // decoder.Stat.DecodeRes2;
+ if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc)
opRes = NExtract::NOperationResult::kIsNotArc;
- else if (UnexpectedEnd)
+ else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd)
opRes = NExtract::NOperationResult::kUnexpectedEnd;
- else if (DataAfterEnd)
+ else if (decoder.Stat.DataAfterEnd)
opRes = NExtract::NOperationResult::kDataAfterEnd;
- else if (CrcError)
+ else if (sres == SZ_ERROR_CRC) // (CrcError)
opRes = NExtract::NOperationResult::kCRCError;
- else if (Unsupported)
+ else if (sres == SZ_ERROR_UNSUPPORTED) // (Unsupported)
opRes = NExtract::NOperationResult::kUnsupportedMethod;
- else if (HeadersError)
+ else if (sres == SZ_ERROR_ARCHIVE) // (HeadersError)
opRes = NExtract::NOperationResult::kDataError;
- else if (DataError)
+ else if (sres == SZ_ERROR_DATA) // (DataError)
opRes = NExtract::NOperationResult::kDataError;
- else if (DecodeRes != SZ_OK)
+ else if (sres != SZ_OK)
opRes = NExtract::NOperationResult::kDataError;
else
opRes = NExtract::NOperationResult::kOK;
return opRes;
}
+
+
+
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
@@ -704,7 +986,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return E_INVALIDARG;
if (_phySize_Defined)
- extractCallback->SetTotal(_stat.PhySize);
+ extractCallback->SetTotal(_stat.InSize);
UInt64 currentTotalPacked = 0;
RINOK(extractCallback->SetCompleted(&currentTotalPacked));
@@ -733,15 +1015,26 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else
_needSeekToStart = true;
- CDecoder decoder;
- RINOK(Decode2(_seqStream, realOutStream, decoder, lpsRef));
- Int32 opRes = decoder.Get_Extract_OperationResult();
+
+ NCompress::NXz::CDecoder decoder;
+
+ HRESULT hres = Decode(decoder, _seqStream, realOutStream, lpsRef);
+
+ if (!decoder.MainDecodeSRes_wasUsed)
+ return hres == S_OK ? E_FAIL : hres;
+
+ Int32 opRes = Get_Extract_OperationResult(decoder);
+ if (opRes == NExtract::NOperationResult::kOK
+ && hres != S_OK)
+ opRes = NExtract::NOperationResult::kDataError;
realOutStream.Release();
return extractCallback->SetOperationResult(opRes);
COM_TRY_END
}
+
+
#ifndef EXTRACT_ONLY
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
@@ -750,16 +1043,17 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
return S_OK;
}
+
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
COM_TRY_BEGIN
- CSeqOutStreamWrap seqOutStream(outStream);
-
if (numItems == 0)
{
- SRes res = Xz_EncodeEmpty(&seqOutStream.p);
+ CSeqOutStreamWrap seqOutStream;
+ seqOutStream.Init(outStream);
+ SRes res = Xz_EncodeEmpty(&seqOutStream.vt);
return SResToHRESULT(res);
}
@@ -795,84 +1089,79 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
RINOK(updateCallback->SetTotal(size));
}
- CLzma2EncProps lzma2Props;
- Lzma2EncProps_Init(&lzma2Props);
+ NCompress::NXz::CEncoder *encoderSpec = new NCompress::NXz::CEncoder;
+ CMyComPtr<ICompressCoder> encoder = encoderSpec;
+
+ CXzProps &xzProps = encoderSpec->xzProps;
+ CLzma2EncProps &lzma2Props = xzProps.lzma2Props;
lzma2Props.lzmaProps.level = GetLevel();
- CMyComPtr<ISequentialInStream> fileInStream;
- RINOK(updateCallback->GetStream(0, &fileInStream));
+ xzProps.reduceSize = size;
+ /*
+ {
+ NCOM::CPropVariant prop = (UInt64)size;
+ RINOK(encoderSpec->SetCoderProp(NCoderPropID::kReduceSize, prop));
+ }
+ */
- CSeqInStreamWrap seqInStream(fileInStream);
+ #ifndef _7ZIP_ST
+ xzProps.numTotalThreads = _numThreads;
+ #endif
+ xzProps.blockSize = _numSolidBytes;
+ if (_numSolidBytes == XZ_PROPS__BLOCK_SIZE__SOLID)
{
- NCOM::CPropVariant prop = (UInt64)size;
- RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props));
+ xzProps.lzma2Props.blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID;
}
- FOR_VECTOR (i, _methods)
+ RINOK(encoderSpec->SetCheckSize(_crcSize));
+
{
- COneMethodInfo &m = _methods[i];
- SetGlobalLevelAndThreads(m
- #ifndef _7ZIP_ST
- , _numThreads
- #endif
- );
+ CXzFilterProps &filter = xzProps.filterProps;
+
+ if (_filterId == XZ_ID_Delta)
{
- FOR_VECTOR (j, m.Props)
+ bool deltaDefined = false;
+ FOR_VECTOR (j, _filterMethod.Props)
{
- const CProp &prop = m.Props[j];
- RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props));
+ const CProp &prop = _filterMethod.Props[j];
+ if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)
+ {
+ UInt32 delta = (UInt32)prop.Value.ulVal;
+ if (delta < 1 || delta > 256)
+ return E_INVALIDARG;
+ filter.delta = delta;
+ deltaDefined = true;
+ }
+ else
+ return E_INVALIDARG;
}
+ if (!deltaDefined)
+ return E_INVALIDARG;
}
+ filter.id = _filterId;
}
- #ifndef _7ZIP_ST
- lzma2Props.numTotalThreads = _numThreads;
- #endif
+ FOR_VECTOR (i, _methods)
+ {
+ COneMethodInfo &m = _methods[i];
+
+ FOR_VECTOR (j, m.Props)
+ {
+ const CProp &prop = m.Props[j];
+ RINOK(encoderSpec->SetCoderProp(prop.Id, prop.Value));
+ }
+ }
+
+ CMyComPtr<ISequentialInStream> fileInStream;
+ RINOK(updateCallback->GetStream(0, &fileInStream));
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true);
- CCompressProgressWrap progressWrap(progress);
- CXzProps xzProps;
- CXzFilterProps filter;
- XzProps_Init(&xzProps);
- XzFilterProps_Init(&filter);
- xzProps.lzma2Props = &lzma2Props;
- xzProps.filterProps = (_filterId != 0 ? &filter : NULL);
- switch (_crcSize)
- {
- case 0: xzProps.checkId = XZ_CHECK_NO; break;
- case 4: xzProps.checkId = XZ_CHECK_CRC32; break;
- case 8: xzProps.checkId = XZ_CHECK_CRC64; break;
- case 32: xzProps.checkId = XZ_CHECK_SHA256; break;
- default: return E_INVALIDARG;
- }
- filter.id = _filterId;
- if (_filterId == XZ_ID_Delta)
- {
- bool deltaDefined = false;
- FOR_VECTOR (j, _filterMethod.Props)
- {
- const CProp &prop = _filterMethod.Props[j];
- if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)
- {
- UInt32 delta = (UInt32)prop.Value.ulVal;
- if (delta < 1 || delta > 256)
- return E_INVALIDARG;
- filter.delta = delta;
- deltaDefined = true;
- }
- }
- if (!deltaDefined)
- return E_INVALIDARG;
- }
- SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &xzProps, &progressWrap.p);
- if (res == SZ_OK)
- return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
- return SResToHRESULT(res);
+ return encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress);
}
if (indexInArchive != 0)
@@ -888,7 +1177,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (_stream)
{
if (_phySize_Defined)
- RINOK(updateCallback->SetTotal(_stat.PhySize));
+ RINOK(updateCallback->SetTotal(_stat.InSize));
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
}
@@ -901,16 +1190,76 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_END
}
+#endif
+
+
+HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
+{
+ UString name = nameSpec;
+ name.MakeLower_Ascii();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+
+ #ifndef EXTRACT_ONLY
+
+ if (name[0] == L's')
+ {
+ const wchar_t *s = name.Ptr(1);
+ if (*s == 0)
+ {
+ bool useStr = false;
+ bool isSolid;
+ switch (value.vt)
+ {
+ case VT_EMPTY: isSolid = true; break;
+ case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
+ case VT_BSTR:
+ if (!StringToBool(value.bstrVal, isSolid))
+ useStr = true;
+ break;
+ default: return E_INVALIDARG;
+ }
+ if (!useStr)
+ {
+ _numSolidBytes = (isSolid ? XZ_PROPS__BLOCK_SIZE__SOLID : XZ_PROPS__BLOCK_SIZE__AUTO);
+ return S_OK;
+ }
+ }
+ return ParseSizeString(s, value,
+ 0, // percentsBase
+ _numSolidBytes) ? S_OK: E_INVALIDARG;
+ }
+
+ return CMultiMethodProps::SetProperty(name, value);
+
+ #else
+
+ {
+ HRESULT hres;
+ if (SetCommonProperty(name, value, hres))
+ return hres;
+ }
+
+ return E_INVALIDARG;
+
+ #endif
+}
+
+
+
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
Init();
+
for (UInt32 i = 0; i < numProps; i++)
{
RINOK(SetProperty(names[i], values[i]));
}
+ #ifndef EXTRACT_ONLY
+
if (!_filterMethod.MethodName.IsEmpty())
{
unsigned k;
@@ -935,16 +1284,19 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
AString &methodName = _methods[0].MethodName;
if (methodName.IsEmpty())
methodName = k_LZMA2_Name;
- else if (!methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name))
+ else if (
+ !methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name)
+ && !methodName.IsEqualTo_Ascii_NoCase("xz"))
return E_INVALIDARG;
}
+ #endif
+
return S_OK;
COM_TRY_END
}
-#endif
REGISTER_ARC_IO(
"xz", "xz txz", "* .tar", 0xC,
diff --git a/CPP/7zip/Archive/XzHandler.h b/CPP/7zip/Archive/XzHandler.h
index a61d4f7..18633fb 100644
--- a/CPP/7zip/Archive/XzHandler.h
+++ b/CPP/7zip/Archive/XzHandler.h
@@ -3,63 +3,9 @@
#ifndef __XZ_HANDLER_H
#define __XZ_HANDLER_H
-#include "../../../C/Xz.h"
-
-#include "../ICoder.h"
-
namespace NArchive {
namespace NXz {
-struct CXzUnpackerCPP
-{
- Byte *InBuf;
- Byte *OutBuf;
- CXzUnpacker p;
-
- CXzUnpackerCPP();
- ~CXzUnpackerCPP();
-};
-
-struct CStatInfo
-{
- UInt64 InSize;
- UInt64 OutSize;
- UInt64 PhySize;
-
- UInt64 NumStreams;
- UInt64 NumBlocks;
-
- bool UnpackSize_Defined;
-
- bool NumStreams_Defined;
- bool NumBlocks_Defined;
-
- bool IsArc;
- bool UnexpectedEnd;
- bool DataAfterEnd;
- bool Unsupported;
- bool HeadersError;
- bool DataError;
- bool CrcError;
-
- CStatInfo() { Clear(); }
-
- void Clear();
-};
-
-struct CDecoder: public CStatInfo
-{
- CXzUnpackerCPP xzu;
- SRes DecodeRes; // it's not HRESULT
-
- CDecoder(): DecodeRes(SZ_OK) {}
-
- /* Decode() can return ERROR code only if there is progress or stream error.
- Decode() returns S_OK in case of xz decoding error, but DecodeRes and CStatInfo contain error information */
- HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress);
- Int32 Get_Extract_OperationResult() const;
-};
-
}}
#endif
diff --git a/CPP/7zip/Asm.mak b/CPP/7zip/Asm.mak
index 1012b16..3ad238a 100644
--- a/CPP/7zip/Asm.mak
+++ b/CPP/7zip/Asm.mak
@@ -2,7 +2,7 @@
!IF "$(CPU)" == "ARM"
$(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm
$(COMPL_ASM)
-!ELSEIF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS"
+!ELSEIF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM64"
$(ASM_OBJS): ../../../../Asm/x86/$(*B).asm
$(COMPL_ASM)
!ENDIF
diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsp b/CPP/7zip/Bundles/Alone7z/Alone.dsp
index 37c059d..6147e10 100644
--- a/CPP/7zip/Bundles/Alone7z/Alone.dsp
+++ b/CPP/7zip/Bundles/Alone7z/Alone.dsp
@@ -44,7 +44,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /FAc /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAc /Yu"StdAfx.h" /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
@@ -69,7 +69,7 @@ LINK32=link.exe
# 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 /Gr /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gr /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
@@ -94,7 +94,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /Yu"StdAfx.h" /FD /c
-# ADD CPP /nologo /Gr /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gr /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
@@ -121,7 +121,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
-# ADD CPP /nologo /Gr /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gr /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
@@ -406,6 +406,10 @@ SOURCE=..\..\..\Common\Wildcard.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\XzCrc64Init.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\XzCrc64Reg.cpp
# End Source File
# End Group
@@ -478,6 +482,14 @@ SOURCE=..\..\..\Windows\FileName.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Windows\FileSystem.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileSystem.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Windows\Handle.h
# End Source File
# Begin Source File
@@ -804,6 +816,22 @@ SOURCE=..\..\Compress\LzmaEncoder.h
SOURCE=..\..\Compress\LzmaRegister.cpp
# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\XzDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\XzDecoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\XzEncoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\XzEncoder.h
+# End Source File
# End Group
# Begin Group "Archive"
@@ -1676,6 +1704,34 @@ SOURCE=..\..\..\..\C\Lzma2Dec.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Lzma2DecMt.c
+
+!IF "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2DecMt.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Lzma2Enc.c
!IF "$(CFG)" == "Alone - Win32 Release"
@@ -1769,6 +1825,34 @@ SOURCE=..\..\..\..\C\MtCoder.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\MtDec.c
+
+!IF "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\MtDec.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Threads.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile
index 814ccb7..91ee192 100644
--- a/CPP/7zip/Bundles/Alone7z/makefile
+++ b/CPP/7zip/Bundles/Alone7z/makefile
@@ -3,7 +3,7 @@ MY_CONSOLE = 1
CFLAGS = $(CFLAGS) -DPROG_VARIANT_R
!IFNDEF UNDER_CE
-CFLAGS = $(CFLAGS) -DWIN_LONG_PATH
+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE
!ENDIF
COMMON_OBJS = \
@@ -22,6 +22,7 @@ COMMON_OBJS = \
$O\UTFConvert.obj \
$O\MyVector.obj \
$O\Wildcard.obj \
+ $O\XzCrc64Init.obj \
$O\XzCrc64Reg.obj \
WIN_OBJS = \
@@ -32,6 +33,7 @@ WIN_OBJS = \
$O\FileIO.obj \
$O\FileLink.obj \
$O\FileName.obj \
+ $O\FileSystem.obj \
$O\MemoryLock.obj \
$O\PropVariant.obj \
$O\PropVariantConv.obj \
@@ -109,6 +111,8 @@ COMPRESS_OBJS = \
$O\LzmaDecoder.obj \
$O\LzmaEncoder.obj \
$O\LzmaRegister.obj \
+ $O\XzDecoder.obj \
+ $O\XzEncoder.obj \
CRYPTO_OBJS = \
$O\7zAes.obj \
@@ -130,10 +134,12 @@ C_OBJS = \
$O\LzFind.obj \
$O\LzFindMt.obj \
$O\Lzma2Dec.obj \
+ $O\Lzma2DecMt.obj \
$O\Lzma2Enc.obj \
$O\LzmaDec.obj \
$O\LzmaEnc.obj \
$O\MtCoder.obj \
+ $O\MtDec.obj \
$O\Sha256.obj \
$O\Sort.obj \
$O\Threads.obj \
@@ -147,5 +153,6 @@ C_OBJS = \
!include "../../Aes.mak"
!include "../../Crc.mak"
!include "../../Crc64.mak"
+!include "../../LzmaDec.mak"
!include "../../7zip.mak"
diff --git a/CPP/7zip/Bundles/Alone7z/resource.rc b/CPP/7zip/Bundles/Alone7z/resource.rc
index 3be08c9..36d70e7 100644
--- a/CPP/7zip/Bundles/Alone7z/resource.rc
+++ b/CPP/7zip/Bundles/Alone7z/resource.rc
@@ -1,3 +1,7 @@
#include "../../../../C/7zVersion.rc"
MY_VERSION_INFO_APP("7-Zip Reduced Standalone Console", "7zr")
+
+#ifndef UNDER_CE
+1 24 MOVEABLE PURE "../../UI/Console/Console.manifest"
+#endif
diff --git a/CPP/7zip/Bundles/Format7zExtractR/makefile b/CPP/7zip/Bundles/Format7zExtractR/makefile
index d34ab46..3a7f981 100644
--- a/CPP/7zip/Bundles/Format7zExtractR/makefile
+++ b/CPP/7zip/Bundles/Format7zExtractR/makefile
@@ -85,9 +85,12 @@ C_OBJS = \
$O\CpuArch.obj \
$O\Delta.obj \
$O\Lzma2Dec.obj \
+ $O\Lzma2DecMt.obj \
$O\LzmaDec.obj \
+ $O\MtDec.obj \
$O\Threads.obj \
!include "../../Crc.mak"
+!include "../../LzmaDec.mak"
!include "../../7zip.mak"
diff --git a/CPP/7zip/Bundles/Format7zR/makefile b/CPP/7zip/Bundles/Format7zR/makefile
index cd63c72..6a9dfb9 100644
--- a/CPP/7zip/Bundles/Format7zR/makefile
+++ b/CPP/7zip/Bundles/Format7zR/makefile
@@ -102,12 +102,15 @@ C_OBJS = \
$O\LzFind.obj \
$O\LzFindMt.obj \
$O\Lzma2Dec.obj \
+ $O\Lzma2DecMt.obj \
$O\Lzma2Enc.obj \
$O\LzmaDec.obj \
$O\LzmaEnc.obj \
$O\MtCoder.obj \
+ $O\MtDec.obj \
$O\Threads.obj \
!include "../../Crc.mak"
+!include "../../LzmaDec.mak"
!include "../../7zip.mak"
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
index fdad478..f273337 100644
--- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
@@ -4,6 +4,8 @@
#include <stdio.h>
+#include "../../../../C/CpuArch.h"
+
#if (defined(_WIN32) || defined(OS2) || defined(MSDOS)) && !defined(UNDER_CE)
#include <fcntl.h>
#include <io.h>
@@ -39,14 +41,16 @@
#include "../../UI/Console/BenchCon.h"
#include "../../UI/Console/ConsoleClose.h"
+bool g_LargePagesMode = false;
+
using namespace NCommandLineParser;
static const unsigned kDictSizeLog = 24;
-static const char *kCopyrightString = "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n\n";
+#define kCopyrightString "\nLZMA " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"
-static const char *kHelpString =
- "Usage: LZMA <command> [inputFile] [outputFile] [<switches>...]\n"
+static const char * const kHelpString =
+ "Usage: lzma <command> [inputFile] [outputFile] [<switches>...]\n"
"\n"
"<command>\n"
" e : Encode file\n"
@@ -67,9 +71,9 @@ static const char *kHelpString =
" -so : write data to stdout\n";
-static const char *kCantAllocate = "Can not allocate memory";
-static const char *kReadError = "Read error";
-static const char *kWriteError = "Write error";
+static const char * const kCantAllocate = "Can not allocate memory";
+static const char * const kReadError = "Read error";
+static const char * const kWriteError = "Write error";
namespace NKey {
@@ -117,6 +121,21 @@ static const CSwitchForm kSwitchForms[] =
};
+static void Convert_UString_to_AString(const UString &s, AString &temp)
+{
+ int codePage = CP_OEMCP;
+ /*
+ int g_CodePage = -1;
+ int codePage = g_CodePage;
+ if (codePage == -1)
+ codePage = CP_OEMCP;
+ if (codePage == CP_UTF8)
+ ConvertUnicodeToUTF8(s, temp);
+ else
+ */
+ UnicodeStringToMultiByte2(temp, s, (UINT)codePage);
+}
+
static void PrintErr(const char *s)
{
fputs(s, stderr);
@@ -135,10 +154,12 @@ static void PrintError(const char *s)
PrintErr_LF(s);
}
-static void PrintError2(const char *s1, const wchar_t *s2)
+static void PrintError2(const char *s1, const UString &s2)
{
PrintError(s1);
- PrintErr_LF(GetOemString(s2));
+ AString a;
+ Convert_UString_to_AString(s2, a);
+ PrintErr_LF(a);
}
static void PrintError_int(const char *s, int code)
@@ -208,7 +229,7 @@ public:
#define BACK_STR \
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
-static const char *kBackSpaces =
+static const char * const kBackSpaces =
BACK_STR
" "
BACK_STR;
@@ -298,7 +319,7 @@ static int Error_HRESULT(const char *s, HRESULT res)
static void AddProp(CObjectVector<CProperty> &props2, const char *name, const wchar_t *val)
{
CProperty &prop = props2.AddNew();
- prop.Name.SetFromAscii(name);
+ prop.Name = name;
prop.Value = val;
}
@@ -322,10 +343,10 @@ static int main2(int numArgs, const char *args[])
for (int i = 1; i < numArgs; i++)
commandStrings.Add(MultiByteToUnicodeString(args[i]));
- CParser parser(ARRAY_SIZE(kSwitchForms));
+ CParser parser;
try
{
- if (!parser.ParseStrings(kSwitchForms, commandStrings))
+ if (!parser.ParseStrings(kSwitchForms, ARRAY_SIZE(kSwitchForms), commandStrings))
{
PrintError2(parser.ErrorMessage, parser.ErrorLine);
return 1;
@@ -376,7 +397,7 @@ static int main2(int numArgs, const char *args[])
AddProp(props2, "x", s);
}
- UString mf = L"BT4";
+ UString mf ("BT4");
if (parser[NKey::kMatchFinder].ThereIs)
mf = parser[NKey::kMatchFinder].PostStrings[0];
diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
index f1e9a9e..8775319 100644
--- a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
+++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
@@ -117,6 +117,10 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h
# End Source File
# Begin Source File
+SOURCE=..\..\Archive\Common\HandlerOut.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Archive\Common\ItemNameUtils.cpp
# End Source File
# Begin Source File
@@ -293,6 +297,10 @@ SOURCE=..\..\Compress\Lzma2Decoder.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\Compress\Lzma2Decoder.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Compress\Lzma2Register.cpp
# End Source File
# Begin Source File
@@ -411,6 +419,14 @@ SOURCE=..\..\..\Windows\Synchronization.cpp
SOURCE=..\..\..\Windows\Synchronization.h
# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.h
+# End Source File
# End Group
# Begin Group "Common"
@@ -822,6 +838,15 @@ SOURCE=..\..\..\..\C\Lzma2Dec.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Lzma2DecMt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2DecMt.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\LzmaDec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
@@ -831,6 +856,15 @@ SOURCE=..\..\..\..\C\LzmaDec.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\MtDec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\MtDec.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Ppmd7.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
index e67c671..9b34a08 100644
--- a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
+++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../../C/CpuArch.h"
+
#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
@@ -37,8 +39,8 @@ HINSTANCE g_hInstance = 0;
int g_CodePage = -1;
extern CStdOutStream *g_StdStream;
-static const char *kCopyrightString =
-"\n7-Zip SFX " MY_VERSION_COPYRIGHT_DATE "\n";
+static const char * const kCopyrightString =
+"\n7-Zip SFX " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n";
static const int kNumSwitches = 6;
@@ -65,7 +67,6 @@ enum EEnum
}
/*
static const char kRecursedIDChar = 'R';
-static const wchar_t *kRecursedPostCharSet = L"0-";
namespace NRecursedPostCharIndex {
enum EEnum
@@ -101,10 +102,10 @@ static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] =
// static const bool kTestExtractRecursedDefault = true;
// static const bool kAddRecursedDefault = false;
-static const wchar_t *kUniversalWildcard = L"*";
+static const char * const kUniversalWildcard = "*";
static const int kCommandIndex = 0;
-static const char *kHelpString =
+static const char * const kHelpString =
"\nUsage: 7zSFX [<command>] [<switches>...] [<file_name>...]\n"
"\n"
"<Commands>\n"
@@ -121,16 +122,16 @@ static const char *kHelpString =
// ---------------------------
// exception messages
-static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError
-// static const char *kIncorrectListFile = "Incorrect wildcard in listfile";
-static const char *kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line";
+static const char * const kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError
+// static const char * const kIncorrectListFile = "Incorrect wildcard in listfile";
+static const char * const kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line";
// static const CSysString kFileIsNotArchiveMessageBefore = "File \"";
// static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive";
-// static const char *kProcessArchiveMessage = " archive: ";
+// static const char * const kProcessArchiveMessage = " archive: ";
-static const char *kCantFindSFX = " cannot find sfx";
+static const char * const kCantFindSFX = " cannot find sfx";
namespace NCommandType
{
@@ -280,13 +281,16 @@ int Main2(
#endif
- commandStrings.Delete(0);
+ #ifndef UNDER_CE
+ if (commandStrings.Size() > 0)
+ commandStrings.Delete(0);
+ #endif
- NCommandLineParser::CParser parser(kNumSwitches);
+ NCommandLineParser::CParser parser;
try
{
- if (!parser.ParseStrings(kSwitchForms, commandStrings))
+ if (!parser.ParseStrings(kSwitchForms, kNumSwitches, commandStrings))
{
g_StdOut << "Command line error:" << endl
<< parser.ErrorMessage << endl
@@ -331,7 +335,7 @@ int Main2(
{
if (nonSwitchStrings.Size() == curCommandIndex)
- AddCommandLineWildcardToCensor(wildcardCensor, kUniversalWildcard, true, recursedType);
+ AddCommandLineWildcardToCensor(wildcardCensor, (UString)kUniversalWildcard, true, recursedType);
for (; curCommandIndex < nonSwitchStrings.Size(); curCommandIndex++)
{
const UString &s = nonSwitchStrings[curCommandIndex];
diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile
index d81e512..30e8a38 100644
--- a/CPP/7zip/Bundles/SFXCon/makefile
+++ b/CPP/7zip/Bundles/SFXCon/makefile
@@ -1,5 +1,7 @@
PROG = 7zCon.sfx
MY_CONSOLE = 1
+MY_FIXED = 1
+
CFLAGS = $(CFLAGS) \
-DEXTRACT_ONLY \
-DNO_READ_FROM_CODER \
@@ -41,6 +43,7 @@ WIN_OBJS = \
$O\PropVariant.obj \
$O\PropVariantConv.obj \
$O\Synchronization.obj \
+ $O\System.obj \
7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \
@@ -117,7 +120,9 @@ C_OBJS = \
$O\Delta.obj \
$O\DllSecur.obj \
$O\Lzma2Dec.obj \
+ $O\Lzma2DecMt.obj \
$O\LzmaDec.obj \
+ $O\MtDec.obj \
$O\Ppmd7.obj \
$O\Ppmd7Dec.obj \
$O\Sha256.obj \
@@ -125,5 +130,6 @@ C_OBJS = \
!include "../../Aes.mak"
!include "../../Crc.mak"
+!include "../../LzmaDec.mak"
!include "../../7zip.mak"
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
index 5708349..d35a24f 100644
--- a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
@@ -15,9 +15,9 @@ using namespace NWindows;
using namespace NFile;
using namespace NDir;
-static LPCWSTR kCantDeleteFile = L"Can not delete output file";
-static LPCWSTR kCantOpenFile = L"Can not open output file";
-static LPCWSTR kUnsupportedMethod = L"Unsupported Method";
+static LPCSTR const kCantDeleteFile = "Can not delete output file";
+static LPCSTR const kCantOpenFile = "Can not open output file";
+static LPCSTR const kUnsupportedMethod = "Unsupported Method";
void CExtractCallbackImp::Init(IInArchive *archiveHandler,
const FString &directoryPath,
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
index 6d5b55a..194e376 100644
--- a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
@@ -18,8 +18,8 @@ using namespace NWindows;
using namespace NFile;
using namespace NDir;
-static LPCWSTR kCantFindArchive = L"Can not find archive file";
-static LPCWSTR kCantOpenArchive = L"Can not open the file as archive";
+static LPCSTR const kCantFindArchive = "Can not find archive file";
+static LPCSTR const kCantOpenArchive = "Can not open the file as archive";
struct CThreadExtracting
{
@@ -73,7 +73,7 @@ struct CThreadExtracting
return;
}
- ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, L"Default", fi.MTime, 0);
+ ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, (UString)"Default", fi.MTime, 0);
Result = ArchiveLink.GetArchive()->Extract(0, (UInt32)(Int32)-1 , BoolToInt(false), ExtractCallback);
}
diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
index 4bf2fb8..b1d740e 100644
--- a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
+++ b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
@@ -449,6 +449,14 @@ SOURCE=..\..\..\Windows\Synchronization.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Windows\System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Windows\Window.cpp
# End Source File
# Begin Source File
@@ -469,6 +477,14 @@ SOURCE=..\..\Common\CreateCoder.h
# End Source File
# Begin Source File
+SOURCE=..\..\Common\CWrappers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\CWrappers.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Common\FileStreams.cpp
# End Source File
# Begin Source File
@@ -724,6 +740,15 @@ SOURCE=..\..\..\..\C\Lzma2Dec.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Lzma2DecMt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2DecMt.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\LzmaDec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
@@ -733,6 +758,15 @@ SOURCE=..\..\..\..\C\LzmaDec.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\MtDec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\MtDec.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Threads.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
index be44f39..1705a8d 100644
--- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
@@ -33,7 +33,7 @@ using namespace NDir;
HINSTANCE g_hInstance;
-static CFSTR kTempDirPrefix = FTEXT("7zS");
+static CFSTR const kTempDirPrefix = FTEXT("7zS");
#define _SHELL_EXECUTE
@@ -169,7 +169,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
return 1;
}
- UString dirPrefix = L"." WSTRING_PATH_SEPARATOR;
+ UString dirPrefix ("." STRING_PATH_SEPARATOR);
UString appLaunched;
bool showProgress = true;
if (!config.IsEmpty())
@@ -181,12 +181,12 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
ShowErrorMessage(L"Config failed");
return 1;
}
- UString friendlyName = GetTextConfigValue(pairs, L"Title");
- UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt");
- UString progress = GetTextConfigValue(pairs, L"Progress");
+ UString friendlyName = GetTextConfigValue(pairs, "Title");
+ UString installPrompt = GetTextConfigValue(pairs, "BeginPrompt");
+ UString progress = GetTextConfigValue(pairs, "Progress");
if (progress.IsEqualTo_Ascii_NoCase("no"))
showProgress = false;
- int index = FindTextConfigItem(pairs, L"Directory");
+ int index = FindTextConfigItem(pairs, "Directory");
if (index >= 0)
dirPrefix = pairs[index].String;
if (!installPrompt.IsEmpty() && !assumeYes)
@@ -195,11 +195,11 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
MB_ICONQUESTION) != IDYES)
return 0;
}
- appLaunched = GetTextConfigValue(pairs, L"RunProgram");
+ appLaunched = GetTextConfigValue(pairs, "RunProgram");
#ifdef _SHELL_EXECUTE
- executeFile = GetTextConfigValue(pairs, L"ExecuteFile");
- executeParameters = GetTextConfigValue(pairs, L"ExecuteParameters");
+ executeFile = GetTextConfigValue(pairs, "ExecuteFile");
+ executeParameters = GetTextConfigValue(pairs, "ExecuteParameters");
#endif
}
@@ -260,7 +260,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
#ifdef _SHELL_EXECUTE
if (!executeFile.IsEmpty())
{
- CSysString filePath = GetSystemString(executeFile);
+ CSysString filePath (GetSystemString(executeFile));
SHELLEXECUTEINFO execInfo;
execInfo.cbSize = sizeof(execInfo);
execInfo.fMask = SEE_MASK_NOCLOSEPROCESS
@@ -278,7 +278,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
executeParameters += switches;
}
- CSysString parametersSys = GetSystemString(executeParameters);
+ CSysString parametersSys (GetSystemString(executeParameters));
if (parametersSys.IsEmpty())
execInfo.lpParameters = NULL;
else
@@ -337,7 +337,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
PROCESS_INFORMATION processInformation;
- CSysString appLaunchedSys = GetSystemString(dirPrefix + appLaunched);
+ CSysString appLaunchedSys (GetSystemString(dirPrefix + appLaunched));
BOOL createResult = CreateProcess(NULL, (LPTSTR)(LPCTSTR)appLaunchedSys,
NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */,
diff --git a/CPP/7zip/Bundles/SFXSetup/makefile b/CPP/7zip/Bundles/SFXSetup/makefile
index 2cd3976..b97daad 100644
--- a/CPP/7zip/Bundles/SFXSetup/makefile
+++ b/CPP/7zip/Bundles/SFXSetup/makefile
@@ -1,4 +1,6 @@
PROG = 7zS.sfx
+MY_FIXED = 1
+
CFLAGS = $(CFLAGS) \
-DNO_REGISTRY \
-DEXTRACT_ONLY \
@@ -33,6 +35,7 @@ WIN_OBJS = \
$O\PropVariant.obj \
$O\ResourceString.obj \
$O\Synchronization.obj \
+ $O\System.obj \
$O\Window.obj \
WIN_CTRL_OBJS = \
@@ -40,6 +43,7 @@ WIN_CTRL_OBJS = \
7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \
+ $O\CWrappers.obj \
$O\FileStreams.obj \
$O\InBuffer.obj \
$O\FilterCoder.obj \
@@ -102,9 +106,12 @@ C_OBJS = \
$O\Delta.obj \
$O\DllSecur.obj \
$O\Lzma2Dec.obj \
+ $O\Lzma2DecMt.obj \
$O\LzmaDec.obj \
+ $O\MtDec.obj \
$O\Threads.obj \
!include "../../Crc.mak"
+!include "../../LzmaDec.mak"
!include "../../7zip.mak"
diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
index 9ee6c77..83ec931 100644
--- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
+++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
@@ -633,6 +633,14 @@ SOURCE=..\..\..\Windows\Synchronization.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Windows\System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Windows\Window.cpp
# End Source File
# Begin Source File
@@ -906,6 +914,15 @@ SOURCE=..\..\..\..\C\Lzma2Dec.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Lzma2DecMt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2DecMt.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\LzmaDec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
@@ -915,6 +932,15 @@ SOURCE=..\..\..\..\C\LzmaDec.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\MtDec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\MtDec.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Ppmd7.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
diff --git a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
index 3f05e10..5eade1a 100644
--- a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
+++ b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
@@ -65,7 +65,7 @@ static DWORD GetDllVersion(LPCTSTR dllName)
bool g_LVN_ITEMACTIVATE_Support = true;
-static const wchar_t *kUnknownExceptionMessage = L"ERROR: Unknown Error!";
+static const wchar_t * const kUnknownExceptionMessage = L"ERROR: Unknown Error!";
void ErrorMessageForHRESULT(HRESULT res)
{
diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile
index 686eaff..21a67dd 100644
--- a/CPP/7zip/Bundles/SFXWin/makefile
+++ b/CPP/7zip/Bundles/SFXWin/makefile
@@ -1,4 +1,6 @@
PROG = 7z.sfx
+MY_FIXED = 1
+
CFLAGS = $(CFLAGS) \
-DNO_REGISTRY \
-DEXTRACT_ONLY \
@@ -41,6 +43,7 @@ WIN_OBJS = \
$O\ResourceString.obj \
$O\Shell.obj \
$O\Synchronization.obj \
+ $O\System.obj \
$O\Window.obj \
WIN_CTRL_OBJS = \
@@ -135,7 +138,9 @@ C_OBJS = \
$O\Delta.obj \
$O\DllSecur.obj \
$O\Lzma2Dec.obj \
+ $O\Lzma2DecMt.obj \
$O\LzmaDec.obj \
+ $O\MtDec.obj \
$O\Ppmd7.obj \
$O\Ppmd7Dec.obj \
$O\Sha256.obj \
@@ -143,5 +148,6 @@ C_OBJS = \
!include "../../Aes.mak"
!include "../../Crc.mak"
+!include "../../LzmaDec.mak"
!include "../../7zip.mak"
diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp
index 8bf3718..e726dad 100644
--- a/CPP/7zip/Common/CWrappers.cpp
+++ b/CPP/7zip/Common/CWrappers.cpp
@@ -8,43 +8,74 @@
#include "StreamUtils.h"
+SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw()
+{
+ switch (res)
+ {
+ case S_OK: return SZ_OK;
+ case E_OUTOFMEMORY: return SZ_ERROR_MEM;
+ case E_INVALIDARG: return SZ_ERROR_PARAM;
+ case E_ABORT: return SZ_ERROR_PROGRESS;
+ case S_FALSE: return SZ_ERROR_DATA;
+ case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED;
+ }
+ return defaultRes;
+}
+
+
+HRESULT SResToHRESULT(SRes res) throw()
+{
+ switch (res)
+ {
+ case SZ_OK: return S_OK;
+
+ case SZ_ERROR_DATA:
+ case SZ_ERROR_CRC:
+ case SZ_ERROR_INPUT_EOF:
+ return S_FALSE;
+
+ case SZ_ERROR_MEM: return E_OUTOFMEMORY;
+ case SZ_ERROR_PARAM: return E_INVALIDARG;
+ case SZ_ERROR_PROGRESS: return E_ABORT;
+ case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
+ // case SZ_ERROR_OUTPUT_EOF:
+ // case SZ_ERROR_READ:
+ // case SZ_ERROR_WRITE:
+ // case SZ_ERROR_THREAD:
+ // case SZ_ERROR_ARCHIVE:
+ // case SZ_ERROR_NO_ARCHIVE:
+ // return E_FAIL;
+ }
+ if (res < 0)
+ return res;
+ return E_FAIL;
+}
+
+
#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1)
#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x)
-static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) throw()
+
+static SRes CompressProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) throw()
{
- CCompressProgressWrap *p = (CCompressProgressWrap *)pp;
+ CCompressProgressWrap *p = CONTAINER_FROM_VTBL(pp, CCompressProgressWrap, vt);
p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize));
- return (SRes)p->Res;
+ return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);
}
-CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress) throw()
+void CCompressProgressWrap::Init(ICompressProgressInfo *progress) throw()
{
- p.Progress = CompressProgress;
+ vt.Progress = CompressProgress;
Progress = progress;
Res = SZ_OK;
}
static const UInt32 kStreamStepSize = (UInt32)1 << 31;
-SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes)
-{
- switch (res)
- {
- case S_OK: return SZ_OK;
- case E_OUTOFMEMORY: return SZ_ERROR_MEM;
- case E_INVALIDARG: return SZ_ERROR_PARAM;
- case E_ABORT: return SZ_ERROR_PROGRESS;
- case S_FALSE: return SZ_ERROR_DATA;
- case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED;
- }
- return defaultRes;
-}
-
-static SRes MyRead(void *object, void *data, size_t *size) throw()
+static SRes MyRead(const ISeqInStream *pp, void *data, size_t *size) throw()
{
- CSeqInStreamWrap *p = (CSeqInStreamWrap *)object;
+ CSeqInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqInStreamWrap, vt);
UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);
p->Res = (p->Stream->Read(data, curSize, &curSize));
*size = curSize;
@@ -54,9 +85,9 @@ static SRes MyRead(void *object, void *data, size_t *size) throw()
return HRESULT_To_SRes(p->Res, SZ_ERROR_READ);
}
-static size_t MyWrite(void *object, const void *data, size_t size) throw()
+static size_t MyWrite(const ISeqOutStream *pp, const void *data, size_t size) throw()
{
- CSeqOutStreamWrap *p = (CSeqOutStreamWrap *)object;
+ CSeqOutStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqOutStreamWrap, vt);
if (p->Stream)
{
p->Res = WriteStream(p->Stream, data, size);
@@ -69,47 +100,36 @@ static size_t MyWrite(void *object, const void *data, size_t size) throw()
return size;
}
-CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream) throw()
+
+void CSeqInStreamWrap::Init(ISequentialInStream *stream) throw()
{
- p.Read = MyRead;
+ vt.Read = MyRead;
Stream = stream;
Processed = 0;
+ Res = S_OK;
}
-CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) throw()
+void CSeqOutStreamWrap::Init(ISequentialOutStream *stream) throw()
{
- p.Write = MyWrite;
+ vt.Write = MyWrite;
Stream = stream;
Res = SZ_OK;
Processed = 0;
}
-HRESULT SResToHRESULT(SRes res) throw()
-{
- switch (res)
- {
- case SZ_OK: return S_OK;
- case SZ_ERROR_MEM: return E_OUTOFMEMORY;
- case SZ_ERROR_PARAM: return E_INVALIDARG;
- case SZ_ERROR_PROGRESS: return E_ABORT;
- case SZ_ERROR_DATA: return S_FALSE;
- case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
- }
- return E_FAIL;
-}
-static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) throw()
+static SRes InStreamWrap_Read(const ISeekInStream *pp, void *data, size_t *size) throw()
{
- CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp;
+ CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);
p->Res = p->Stream->Read(data, curSize, &curSize);
*size = curSize;
return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;
}
-static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) throw()
+static SRes InStreamWrap_Seek(const ISeekInStream *pp, Int64 *offset, ESzSeek origin) throw()
{
- CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp;
+ CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
UInt32 moveMethod;
switch (origin)
{
@@ -124,11 +144,11 @@ static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) throw()
return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;
}
-CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream) throw()
+void CSeekInStreamWrap::Init(IInStream *stream) throw()
{
Stream = stream;
- p.Read = InStreamWrap_Read;
- p.Seek = InStreamWrap_Seek;
+ vt.Read = InStreamWrap_Read;
+ vt.Seek = InStreamWrap_Seek;
Res = S_OK;
}
@@ -168,9 +188,9 @@ Byte CByteInBufWrap::ReadByteFromNewBlock() throw()
return 0;
}
-static Byte Wrap_ReadByte(void *pp) throw()
+static Byte Wrap_ReadByte(const IByteIn *pp) throw()
{
- CByteInBufWrap *p = (CByteInBufWrap *)pp;
+ CByteInBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteInBufWrap, vt);
if (p->Cur != p->Lim)
return *p->Cur++;
return p->ReadByteFromNewBlock();
@@ -178,7 +198,7 @@ static Byte Wrap_ReadByte(void *pp) throw()
CByteInBufWrap::CByteInBufWrap(): Buf(0)
{
- p.Read = Wrap_ReadByte;
+ vt.Read = Wrap_ReadByte;
}
@@ -214,9 +234,9 @@ HRESULT CByteOutBufWrap::Flush() throw()
return Res;
}
-static void Wrap_WriteByte(void *pp, Byte b) throw()
+static void Wrap_WriteByte(const IByteOut *pp, Byte b) throw()
{
- CByteOutBufWrap *p = (CByteOutBufWrap *)pp;
+ CByteOutBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteOutBufWrap, vt);
Byte *dest = p->Cur;
*dest = b;
p->Cur = ++dest;
@@ -226,5 +246,5 @@ static void Wrap_WriteByte(void *pp, Byte b) throw()
CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0)
{
- p.Write = Wrap_WriteByte;
+ vt.Write = Wrap_WriteByte;
}
diff --git a/CPP/7zip/Common/CWrappers.h b/CPP/7zip/Common/CWrappers.h
index 0872133..f93c98a 100644
--- a/CPP/7zip/Common/CWrappers.h
+++ b/CPP/7zip/Common/CWrappers.h
@@ -6,49 +6,54 @@
#include "../ICoder.h"
#include "../../Common/MyCom.h"
+SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw();
+HRESULT SResToHRESULT(SRes res) throw();
+
struct CCompressProgressWrap
{
- ICompressProgress p;
+ ICompressProgress vt;
ICompressProgressInfo *Progress;
HRESULT Res;
- CCompressProgressWrap(ICompressProgressInfo *progress) throw();
+ void Init(ICompressProgressInfo *progress) throw();
};
+
struct CSeqInStreamWrap
{
- ISeqInStream p;
+ ISeqInStream vt;
ISequentialInStream *Stream;
HRESULT Res;
UInt64 Processed;
- CSeqInStreamWrap(ISequentialInStream *stream) throw();
+ void Init(ISequentialInStream *stream) throw();
};
+
struct CSeekInStreamWrap
{
- ISeekInStream p;
+ ISeekInStream vt;
IInStream *Stream;
HRESULT Res;
- CSeekInStreamWrap(IInStream *stream) throw();
+ void Init(IInStream *stream) throw();
};
+
struct CSeqOutStreamWrap
{
- ISeqOutStream p;
+ ISeqOutStream vt;
ISequentialOutStream *Stream;
HRESULT Res;
UInt64 Processed;
- CSeqOutStreamWrap(ISequentialOutStream *stream) throw();
+ void Init(ISequentialOutStream *stream) throw();
};
-HRESULT SResToHRESULT(SRes res) throw();
struct CByteInBufWrap
{
- IByteIn p;
+ IByteIn vt;
const Byte *Cur;
const Byte *Lim;
Byte *Buf;
@@ -79,9 +84,10 @@ struct CByteInBufWrap
}
};
+
struct CByteOutBufWrap
{
- IByteOut p;
+ IByteOut vt;
Byte *Cur;
const Byte *Lim;
Byte *Buf;
diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp
index 53e7631..5040765 100644
--- a/CPP/7zip/Common/CreateCoder.cpp
+++ b/CPP/7zip/Common/CreateCoder.cpp
@@ -148,20 +148,23 @@ HRESULT CExternalCodecs::Load()
#endif
-bool FindMethod(
+int FindMethod_Index(
DECL_EXTERNAL_CODECS_LOC_VARS
const AString &name,
- CMethodId &methodId, UInt32 &numStreams)
+ bool encode,
+ CMethodId &methodId,
+ UInt32 &numStreams)
{
unsigned i;
for (i = 0; i < g_NumCodecs; i++)
{
const CCodecInfo &codec = *g_Codecs[i];
- if (StringsAreEqualNoCase_Ascii(name, codec.Name))
+ if ((encode ? codec.CreateEncoder : codec.CreateDecoder)
+ && StringsAreEqualNoCase_Ascii(name, codec.Name))
{
methodId = codec.Id;
numStreams = codec.NumStreams;
- return true;
+ return i;
}
}
@@ -173,19 +176,51 @@ bool FindMethod(
for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
{
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
- if (StringsAreEqualNoCase_Ascii(name, codec.Name))
+ if ((encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)
+ && StringsAreEqualNoCase_Ascii(name, codec.Name))
{
methodId = codec.Id;
numStreams = codec.NumStreams;
- return true;
+ return g_NumCodecs + i;
}
}
#endif
- return false;
+ return -1;
+}
+
+
+static int FindMethod_Index(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode)
+{
+ unsigned i;
+ for (i = 0; i < g_NumCodecs; i++)
+ {
+ const CCodecInfo &codec = *g_Codecs[i];
+ if (codec.Id == methodId && (encode ? codec.CreateEncoder : codec.CreateDecoder))
+ return i;
+ }
+
+ #ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
+ if (__externalCodecs)
+ for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
+ {
+ const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
+ if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned))
+ return g_NumCodecs + i;
+ }
+
+ #endif
+
+ return -1;
}
+
bool FindMethod(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId,
@@ -280,9 +315,11 @@ void GetHashMethods(
#endif
}
-HRESULT CreateCoder(
+
+
+HRESULT CreateCoder_Index(
DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId, bool encode,
+ unsigned i, bool encode,
CMyComPtr<ICompressFilter> &filter,
CCreatedCoder &cod)
{
@@ -290,11 +327,10 @@ HRESULT CreateCoder(
cod.IsFilter = false;
cod.NumStreams = 1;
- unsigned i;
- for (i = 0; i < g_NumCodecs; i++)
+ if (i < g_NumCodecs)
{
const CCodecInfo &codec = *g_Codecs[i];
- if (codec.Id == methodId)
+ // if (codec.Id == methodId)
{
if (encode)
{
@@ -325,11 +361,12 @@ HRESULT CreateCoder(
if (__externalCodecs)
{
+ i -= g_NumCodecs;
cod.IsExternal = true;
- for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
+ if (i < __externalCodecs->Codecs.Size())
{
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
- if (codec.Id == methodId)
+ // if (codec.Id == methodId)
{
if (encode)
{
@@ -371,13 +408,50 @@ HRESULT CreateCoder(
return S_OK;
}
-HRESULT CreateCoder(
+
+HRESULT CreateCoder_Index(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ unsigned index, bool encode,
+ CCreatedCoder &cod)
+{
+ CMyComPtr<ICompressFilter> filter;
+ HRESULT res = CreateCoder_Index(
+ EXTERNAL_CODECS_LOC_VARS
+ index, encode,
+ filter, cod);
+
+ if (filter)
+ {
+ cod.IsFilter = true;
+ CFilterCoder *coderSpec = new CFilterCoder(encode);
+ cod.Coder = coderSpec;
+ coderSpec->Filter = filter;
+ }
+
+ return res;
+}
+
+
+HRESULT CreateCoder_Id(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressFilter> &filter,
+ CCreatedCoder &cod)
+{
+ int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode);
+ if (index < 0)
+ return S_OK;
+ return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS index, encode, filter, cod);
+}
+
+
+HRESULT CreateCoder_Id(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId, bool encode,
CCreatedCoder &cod)
{
CMyComPtr<ICompressFilter> filter;
- HRESULT res = CreateCoder(
+ HRESULT res = CreateCoder_Id(
EXTERNAL_CODECS_LOC_VARS
methodId, encode,
filter, cod);
@@ -393,13 +467,14 @@ HRESULT CreateCoder(
return res;
}
-HRESULT CreateCoder(
+
+HRESULT CreateCoder_Id(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId, bool encode,
CMyComPtr<ICompressCoder> &coder)
{
CCreatedCoder cod;
- HRESULT res = CreateCoder(
+ HRESULT res = CreateCoder_Id(
EXTERNAL_CODECS_LOC_VARS
methodId, encode,
cod);
@@ -413,7 +488,7 @@ HRESULT CreateFilter(
CMyComPtr<ICompressFilter> &filter)
{
CCreatedCoder cod;
- return CreateCoder(
+ return CreateCoder_Id(
EXTERNAL_CODECS_LOC_VARS
methodId, encode,
filter, cod);
diff --git a/CPP/7zip/Common/CreateCoder.h b/CPP/7zip/Common/CreateCoder.h
index e0956e1..2105818 100644
--- a/CPP/7zip/Common/CreateCoder.h
+++ b/CPP/7zip/Common/CreateCoder.h
@@ -116,13 +116,12 @@ extern CExternalCodecs g_ExternalCodecs;
#endif
-
-
-
-bool FindMethod(
+int FindMethod_Index(
DECL_EXTERNAL_CODECS_LOC_VARS
const AString &name,
- CMethodId &methodId, UInt32 &numStreams);
+ bool encode,
+ CMethodId &methodId,
+ UInt32 &numStreams);
bool FindMethod(
DECL_EXTERNAL_CODECS_LOC_VARS
@@ -152,18 +151,29 @@ struct CCreatedCoder
};
-HRESULT CreateCoder(
+HRESULT CreateCoder_Index(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ unsigned codecIndex, bool encode,
+ CMyComPtr<ICompressFilter> &filter,
+ CCreatedCoder &cod);
+
+HRESULT CreateCoder_Index(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ unsigned index, bool encode,
+ CCreatedCoder &cod);
+
+HRESULT CreateCoder_Id(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId, bool encode,
CMyComPtr<ICompressFilter> &filter,
CCreatedCoder &cod);
-HRESULT CreateCoder(
+HRESULT CreateCoder_Id(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId, bool encode,
CCreatedCoder &cod);
-HRESULT CreateCoder(
+HRESULT CreateCoder_Id(
DECL_EXTERNAL_CODECS_LOC_VARS
CMethodId methodId, bool encode,
CMyComPtr<ICompressCoder> &coder);
diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp
index 6cbadf5..84c9e2b 100644
--- a/CPP/7zip/Common/FilePathAutoRename.cpp
+++ b/CPP/7zip/Common/FilePathAutoRename.cpp
@@ -2,9 +2,6 @@
#include "StdAfx.h"
-#include "../../Common/Defs.h"
-#include "../../Common/IntToString.h"
-
#include "../../Windows/FileFind.h"
#include "FilePathAutoRename.h"
@@ -14,10 +11,8 @@ using namespace NWindows;
static bool MakeAutoName(const FString &name,
const FString &extension, UInt32 value, FString &path)
{
- char temp[16];
- ConvertUInt32ToString(value, temp);
path = name;
- path.AddAscii(temp);
+ path.Add_UInt32(value);
path += extension;
return NFile::NFind::DoesFileOrDirExist(path);
}
@@ -34,7 +29,7 @@ bool AutoRenamePath(FString &path)
name.DeleteFrom(dotPos);
extension = path.Ptr(dotPos);
}
- name += FTEXT('_');
+ name += '_';
FString temp;
diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h
index 7890e56..0e2f84f 100644
--- a/CPP/7zip/Common/FilterCoder.h
+++ b/CPP/7zip/Common/FilterCoder.h
@@ -153,6 +153,15 @@ public:
~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }
};
+ class C_Filter_Releaser
+ {
+ public:
+ CFilterCoder *FilterCoder;
+ C_Filter_Releaser(): FilterCoder(NULL) {}
+ ~C_Filter_Releaser() { if (FilterCoder) FilterCoder->Filter.Release(); }
+ };
+
+
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp
index 7765d1b..826e98b 100644
--- a/CPP/7zip/Common/InBuffer.cpp
+++ b/CPP/7zip/Common/InBuffer.cpp
@@ -97,6 +97,33 @@ Byte CInBufferBase::ReadByte_FromNewBlock()
size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
{
+ size_t num = 0;
+ for (;;)
+ {
+ const size_t rem = _bufLim - _buf;
+ if (size <= rem)
+ {
+ if (size != 0)
+ {
+ memcpy(buf, _buf, size);
+ _buf += size;
+ num += size;
+ }
+ return num;
+ }
+ if (rem != 0)
+ {
+ memcpy(buf, _buf, rem);
+ _buf += rem;
+ buf += rem;
+ num += rem;
+ size -= rem;
+ }
+ if (!ReadBlock())
+ return num;
+ }
+
+ /*
if ((size_t)(_bufLim - _buf) >= size)
{
const Byte *src = _buf;
@@ -113,6 +140,7 @@ size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
buf[i] = *_buf++;
}
return size;
+ */
}
size_t CInBufferBase::Skip(size_t size)
diff --git a/CPP/7zip/Common/InBuffer.h b/CPP/7zip/Common/InBuffer.h
index f353b37..76e359a 100644
--- a/CPP/7zip/Common/InBuffer.h
+++ b/CPP/7zip/Common/InBuffer.h
@@ -59,7 +59,8 @@ public:
}
void Init() throw();
-
+
+ MY_FORCE_INLINE
bool ReadByte(Byte &b)
{
if (_buf >= _bufLim)
@@ -68,6 +69,7 @@ public:
return true;
}
+ MY_FORCE_INLINE
Byte ReadByte()
{
if (_buf >= _bufLim)
diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp
index cf4bffe..d83d674 100644
--- a/CPP/7zip/Common/InOutTempBuffer.cpp
+++ b/CPP/7zip/Common/InOutTempBuffer.cpp
@@ -15,7 +15,7 @@ using namespace NDir;
static const size_t kTempBufSize = (1 << 20);
-static CFSTR kTempFilePrefixString = FTEXT("7zt");
+#define kTempFilePrefixString FTEXT("7zt")
CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }
diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp
index 7036572..2134462 100644
--- a/CPP/7zip/Common/MethodProps.cpp
+++ b/CPP/7zip/Common/MethodProps.cpp
@@ -8,9 +8,9 @@
using namespace NWindows;
-bool StringToBool(const UString &s, bool &res)
+bool StringToBool(const wchar_t *s, bool &res)
{
- if (s.IsEmpty() || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON"))
+ if (s[0] == 0 || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON"))
{
res = true;
return true;
@@ -42,6 +42,14 @@ unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number)
return (unsigned)(end - start);
}
+static unsigned ParseStringToUInt64(const UString &srcString, UInt64 &number)
+{
+ const wchar_t *start = srcString;
+ const wchar_t *end;
+ number = ConvertStringToUInt64(start, &end);
+ return (unsigned)(end - start);
+}
+
HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
{
// =VT_UI4
@@ -95,7 +103,7 @@ static HRESULT StringToDictSize(const UString &s, NCOM::CPropVariant &destProp)
{
const wchar_t *end;
UInt32 number = ConvertStringToUInt32(s, &end);
- unsigned numDigits = (unsigned)(end - s);
+ unsigned numDigits = (unsigned)(end - s.Ptr());
if (numDigits == 0 || s.Len() > numDigits + 1)
return E_INVALIDARG;
@@ -144,17 +152,29 @@ static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, NCOM::CPropVaria
return S_OK;
}
if (prop.vt == VT_BSTR)
- return StringToDictSize(prop.bstrVal, destProp);
+ {
+ UString s;
+ s = prop.bstrVal;
+ return StringToDictSize(s, destProp);
+ }
return E_INVALIDARG;
}
-void CProps::AddProp32(PROPID propid, UInt32 level)
+void CProps::AddProp32(PROPID propid, UInt32 val)
+{
+ CProp &prop = Props.AddNew();
+ prop.IsOptional = true;
+ prop.Id = propid;
+ prop.Value = (UInt32)val;
+}
+
+void CProps::AddPropBool(PROPID propid, bool val)
{
CProp &prop = Props.AddNew();
prop.IsOptional = true;
prop.Id = propid;
- prop.Value = (UInt32)level;
+ prop.Value = val;
}
class CCoderProps
@@ -233,6 +253,9 @@ struct CNameToPropID
const char *Name;
};
+
+// the following are related to NCoderPropID::EEnum values
+
static const CNameToPropID g_NameToPropID[] =
{
{ VT_UI4, "" },
@@ -251,7 +274,12 @@ static const CNameToPropID g_NameToPropID[] =
{ VT_UI4, "mt" },
{ VT_BOOL, "eos" },
{ VT_UI4, "x" },
- { VT_UI4, "reduceSize" }
+ { VT_UI8, "reduce" },
+ { VT_UI8, "expect" },
+ { VT_UI4, "b" },
+ { VT_UI4, "check" },
+ { VT_BSTR, "filter" },
+ { VT_UI8, "memuse" }
};
static int FindPropIdExact(const UString &name)
@@ -269,6 +297,13 @@ static bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::C
destProp = srcProp;
return true;
}
+
+ if (varType == VT_UI8 && srcProp.vt == VT_UI4)
+ {
+ destProp = (UInt64)srcProp.ulVal;
+ return true;
+ }
+
if (varType == VT_BOOL)
{
bool res;
@@ -333,7 +368,8 @@ static bool IsLogSizeProp(PROPID propid)
case NCoderPropID::kDictionarySize:
case NCoderPropID::kUsedMemorySize:
case NCoderPropID::kBlockSize:
- case NCoderPropID::kReduceSize:
+ case NCoderPropID::kBlockSize2:
+ // case NCoderPropID::kReduceSize:
return true;
}
return false;
@@ -366,9 +402,22 @@ HRESULT CMethodProps::SetParam(const UString &name, const UString &value)
}
else if (!value.IsEmpty())
{
- UInt32 number;
- if (ParseStringToUInt32(value, number) == value.Len())
- propValue = number;
+ if (nameToPropID.VarType == VT_UI4)
+ {
+ UInt32 number;
+ if (ParseStringToUInt32(value, number) == value.Len())
+ propValue = number;
+ else
+ propValue = value;
+ }
+ else if (nameToPropID.VarType == VT_UI8)
+ {
+ UInt64 number;
+ if (ParseStringToUInt64(value, number) == value.Len())
+ propValue = number;
+ else
+ propValue = value;
+ }
else
propValue = value;
}
@@ -454,5 +503,7 @@ HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, cons
// -m{N}=method
if (value.vt != VT_BSTR)
return E_INVALIDARG;
- return ParseMethodFromString(value.bstrVal);
+ UString s;
+ s = value.bstrVal;
+ return ParseMethodFromString(s);
}
diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h
index 3f31c77..c8a3d0d 100644
--- a/CPP/7zip/Common/MethodProps.h
+++ b/CPP/7zip/Common/MethodProps.h
@@ -4,12 +4,15 @@
#define __7Z_METHOD_PROPS_H
#include "../../Common/MyString.h"
+#include "../../Common/Defs.h"
+
+#include "../../Windows/Defs.h"
#include "../../Windows/PropVariant.h"
#include "../ICoder.h"
-bool StringToBool(const UString &s, bool &res);
+bool StringToBool(const wchar_t *s, bool &res);
HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest);
unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number);
HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
@@ -38,7 +41,9 @@ struct CProps
return false;
}
- void AddProp32(PROPID propid, UInt32 level);
+ void AddProp32(PROPID propid, UInt32 val);
+
+ void AddPropBool(PROPID propid, bool val);
void AddProp_Ascii(PROPID propid, const char *s)
{
@@ -99,6 +104,18 @@ public:
return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26));
}
+ bool Get_Lzma_Eos() const
+ {
+ int i = FindProp(NCoderPropID::kEndMarker);
+ if (i >= 0)
+ {
+ const NWindows::NCOM::CPropVariant &val = Props[i].Value;
+ if (val.vt == VT_BOOL)
+ return VARIANT_BOOLToBool(val.boolVal);
+ }
+ return false;
+ }
+
bool Are_Lzma_Model_Props_Defined() const
{
if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true;
@@ -107,18 +124,64 @@ public:
return false;
}
- UInt32 Get_Lzma_NumThreads(bool &fixedNumber) const
+ UInt32 Get_Lzma_NumThreads() const
{
- fixedNumber = false;
+ if (Get_Lzma_Algo() == 0)
+ return 1;
int numThreads = Get_NumThreads();
if (numThreads >= 0)
- {
- fixedNumber = true;
return numThreads < 2 ? 1 : 2;
+ return 2;
+ }
+
+ int Get_Xz_NumThreads(UInt32 &lzmaThreads) const
+ {
+ lzmaThreads = 1;
+ int numThreads = Get_NumThreads();
+ if (numThreads >= 0 && numThreads <= 1)
+ return 1;
+ if (Get_Lzma_Algo() != 0)
+ lzmaThreads = 2;
+ return numThreads;
+ }
+
+ UInt64 GetProp_BlockSize(PROPID id) const
+ {
+ int i = FindProp(id);
+ if (i >= 0)
+ {
+ const NWindows::NCOM::CPropVariant &val = Props[i].Value;
+ if (val.vt == VT_UI4) { return val.ulVal; }
+ if (val.vt == VT_UI8) { return val.uhVal.QuadPart; }
}
- return Get_Lzma_Algo() == 0 ? 1 : 2;
+ return 0;
}
+ UInt64 Get_Xz_BlockSize() const
+ {
+ {
+ UInt64 blockSize1 = GetProp_BlockSize(NCoderPropID::kBlockSize);
+ UInt64 blockSize2 = GetProp_BlockSize(NCoderPropID::kBlockSize2);
+ UInt64 minSize = MyMin(blockSize1, blockSize2);
+ if (minSize != 0)
+ return minSize;
+ UInt64 maxSize = MyMax(blockSize1, blockSize2);
+ if (maxSize != 0)
+ return maxSize;
+ }
+ const UInt32 kMinSize = (UInt32)1 << 20;
+ const UInt32 kMaxSize = (UInt32)1 << 28;
+ UInt32 dictSize = Get_Lzma_DicSize();
+ 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);
+ return blockSize;
+ }
+
+
UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const
{
fixedNumber = false;
@@ -127,7 +190,8 @@ public:
{
fixedNumber = true;
if (numThreads < 1) return 1;
- if (numThreads > 64) return 64;
+ const unsigned kNumBZip2ThreadsMax = 64;
+ if (numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax;
return numThreads;
}
return 1;
@@ -170,6 +234,12 @@ public:
AddProp32(NCoderPropID::kNumThreads, numThreads);
}
+ void AddProp_EndMarker_if_NotFound(bool eos)
+ {
+ if (FindProp(NCoderPropID::kEndMarker) < 0)
+ AddPropBool(NCoderPropID::kEndMarker, eos);
+ }
+
HRESULT ParseParamsFromString(const UString &srcString);
HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
};
diff --git a/CPP/7zip/Common/OutBuffer.h b/CPP/7zip/Common/OutBuffer.h
index 90ce25d..2ffb5cd 100644
--- a/CPP/7zip/Common/OutBuffer.h
+++ b/CPP/7zip/Common/OutBuffer.h
@@ -47,8 +47,11 @@ public:
void WriteByte(Byte b)
{
- _buf[_pos++] = b;
- if (_pos == _limitPos)
+ UInt32 pos = _pos;
+ _buf[pos] = b;
+ pos++;
+ _pos = pos;
+ if (pos == _limitPos)
FlushWithCheck();
}
void WriteBytes(const void *data, size_t size)
diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp
index 261a626..4e083bf 100644
--- a/CPP/7zip/Compress/Bcj2Coder.cpp
+++ b/CPP/7zip/Compress/Bcj2Coder.cpp
@@ -463,10 +463,10 @@ HRESULT CDecoder::Code(ISequentialInStream * const *inStreams, const UInt64 * co
if (progress)
{
- UInt64 outSize2 = outSizeProcessed + (dec.dest - _bufs[BCJ2_NUM_STREAMS]);
+ const UInt64 outSize2 = outSizeProcessed + (dec.dest - _bufs[BCJ2_NUM_STREAMS]);
if (outSize2 - prevProgress >= (1 << 22))
{
- UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]);
+ const UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]);
RINOK(progress->SetRatioInfo(&inSize2, &outSize2));
prevProgress = outSize2;
}
@@ -655,4 +655,12 @@ STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
return res;
}
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value)
+{
+ const size_t rem = dec.lims[streamIndex] - dec.bufs[streamIndex] + _extraReadSizes[streamIndex];
+ *value = _inStreamsProcessed[streamIndex] - rem;
+ return S_OK;
+}
+
}}
diff --git a/CPP/7zip/Compress/Bcj2Coder.h b/CPP/7zip/Compress/Bcj2Coder.h
index ec58dab..666bf8c 100644
--- a/CPP/7zip/Compress/Bcj2Coder.h
+++ b/CPP/7zip/Compress/Bcj2Coder.h
@@ -62,6 +62,7 @@ public:
class CDecoder:
public ICompressCoder2,
public ICompressSetFinishMode,
+ public ICompressGetInStreamProcessedSize2,
public ICompressSetInStream2,
public ISequentialInStream,
public ICompressSetOutStreamSize,
@@ -84,9 +85,10 @@ class CDecoder:
// HRESULT ReadSpec();
public:
- MY_UNKNOWN_IMP6(
+ MY_UNKNOWN_IMP7(
ICompressCoder2,
ICompressSetFinishMode,
+ ICompressGetInStreamProcessedSize2,
ICompressSetInStream2,
ISequentialInStream,
ICompressSetOutStreamSize,
@@ -98,6 +100,7 @@ public:
ICompressProgressInfo *progress);
STDMETHOD(SetFinishMode)(UInt32 finishMode);
+ STDMETHOD(GetInStreamProcessedSize2)(UInt32 streamIndex, UInt64 *value);
STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream2)(UInt32 streamIndex);
diff --git a/CPP/7zip/Compress/CopyCoder.cpp b/CPP/7zip/Compress/CopyCoder.cpp
index 925493f..89b5237 100644
--- a/CPP/7zip/Compress/CopyCoder.cpp
+++ b/CPP/7zip/Compress/CopyCoder.cpp
@@ -15,6 +15,11 @@ CCopyCoder::~CCopyCoder()
::MidFree(_buf);
}
+STDMETHODIMP CCopyCoder::SetFinishMode(UInt32 /* finishMode */)
+{
+ return S_OK;
+}
+
STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 *outSize,
diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h
index f2620f1..b2fa491 100644
--- a/CPP/7zip/Compress/CopyCoder.h
+++ b/CPP/7zip/Compress/CopyCoder.h
@@ -13,6 +13,7 @@ class CCopyCoder:
public ICompressCoder,
public ICompressSetInStream,
public ISequentialInStream,
+ public ICompressSetFinishMode,
public ICompressGetInStreamProcessedSize,
public CMyUnknownImp
{
@@ -24,10 +25,11 @@ public:
CCopyCoder(): _buf(0), TotalSize(0) {};
~CCopyCoder();
- MY_UNKNOWN_IMP4(
+ MY_UNKNOWN_IMP5(
ICompressCoder,
ICompressSetInStream,
ISequentialInStream,
+ ICompressSetFinishMode,
ICompressGetInStreamProcessedSize)
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
@@ -35,6 +37,7 @@ public:
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream)();
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(SetFinishMode)(UInt32 finishMode);
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
};
diff --git a/CPP/7zip/Compress/Lzma2Decoder.cpp b/CPP/7zip/Compress/Lzma2Decoder.cpp
index 8b4afe2..bb631c5 100644
--- a/CPP/7zip/Compress/Lzma2Decoder.cpp
+++ b/CPP/7zip/Compress/Lzma2Decoder.cpp
@@ -2,263 +2,262 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#include "../../../C/Alloc.h"
+// #include "../../../C/CpuTicks.h"
#include "../Common/StreamUtils.h"
#include "Lzma2Decoder.h"
-static HRESULT SResToHRESULT(SRes res)
-{
- switch (res)
- {
- case SZ_OK: return S_OK;
- case SZ_ERROR_MEM: return E_OUTOFMEMORY;
- case SZ_ERROR_PARAM: return E_INVALIDARG;
- // case SZ_ERROR_PROGRESS: return E_ABORT;
- case SZ_ERROR_DATA: return S_FALSE;
- }
- return E_FAIL;
-}
-
namespace NCompress {
namespace NLzma2 {
CDecoder::CDecoder():
- _inBuf(NULL),
- _inBufSize(0),
- _inBufSizeNew(1 << 20),
- _outStepSize(1 << 22),
- _outSizeDefined(false),
- _finishMode(false)
-{
- Lzma2Dec_Construct(&_state);
-}
-
-STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; }
-STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStepSize = size; return S_OK; }
+ _dec(NULL)
+ , _inProcessed(0)
+ , _prop(0xFF)
+ , _finishMode(false)
+ , _inBufSize(1 << 20)
+ , _outStep(1 << 20)
+ #ifndef _7ZIP_ST
+ , _tryMt(1)
+ , _numThreads(1)
+ , _memUsage((UInt64)(sizeof(size_t)) << 28)
+ #endif
+{}
CDecoder::~CDecoder()
{
- Lzma2Dec_Free(&_state, &g_Alloc);
- MidFree(_inBuf);
+ if (_dec)
+ Lzma2DecMt_Destroy(_dec);
}
+STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; }
+
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
{
if (size != 1)
return E_NOTIMPL;
-
- RINOK(SResToHRESULT(Lzma2Dec_Allocate(&_state, prop[0], &g_Alloc)));
- if (!_inBuf || _inBufSize != _inBufSizeNew)
- {
- MidFree(_inBuf);
- _inBufSize = 0;
- _inBuf = (Byte *)MidAlloc(_inBufSizeNew);
- if (!_inBuf)
- return E_OUTOFMEMORY;
- _inBufSize = _inBufSizeNew;
- }
-
+ if (prop[0] > 40)
+ return E_NOTIMPL;
+ _prop = prop[0];
return S_OK;
}
-STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; }
-STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
-STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
-STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
+STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
{
- _outSizeDefined = (outSize != NULL);
- _outSize = 0;
- if (_outSizeDefined)
- _outSize = *outSize;
-
- Lzma2Dec_Init(&_state);
-
- _inPos = _inSize = 0;
- _inSizeProcessed = _outSizeProcessed = 0;
+ _finishMode = (finishMode != 0);
return S_OK;
}
-STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
+
+
+#ifndef _7ZIP_ST
+
+static UInt64 Get_ExpectedBlockSize_From_Dict(UInt32 dictSize)
{
- _finishMode = (finishMode != 0);
- return S_OK;
+ const UInt32 kMinSize = (UInt32)1 << 20;
+ const UInt32 kMaxSize = (UInt32)1 << 28;
+ 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);
+ return blockSize;
}
-STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
- ISequentialOutStream *outStream, const UInt64 *inSize,
- const UInt64 *outSize, ICompressProgressInfo *progress)
+#define LZMA2_DIC_SIZE_FROM_PROP_FULL(p) ((p) == 40 ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)))
+
+#endif
+
+#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes;
+
+#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
{
- if (!_inBuf)
- return S_FALSE;
- SetOutStreamSize(outSize);
-
- UInt32 step = _outStepSize;
- const UInt32 kOutStepSize_Min = 1 << 12;
- if (step < kOutStepSize_Min)
- step = kOutStepSize_Min;
-
- SizeT wrPos = _state.decoder.dicPos;
+ _inProcessed = 0;
+
+ if (!_dec)
+ {
+ _dec = Lzma2DecMt_Create(
+ // &g_AlignedAlloc,
+ &g_Alloc,
+ &g_MidAlloc);
+ if (!_dec)
+ return E_OUTOFMEMORY;
+ }
- SizeT next = (_state.decoder.dicBufSize - _state.decoder.dicPos < step) ?
- _state.decoder.dicBufSize :
- _state.decoder.dicPos + step;
+ CLzma2DecMtProps props;
+ Lzma2DecMtProps_Init(&props);
- HRESULT hres = S_OK;
+ props.inBufSize_ST = _inBufSize;
+ props.outStep_ST = _outStep;
- for (;;)
+ #ifndef _7ZIP_ST
{
- if (_inPos == _inSize)
- {
- _inPos = _inSize = 0;
- hres = inStream->Read(_inBuf, _inBufSize, &_inSize);
- if (hres != S_OK)
- break;
- }
+ props.numThreads = 1;
+ UInt32 numThreads = _numThreads;
- SizeT dicPos = _state.decoder.dicPos;
- SizeT curSize = next - dicPos;
-
- ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
- if (_outSizeDefined)
+ if (_tryMt && numThreads >= 1)
{
- const UInt64 rem = _outSize - _outSizeProcessed;
- if (curSize >= rem)
+ UInt64 useLimit = _memUsage;
+ UInt32 dictSize = LZMA2_DIC_SIZE_FROM_PROP_FULL(_prop);
+ UInt64 expectedBlockSize64 = Get_ExpectedBlockSize_From_Dict(dictSize);
+ size_t expectedBlockSize = (size_t)expectedBlockSize64;
+ size_t inBlockMax = expectedBlockSize + expectedBlockSize / 16;
+ if (expectedBlockSize == expectedBlockSize64 && inBlockMax >= expectedBlockSize)
{
- curSize = (SizeT)rem;
- if (_finishMode)
- finishMode = LZMA_FINISH_END;
+ props.outBlockMax = expectedBlockSize;
+ props.inBlockMax = inBlockMax;
+ const size_t kOverheadSize = props.inBufSize_MT + (1 << 16);
+ UInt64 okThreads = useLimit / (props.outBlockMax + props.inBlockMax + kOverheadSize);
+ if (numThreads > okThreads)
+ numThreads = (UInt32)okThreads;
+ if (numThreads == 0)
+ numThreads = 1;
+ props.numThreads = numThreads;
}
}
+ }
+ #endif
- SizeT inSizeProcessed = _inSize - _inPos;
- ELzmaStatus status;
- SRes res = Lzma2Dec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status);
+ CSeqInStreamWrap inWrap;
+ CSeqOutStreamWrap outWrap;
+ CCompressProgressWrap progressWrap;
- _inPos += (UInt32)inSizeProcessed;
- _inSizeProcessed += inSizeProcessed;
- SizeT outSizeProcessed = _state.decoder.dicPos - dicPos;
- _outSizeProcessed += outSizeProcessed;
+ inWrap.Init(inStream);
+ outWrap.Init(outStream);
+ progressWrap.Init(progress);
- bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0
- || status == LZMA_STATUS_FINISHED_WITH_MARK);
- bool outFinished = (_outSizeDefined && _outSizeProcessed >= _outSize);
+ SRes res;
- if (res != 0
- || _state.decoder.dicPos >= next
- || finished
- || outFinished)
- {
- HRESULT res2 = WriteStream(outStream, _state.decoder.dic + wrPos, _state.decoder.dicPos - wrPos);
+ UInt64 inProcessed = 0;
+ int isMT = False;
- if (_state.decoder.dicPos == _state.decoder.dicBufSize)
- _state.decoder.dicPos = 0;
-
- wrPos = _state.decoder.dicPos;
+ #ifndef _7ZIP_ST
+ isMT = _tryMt;
+ #endif
- next = (_state.decoder.dicBufSize - _state.decoder.dicPos < step) ?
- _state.decoder.dicBufSize :
- _state.decoder.dicPos + step;
+ // UInt64 cpuTicks = GetCpuTicks();
- if (res != 0)
- return S_FALSE;
- RINOK(res2);
+ res = Lzma2DecMt_Decode(_dec, _prop, &props,
+ &outWrap.vt, outSize, _finishMode,
+ &inWrap.vt,
+ &inProcessed,
+ &isMT,
+ progress ? &progressWrap.vt : NULL);
- if (finished)
- {
- if (status == LZMA_STATUS_FINISHED_WITH_MARK)
- {
- if (_finishMode && inSize && *inSize != _inSizeProcessed)
- return S_FALSE;
- if (finishMode == LZMA_FINISH_END && !outFinished)
- return S_FALSE;
- return S_OK;
- }
- return (finishMode == LZMA_FINISH_END) ? S_FALSE : S_OK;
- }
+ /*
+ cpuTicks = GetCpuTicks() - cpuTicks;
+ printf("\n ticks = %10I64u\n", cpuTicks / 1000000);
+ */
- if (outFinished && finishMode == LZMA_FINISH_ANY)
- return S_OK;
- }
-
- if (progress)
- {
- RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed));
- }
+
+ #ifndef _7ZIP_ST
+ /* we reset _tryMt, only if p->props.numThreads was changed */
+ if (props.numThreads > 1)
+ _tryMt = isMT;
+ #endif
+
+ _inProcessed = inProcessed;
+
+ RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
+ RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
+ RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)
+
+ if (res == SZ_OK && _finishMode)
+ {
+ if (inSize && *inSize != inProcessed)
+ res = SZ_ERROR_DATA;
+ if (outSize && *outSize != outWrap.Processed)
+ res = SZ_ERROR_DATA;
}
- HRESULT res2 = WriteStream(outStream, _state.decoder.dic + wrPos, _state.decoder.dicPos - wrPos);
- if (hres != S_OK)
- return hres;
- return res2;
+ return SResToHRESULT(res);
}
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+ *value = _inProcessed;
+ return S_OK;
+}
+
+
+#ifndef _7ZIP_ST
+
+STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads)
+{
+ _numThreads = numThreads;
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetMemLimit(UInt64 memUsage)
+{
+ _memUsage = memUsage;
+ return S_OK;
+}
+
+#endif
+
+
#ifndef NO_READ_FROM_CODER
-STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
{
- UInt32 totalProcessed = 0;
+ CLzma2DecMtProps props;
+ Lzma2DecMtProps_Init(&props);
+ props.inBufSize_ST = _inBufSize;
+ props.outStep_ST = _outStep;
+
+ _inProcessed = 0;
+
+ if (!_dec)
+ {
+ _dec = Lzma2DecMt_Create(&g_AlignedAlloc, &g_MidAlloc);
+ if (!_dec)
+ return E_OUTOFMEMORY;
+ }
+
+ _inWrap.Init(_inStream);
+ SRes res = Lzma2DecMt_Init(_dec, _prop, &props, outSize, _finishMode, &_inWrap.vt);
+
+ if (res != SZ_OK)
+ return SResToHRESULT(res);
+ return S_OK;
+}
+
+
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
+STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
+
+
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
if (processedSize)
*processedSize = 0;
- for (;;)
- {
- if (_inPos == _inSize)
- {
- _inPos = _inSize = 0;
- RINOK(_inStream->Read(_inBuf, _inBufSize, &_inSize));
- }
- {
- ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
- if (_outSizeDefined)
- {
- const UInt64 rem = _outSize - _outSizeProcessed;
- if (rem <= size)
- {
- size = (UInt32)rem;
- if (_finishMode)
- finishMode = LZMA_FINISH_END;
- }
- }
+ size_t size2 = size;
+ UInt64 inProcessed = 0;
- SizeT outProcessed = size;
- SizeT inProcessed = _inSize - _inPos;
-
- ELzmaStatus status;
- SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,
- _inBuf + _inPos, &inProcessed, finishMode, &status);
-
- _inPos += (UInt32)inProcessed;
- _inSizeProcessed += inProcessed;
- _outSizeProcessed += outProcessed;
- size -= (UInt32)outProcessed;
- data = (Byte *)data + outProcessed;
-
- totalProcessed += (UInt32)outProcessed;
- if (processedSize)
- *processedSize = totalProcessed;
-
- if (res != SZ_OK)
- {
- if (totalProcessed != 0)
- return S_OK;
- return SResToHRESULT(res);
- }
-
- if (inProcessed == 0 && outProcessed == 0)
- return S_OK;
- if (status == LZMA_STATUS_FINISHED_WITH_MARK)
- return S_OK;
- if (outProcessed != 0)
- {
- if (finishMode != LZMA_FINISH_END || _outSize != _outSizeProcessed)
- return S_OK;
- }
- }
- }
+ SRes res = Lzma2DecMt_Read(_dec, (Byte *)data, &size2, &inProcessed);
+
+ _inProcessed += inProcessed;
+ if (processedSize)
+ *processedSize = (UInt32)size2;
+ if (res != SZ_OK)
+ return SResToHRESULT(res);
+ return S_OK;
}
#endif
diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h
index 0ae43b0..b56488e 100644
--- a/CPP/7zip/Compress/Lzma2Decoder.h
+++ b/CPP/7zip/Compress/Lzma2Decoder.h
@@ -3,11 +3,9 @@
#ifndef __LZMA2_DECODER_H
#define __LZMA2_DECODER_H
-#include "../../../C/Lzma2Dec.h"
+#include "../../../C/Lzma2DecMt.h"
-#include "../../Common/MyCom.h"
-
-#include "../ICoder.h"
+#include "../Common/CWrappers.h"
namespace NCompress {
namespace NLzma2 {
@@ -18,69 +16,79 @@ class CDecoder:
public ICompressSetFinishMode,
public ICompressGetInStreamProcessedSize,
public ICompressSetBufSize,
+
#ifndef NO_READ_FROM_CODER
public ICompressSetInStream,
public ICompressSetOutStreamSize,
public ISequentialInStream,
#endif
- public CMyUnknownImp
-{
- CMyComPtr<ISequentialInStream> _inStream;
- Byte *_inBuf;
- UInt32 _inPos;
- UInt32 _inSize;
- bool _finishMode;
- bool _outSizeDefined;
- UInt64 _outSize;
+ #ifndef _7ZIP_ST
+ public ICompressSetCoderMt,
+ public ICompressSetMemLimit,
+ #endif
- UInt64 _inSizeProcessed;
- UInt64 _outSizeProcessed;
-
+ public CMyUnknownImp
+{
+ CLzma2DecMtHandle _dec;
+ UInt64 _inProcessed;
+ Byte _prop;
+ int _finishMode;
UInt32 _inBufSize;
- UInt32 _inBufSizeNew;
- UInt32 _outStepSize;
+ UInt32 _outStep;
- CLzma2Dec _state;
public:
-
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)
MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)
MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
+
#ifndef NO_READ_FROM_CODER
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
#endif
+
+ #ifndef _7ZIP_ST
+ MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetMemLimit)
+ #endif
+
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
-
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
-
STDMETHOD(SetFinishMode)(UInt32 finishMode);
-
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
-
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
- STDMETHOD(SetInStream)(ISequentialInStream *inStream);
- STDMETHOD(ReleaseInStream)();
-
- STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
+ #ifndef _7ZIP_ST
+private:
+ int _tryMt;
+ UInt32 _numThreads;
+ UInt64 _memUsage;
+public:
+ STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);
+ STDMETHOD(SetMemLimit)(UInt64 memUsage);
+ #endif
#ifndef NO_READ_FROM_CODER
+private:
+ CMyComPtr<ISequentialInStream> _inStream;
+ CSeqInStreamWrap _inWrap;
+public:
+ STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream);
+ STDMETHOD(ReleaseInStream)();
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
#endif
CDecoder();
virtual ~CDecoder();
-
};
}}
diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp
index 7fea9cc..18f7d02 100644
--- a/CPP/7zip/Compress/Lzma2Encoder.cpp
+++ b/CPP/7zip/Compress/Lzma2Encoder.cpp
@@ -21,18 +21,19 @@ namespace NLzma2 {
CEncoder::CEncoder()
{
- _encoder = 0;
- _encoder = Lzma2Enc_Create(&g_Alloc, &g_BigAlloc);
- if (_encoder == 0)
+ _encoder = NULL;
+ _encoder = Lzma2Enc_Create(&g_AlignedAlloc, &g_BigAlloc);
+ if (!_encoder)
throw 1;
}
CEncoder::~CEncoder()
{
- if (_encoder != 0)
+ if (_encoder)
Lzma2Enc_Destroy(_encoder);
}
+
HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props)
{
switch (propID)
@@ -42,12 +43,7 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm
if (prop.vt == VT_UI4)
lzma2Props.blockSize = prop.ulVal;
else if (prop.vt == VT_UI8)
- {
- size_t v = (size_t)prop.uhVal.QuadPart;
- if (v != prop.uhVal.QuadPart)
- return E_INVALIDARG;
- lzma2Props.blockSize = v;
- }
+ lzma2Props.blockSize = prop.uhVal.QuadPart;
else
return E_INVALIDARG;
break;
@@ -60,6 +56,7 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm
return S_OK;
}
+
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
const PROPVARIANT *coderProps, UInt32 numProps)
{
@@ -73,26 +70,52 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props));
}
+
+STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
+ const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ const PROPVARIANT &prop = coderProps[i];
+ PROPID propID = propIDs[i];
+ if (propID == NCoderPropID::kExpectedDataSize)
+ if (prop.vt == VT_UI8)
+ Lzma2Enc_SetDataSize(_encoder, prop.uhVal.QuadPart);
+ }
+ return S_OK;
+}
+
+
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
{
Byte prop = Lzma2Enc_WriteProperties(_encoder);
return WriteStream(outStream, &prop, 1);
}
+
+#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
+
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
{
- CSeqInStreamWrap inWrap(inStream);
- CSeqOutStreamWrap outWrap(outStream);
- CCompressProgressWrap progressWrap(progress);
-
- SRes res = Lzma2Enc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL);
- if (res == SZ_ERROR_READ && inWrap.Res != S_OK)
- return inWrap.Res;
- if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)
- return outWrap.Res;
- if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK)
- return progressWrap.Res;
+ CSeqInStreamWrap inWrap;
+ CSeqOutStreamWrap outWrap;
+ CCompressProgressWrap progressWrap;
+
+ inWrap.Init(inStream);
+ outWrap.Init(outStream);
+ progressWrap.Init(progress);
+
+ SRes res = Lzma2Enc_Encode2(_encoder,
+ &outWrap.vt, NULL, NULL,
+ &inWrap.vt, NULL, 0,
+ progress ? &progressWrap.vt : NULL);
+
+ RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
+ RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
+ RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
+
return SResToHRESULT(res);
}
diff --git a/CPP/7zip/Compress/Lzma2Encoder.h b/CPP/7zip/Compress/Lzma2Encoder.h
index 3b3d218..6539e73 100644
--- a/CPP/7zip/Compress/Lzma2Encoder.h
+++ b/CPP/7zip/Compress/Lzma2Encoder.h
@@ -16,16 +16,22 @@ class CEncoder:
public ICompressCoder,
public ICompressSetCoderProperties,
public ICompressWriteCoderProperties,
+ public ICompressSetCoderPropertiesOpt,
public CMyUnknownImp
{
CLzma2EncHandle _encoder;
public:
- MY_UNKNOWN_IMP3(ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties)
+ MY_UNKNOWN_IMP4(
+ ICompressCoder,
+ ICompressSetCoderProperties,
+ ICompressWriteCoderProperties,
+ ICompressSetCoderPropertiesOpt)
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+ STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
CEncoder();
virtual ~CEncoder();
diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp
index 20e409e..b6a8d3f 100644
--- a/CPP/7zip/Compress/LzmaDecoder.cpp
+++ b/CPP/7zip/Compress/LzmaDecoder.cpp
@@ -24,243 +24,318 @@ static HRESULT SResToHRESULT(SRes res)
namespace NCompress {
namespace NLzma {
-CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false),
- _inBufSize(1 << 20),
- _outBufSize(1 << 22),
+CDecoder::CDecoder():
+ _inBuf(NULL),
+ _lzmaStatus(LZMA_STATUS_NOT_SPECIFIED),
FinishStream(false),
- NeedMoreInput(false)
+ _propsWereSet(false),
+ _outSizeDefined(false),
+ _outStep(1 << 20),
+ _inBufSize(0),
+ _inBufSizeNew(1 << 20)
{
- _inSizeProcessed = 0;
- _inPos = _inSize = 0;
+ _inProcessed = 0;
+ _inPos = _inLim = 0;
+
+ /*
+ AlignOffsetAlloc_CreateVTable(&_alloc);
+ _alloc.numAlignBits = 7;
+ _alloc.offset = 0;
+ */
LzmaDec_Construct(&_state);
}
CDecoder::~CDecoder()
{
- LzmaDec_Free(&_state, &g_Alloc);
+ LzmaDec_Free(&_state, &g_AlignedAlloc); // &_alloc.vt
MyFree(_inBuf);
}
-STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
-STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }
+STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; }
+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; }
HRESULT CDecoder::CreateInputBuffer()
{
- if (_inBuf == 0 || _inBufSize != _inBufSizeAllocated)
+ if (!_inBuf || _inBufSizeNew != _inBufSize)
{
MyFree(_inBuf);
- _inBuf = (Byte *)MyAlloc(_inBufSize);
- if (_inBuf == 0)
+ _inBufSize = 0;
+ _inBuf = (Byte *)MyAlloc(_inBufSizeNew);
+ if (!_inBuf)
return E_OUTOFMEMORY;
- _inBufSizeAllocated = _inBufSize;
+ _inBufSize = _inBufSizeNew;
}
return S_OK;
}
+
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
{
- RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc)));
+ RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_AlignedAlloc))) // &_alloc.vt
_propsWereSet = true;
return CreateInputBuffer();
}
+
void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize)
{
_outSizeDefined = (outSize != NULL);
+ _outSize = 0;
if (_outSizeDefined)
_outSize = *outSize;
- _outSizeProcessed = 0;
- _wrPos = 0;
+ _outProcessed = 0;
+ _lzmaStatus = LZMA_STATUS_NOT_SPECIFIED;
+
LzmaDec_Init(&_state);
}
+
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
{
- _inSizeProcessed = 0;
- _inPos = _inSize = 0;
- NeedMoreInput = false;
+ _inProcessed = 0;
+ _inPos = _inLim = 0;
SetOutStreamSizeResume(outSize);
return S_OK;
}
+
STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
{
FinishStream = (finishMode != 0);
return S_OK;
}
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+ *value = _inProcessed;
+ return S_OK;
+}
+
+
HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
{
- if (_inBuf == 0 || !_propsWereSet)
+ if (!_inBuf || !_propsWereSet)
return S_FALSE;
+
+ const UInt64 startInProgress = _inProcessed;
+ SizeT wrPos = _state.dicPos;
+ HRESULT readRes = S_OK;
- UInt64 startInProgress = _inSizeProcessed;
-
- SizeT next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize);
for (;;)
{
- if (_inPos == _inSize)
+ if (_inPos == _inLim && readRes == S_OK)
{
- _inPos = _inSize = 0;
- RINOK(inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
+ _inPos = _inLim = 0;
+ readRes = inStream->Read(_inBuf, _inBufSize, &_inLim);
+ }
+
+ const SizeT dicPos = _state.dicPos;
+ SizeT size;
+ {
+ SizeT next = _state.dicBufSize;
+ if (next - wrPos > _outStep)
+ next = wrPos + _outStep;
+ size = next - dicPos;
}
- SizeT dicPos = _state.dicPos;
- SizeT curSize = next - dicPos;
-
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
if (_outSizeDefined)
{
- const UInt64 rem = _outSize - _outSizeProcessed;
- if (rem <= curSize)
+ const UInt64 rem = _outSize - _outProcessed;
+ if (size >= rem)
{
- curSize = (SizeT)rem;
+ size = (SizeT)rem;
if (FinishStream)
finishMode = LZMA_FINISH_END;
}
}
- SizeT inSizeProcessed = _inSize - _inPos;
+ SizeT inProcessed = _inLim - _inPos;
ELzmaStatus status;
- SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status);
+
+ SRes res = LzmaDec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status);
+
+ _lzmaStatus = status;
+ _inPos += (UInt32)inProcessed;
+ _inProcessed += inProcessed;
+ const SizeT outProcessed = _state.dicPos - dicPos;
+ _outProcessed += outProcessed;
- _inPos += (UInt32)inSizeProcessed;
- _inSizeProcessed += inSizeProcessed;
- SizeT outSizeProcessed = _state.dicPos - dicPos;
- _outSizeProcessed += outSizeProcessed;
+ // we check for LZMA_STATUS_NEEDS_MORE_INPUT to allow RangeCoder initialization, if (_outSizeDefined && _outSize == 0)
+ bool outFinished = (_outSizeDefined && _outProcessed >= _outSize);
- bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0);
- bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize);
+ bool needStop = (res != 0
+ || (inProcessed == 0 && outProcessed == 0)
+ || status == LZMA_STATUS_FINISHED_WITH_MARK
+ || (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT));
- if (res != 0 || _state.dicPos == next || finished || stopDecoding)
+ if (needStop || outProcessed >= size)
{
- HRESULT res2 = WriteStream(outStream, _state.dic + _wrPos, _state.dicPos - _wrPos);
+ HRESULT res2 = WriteStream(outStream, _state.dic + wrPos, _state.dicPos - wrPos);
- _wrPos = _state.dicPos;
if (_state.dicPos == _state.dicBufSize)
- {
_state.dicPos = 0;
- _wrPos = 0;
- }
- next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize);
-
- if (res != 0)
- return S_FALSE;
+ wrPos = _state.dicPos;
+
RINOK(res2);
- if (stopDecoding)
+
+ if (needStop)
{
- if (status == LZMA_STATUS_NEEDS_MORE_INPUT)
- NeedMoreInput = true;
- if (FinishStream &&
- status != LZMA_STATUS_FINISHED_WITH_MARK &&
- status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
+ if (res != 0)
return S_FALSE;
- return S_OK;
- }
- if (finished)
- {
- if (status == LZMA_STATUS_NEEDS_MORE_INPUT)
- NeedMoreInput = true;
- return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);
+
+ if (status == LZMA_STATUS_FINISHED_WITH_MARK)
+ {
+ if (FinishStream)
+ if (_outSizeDefined && _outSize != _outProcessed)
+ return S_FALSE;
+ return readRes;
+ }
+
+ if (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT)
+ if (!FinishStream || status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
+ return readRes;
+
+ return S_FALSE;
}
}
+
if (progress)
{
- UInt64 inSize = _inSizeProcessed - startInProgress;
- RINOK(progress->SetRatioInfo(&inSize, &_outSizeProcessed));
+ const UInt64 inSize = _inProcessed - startInProgress;
+ RINOK(progress->SetRatioInfo(&inSize, &_outProcessed));
}
}
}
+
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
{
- if (_inBuf == 0)
+ if (!_inBuf)
return E_INVALIDARG;
SetOutStreamSize(outSize);
- return CodeSpec(inStream, outStream, progress);
+ HRESULT res = CodeSpec(inStream, outStream, progress);
+ if (res == S_OK)
+ if (FinishStream && inSize && *inSize != _inProcessed)
+ res = S_FALSE;
+ return res;
}
+
#ifndef NO_READ_FROM_CODER
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
+
STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
*processedSize = 0;
- do
+
+ ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
+ if (_outSizeDefined)
{
- if (_inPos == _inSize)
+ const UInt64 rem = _outSize - _outProcessed;
+ if (size >= rem)
{
- _inPos = _inSize = 0;
- RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
+ size = (UInt32)rem;
+ if (FinishStream)
+ finishMode = LZMA_FINISH_END;
}
+ }
+
+ HRESULT readRes = S_OK;
+
+ for (;;)
+ {
+ if (_inPos == _inLim && readRes == S_OK)
{
- SizeT inProcessed = _inSize - _inPos;
+ _inPos = _inLim = 0;
+ readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);
+ }
- if (_outSizeDefined)
- {
- const UInt64 rem = _outSize - _outSizeProcessed;
- if (rem < size)
- size = (UInt32)rem;
- }
+ SizeT inProcessed = _inLim - _inPos;
+ SizeT outProcessed = size;
+ ELzmaStatus status;
+
+ SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,
+ _inBuf + _inPos, &inProcessed, finishMode, &status);
+
+ _lzmaStatus = status;
+ _inPos += (UInt32)inProcessed;
+ _inProcessed += inProcessed;
+ _outProcessed += outProcessed;
+ size -= (UInt32)outProcessed;
+ data = (Byte *)data + outProcessed;
+ if (processedSize)
+ *processedSize += (UInt32)outProcessed;
+
+ if (res != 0)
+ return S_FALSE;
+
+ /*
+ if (status == LZMA_STATUS_FINISHED_WITH_MARK)
+ return readRes;
- SizeT outProcessed = size;
- ELzmaStatus status;
- SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,
- _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status);
- _inPos += (UInt32)inProcessed;
- _inSizeProcessed += inProcessed;
- _outSizeProcessed += outProcessed;
- size -= (UInt32)outProcessed;
- data = (Byte *)data + outProcessed;
- if (processedSize)
- *processedSize += (UInt32)outProcessed;
- RINOK(SResToHRESULT(res));
- if (inProcessed == 0 && outProcessed == 0)
- return S_OK;
+ if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
+ {
+ if (FinishStream
+ && _outSizeDefined && _outProcessed >= _outSize
+ && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
+ return S_FALSE;
+ return readRes;
}
+ */
+
+ if (inProcessed == 0 && outProcessed == 0)
+ return readRes;
}
- while (size != 0);
- return S_OK;
}
+
HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)
{
SetOutStreamSizeResume(outSize);
return CodeSpec(_inStream, outStream, progress);
}
+
HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize)
{
RINOK(CreateInputBuffer());
+
if (processedSize)
*processedSize = 0;
- while (size > 0)
+
+ HRESULT readRes = S_OK;
+
+ while (size != 0)
{
- if (_inPos == _inSize)
+ if (_inPos == _inLim)
{
- _inPos = _inSize = 0;
- RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
- if (_inSize == 0)
+ _inPos = _inLim = 0;
+ if (readRes == S_OK)
+ readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);
+ if (_inLim == 0)
break;
}
- {
- UInt32 curSize = _inSize - _inPos;
- if (curSize > size)
- curSize = size;
- memcpy(data, _inBuf + _inPos, curSize);
- _inPos += curSize;
- _inSizeProcessed += curSize;
- size -= curSize;
- data = (Byte *)data + curSize;
- if (processedSize)
- *processedSize += curSize;
- }
+
+ UInt32 cur = _inLim - _inPos;
+ if (cur > size)
+ cur = size;
+ memcpy(data, _inBuf + _inPos, cur);
+ _inPos += cur;
+ _inProcessed += cur;
+ size -= cur;
+ data = (Byte *)data + cur;
+ if (processedSize)
+ *processedSize += cur;
}
- return S_OK;
+
+ return readRes;
}
#endif
diff --git a/CPP/7zip/Compress/LzmaDecoder.h b/CPP/7zip/Compress/LzmaDecoder.h
index a4d7206..08b7c1b 100644
--- a/CPP/7zip/Compress/LzmaDecoder.h
+++ b/CPP/7zip/Compress/LzmaDecoder.h
@@ -3,6 +3,7 @@
#ifndef __LZMA_DECODER_H
#define __LZMA_DECODER_H
+// #include "../../../C/Alloc.h"
#include "../../../C/LzmaDec.h"
#include "../../Common/MyCom.h"
@@ -15,6 +16,7 @@ class CDecoder:
public ICompressCoder,
public ICompressSetDecoderProperties2,
public ICompressSetFinishMode,
+ public ICompressGetInStreamProcessedSize,
public ICompressSetBufSize,
#ifndef NO_READ_FROM_CODER
public ICompressSetInStream,
@@ -23,21 +25,29 @@ class CDecoder:
#endif
public CMyUnknownImp
{
- CMyComPtr<ISequentialInStream> _inStream;
Byte *_inBuf;
UInt32 _inPos;
- UInt32 _inSize;
- CLzmaDec _state;
+ UInt32 _inLim;
+
+ ELzmaStatus _lzmaStatus;
+
+public:
+ bool FinishStream; // set it before decoding, if you need to decode full LZMA stream
+
+private:
bool _propsWereSet;
bool _outSizeDefined;
UInt64 _outSize;
- UInt64 _inSizeProcessed;
- UInt64 _outSizeProcessed;
+ UInt64 _inProcessed;
+ UInt64 _outProcessed;
- UInt32 _inBufSizeAllocated;
+ UInt32 _outStep;
UInt32 _inBufSize;
- UInt32 _outBufSize;
- SizeT _wrPos;
+ UInt32 _inBufSizeNew;
+
+ // CAlignOffsetAlloc _alloc;
+
+ CLzmaDec _state;
HRESULT CreateInputBuffer();
HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
@@ -47,6 +57,7 @@ public:
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)
MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
+ MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)
MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
#ifndef NO_READ_FROM_CODER
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
@@ -60,11 +71,16 @@ public:
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
STDMETHOD(SetFinishMode)(UInt32 finishMode);
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
#ifndef NO_READ_FROM_CODER
+
+private:
+ CMyComPtr<ISequentialInStream> _inStream;
+public:
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream)();
@@ -72,18 +88,24 @@ public:
HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress);
HRESULT ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize);
- UInt64 GetInputProcessedSize() const { return _inSizeProcessed; }
-
+
#endif
- bool FinishStream; // set it before decoding, if you need to decode full LZMA stream
-
- bool NeedMoreInput; // it's set by decoder, if it needs more input data to decode stream
+ UInt64 GetInputProcessedSize() const { return _inProcessed; }
CDecoder();
virtual ~CDecoder();
- UInt64 GetOutputProcessedSize() const { return _outSizeProcessed; }
+ UInt64 GetOutputProcessedSize() const { return _outProcessed; }
+
+ bool NeedsMoreInput() const { return _lzmaStatus == LZMA_STATUS_NEEDS_MORE_INPUT; }
+
+ bool CheckFinishStatus(bool withEndMark) const
+ {
+ return _lzmaStatus == (withEndMark ?
+ LZMA_STATUS_FINISHED_WITH_MARK :
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK);
+ }
};
}}
diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp
index 10af8c5..3151c3d 100644
--- a/CPP/7zip/Compress/LzmaEncoder.cpp
+++ b/CPP/7zip/Compress/LzmaEncoder.cpp
@@ -15,7 +15,7 @@ namespace NLzma {
CEncoder::CEncoder()
{
_encoder = NULL;
- _encoder = LzmaEnc_Create(&g_Alloc);
+ _encoder = LzmaEnc_Create(&g_AlignedAlloc);
if (!_encoder)
throw 1;
}
@@ -23,7 +23,7 @@ CEncoder::CEncoder()
CEncoder::~CEncoder()
{
if (_encoder)
- LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc);
+ LzmaEnc_Destroy(_encoder, &g_AlignedAlloc, &g_BigAlloc);
}
static inline wchar_t GetUpperChar(wchar_t c)
@@ -74,14 +74,19 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)
return E_INVALIDARG;
return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;
}
+
if (propID > NCoderPropID::kReduceSize)
return S_OK;
+
if (propID == NCoderPropID::kReduceSize)
{
if (prop.vt == VT_UI8)
ep.reduceSize = prop.uhVal.QuadPart;
+ else
+ return E_INVALIDARG;
return S_OK;
}
+
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 v = prop.ulVal;
@@ -123,6 +128,22 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props));
}
+
+STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
+ const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ const PROPVARIANT &prop = coderProps[i];
+ PROPID propID = propIDs[i];
+ if (propID == NCoderPropID::kExpectedDataSize)
+ if (prop.vt == VT_UI8)
+ LzmaEnc_SetDataSize(_encoder, prop.uhVal.QuadPart);
+ }
+ return S_OK;
+}
+
+
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
{
Byte props[LZMA_PROPS_SIZE];
@@ -131,21 +152,30 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
return WriteStream(outStream, props, size);
}
+
+#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
+
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
{
- CSeqInStreamWrap inWrap(inStream);
- CSeqOutStreamWrap outWrap(outStream);
- CCompressProgressWrap progressWrap(progress);
+ CSeqInStreamWrap inWrap;
+ CSeqOutStreamWrap outWrap;
+ CCompressProgressWrap progressWrap;
+
+ inWrap.Init(inStream);
+ outWrap.Init(outStream);
+ progressWrap.Init(progress);
+
+ SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt,
+ progress ? &progressWrap.vt : NULL, &g_AlignedAlloc, &g_BigAlloc);
- SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc);
_inputProcessed = inWrap.Processed;
- if (res == SZ_ERROR_READ && inWrap.Res != S_OK)
- return inWrap.Res;
- if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)
- return outWrap.Res;
- if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK)
- return progressWrap.Res;
+
+ RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
+ RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
+ RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
+
return SResToHRESULT(res);
}
diff --git a/CPP/7zip/Compress/LzmaEncoder.h b/CPP/7zip/Compress/LzmaEncoder.h
index 7feafc2..7b31c66 100644
--- a/CPP/7zip/Compress/LzmaEncoder.h
+++ b/CPP/7zip/Compress/LzmaEncoder.h
@@ -16,21 +16,29 @@ class CEncoder:
public ICompressCoder,
public ICompressSetCoderProperties,
public ICompressWriteCoderProperties,
+ public ICompressSetCoderPropertiesOpt,
public CMyUnknownImp
{
CLzmaEncHandle _encoder;
UInt64 _inputProcessed;
public:
- MY_UNKNOWN_IMP3(ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties)
+ MY_UNKNOWN_IMP4(
+ ICompressCoder,
+ ICompressSetCoderProperties,
+ ICompressWriteCoderProperties,
+ ICompressSetCoderPropertiesOpt)
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+ STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
CEncoder();
virtual ~CEncoder();
+
UInt64 GetInputProcessedSize() const { return _inputProcessed; }
+ bool IsWriteEndMark() const { return LzmaEnc_IsWriteEndMark(_encoder) != 0; }
};
}}
diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp
index f86005b..4820c0a 100644
--- a/CPP/7zip/Compress/PpmdDecoder.cpp
+++ b/CPP/7zip/Compress/PpmdDecoder.cpp
@@ -75,7 +75,7 @@ HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)
int sym = 0;
for (i = 0; i != size; i++)
{
- sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.p);
+ sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.vt);
if (_inStream.Extra || sym < 0)
break;
memStream[i] = (Byte)sym;
@@ -134,6 +134,13 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
return S_OK;
}
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+ *value = _inStream.GetProcessed();
+ return S_OK;
+}
+
#ifndef NO_READ_FROM_CODER
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
diff --git a/CPP/7zip/Compress/PpmdDecoder.h b/CPP/7zip/Compress/PpmdDecoder.h
index c61d1d0..3c2f493 100644
--- a/CPP/7zip/Compress/PpmdDecoder.h
+++ b/CPP/7zip/Compress/PpmdDecoder.h
@@ -18,6 +18,7 @@ namespace NPpmd {
class CDecoder :
public ICompressCoder,
public ICompressSetDecoderProperties2,
+ public ICompressGetInStreamProcessedSize,
#ifndef NO_READ_FROM_CODER
public ICompressSetInStream,
public ICompressSetOutStreamSize,
@@ -42,19 +43,26 @@ public:
#ifndef NO_READ_FROM_CODER
CMyComPtr<ISequentialInStream> InSeqStream;
- MY_UNKNOWN_IMP4(
- ICompressSetDecoderProperties2,
- ICompressSetInStream,
- ICompressSetOutStreamSize,
- ISequentialInStream)
- #else
- MY_UNKNOWN_IMP1(
- ICompressSetDecoderProperties2)
#endif
+ MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)
+ // MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
+ MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)
+ #ifndef NO_READ_FROM_CODER
+ MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
+ MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
+
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
#ifndef NO_READ_FROM_CODER
@@ -66,7 +74,7 @@ public:
CDecoder(): _outBuf(NULL), _outSizeDefined(false)
{
Ppmd7z_RangeDec_CreateVTable(&_rangeDec);
- _rangeDec.Stream = &_inStream.p;
+ _rangeDec.Stream = &_inStream.vt;
Ppmd7_Construct(&_ppmd);
}
diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp
index 49d6508..0aef701 100644
--- a/CPP/7zip/Compress/PpmdEncoder.cpp
+++ b/CPP/7zip/Compress/PpmdEncoder.cpp
@@ -43,7 +43,7 @@ CEncoder::CEncoder():
_inBuf(NULL)
{
_props.Normalize(-1);
- _rangeEnc.Stream = &_outStream.p;
+ _rangeEnc.Stream = &_outStream.vt;
Ppmd7_Construct(&_ppmd);
}
diff --git a/CPP/7zip/Compress/XzDecoder.cpp b/CPP/7zip/Compress/XzDecoder.cpp
new file mode 100644
index 0000000..4fcd09f
--- /dev/null
+++ b/CPP/7zip/Compress/XzDecoder.cpp
@@ -0,0 +1,150 @@
+// XzDecoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "../Common/CWrappers.h"
+
+#include "XzDecoder.h"
+
+namespace NCompress {
+namespace NXz {
+
+#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes;
+
+#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
+
+static HRESULT SResToHRESULT_Code(SRes res) throw()
+{
+ if (res < 0)
+ return res;
+ switch (res)
+ {
+ case SZ_OK: return S_OK;
+ case SZ_ERROR_MEM: return E_OUTOFMEMORY;
+ case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
+ }
+ return S_FALSE;
+}
+
+
+HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
+ const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress)
+{
+ MainDecodeSRes = S_OK;
+ MainDecodeSRes_wasUsed = false;
+ XzStatInfo_Clear(&Stat);
+
+ if (!xz)
+ {
+ xz = XzDecMt_Create(&g_Alloc, &g_MidAlloc);
+ if (!xz)
+ return E_OUTOFMEMORY;
+ }
+
+ CXzDecMtProps props;
+ XzDecMtProps_Init(&props);
+
+ int isMT = False;
+
+ #ifndef _7ZIP_ST
+ {
+ props.numThreads = 1;
+ UInt32 numThreads = _numThreads;
+
+ if (_tryMt && numThreads > 1)
+ {
+ size_t memUsage = (size_t)_memUsage;
+ if (memUsage != _memUsage)
+ memUsage = (size_t)0 - 1;
+ props.memUseMax = memUsage;
+ isMT = (numThreads > 1);
+ }
+
+ props.numThreads = numThreads;
+ }
+ #endif
+
+ CSeqInStreamWrap inWrap;
+ CSeqOutStreamWrap outWrap;
+ CCompressProgressWrap progressWrap;
+
+ inWrap.Init(seqInStream);
+ outWrap.Init(outStream);
+ progressWrap.Init(progress);
+
+ SRes res = XzDecMt_Decode(xz,
+ &props,
+ outSizeLimit, finishStream,
+ &outWrap.vt,
+ &inWrap.vt,
+ &Stat,
+ &isMT,
+ progress ? &progressWrap.vt : NULL);
+
+ MainDecodeSRes = res;
+
+ #ifndef _7ZIP_ST
+ // _tryMt = isMT;
+ #endif
+
+ RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
+ RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
+ RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)
+
+ // return E_OUTOFMEMORY;
+
+ MainDecodeSRes_wasUsed = true;
+
+ if (res == SZ_OK && finishStream)
+ {
+ /*
+ if (inSize && *inSize != Stat.PhySize)
+ res = SZ_ERROR_DATA;
+ */
+ if (outSizeLimit && *outSizeLimit != outWrap.Processed)
+ res = SZ_ERROR_DATA;
+ }
+
+ return SResToHRESULT_Code(res);
+}
+
+
+HRESULT CComDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ return Decode(inStream, outStream, outSize, _finishStream, progress);
+}
+
+STDMETHODIMP CComDecoder::SetFinishMode(UInt32 finishMode)
+{
+ _finishStream = (finishMode != 0);
+ return S_OK;
+}
+
+STDMETHODIMP CComDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+ *value = Stat.InSize;
+ return S_OK;
+}
+
+#ifndef _7ZIP_ST
+
+STDMETHODIMP CComDecoder::SetNumberOfThreads(UInt32 numThreads)
+{
+ _numThreads = numThreads;
+ return S_OK;
+}
+
+STDMETHODIMP CComDecoder::SetMemLimit(UInt64 memUsage)
+{
+ _memUsage = memUsage;
+ return S_OK;
+}
+
+#endif
+
+}}
diff --git a/CPP/7zip/Compress/XzDecoder.h b/CPP/7zip/Compress/XzDecoder.h
new file mode 100644
index 0000000..76694ee
--- /dev/null
+++ b/CPP/7zip/Compress/XzDecoder.h
@@ -0,0 +1,92 @@
+// XzDecoder.h
+
+#ifndef __XZ_DECODER_H
+#define __XZ_DECODER_H
+
+#include "../../../C/Xz.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+namespace NCompress {
+namespace NXz {
+
+struct CDecoder
+{
+ CXzDecMtHandle xz;
+ int _tryMt;
+ UInt32 _numThreads;
+ UInt64 _memUsage;
+
+ SRes MainDecodeSRes; // it's not HRESULT
+ bool MainDecodeSRes_wasUsed;
+ CXzStatInfo Stat;
+
+ CDecoder():
+ xz(NULL),
+ _tryMt(True),
+ _numThreads(1),
+ _memUsage((UInt64)(sizeof(size_t)) << 28),
+ MainDecodeSRes(SZ_OK),
+ MainDecodeSRes_wasUsed(false)
+ {}
+
+ ~CDecoder()
+ {
+ if (xz)
+ XzDecMt_Destroy(xz);
+ }
+
+ /* Decode() can return ERROR code only if there is progress or stream error.
+ Decode() returns S_OK in case of xz decoding error, but DecodeRes and CStatInfo contain error information */
+ HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
+ const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *compressProgress);
+};
+
+
+class CComDecoder:
+ public ICompressCoder,
+ public ICompressSetFinishMode,
+ public ICompressGetInStreamProcessedSize,
+
+ #ifndef _7ZIP_ST
+ public ICompressSetCoderMt,
+ public ICompressSetMemLimit,
+ #endif
+
+ public CMyUnknownImp,
+ public CDecoder
+{
+ bool _finishStream;
+
+public:
+ MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
+
+ MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
+ MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)
+
+ #ifndef _7ZIP_ST
+ MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetMemLimit)
+ #endif
+
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+ STDMETHOD(SetFinishMode)(UInt32 finishMode);
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
+
+ #ifndef _7ZIP_ST
+ STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);
+ STDMETHOD(SetMemLimit)(UInt64 memUsage);
+ #endif
+
+ CComDecoder(): _finishStream(false) {}
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Compress/XzEncoder.cpp b/CPP/7zip/Compress/XzEncoder.cpp
new file mode 100644
index 0000000..458a928
--- /dev/null
+++ b/CPP/7zip/Compress/XzEncoder.cpp
@@ -0,0 +1,245 @@
+// XzEncoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "../../Common/MyString.h"
+#include "../../Common/StringToInt.h"
+
+#include "../Common/CWrappers.h"
+#include "../Common/StreamUtils.h"
+
+#include "XzEncoder.h"
+
+namespace NCompress {
+
+namespace NLzma2 {
+
+HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);
+
+}
+
+namespace NXz {
+
+void CEncoder::InitCoderProps()
+{
+ XzProps_Init(&xzProps);
+}
+
+CEncoder::CEncoder()
+{
+ XzProps_Init(&xzProps);
+ _encoder = NULL;
+ _encoder = XzEnc_Create(&g_Alloc, &g_BigAlloc);
+ if (!_encoder)
+ throw 1;
+}
+
+CEncoder::~CEncoder()
+{
+ if (_encoder)
+ XzEnc_Destroy(_encoder);
+}
+
+
+struct CMethodNamePair
+{
+ UInt32 Id;
+ const char *Name;
+};
+
+static const CMethodNamePair g_NamePairs[] =
+{
+ { XZ_ID_Delta, "Delta" },
+ { XZ_ID_X86, "BCJ" },
+ { XZ_ID_PPC, "PPC" },
+ { XZ_ID_IA64, "IA64" },
+ { XZ_ID_ARM, "ARM" },
+ { XZ_ID_ARMT, "ARMT" },
+ { XZ_ID_SPARC, "SPARC" }
+ // { XZ_ID_LZMA2, "LZMA2" }
+};
+
+static int FilterIdFromName(const wchar_t *name)
+{
+ for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++)
+ {
+ const CMethodNamePair &pair = g_NamePairs[i];
+ if (StringsAreEqualNoCase_Ascii(name, pair.Name))
+ return (int)pair.Id;
+ }
+ return -1;
+}
+
+
+HRESULT CEncoder::SetCheckSize(UInt32 checkSizeInBytes)
+{
+ unsigned id;
+ switch (checkSizeInBytes)
+ {
+ case 0: id = XZ_CHECK_NO; break;
+ case 4: id = XZ_CHECK_CRC32; break;
+ case 8: id = XZ_CHECK_CRC64; break;
+ case 32: id = XZ_CHECK_SHA256; break;
+ default: return E_INVALIDARG;
+ }
+ xzProps.checkId = id;
+ return S_OK;
+}
+
+
+HRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop)
+{
+ if (propID == NCoderPropID::kNumThreads)
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ xzProps.numTotalThreads = (int)(prop.ulVal);
+ return S_OK;
+ }
+
+ if (propID == NCoderPropID::kCheckSize)
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ return SetCheckSize(prop.ulVal);
+ }
+
+ if (propID == NCoderPropID::kBlockSize2)
+ {
+ if (prop.vt == VT_UI4)
+ xzProps.blockSize = prop.ulVal;
+ else if (prop.vt == VT_UI8)
+ xzProps.blockSize = prop.uhVal.QuadPart;
+ else
+ return E_INVALIDARG;
+ return S_OK;
+ }
+
+ if (propID == NCoderPropID::kReduceSize)
+ {
+ if (prop.vt == VT_UI8)
+ xzProps.reduceSize = prop.uhVal.QuadPart;
+ else
+ return E_INVALIDARG;
+ return S_OK;
+ }
+
+ if (propID == NCoderPropID::kFilter)
+ {
+ if (prop.vt == VT_UI4)
+ {
+ UInt32 id32 = prop.ulVal;
+ if (id32 == XZ_ID_Delta)
+ return E_INVALIDARG;
+ xzProps.filterProps.id = prop.ulVal;
+ }
+ else
+ {
+ if (prop.vt != VT_BSTR)
+ return E_INVALIDARG;
+
+ const wchar_t *name = prop.bstrVal;
+ const wchar_t *end;
+
+ UInt32 id32 = ConvertStringToUInt32(name, &end);
+
+ if (end != name)
+ name = end;
+ else
+ {
+ if (IsString1PrefixedByString2_NoCase_Ascii(name, "Delta"))
+ {
+ name += 5; // strlen("Delta");
+ id32 = XZ_ID_Delta;
+ }
+ else
+ {
+ int filterId = FilterIdFromName(prop.bstrVal);
+ if (filterId < 0 /* || filterId == XZ_ID_LZMA2 */)
+ return E_INVALIDARG;
+ id32 = filterId;
+ }
+ }
+
+ if (id32 == XZ_ID_Delta)
+ {
+ wchar_t c = *name;
+ if (c != '-' && c != ':')
+ return E_INVALIDARG;
+ name++;
+ UInt32 delta = ConvertStringToUInt32(name, &end);
+ if (end == name || *end != 0 || delta == 0 || delta > 256)
+ return E_INVALIDARG;
+ xzProps.filterProps.delta = delta;
+ }
+
+ xzProps.filterProps.id = id32;
+ }
+
+ return S_OK;
+ }
+
+ return NLzma2::SetLzma2Prop(propID, prop, xzProps.lzma2Props);
+}
+
+
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
+ const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ XzProps_Init(&xzProps);
+
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ RINOK(SetCoderProp(propIDs[i], coderProps[i]));
+ }
+
+ return S_OK;
+ // return SResToHRESULT(XzEnc_SetProps(_encoder, &xzProps));
+}
+
+
+STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
+ const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ const PROPVARIANT &prop = coderProps[i];
+ PROPID propID = propIDs[i];
+ if (propID == NCoderPropID::kExpectedDataSize)
+ if (prop.vt == VT_UI8)
+ XzEnc_SetDataSize(_encoder, prop.uhVal.QuadPart);
+ }
+ return S_OK;
+}
+
+
+#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
+
+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
+{
+ CSeqInStreamWrap inWrap;
+ CSeqOutStreamWrap outWrap;
+ CCompressProgressWrap progressWrap;
+
+ inWrap.Init(inStream);
+ outWrap.Init(outStream);
+ progressWrap.Init(progress);
+
+ SRes res = XzEnc_SetProps(_encoder, &xzProps);
+ if (res == SZ_OK)
+ res = XzEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL);
+
+ // SRes res = Xz_Encode(&outWrap.vt, &inWrap.vt, &xzProps, progress ? &progressWrap.vt : NULL);
+
+ RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
+ RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
+ RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
+
+ return SResToHRESULT(res);
+}
+
+}}
diff --git a/CPP/7zip/Compress/XzEncoder.h b/CPP/7zip/Compress/XzEncoder.h
new file mode 100644
index 0000000..79d81f7
--- /dev/null
+++ b/CPP/7zip/Compress/XzEncoder.h
@@ -0,0 +1,46 @@
+// XzEncoder.h
+
+#ifndef __XZ_ENCODER_H
+#define __XZ_ENCODER_H
+
+#include "../../../C/XzEnc.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+namespace NCompress {
+namespace NXz {
+
+
+class CEncoder:
+ public ICompressCoder,
+ public ICompressSetCoderProperties,
+ public ICompressSetCoderPropertiesOpt,
+ public CMyUnknownImp
+{
+ CXzEncHandle _encoder;
+public:
+ CXzProps xzProps;
+
+ MY_UNKNOWN_IMP3(
+ ICompressCoder,
+ ICompressSetCoderProperties,
+ ICompressSetCoderPropertiesOpt)
+
+ void InitCoderProps();
+ HRESULT SetCheckSize(UInt32 checkSizeInBytes);
+ HRESULT SetCoderProp(PROPID propID, const PROPVARIANT &prop);
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+ STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+
+ CEncoder();
+ virtual ~CEncoder();
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak
index 1da536a..19a7f7b 100644
--- a/CPP/7zip/Crc.mak
+++ b/CPP/7zip/Crc.mak
@@ -1,6 +1,6 @@
C_OBJS = $(C_OBJS) \
$O\7zCrc.obj
-!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM"
+!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM" || "$(CPU)" == "ARM64"
C_OBJS = $(C_OBJS) \
!ELSE
ASM_OBJS = $(ASM_OBJS) \
diff --git a/CPP/7zip/Crc64.mak b/CPP/7zip/Crc64.mak
index 08e56f9..1ac6a0c 100644
--- a/CPP/7zip/Crc64.mak
+++ b/CPP/7zip/Crc64.mak
@@ -1,6 +1,6 @@
C_OBJS = $(C_OBJS) \
$O\XzCrc64.obj
-!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM"
+!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM" || "$(CPU)" == "ARM64"
C_OBJS = $(C_OBJS) \
!ELSE
ASM_OBJS = $(ASM_OBJS) \
diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h
index 2c10048..8d5ed98 100644
--- a/CPP/7zip/Crypto/MyAes.h
+++ b/CPP/7zip/Crypto/MyAes.h
@@ -30,6 +30,8 @@ class CAesCbcCoder:
public:
CAesCbcCoder(bool encodeMode, unsigned keySize);
+ virtual ~CAesCbcCoder() {}; // we need virtual destructor for derived classes
+
MY_UNKNOWN_IMP3(ICompressFilter, ICryptoProperties, ICompressSetCoderProperties)
INTERFACE_ICompressFilter(;)
diff --git a/CPP/7zip/GuiCommon.rc b/CPP/7zip/GuiCommon.rc
index c11017b..565ee70 100644
--- a/CPP/7zip/GuiCommon.rc
+++ b/CPP/7zip/GuiCommon.rc
@@ -71,6 +71,9 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
DEFPUSHBUTTON "OK", IDOK, bx2, by, bxs, bys \
PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
+#define MY_BUTTON__CLOSE \
+ DEFPUSHBUTTON "&Close", IDCLOSE, bx1, by, bxs, bys
+
#define MY_COMBO CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
#define MY_COMBO_SORTED MY_COMBO | CBS_SORT
diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt
index c746316..e5e0612 100644
--- a/CPP/7zip/Guid.txt
+++ b/CPP/7zip/Guid.txt
@@ -40,6 +40,7 @@
04 ICompressProgressInfo
05 ICompressCoder
18 ICompressCoder2
+ 1F ICompressSetCoderPropertiesOpt
20 ICompressSetCoderProperties
21 ICompressSetDecoderProperties //
22 ICompressSetDecoderProperties2
@@ -47,6 +48,8 @@
24 ICompressGetInStreamProcessedSize
25 ICompressSetCoderMt
26 ICompressSetFinishMode
+ 27 ICompressGetInStreamProcessedSize2
+ 28 ICompressSetMemLimit
30 ICompressGetSubStreamSize
31 ICompressSetInStream
@@ -163,6 +166,7 @@ Handler GUIDs:
0C xz
0D ppmd
+ C6 COFF
C7 Ext
C8 VMDK
C9 VDI
diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h
index 454240d..54b2476 100644
--- a/CPP/7zip/ICoder.h
+++ b/CPP/7zip/ICoder.h
@@ -43,6 +43,7 @@ CODER_INTERFACE(ICompressCoder2, 0x18)
S_OK : OK
S_FALSE : data error (for decoders)
E_OUTOFMEMORY : memory allocation error
+ E_NOTIMPL : unsupported encoding method (for decoders)
another error code : some error. For example, it can be error code received from inStream or outStream function.
Parameters:
@@ -104,25 +105,41 @@ namespace NCoderPropID
enum EEnum
{
kDefaultProp = 0,
- kDictionarySize,
- kUsedMemorySize,
- kOrder,
- kBlockSize,
- kPosStateBits,
- kLitContextBits,
- kLitPosBits,
- kNumFastBytes,
- kMatchFinder,
- kMatchFinderCycles,
- kNumPasses,
- kAlgorithm,
- kNumThreads,
- kEndMarker,
- kLevel,
- kReduceSize // estimated size of data that will be compressed. Encoder can use this value to reduce dictionary size.
+ kDictionarySize, // VT_UI4
+ kUsedMemorySize, // VT_UI4
+ kOrder, // VT_UI4
+ kBlockSize, // VT_UI4 or VT_UI8
+ kPosStateBits, // VT_UI4
+ kLitContextBits, // VT_UI4
+ kLitPosBits, // VT_UI4
+ kNumFastBytes, // VT_UI4
+ kMatchFinder, // VT_BSTR
+ kMatchFinderCycles, // VT_UI4
+ kNumPasses, // VT_UI4
+ kAlgorithm, // VT_UI4
+ kNumThreads, // VT_UI4
+ kEndMarker, // VT_BOOL
+ kLevel, // VT_UI4
+ kReduceSize, // VT_UI8 : it's estimated size of largest data stream that will be compressed
+ // encoder can use this value to reduce dictionary size and allocate data buffers
+
+ kExpectedDataSize, // VT_UI8 : for ICompressSetCoderPropertiesOpt :
+ // it's estimated size of current data stream
+ // real data size can differ from that size
+ // encoder can use this value to optimize encoder initialization
+
+ kBlockSize2, // VT_UI4 or VT_UI8
+ kCheckSize, // VT_UI4 : size of digest in bytes
+ kFilter, // VT_BSTR
+ kMemUse // VT_UI8
};
}
+CODER_INTERFACE(ICompressSetCoderPropertiesOpt, 0x1F)
+{
+ STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE;
+};
+
CODER_INTERFACE(ICompressSetCoderProperties, 0x20)
{
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE;
@@ -170,6 +187,17 @@ CODER_INTERFACE(ICompressSetFinishMode, 0x26)
1 : full decoding. The stream must be finished at the end of decoding. */
};
+CODER_INTERFACE(ICompressGetInStreamProcessedSize2, 0x27)
+{
+ STDMETHOD(GetInStreamProcessedSize2)(UInt32 streamIndex, UInt64 *value) PURE;
+};
+
+CODER_INTERFACE(ICompressSetMemLimit, 0x28)
+{
+ STDMETHOD(SetMemLimit)(UInt64 memUsage) PURE;
+};
+
+
CODER_INTERFACE(ICompressGetSubStreamSize, 0x30)
{
diff --git a/CPP/7zip/LzmaDec.mak b/CPP/7zip/LzmaDec.mak
new file mode 100644
index 0000000..3c0e7c5
--- /dev/null
+++ b/CPP/7zip/LzmaDec.mak
@@ -0,0 +1,5 @@
+!IF "$(CPU)" == "AMD64"
+CFLAGS_C_SPEC = -D_LZMA_DEC_OPT
+ASM_OBJS = $(ASM_OBJS) \
+ $O\LzmaDecOpt.obj
+!ENDIF
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
index 5f25f19..9a06cdc 100644
--- a/CPP/7zip/UI/Client7z/Client7z.cpp
+++ b/CPP/7zip/UI/Client7z/Client7z.cpp
@@ -49,21 +49,35 @@ using namespace NDir;
#define kDllName "7z.dll"
-static const char *kCopyrightString = "\n7-Zip " MY_VERSION
-" (" kDllName " client) "
-MY_COPYRIGHT " " MY_DATE "\n";
-
-static const char *kHelpString =
-"Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n"
+static const char * const kCopyrightString =
+ "\n"
+ "7-Zip"
+ " (" kDllName " client)"
+ " " MY_VERSION
+ " : " MY_COPYRIGHT_DATE
+ "\n";
+
+static const char * const kHelpString =
+"Usage: 7zcl.exe [a | l | x] archive.7z [fileName ...]\n"
"Examples:\n"
-" Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n"
-" Client7z.exe l archive.7z : List contents of archive.7z\n"
-" Client7z.exe x archive.7z : eXtract files from archive.7z\n";
+" 7zcl.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n"
+" 7zcl.exe l archive.7z : List contents of archive.7z\n"
+" 7zcl.exe x archive.7z : eXtract files from archive.7z\n";
-static AString FStringToConsoleString(const FString &s)
+static void Convert_UString_to_AString(const UString &s, AString &temp)
{
- return GetOemString(fs2us(s));
+ int codePage = CP_OEMCP;
+ /*
+ int g_CodePage = -1;
+ int codePage = g_CodePage;
+ if (codePage == -1)
+ codePage = CP_OEMCP;
+ if (codePage == CP_UTF8)
+ ConvertUnicodeToUTF8(s, temp);
+ else
+ */
+ UnicodeStringToMultiByte2(temp, s, (UINT)codePage);
}
static FString CmdStringToFString(const char *s)
@@ -71,42 +85,54 @@ static FString CmdStringToFString(const char *s)
return us2fs(GetUnicodeString(s));
}
-static void PrintString(const UString &s)
+static void Print(const char *s)
+{
+ fputs(s, stdout);
+}
+
+static void Print(const AString &s)
{
- printf("%s", (LPCSTR)GetOemString(s));
+ Print(s.Ptr());
}
-static void PrintString(const AString &s)
+static void Print(const UString &s)
{
- printf("%s", (LPCSTR)s);
+ AString as;
+ Convert_UString_to_AString(s, as);
+ Print(as);
+}
+
+static void Print(const wchar_t *s)
+{
+ Print(UString(s));
}
static void PrintNewLine()
{
- PrintString("\n");
+ Print("\n");
}
-static void PrintStringLn(const AString &s)
+static void PrintStringLn(const char *s)
{
- PrintString(s);
+ Print(s);
PrintNewLine();
}
-static void PrintError(const char *message, const FString &name)
+static void PrintError(const char *message)
{
- printf("Error: %s", (LPCSTR)message);
+ Print("Error: ");
PrintNewLine();
- PrintString(FStringToConsoleString(name));
+ Print(message);
PrintNewLine();
}
-static void PrintError(const AString &s)
+static void PrintError(const char *message, const FString &name)
{
- PrintNewLine();
- PrintString(s);
- PrintNewLine();
+ PrintError(message);
+ Print(name);
}
+
static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
{
NCOM::CPropVariant prop;
@@ -126,7 +152,7 @@ static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &resu
}
-static const wchar_t *kEmptyFileAlias = L"[Content]";
+static const wchar_t * const kEmptyFileAlias = L"[Content]";
//////////////////////////////////////////////////////////////
@@ -176,21 +202,25 @@ STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password)
}
+
+static const char * const kIncorrectCommand = "incorrect command";
+
//////////////////////////////////////////////////////////////
// Archive Extracting callback class
-static const char *kTestingString = "Testing ";
-static const char *kExtractingString = "Extracting ";
-static const char *kSkippingString = "Skipping ";
+static const char * const kTestingString = "Testing ";
+static const char * const kExtractingString = "Extracting ";
+static const char * const kSkippingString = "Skipping ";
+
+static const char * const kUnsupportedMethod = "Unsupported Method";
+static const char * const kCRCFailed = "CRC Failed";
+static const char * const kDataError = "Data Error";
+static const char * const kUnavailableData = "Unavailable data";
+static const char * const kUnexpectedEnd = "Unexpected end of data";
+static const char * const kDataAfterEnd = "There are some data after the end of the payload data";
+static const char * const kIsNotArc = "Is not archive";
+static const char * const kHeadersError = "Headers Error";
-static const char *kUnsupportedMethod = "Unsupported Method";
-static const char *kCRCFailed = "CRC Failed";
-static const char *kDataError = "Data Error";
-static const char *kUnavailableData = "Unavailable data";
-static const char *kUnexpectedEnd = "Unexpected end of data";
-static const char *kDataAfterEnd = "There are some data after the end of the payload data";
-static const char *kIsNotArc = "Is not archive";
-static const char *kHeadersError = "Headers Error";
class CArchiveExtractCallback:
public IArchiveExtractCallback,
@@ -380,11 +410,11 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
};
switch (askExtractMode)
{
- case NArchive::NExtract::NAskMode::kExtract: PrintString(kExtractingString); break;
- case NArchive::NExtract::NAskMode::kTest: PrintString(kTestingString); break;
- case NArchive::NExtract::NAskMode::kSkip: PrintString(kSkippingString); break;
+ case NArchive::NExtract::NAskMode::kExtract: Print(kExtractingString); break;
+ case NArchive::NExtract::NAskMode::kTest: Print(kTestingString); break;
+ case NArchive::NExtract::NAskMode::kSkip: Print(kSkippingString); break;
};
- PrintString(_filePath);
+ Print(_filePath);
return S_OK;
}
@@ -397,7 +427,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
default:
{
NumErrors++;
- PrintString(" : ");
+ Print(" : ");
const char *s = NULL;
switch (operationResult)
{
@@ -428,15 +458,15 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
}
if (s)
{
- PrintString("Error : ");
- PrintString(s);
+ Print("Error : ");
+ Print(s);
}
else
{
char temp[16];
ConvertUInt32ToString(operationResult, temp);
- PrintString("Error #");
- PrintString(temp);
+ Print("Error #");
+ Print(temp);
}
}
}
@@ -449,7 +479,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
}
_outFileStream.Release();
if (_extractMode && _processedFileInfo.AttribDefined)
- SetFileAttrib(_diskFilePath, _processedFileInfo.Attrib);
+ SetFileAttrib_PosixHighDetect(_diskFilePath, _processedFileInfo.Attrib);
PrintNewLine();
return S_OK;
}
@@ -602,10 +632,10 @@ HRESULT CArchiveUpdateCallback::Finilize()
static void GetStream2(const wchar_t *name)
{
- PrintString("Compressing ");
+ Print("Compressing ");
if (name[0] == 0)
name = kEmptyFileAlias;
- PrintString(name);
+ Print(name);
}
STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
@@ -631,7 +661,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream
{
PrintNewLine();
PrintError("WARNING: can't open file");
- // PrintString(NError::MyFormatMessageW(systemError));
+ // Print(NError::MyFormatMessageW(systemError));
return S_FALSE;
}
// return sysError;
@@ -665,7 +695,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu
while (res.Len() < 2)
res.InsertAtFront(L'0');
UString fileName = VolName;
- fileName += L'.';
+ fileName += '.';
fileName += res;
fileName += VolExt;
COutFileStream *streamSpec = new COutFileStream;
@@ -704,11 +734,18 @@ int MY_CDECL main(int numArgs, const char *args[])
PrintStringLn(kCopyrightString);
- if (numArgs < 3)
+ if (numArgs < 2)
{
PrintStringLn(kHelpString);
+ return 0;
+ }
+
+ if (numArgs < 3)
+ {
+ PrintError(kIncorrectCommand);
return 1;
}
+
NDLL::CLibrary lib;
if (!lib.Load(NDLL::GetModuleDirPrefix() + FTEXT(kDllName)))
@@ -726,10 +763,10 @@ int MY_CDECL main(int numArgs, const char *args[])
char c;
{
- AString command = args[1];
+ AString command (args[1]);
if (command.Len() != 1)
{
- PrintError("incorrect command");
+ PrintError(kIncorrectCommand);
return 1;
}
c = (char)MyCharLower_Ascii(command[0]);
@@ -742,7 +779,7 @@ int MY_CDECL main(int numArgs, const char *args[])
// create archive command
if (numArgs < 4)
{
- PrintStringLn(kHelpString);
+ PrintError(kIncorrectCommand);
return 1;
}
CObjectVector<CDirItem> dirItems;
@@ -839,7 +876,7 @@ int MY_CDECL main(int numArgs, const char *args[])
{
if (numArgs != 3)
{
- PrintStringLn(kHelpString);
+ PrintError(kIncorrectCommand);
return 1;
}
@@ -851,7 +888,7 @@ int MY_CDECL main(int numArgs, const char *args[])
listCommand = false;
else
{
- PrintError("incorrect command");
+ PrintError(kIncorrectCommand);
return 1;
}
@@ -899,17 +936,17 @@ int MY_CDECL main(int numArgs, const char *args[])
archive->GetProperty(i, kpidSize, &prop);
char s[32];
ConvertPropVariantToShortString(prop, s);
- PrintString(s);
- PrintString(" ");
+ Print(s);
+ Print(" ");
}
{
// Get name of file
NCOM::CPropVariant prop;
archive->GetProperty(i, kpidPath, &prop);
if (prop.vt == VT_BSTR)
- PrintString(prop.bstrVal);
+ Print(prop.bstrVal);
else if (prop.vt != VT_EMPTY)
- PrintString("ERROR!");
+ Print("ERROR!");
}
PrintNewLine();
}
@@ -919,10 +956,10 @@ int MY_CDECL main(int numArgs, const char *args[])
// Extract command
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
- extractCallbackSpec->Init(archive, FTEXT("")); // second parameter is output folder path
+ extractCallbackSpec->Init(archive, FString()); // second parameter is output folder path
extractCallbackSpec->PasswordIsDefined = false;
// extractCallbackSpec->PasswordIsDefined = true;
- // extractCallbackSpec->Password = L"1";
+ // extractCallbackSpec->Password = "1";
/*
const wchar_t *names[] =
diff --git a/CPP/7zip/UI/Client7z/Client7z.dsp b/CPP/7zip/UI/Client7z/Client7z.dsp
index 4a4711c..d9ec4ca 100644
--- a/CPP/7zip/UI/Client7z/Client7z.dsp
+++ b/CPP/7zip/UI/Client7z/Client7z.dsp
@@ -66,7 +66,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
-# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
diff --git a/CPP/7zip/UI/Client7z/resource.rc b/CPP/7zip/UI/Client7z/resource.rc
index 0ca293c..701a783 100644
--- a/CPP/7zip/UI/Client7z/resource.rc
+++ b/CPP/7zip/UI/Client7z/resource.rc
@@ -1,3 +1,3 @@
#include "../../MyVersionInfo.rc"
-MY_VERSION_INFO_APP("7-Zip client", "7zcl")
+MY_VERSION_INFO_APP("7-Zip client" , "7zcl")
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
index ad48b5e..f14aafb 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -8,9 +8,17 @@
#ifndef UNDER_CE
#include <io.h>
#endif
+#else
+// for isatty()
+#include <unistd.h>
#endif
+
#include <stdio.h>
+#ifdef _7ZIP_LARGE_PAGES
+#include "../../../../C/Alloc.h"
+#endif
+
#include "../../../Common/ListFileUtils.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/StringToInt.h"
@@ -19,16 +27,19 @@
#include "../../../Windows/FileName.h"
#ifdef _WIN32
#include "../../../Windows/FileMapping.h"
+#include "../../../Windows/MemoryLock.h"
#include "../../../Windows/Synchronization.h"
#endif
#include "ArchiveCommandLine.h"
#include "EnumDirItems.h"
-#include "SortUtils.h"
#include "Update.h"
#include "UpdateAction.h"
extern bool g_CaseSensitive;
+extern bool g_PathTrailReplaceMode;
+
+bool g_LargePagesMode = false;
#ifdef UNDER_CE
@@ -59,15 +70,6 @@ static bool StringToUInt32(const wchar_t *s, UInt32 &v)
return *end == 0;
}
-CArcCmdLineException::CArcCmdLineException(const char *a, const wchar_t *u)
-{
- (*this) += MultiByteToUnicodeString(a);
- if (u)
- {
- this->Add_LF();
- (*this) += u;
- }
-}
int g_CodePage = -1;
@@ -123,6 +125,7 @@ enum Enum
kTechMode,
kShareForWrite,
+ kStopAfterOpenError,
kCaseSensitive,
kArcNameMode,
@@ -133,10 +136,13 @@ enum Enum
kHardLinks,
kSymLinks,
kNtSecurity,
+
kAltStreams,
kReplaceColonForAltStream,
kWriteToAltStreamIfColon,
+ kNameTrailReplace,
+
kDeleteAfterCompressing,
kSetArcMTime
@@ -149,11 +155,11 @@ enum Enum
static const wchar_t kRecursedIDChar = 'r';
-static const char *kRecursedPostCharSet = "0-";
+static const char * const kRecursedPostCharSet = "0-";
-static const char *k_ArcNameMode_PostCharSet = "sea";
+static const char * const k_ArcNameMode_PostCharSet = "sea";
-static const char *k_Stream_PostCharSet = "012";
+static const char * const k_Stream_PostCharSet = "012";
static inline const EArcNameMode ParseArcNameMode(int postCharIndex)
{
@@ -180,7 +186,7 @@ static const char kFileListID = '@';
static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be
static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be
-static const char *kOverwritePostCharSet = "asut";
+static const char * const kOverwritePostCharSet = "asut";
static const NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =
{
@@ -235,12 +241,13 @@ static const CSwitchForm kSwitchForms[] =
{ "si", NSwitchType::kString },
{ "so" },
- { "slp", NSwitchType::kMinus },
+ { "slp", NSwitchType::kString },
{ "scs", NSwitchType::kString },
{ "scc", NSwitchType::kString },
{ "slt" },
{ "ssw" },
+ { "sse" },
{ "ssc", NSwitchType::kMinus },
{ "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet },
@@ -251,10 +258,13 @@ static const CSwitchForm kSwitchForms[] =
{ "snh", NSwitchType::kMinus },
{ "snl", NSwitchType::kMinus },
{ "sni" },
+
{ "sns", NSwitchType::kMinus },
{ "snr" },
{ "snc" },
+ { "snt", NSwitchType::kMinus },
+
{ "sdel" },
{ "stl" }
@@ -263,17 +273,16 @@ static const CSwitchForm kSwitchForms[] =
#endif
};
-static const wchar_t *kUniversalWildcard = L"*";
+static const char * const kUniversalWildcard = "*";
static const unsigned kMinNonSwitchWords = 1;
static const unsigned kCommandIndex = 0;
-// static const char *kUserErrorMessage = "Incorrect command line";
-static const char *kCannotFindListFile = "Cannot find listfile";
-static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch.";
-static const char *kTerminalOutError = "I won't write compressed data to a terminal";
-static const char *kSameTerminalError = "I won't write data and program's messages to same stream";
-static const char *kEmptyFilePath = "Empty file path";
-static const char *kCannotFindArchive = "Cannot find archive";
+// static const char * const kUserErrorMessage = "Incorrect command line";
+static const char * const kCannotFindListFile = "Cannot find listfile";
+static const char * const kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch.";
+static const char * const kTerminalOutError = "I won't write compressed data to a terminal";
+static const char * const kSameTerminalError = "I won't write data and program's messages to same stream";
+static const char * const kEmptyFilePath = "Empty file path";
bool CArcCommand::IsFromExtractGroup() const
{
@@ -328,7 +337,7 @@ static const char *g_Commands = "audtexlbih";
static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command)
{
- UString s = commandString;
+ UString s (commandString);
s.MakeLower_Ascii();
if (s.Len() == 1)
{
@@ -386,9 +395,9 @@ static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs,
val += pair.NewName;
val.Add_LF();
if (type == NRecursedType::kRecursed)
- val.AddAscii("-r");
+ val += "-r";
else if (type == NRecursedType::kWildcardOnlyRecursed)
- val.AddAscii("-r0");
+ val += "-r0";
throw CArcCmdLineException("Unsupported rename command:", val);
}
}
@@ -422,23 +431,28 @@ static void AddToCensorFromNonSwitchesStrings(
CObjectVector<CRenamePair> *renamePairs,
unsigned startIndex,
NWildcard::CCensor &censor,
- const UStringVector &nonSwitchStrings, NRecursedType::EEnum type,
+ const UStringVector &nonSwitchStrings,
+ int stopSwitchIndex,
+ NRecursedType::EEnum type,
bool wildcardMatching,
bool thereAreSwitchIncludes, Int32 codePage)
{
if ((renamePairs || nonSwitchStrings.Size() == startIndex) && !thereAreSwitchIncludes)
- AddNameToCensor(censor, kUniversalWildcard, true, type,
+ AddNameToCensor(censor, UString(kUniversalWildcard), true, type,
true // wildcardMatching
);
int oldIndex = -1;
+ if (stopSwitchIndex < 0)
+ stopSwitchIndex = nonSwitchStrings.Size();
+
for (unsigned i = startIndex; i < nonSwitchStrings.Size(); i++)
{
const UString &s = nonSwitchStrings[i];
if (s.IsEmpty())
throw CArcCmdLineException(kEmptyFilePath);
- if (s[0] == kFileListID)
+ if (i < (unsigned)stopSwitchIndex && s[0] == kFileListID)
AddToCensorFromListFile(renamePairs, censor, s.Ptr(1), true, type, wildcardMatching, codePage);
else if (renamePairs)
{
@@ -477,7 +491,7 @@ struct CEventSetEnd
}
};
-const char *k_IncorrectMapCommand = "Incorrect Map command";
+static const char * const k_IncorrectMapCommand = "Incorrect Map command";
static const char *ParseMapWithPaths(
NWildcard::CCensor &censor,
@@ -485,7 +499,7 @@ static const char *ParseMapWithPaths(
NRecursedType::EEnum commonRecursedType,
bool wildcardMatching)
{
- UString s = s2;
+ UString s (s2);
int pos = s.Find(L':');
if (pos < 0)
return k_IncorrectMapCommand;
@@ -577,7 +591,7 @@ static void AddSwitchWildcardsToCensor(
break;
}
- UString tail = name.Ptr(pos + 1);
+ const UString tail = name.Ptr(pos + 1);
if (name[pos] == kImmediateNameID)
AddNameToCensor(censor, tail, include, recursedType, wildcardMatching);
@@ -601,84 +615,6 @@ static void AddSwitchWildcardsToCensor(
throw CArcCmdLineException(errorMessage, strings[i]);
}
-#ifdef _WIN32
-
-// This code converts all short file names to long file names.
-
-static void ConvertToLongName(const UString &prefix, UString &name)
-{
- if (name.IsEmpty() || DoesNameContainWildcard(name))
- return;
- NFind::CFileInfo fi;
- const FString path = us2fs(prefix + name);
- #ifndef UNDER_CE
- if (NFile::NName::IsDevicePath(path))
- return;
- #endif
- if (fi.Find(path))
- name = fs2us(fi.Name);
-}
-
-static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items)
-{
- FOR_VECTOR (i, items)
- {
- NWildcard::CItem &item = items[i];
- if (item.Recursive || item.PathParts.Size() != 1)
- continue;
- if (prefix.IsEmpty() && item.IsDriveItem())
- continue;
- ConvertToLongName(prefix, item.PathParts.Front());
- }
-}
-
-static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node)
-{
- ConvertToLongNames(prefix, node.IncludeItems);
- ConvertToLongNames(prefix, node.ExcludeItems);
- unsigned i;
- for (i = 0; i < node.SubNodes.Size(); i++)
- {
- UString &name = node.SubNodes[i].Name;
- if (prefix.IsEmpty() && NWildcard::IsDriveColonName(name))
- continue;
- ConvertToLongName(prefix, name);
- }
- // mix folders with same name
- for (i = 0; i < node.SubNodes.Size(); i++)
- {
- NWildcard::CCensorNode &nextNode1 = node.SubNodes[i];
- for (unsigned j = i + 1; j < node.SubNodes.Size();)
- {
- const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];
- if (nextNode1.Name.IsEqualTo_NoCase(nextNode2.Name))
- {
- nextNode1.IncludeItems += nextNode2.IncludeItems;
- nextNode1.ExcludeItems += nextNode2.ExcludeItems;
- node.SubNodes.Delete(j);
- }
- else
- j++;
- }
- }
- for (i = 0; i < node.SubNodes.Size(); i++)
- {
- NWildcard::CCensorNode &nextNode = node.SubNodes[i];
- ConvertToLongNames(prefix + nextNode.Name + WCHAR_PATH_SEPARATOR, nextNode);
- }
-}
-
-void ConvertToLongNames(NWildcard::CCensor &censor)
-{
- FOR_VECTOR (i, censor.Pairs)
- {
- NWildcard::CPair &pair = censor.Pairs[i];
- ConvertToLongNames(pair.Prefix, pair.Head);
- }
-}
-
-#endif
-
/*
static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)
{
@@ -693,11 +629,11 @@ static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)
}
*/
-static const wchar_t *kUpdatePairStateIDSet = L"pqrxyzw";
+static const char * const kUpdatePairStateIDSet = "pqrxyzw";
static const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};
static const unsigned kNumUpdatePairActions = 4;
-static const char *kUpdateIgnoreItselfPostStringID = "-";
+static const char * const kUpdateIgnoreItselfPostStringID = "-";
static const wchar_t kUpdateNewArchivePostCharID = '!';
@@ -707,8 +643,8 @@ static bool ParseUpdateCommandString2(const UString &command,
for (unsigned i = 0; i < command.Len();)
{
wchar_t c = MyCharLower_Ascii(command[i]);
- int statePos = FindCharPosInString(kUpdatePairStateIDSet, c);
- if (statePos < 0)
+ int statePos = FindCharPosInString(kUpdatePairStateIDSet, (char)c);
+ if (c > 0x7F || statePos < 0)
{
postString = command.Ptr(i);
return true;
@@ -849,7 +785,6 @@ static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &pr
}
}
-CArcCmdLineParser::CArcCmdLineParser(): parser(ARRAY_SIZE(kSwitchForms)) {}
static inline void SetStreamMode(const CSwitchResult &sw, unsigned &res)
{
@@ -857,10 +792,11 @@ static inline void SetStreamMode(const CSwitchResult &sw, unsigned &res)
res = sw.PostCharIndex;
}
+
void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
CArcCmdLineOptions &options)
{
- if (!parser.ParseStrings(kSwitchForms, commandStrings))
+ if (!parser.ParseStrings(kSwitchForms, ARRAY_SIZE(kSwitchForms), commandStrings))
throw CArcCmdLineException(parser.ErrorMessage, parser.ErrorLine);
options.IsInTerminal = MY_IS_TERMINAL(stdin);
@@ -908,9 +844,45 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
options.CaseSensitive = g_CaseSensitive;
}
- options.LargePages = false;
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ NSecurity::EnablePrivilege_SymLink();
+ #endif
+
+ // options.LargePages = false;
+
if (parser[NKey::kLargePages].ThereIs)
- options.LargePages = !parser[NKey::kLargePages].WithMinus;
+ {
+ unsigned slp = 0;
+ const UString &s = parser[NKey::kLargePages].PostStrings[0];
+ if (s.IsEmpty())
+ slp = 1;
+ else if (s != L"-")
+ {
+ if (!StringToUInt32(s, slp))
+ throw CArcCmdLineException("Unsupported switch postfix for -slp", s);
+ }
+
+ #ifdef _7ZIP_LARGE_PAGES
+ if (slp >
+ #ifndef UNDER_CE
+ (unsigned)NSecurity::Get_LargePages_RiskLevel()
+ #else
+ 0
+ #endif
+ )
+ {
+ SetLargePageSize();
+ // note: this process also can inherit that Privilege from parent process
+ g_LargePagesMode =
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ NSecurity::EnablePrivilege_LockMemory();
+ #else
+ true;
+ #endif
+ }
+ #endif
+ }
#ifndef UNDER_CE
@@ -965,7 +937,7 @@ static Int32 FindCharset(const NCommandLineParser::CParser &parser, unsigned key
if (!parser[keyIndex].ThereIs)
return defaultVal;
- UString name = parser[keyIndex].PostStrings.Back();
+ UString name (parser[keyIndex].PostStrings.Back());
UInt32 v;
if (StringToUInt32(name, v))
if (v < ((UInt32)1 << 16))
@@ -982,64 +954,6 @@ static Int32 FindCharset(const NCommandLineParser::CParser &parser, unsigned key
}
}
-HRESULT EnumerateDirItemsAndSort(
- NWildcard::CCensor &censor,
- NWildcard::ECensorPathMode censorPathMode,
- const UString &addPathPrefix,
- UStringVector &sortedPaths,
- UStringVector &sortedFullPaths,
- CDirItemsStat &st,
- IDirItemsCallback *callback)
-{
- FStringVector paths;
-
- {
- CDirItems dirItems;
- dirItems.Callback = callback;
- {
- HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems);
- st = dirItems.Stat;
- RINOK(res);
- }
-
- FOR_VECTOR (i, dirItems.Items)
- {
- const CDirItem &dirItem = dirItems.Items[i];
- if (!dirItem.IsDir())
- paths.Add(dirItems.GetPhyPath(i));
- }
- }
-
- if (paths.Size() == 0)
- throw CArcCmdLineException(kCannotFindArchive);
-
- UStringVector fullPaths;
-
- unsigned i;
-
- for (i = 0; i < paths.Size(); i++)
- {
- FString fullPath;
- NFile::NDir::MyGetFullPathName(paths[i], fullPath);
- fullPaths.Add(fs2us(fullPath));
- }
-
- CUIntVector indices;
- SortFileNames(fullPaths, indices);
- sortedPaths.ClearAndReserve(indices.Size());
- sortedFullPaths.ClearAndReserve(indices.Size());
-
- for (i = 0; i < indices.Size(); i++)
- {
- unsigned index = indices[i];
- sortedPaths.AddInReserved(fs2us(paths[index]));
- sortedFullPaths.AddInReserved(fullPaths[index]);
- if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0)
- throw CArcCmdLineException("Duplicate archive path:", sortedFullPaths[i]);
- }
-
- return S_OK;
-}
static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp)
{
@@ -1051,7 +965,7 @@ static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID,
void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
{
const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
- unsigned numNonSwitchStrings = nonSwitchStrings.Size();
+ const unsigned numNonSwitchStrings = nonSwitchStrings.Size();
if (numNonSwitchStrings < kMinNonSwitchWords)
throw CArcCmdLineException("The command must be specified");
@@ -1082,6 +996,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
}
}
+ if (parser[NKey::kNameTrailReplace].ThereIs)
+ g_PathTrailReplaceMode = !parser[NKey::kNameTrailReplace].WithMinus;
+
NRecursedType::EEnum recursedType;
if (parser[NKey::kRecursed].ThereIs)
recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex);
@@ -1138,7 +1055,8 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL,
curCommandIndex, options.Censor,
- nonSwitchStrings, recursedType, wildcardMatching,
+ nonSwitchStrings, parser.StopSwitchIndex,
+ recursedType, wildcardMatching,
thereAreSwitchIncludes, codePage);
options.YesToAll = parser[NKey::kYes].ThereIs;
@@ -1283,6 +1201,8 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
if (parser[NKey::kShareForWrite].ThereIs)
updateOptions.OpenShareForWrite = true;
+ if (parser[NKey::kStopAfterOpenError].ThereIs)
+ updateOptions.StopAfterOpenError = true;
updateOptions.PathMode = censorPathMode;
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h
index a91df0c..bba3c98 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.h
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h
@@ -6,14 +6,13 @@
#include "../../../Common/CommandLineParser.h"
#include "../../../Common/Wildcard.h"
+#include "EnumDirItems.h"
+
#include "Extract.h"
#include "HashCalc.h"
#include "Update.h"
-struct CArcCmdLineException: public UString
-{
- CArcCmdLineException(const char *a, const wchar_t *u = NULL);
-};
+typedef CMessagePathException CArcCmdLineException;
namespace NCommandType { enum EEnum
{
@@ -51,7 +50,7 @@ struct CArcCmdLineOptions
{
bool HelpMode;
- bool LargePages;
+ // bool LargePages;
bool CaseSensitiveChange;
bool CaseSensitive;
@@ -110,7 +109,7 @@ struct CArcCmdLineOptions
UInt32 NumIterations;
CArcCmdLineOptions():
- LargePages(false),
+ // LargePages(false),
CaseSensitiveChange(false),
CaseSensitive(false),
@@ -130,18 +129,8 @@ class CArcCmdLineParser
{
NCommandLineParser::CParser parser;
public:
- CArcCmdLineParser();
void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options);
void Parse2(CArcCmdLineOptions &options);
};
-HRESULT EnumerateDirItemsAndSort(
- NWildcard::CCensor &censor,
- NWildcard::ECensorPathMode pathMode,
- const UString &addPathPrefix,
- UStringVector &sortedPaths,
- UStringVector &sortedFullPaths,
- CDirItemsStat &st,
- IDirItemsCallback *callback);
-
#endif
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index 39e9653..1119d1b 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -5,7 +5,12 @@
#undef sprintf
#undef printf
+// #include <stdio.h>
+// #include "../../../../C/CpuTicks.h"
+
#include "../../../../C/Alloc.h"
+#include "../../../../C/CpuArch.h"
+
#include "../../../Common/ComTry.h"
#include "../../../Common/IntToString.h"
@@ -36,10 +41,14 @@ using namespace NWindows;
using namespace NFile;
using namespace NDir;
-static const char *kCantAutoRename = "Can not create file with auto name";
-static const char *kCantRenameFile = "Can not rename existing file";
-static const char *kCantDeleteOutputFile = "Can not delete output file";
-static const char *kCantDeleteOutputDir = "Can not delete output folder";
+static const char * const kCantAutoRename = "Can not create file with auto name";
+static const char * const kCantRenameFile = "Can not rename existing file";
+static const char * const kCantDeleteOutputFile = "Can not delete output file";
+static const char * const kCantDeleteOutputDir = "Can not delete output folder";
+static const char * const kCantCreateHardLink = "Can not create hard link";
+static const char * const kCantCreateSymLink = "Can not create symbolic link";
+static const char * const kCantOpenOutFile = "Can not open output file";
+static const char * const kCantSetFileLen = "Can not set length for output file";
#ifndef _SFX
@@ -173,6 +182,7 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r
#endif
CArchiveExtractCallback::CArchiveExtractCallback():
+ _arc(NULL),
WriteCTime(true),
WriteATime(true),
WriteMTime(true),
@@ -196,8 +206,8 @@ void CArchiveExtractCallback::Init(
const UStringVector &removePathParts, bool removePartsForAltStreams,
UInt64 packSize)
{
- _extractedFolderPaths.Clear();
- _extractedFolderIndices.Clear();
+ ClearExtractedDirsInfo();
+ _outFileStream.Release();
#ifdef SUPPORT_LINKS
_hardLinks.Clear();
@@ -359,9 +369,11 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
}
}
-HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
+HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
{
filetimeIsDefined = false;
+ filetime.dwLowDateTime = 0;
+ filetime.dwHighDateTime = 0;
NCOM::CPropVariant prop;
RINOK(_arc->Archive->GetProperty(index, propID, &prop));
if (prop.vt == VT_FILETIME)
@@ -381,14 +393,13 @@ HRESULT CArchiveExtractCallback::GetUnpackSize()
static void AddPathToMessage(UString &s, const FString &path)
{
- s.AddAscii(" : ");
+ s += " : ";
s += fs2us(path);
}
HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path)
{
- UString s;
- s.AddAscii(message);
+ UString s (message);
AddPathToMessage(s, path);
return _extractCallback2->MessageError(s);
}
@@ -396,11 +407,10 @@ HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FSt
HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path)
{
DWORD errorCode = GetLastError();
- UString s;
- s.AddAscii(message);
+ UString s (message);
if (errorCode != 0)
{
- s.AddAscii(" : ");
+ s += " : ";
s += NError::MyFormatMessage(errorCode);
}
AddPathToMessage(s, path);
@@ -409,8 +419,7 @@ HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *mes
HRESULT CArchiveExtractCallback::SendMessageError2(const char *message, const FString &path1, const FString &path2)
{
- UString s;
- s.AddAscii(message);
+ UString s (message);
AddPathToMessage(s, path1);
AddPathToMessage(s, path2);
return _extractCallback2->MessageError(s);
@@ -440,7 +449,7 @@ STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value)
static UString GetDirPrefixOf(const UString &src)
{
- UString s = src;
+ UString s (src);
if (!s.IsEmpty())
{
if (IsPathSepar(s.Back()))
@@ -514,7 +523,7 @@ bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcIte
if (pathParts2.IsEmpty())
pathParts2.AddNew();
UString &back = pathParts2.Back();
- back += L':';
+ back += ':';
back += item.AltStreamName;
bool include2;
@@ -541,7 +550,7 @@ bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem
static FString MakePath_from_2_Parts(const FString &prefix, const FString &path)
{
- FString s = prefix;
+ FString s (prefix);
#if defined(_WIN32) && !defined(UNDER_CE)
if (!path.IsEmpty() && path[0] == ':' && !prefix.IsEmpty() && IsPathSepar(prefix.Back()))
{
@@ -596,6 +605,7 @@ HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream)
#endif
*/
+
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
{
COM_TRY_BEGIN
@@ -616,6 +626,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
_curSize = 0;
_curSizeDefined = false;
+ _fileLengthWasSet = false;
_index = index;
_diskFilePath.Empty();
@@ -726,7 +737,8 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
return E_FAIL;
UString s;
CReparseAttr reparse;
- isOkReparse = reparse.Parse((const Byte *)data, dataSize);
+ DWORD errorCode = 0;
+ isOkReparse = reparse.Parse((const Byte *)data, dataSize, errorCode);
if (isOkReparse)
{
isHardLink = false;
@@ -928,13 +940,13 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
}
GetProp_Spec->Arc = _arc;
GetProp_Spec->IndexInArc = index;
- UString name = MakePathFromParts(pathParts);
+ UString name (MakePathFromParts(pathParts));
#ifdef SUPPORT_ALT_STREAMS
if (_item.IsAltStream)
{
if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt))
- name += L':';
+ name += ':';
name += _item.AltStreamName;
}
#endif
@@ -980,13 +992,13 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|| !pathParts.IsEmpty()
|| !(_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt))
#endif
- Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, pathParts, _item.MainIsDir);
+ Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, _keepAndReplaceEmptyDirPrefixes, pathParts, _item.MainIsDir);
#ifdef SUPPORT_ALT_STREAMS
if (_item.IsAltStream)
{
- UString s = _item.AltStreamName;
+ UString s (_item.AltStreamName);
Correct_AltStream_Name(s);
bool needColon = true;
@@ -1002,13 +1014,13 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
UString &name = pathParts.Back();
if (needColon)
- name += (wchar_t)(_ntOptions.ReplaceColonForAltStream ? L'_' : L':');
+ name += (char)(_ntOptions.ReplaceColonForAltStream ? '_' : ':');
name += s;
}
#endif
- UString processedPath = MakePathFromParts(pathParts);
+ UString processedPath (MakePathFromParts(pathParts));
if (!isAnti)
{
@@ -1022,20 +1034,42 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
{
FString fullPathNew;
CreateComplexDirectory(pathParts, fullPathNew);
+
if (_item.IsDir)
{
- _extractedFolderPaths.Add(fullPathNew);
- _extractedFolderIndices.Add(index);
- SetDirTime(fullPathNew,
- (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
- (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
- (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
+ CDirPathTime &pt = _extractedFolders.AddNew();
+
+ pt.CTime = _fi.CTime;
+ pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined);
+
+ pt.ATime = _fi.ATime;
+ pt.ATimeDefined = (WriteATime && _fi.ATimeDefined);
+
+ pt.MTimeDefined = false;
+
+ if (WriteMTime)
+ {
+ if (_fi.MTimeDefined)
+ {
+ pt.MTime = _fi.MTime;
+ pt.MTimeDefined = true;
+ }
+ else if (_arc->MTimeDefined)
+ {
+ pt.MTime = _arc->MTime;
+ pt.MTimeDefined = true;
+ }
+ }
+
+ pt.Path = fullPathNew;
+
+ pt.SetDirTime();
}
}
}
- FString fullProcessedPath = us2fs(processedPath);
+ FString fullProcessedPath (us2fs(processedPath));
if (_pathMode != NExtract::NPathMode::kAbsPaths
|| !NName::IsAbsolutePath(processedPath))
{
@@ -1051,8 +1085,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
{
const CIndexToPathPair &pair = _renamedFiles[renIndex];
fullProcessedPath = pair.Path;
- fullProcessedPath += (FChar)':';
- UString s = _item.AltStreamName;
+ fullProcessedPath += ':';
+ UString s (_item.AltStreamName);
Correct_AltStream_Name(s);
fullProcessedPath += us2fs(s);
}
@@ -1086,7 +1120,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
case NExtract::NOverwriteMode::kAsk:
{
int slashPos = fullProcessedPath.ReverseFind_PathSepar();
- FString realFullProcessedPath = fullProcessedPath.Left(slashPos + 1) + fileInfo.Name;
+ FString realFullProcessedPath (fullProcessedPath.Left(slashPos + 1) + fileInfo.Name);
Int32 overwriteResult;
RINOK(_extractCallback2->AskOverwrite(
@@ -1119,7 +1153,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
}
else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting)
{
- FString existPath = fullProcessedPath;
+ FString existPath (fullProcessedPath);
if (!AutoRenamePath(existPath))
{
RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));
@@ -1165,7 +1199,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
int colonPos = NName::FindAltStreamColon(fullProcessedPath);
if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0)
{
- FString parentFsPath = fullProcessedPath;
+ FString parentFsPath (fullProcessedPath);
parentFsPath.DeleteFrom(colonPos);
NFind::CFileInfo parentFi;
if (parentFi.Find(parentFsPath))
@@ -1222,7 +1256,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
{
if (!MyCreateHardLink(fullProcessedPath, existPath))
{
- RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath));
+ RINOK(SendMessageError2(kCantCreateHardLink, fullProcessedPath, existPath));
// return S_OK;
}
}
@@ -1262,7 +1296,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
if (FillLinkData(data, fs2us(existPath), !isJunction))
{
CReparseAttr attr;
- if (!attr.Parse(data, data.Size()))
+ DWORD errorCode = 0;
+ if (!attr.Parse(data, data.Size(), errorCode))
{
RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path)));
// return E_FAIL;
@@ -1270,7 +1305,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
else
if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size()))
{
- RINOK(SendMessageError_with_LastError("Can not create symbolic link", fullProcessedPath));
+ RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath));
}
}
}
@@ -1304,7 +1339,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
{
if (!MyCreateHardLink(fullProcessedPath, hl))
{
- RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, hl));
+ RINOK(SendMessageError2(kCantCreateHardLink, fullProcessedPath, hl));
return S_OK;
}
needWriteFile = false;
@@ -1323,11 +1358,24 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
{
// if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
{
- RINOK(SendMessageError_with_LastError("Can not open output file", fullProcessedPath));
+ RINOK(SendMessageError_with_LastError(kCantOpenOutFile, fullProcessedPath));
return S_OK;
}
}
+ if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSizeDefined && _curSize > (1 << 12))
+ {
+ // UInt64 ticks = GetCpuTicks();
+ bool res = _outFileStreamSpec->File.SetLength(_curSize);
+ _fileLengthWasSet = res;
+ _outFileStreamSpec->File.SeekToBegin();
+ // ticks = GetCpuTicks() - ticks;
+ // printf("\nticks = %10d\n", (unsigned)ticks);
+ if (!res)
+ {
+ RINOK(SendMessageError_with_LastError(kCantSetFileLen, fullProcessedPath));
+ }
+ }
#ifdef SUPPORT_ALT_STREAMS
if (isRenamed && !_item.IsAltStream)
@@ -1426,6 +1474,33 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
}
+HRESULT CArchiveExtractCallback::CloseFile()
+{
+ if (!_outFileStream)
+ return S_OK;
+
+ HRESULT hres = S_OK;
+ _outFileStreamSpec->SetTime(
+ (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
+ (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
+ (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
+
+ const UInt64 processedSize = _outFileStreamSpec->ProcessedSize;
+ if (_fileLengthWasSet && _curSize > processedSize)
+ {
+ bool res = _outFileStreamSpec->File.SetLength(processedSize);
+ _fileLengthWasSet = res;
+ if (!res)
+ hres = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path));
+ }
+ _curSize = processedSize;
+ _curSizeDefined = true;
+ RINOK(_outFileStreamSpec->Close());
+ _outFileStream.Release();
+ return hres;
+}
+
+
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
{
COM_TRY_BEGIN
@@ -1454,17 +1529,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
#endif
- if (_outFileStream)
- {
- _outFileStreamSpec->SetTime(
- (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
- (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
- (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
- _curSize = _outFileStreamSpec->ProcessedSize;
- _curSizeDefined = true;
- RINOK(_outFileStreamSpec->Close());
- _outFileStream.Release();
- }
+ RINOK(CloseFile());
#ifdef _USE_SECURITY_CODE
if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps)
@@ -1511,7 +1576,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
NumFiles++;
if (!_stdOutMode && _extractMode && _fi.AttribDefined)
- SetFileAttrib(_diskFilePath, _fi.Attrib);
+ SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib);
RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)));
@@ -1525,23 +1590,19 @@ STDMETHODIMP CArchiveExtractCallback::ReportExtractResult(UInt32 indexType, UInt
if (_folderArchiveExtractCallback2)
{
bool isEncrypted = false;
- wchar_t temp[16];
- UString s2;
- const wchar_t *s = NULL;
+ UString s;
if (indexType == NArchive::NEventIndexType::kInArcIndex && index != (UInt32)(Int32)-1)
{
CReadArcItem item;
RINOK(_arc->GetItem(index, item));
- s2 = item.Path;
- s = s2;
+ s = item.Path;
RINOK(Archive_GetItemBoolProp(_arc->Archive, index, kpidEncrypted, isEncrypted));
}
else
{
- temp[0] = '#';
- ConvertUInt32ToString(index, temp + 1);
- s = temp;
+ s = '#';
+ s.Add_UInt32(index);
// if (indexType == NArchive::NEventIndexType::kBlockIndex) {}
}
@@ -1565,71 +1626,66 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
}
-struct CExtrRefSortPair
-{
- unsigned Len;
- unsigned Index;
-
- int Compare(const CExtrRefSortPair &a) const;
-};
-
-#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
-
-int CExtrRefSortPair::Compare(const CExtrRefSortPair &a) const
-{
- RINOZ(-MyCompare(Len, a.Len));
- return MyCompare(Index, a.Index);
-}
-
-static unsigned GetNumSlashes(const FChar *s)
+void CDirPathSortPair::SetNumSlashes(const FChar *s)
{
for (unsigned numSlashes = 0;;)
{
FChar c = *s++;
if (c == 0)
- return numSlashes;
+ {
+ Len = numSlashes;
+ return;
+ }
if (IS_PATH_SEPAR(c))
numSlashes++;
}
}
+
+bool CDirPathTime::SetDirTime()
+{
+ return NDir::SetDirTime(Path,
+ CTimeDefined ? &CTime : NULL,
+ ATimeDefined ? &ATime : NULL,
+ MTimeDefined ? &MTime : NULL);
+}
+
+
HRESULT CArchiveExtractCallback::SetDirsTimes()
{
- CRecordVector<CExtrRefSortPair> pairs;
- pairs.ClearAndSetSize(_extractedFolderPaths.Size());
+ if (!_arc)
+ return S_OK;
+
+ CRecordVector<CDirPathSortPair> pairs;
+ pairs.ClearAndSetSize(_extractedFolders.Size());
unsigned i;
- for (i = 0; i < _extractedFolderPaths.Size(); i++)
+ for (i = 0; i < _extractedFolders.Size(); i++)
{
- CExtrRefSortPair &pair = pairs[i];
+ CDirPathSortPair &pair = pairs[i];
pair.Index = i;
- pair.Len = GetNumSlashes(_extractedFolderPaths[i]);
+ pair.SetNumSlashes(_extractedFolders[i].Path);
}
pairs.Sort2();
for (i = 0; i < pairs.Size(); i++)
{
- int pairIndex = pairs[i].Index;
- int index = _extractedFolderIndices[pairIndex];
-
- FILETIME CTime;
- FILETIME ATime;
- FILETIME MTime;
-
- bool CTimeDefined;
- bool ATimeDefined;
- bool MTimeDefined;
-
- RINOK(GetTime(index, kpidCTime, CTime, CTimeDefined));
- RINOK(GetTime(index, kpidATime, ATime, ATimeDefined));
- RINOK(GetTime(index, kpidMTime, MTime, MTimeDefined));
-
- // printf("\n%S", _extractedFolderPaths[pairIndex]);
- SetDirTime(_extractedFolderPaths[pairIndex],
- (WriteCTime && CTimeDefined) ? &CTime : NULL,
- (WriteATime && ATimeDefined) ? &ATime : NULL,
- (WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
+ _extractedFolders[pairs[i].Index].SetDirTime();
+ // if (!) return GetLastError();
}
+
+ ClearExtractedDirsInfo();
return S_OK;
}
+
+
+HRESULT CArchiveExtractCallback::CloseArc()
+{
+ HRESULT res = CloseFile();
+ HRESULT res2 = SetDirsTimes();
+ if (res == S_OK)
+ res = res2;
+ _arc = NULL;
+ return res;
+}
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index 37979f4..af38f13 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -57,6 +57,8 @@ struct CExtractNtOptions
bool ReplaceColonForAltStream;
bool WriteToAltStreamIfColon;
+ bool PreAllocateOutFile;
+
CExtractNtOptions():
ReplaceColonForAltStream(false),
WriteToAltStreamIfColon(false)
@@ -64,6 +66,13 @@ struct CExtractNtOptions
SymLinks.Val = true;
HardLinks.Val = true;
AltStreams.Val = true;
+
+ PreAllocateOutFile =
+ #ifdef _WIN32
+ true;
+ #else
+ false;
+ #endif
}
};
@@ -142,6 +151,25 @@ struct CIndexToPathPair
#endif
+
+
+struct CDirPathTime
+{
+ FILETIME CTime;
+ FILETIME ATime;
+ FILETIME MTime;
+
+ bool CTimeDefined;
+ bool ATimeDefined;
+ bool MTimeDefined;
+
+ FString Path;
+
+ bool SetDirTime();
+};
+
+
+
class CArchiveExtractCallback:
public IArchiveExtractCallback,
public IArchiveExtractCallbackMessage,
@@ -163,6 +191,7 @@ class CArchiveExtractCallback:
FString _dirPathPrefix_Full;
NExtract::NPathMode::EEnum _pathMode;
NExtract::NOverwriteMode::EEnum _overwriteMode;
+ bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
#ifndef _SFX
@@ -201,6 +230,7 @@ class CArchiveExtractCallback:
UInt32 _index;
UInt64 _curSize;
bool _curSizeDefined;
+ bool _fileLengthWasSet;
COutFileStream *_outFileStreamSpec;
CMyComPtr<ISequentialOutStream> _outFileStream;
@@ -230,15 +260,14 @@ class CArchiveExtractCallback:
UInt64 _progressTotal;
bool _progressTotal_Defined;
- FStringVector _extractedFolderPaths;
- CRecordVector<UInt32> _extractedFolderIndices;
+ CObjectVector<CDirPathTime> _extractedFolders;
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
bool _saclEnabled;
#endif
void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
- HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
+ HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
HRESULT GetUnpackSize();
HRESULT SendMessageError(const char *message, const FString &path);
@@ -268,11 +297,13 @@ public:
void InitForMulti(bool multiArchives,
NExtract::NPathMode::EEnum pathMode,
- NExtract::NOverwriteMode::EEnum overwriteMode)
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ bool keepAndReplaceEmptyDirPrefixes)
{
_multiArchives = multiArchives;
_pathMode = pathMode;
_overwriteMode = overwriteMode;
+ _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
}
@@ -330,9 +361,43 @@ public:
}
#endif
+ HRESULT CloseArc();
+
+private:
+ void ClearExtractedDirsInfo()
+ {
+ _extractedFolders.Clear();
+ }
+
+ HRESULT CloseFile();
HRESULT SetDirsTimes();
};
+
+struct CArchiveExtractCallback_Closer
+{
+ CArchiveExtractCallback *_ref;
+
+ CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {}
+
+ HRESULT Close()
+ {
+ HRESULT res = S_OK;
+ if (_ref)
+ {
+ res = _ref->CloseArc();
+ _ref = NULL;
+ }
+ return res;
+ }
+
+ ~CArchiveExtractCallback_Closer()
+ {
+ Close();
+ }
+};
+
+
bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
#endif
diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp
index c5dad2a..aa47f7a 100644
--- a/CPP/7zip/UI/Common/ArchiveName.cpp
+++ b/CPP/7zip/UI/Common/ArchiveName.cpp
@@ -29,7 +29,7 @@ UString CreateArchiveName(const NFind::CFileInfo &fi, bool keepName)
static FString CreateArchiveName2(const FString &path, bool fromPrev, bool keepName)
{
- FString resultName = FTEXT("Archive");
+ FString resultName ("Archive");
if (fromPrev)
{
FString dirPrefix;
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp
index 14aabcc..c0d0e54 100644
--- a/CPP/7zip/UI/Common/Bench.cpp
+++ b/CPP/7zip/UI/Common/Bench.cpp
@@ -32,8 +32,6 @@
#include "../../../../C/Alloc.h"
#include "../../../../C/CpuArch.h"
-#include "../../../Windows/System.h"
-
#ifndef _7ZIP_ST
#include "../../../Windows/Synchronization.h"
#include "../../../Windows/Thread.h"
@@ -1185,9 +1183,11 @@ static HRESULT MethodBench(
COneMethodInfo method = method2;
UInt64 methodId;
UInt32 numStreams;
- if (!FindMethod(
+ int codecIndex = FindMethod_Index(
EXTERNAL_CODECS_LOC_VARS
- method.MethodName, methodId, numStreams))
+ method.MethodName, true,
+ methodId, numStreams);
+ if (codecIndex < 0)
return E_NOTIMPL;
if (numStreams != 1)
return E_INVALIDARG;
@@ -1200,10 +1200,9 @@ static HRESULT MethodBench(
if (oldLzmaBenchMode && methodId == k_LZMA)
{
- bool fixedNumber;
- UInt32 numLzmaThreads = method.Get_Lzma_NumThreads(fixedNumber);
- if (!fixedNumber && numThreads == 1)
+ if (numThreads == 1 && method.Get_NumThreads() < 0)
method.AddProp_NumThreads(1);
+ const UInt32 numLzmaThreads = method.Get_Lzma_NumThreads();
if (numThreads > 1 && numLzmaThreads > 1)
{
numEncoderThreads = numThreads / 2;
@@ -1225,7 +1224,7 @@ static HRESULT MethodBench(
{
CCreatedCoder cod;
- RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, true, encoder._encoderFilter, cod));
+ RINOK(CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS codecIndex, true, encoder._encoderFilter, cod));
encoder._encoder = cod.Coder;
if (!encoder._encoder && !encoder._encoderFilter)
return E_NOTIMPL;
@@ -1242,7 +1241,7 @@ static HRESULT MethodBench(
{
CCreatedCoder cod;
CMyComPtr<ICompressCoder> &decoder = encoder._decoders[j];
- RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, false, encoder._decoderFilter, cod));
+ RINOK(CreateCoder_Id(EXTERNAL_CODECS_LOC_VARS methodId, false, encoder._decoderFilter, cod));
decoder = cod.Coder;
if (!encoder._decoderFilter && !decoder)
return E_NOTIMPL;
@@ -1858,6 +1857,37 @@ static void PrintTotals(IBenchPrintCallback &f, bool showFreq, UInt64 cpuFreq, c
PrintResults(f, res.Usage / numIterations2, res.RPU / numIterations2, res.Rating / numIterations2, showFreq, cpuFreq);
}
+
+static void PrintHex(AString &s, UInt64 v)
+{
+ char temp[32];
+ ConvertUInt64ToHex(v, temp);
+ s += temp;
+}
+
+AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti)
+{
+ AString s;
+ // s.Add_UInt32(ti.numProcessThreads);
+ if (ti.processAffinityMask != ti.systemAffinityMask)
+ {
+ // if (ti.numProcessThreads != ti.numSysThreads)
+ {
+ s += " / ";
+ s.Add_UInt32(ti.GetNumSystemThreads());
+ }
+ s += " : ";
+ PrintHex(s, ti.processAffinityMask);
+ s += " / ";
+ PrintHex(s, ti.systemAffinityMask);
+ }
+ return s;
+}
+
+
+extern bool g_LargePagesMode;
+
+
static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString,
bool size_Defined, UInt64 size, const char *threadsString, UInt32 numThreads)
{
@@ -1867,12 +1897,16 @@ static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString,
PrintNumber(f, (size >> 20), 6);
else
f.Print(" ?");
- f.Print(" MB, # ");
+ f.Print(" MB");
+ if (g_LargePagesMode)
+ f.Print(" LP");
+ f.Print(", # ");
f.Print(threadsString);
PrintNumber(f, numThreads, 3);
- f.NewLine();
}
+
+
struct CBenchCallbackToPrint: public IBenchCallback
{
CBenchProps BenchProps;
@@ -1930,7 +1964,7 @@ HRESULT CBenchCallbackToPrint::SetEncodeResult(const CBenchInfo &info, bool fina
return S_OK;
}
-static const char *kSep = " | ";
+static const char * const kSep = " | ";
HRESULT CBenchCallbackToPrint::SetDecodeResult(const CBenchInfo &info, bool final)
{
@@ -2147,7 +2181,7 @@ static HRESULT CrcBench(
numThreads = 1;
#endif
- AString methodName = method.MethodName;
+ const AString &methodName = method.MethodName;
// methodName.RemoveChar(L'-');
CMethodId hashID;
if (!FindHashMethod(
@@ -2344,15 +2378,7 @@ static UInt32 GetNumThreadsNext(unsigned i, UInt32 numThreads)
static bool AreSameMethodNames(const char *fullName, const char *shortName)
{
- for (;;)
- {
- char c2 = *shortName++;
- if (c2 == 0)
- return true;
- char c1 = *fullName++;
- if (MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
- return false;
- }
+ return StringsAreEqualNoCase_Ascii(fullName, shortName);
}
@@ -2410,6 +2436,245 @@ static void x86cpuid_to_String(const Cx86cpuid &c, AString &s)
#endif
+
+static const char * const k_PROCESSOR_ARCHITECTURE[] =
+{
+ "x86" // "INTEL"
+ , "MIPS"
+ , "ALPHA"
+ , "PPC"
+ , "SHX"
+ , "ARM"
+ , "IA64"
+ , "ALPHA64"
+ , "MSIL"
+ , "x64" // "AMD64"
+ , "IA32_ON_WIN64"
+ , "NEUTRAL"
+ , "ARM64"
+ , "ARM32_ON_WIN64"
+};
+
+#define MY__PROCESSOR_ARCHITECTURE_INTEL 0
+#define MY__PROCESSOR_ARCHITECTURE_AMD64 9
+
+
+#define MY__PROCESSOR_INTEL_PENTIUM 586
+#define MY__PROCESSOR_AMD_X8664 8664
+
+/*
+static const CUInt32PCharPair k_PROCESSOR[] =
+{
+ { 2200, "IA64" },
+ { 8664, "x64" }
+};
+
+#define PROCESSOR_INTEL_386 386
+#define PROCESSOR_INTEL_486 486
+#define PROCESSOR_INTEL_PENTIUM 586
+#define PROCESSOR_INTEL_860 860
+#define PROCESSOR_INTEL_IA64 2200
+#define PROCESSOR_AMD_X8664 8664
+#define PROCESSOR_MIPS_R2000 2000
+#define PROCESSOR_MIPS_R3000 3000
+#define PROCESSOR_MIPS_R4000 4000
+#define PROCESSOR_ALPHA_21064 21064
+#define PROCESSOR_PPC_601 601
+#define PROCESSOR_PPC_603 603
+#define PROCESSOR_PPC_604 604
+#define PROCESSOR_PPC_620 620
+#define PROCESSOR_HITACHI_SH3 10003
+#define PROCESSOR_HITACHI_SH3E 10004
+#define PROCESSOR_HITACHI_SH4 10005
+#define PROCESSOR_MOTOROLA_821 821
+#define PROCESSOR_SHx_SH3 103
+#define PROCESSOR_SHx_SH4 104
+#define PROCESSOR_STRONGARM 2577 // 0xA11
+#define PROCESSOR_ARM720 1824 // 0x720
+#define PROCESSOR_ARM820 2080 // 0x820
+#define PROCESSOR_ARM920 2336 // 0x920
+#define PROCESSOR_ARM_7TDMI 70001
+#define PROCESSOR_OPTIL 18767 // 0x494f
+*/
+
+#ifdef _WIN32
+
+static const char * const k_PF[] =
+{
+ "FP_ERRATA"
+ , "FP_EMU"
+ , "CMPXCHG"
+ , "MMX"
+ , "PPC_MOVEMEM_64BIT"
+ , "ALPHA_BYTE"
+ , "SSE"
+ , "3DNOW"
+ , "RDTSC"
+ , "PAE"
+ , "SSE2"
+ , "SSE_DAZ"
+ , "NX"
+ , "SSE3"
+ , "CMPXCHG16B"
+ , "CMP8XCHG16"
+ , "CHANNELS"
+ , "XSAVE"
+ , "ARM_VFP_32"
+ , "ARM_NEON"
+ , "L2AT"
+ , "VIRT_FIRMWARE"
+ , "RDWRFSGSBASE"
+ , "FASTFAIL"
+ , "ARM_DIVIDE"
+ , "ARM_64BIT_LOADSTORE_ATOMIC"
+ , "ARM_EXTERNAL_CACHE"
+ , "ARM_FMAC"
+ , "RDRAND"
+ , "ARM_V8"
+ , "ARM_V8_CRYPTO"
+ , "ARM_V8_CRC32"
+ , "RDTSCP"
+};
+
+#endif
+
+
+static void PrintSize(AString &s, UInt64 v)
+{
+ char c = 0;
+ if ((v & 0x3FF) == 0) { v >>= 10; c = 'K';
+ if ((v & 0x3FF) == 0) { v >>= 10; c = 'M';
+ if ((v & 0x3FF) == 0) { v >>= 10; c = 'G';
+ if ((v & 0x3FF) == 0) { v >>= 10; c = 'T';
+ }}}}
+ else
+ {
+ PrintHex(s, v);
+ return;
+ }
+ char temp[32];
+ ConvertUInt64ToString(v, temp);
+ s += temp;
+ if (c)
+ s += c;
+}
+
+
+static void PrintPage(AString &s, UInt32 v)
+{
+ if ((v & 0x3FF) == 0)
+ {
+ s.Add_UInt32(v >> 10);
+ s += "K";
+ }
+ else
+ s.Add_UInt32(v >> 10);
+}
+
+static AString TypeToString2(const char * const table[], unsigned num, UInt32 value)
+{
+ char sz[16];
+ const char *p = NULL;
+ if (value < num)
+ p = table[value];
+ if (!p)
+ {
+ ConvertUInt32ToString(value, sz);
+ p = sz;
+ }
+ return (AString)p;
+}
+
+#ifdef _WIN32
+
+static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si)
+{
+ s += TypeToString2(k_PROCESSOR_ARCHITECTURE, ARRAY_SIZE(k_PROCESSOR_ARCHITECTURE), si.wProcessorArchitecture);
+
+ if (!( si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_INTEL && si.dwProcessorType == MY__PROCESSOR_INTEL_PENTIUM
+ || si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_AMD64 && si.dwProcessorType == MY__PROCESSOR_AMD_X8664))
+ {
+ s += " ";
+ // s += TypePairToString(k_PROCESSOR, ARRAY_SIZE(k_PROCESSOR), si.dwProcessorType);
+ s.Add_UInt32(si.dwProcessorType);
+ }
+ s += " ";
+ PrintHex(s, si.wProcessorLevel);
+ s += ".";
+ PrintHex(s, si.wProcessorRevision);
+ if ((UInt64)si.dwActiveProcessorMask + 1 != ((UInt64)1 << si.dwNumberOfProcessors))
+ if ((UInt64)si.dwActiveProcessorMask + 1 != 0 || si.dwNumberOfProcessors != sizeof(UInt64) * 8)
+ {
+ s += " act:";
+ PrintHex(s, si.dwActiveProcessorMask);
+ }
+ s += " cpus:";
+ s.Add_UInt32(si.dwNumberOfProcessors);
+ if (si.dwPageSize != 1 << 12)
+ {
+ s += " page:";
+ PrintPage(s, si.dwPageSize);
+ }
+ if (si.dwAllocationGranularity != 1 << 16)
+ {
+ s += " gran:";
+ PrintPage(s, si.dwAllocationGranularity);
+ }
+ s += " ";
+
+ DWORD_PTR minAdd = (DWORD_PTR)si.lpMinimumApplicationAddress;
+ UInt64 maxSize = (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1;
+ const UInt32 kReserveSize = ((UInt32)1 << 16);
+ if (minAdd != kReserveSize)
+ {
+ PrintSize(s, minAdd);
+ s += "-";
+ }
+ else
+ {
+ if ((maxSize & (kReserveSize - 1)) == 0)
+ maxSize += kReserveSize;
+ }
+ PrintSize(s, maxSize);
+}
+
+#ifndef _WIN64
+typedef VOID (WINAPI *Func_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo);
+#endif
+
+#endif
+
+void GetSysInfo(AString &s1, AString &s2)
+{
+ s1.Empty();
+ s2.Empty();
+
+ #ifdef _WIN32
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ {
+ SysInfo_To_String(s1, si);
+ // s += " : ";
+ }
+
+ #if !defined(_WIN64) && !defined(UNDER_CE)
+ Func_GetNativeSystemInfo fn_GetNativeSystemInfo = (Func_GetNativeSystemInfo)GetProcAddress(
+ GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo");
+ if (fn_GetNativeSystemInfo)
+ {
+ SYSTEM_INFO si2;
+ fn_GetNativeSystemInfo(&si2);
+ // if (memcmp(&si, &si2, sizeof(si)) != 0)
+ {
+ // s += " - ";
+ SysInfo_To_String(s2, si2);
+ }
+ }
+ #endif
+ #endif
+}
+
+
void GetCpuName(AString &s)
{
s.Empty();
@@ -2419,31 +2684,79 @@ void GetCpuName(AString &s)
Cx86cpuid cpuid;
if (x86cpuid_CheckAndRead(&cpuid))
{
- x86cpuid_to_String(cpuid, s);
- return;
+ AString s2;
+ x86cpuid_to_String(cpuid, s2);
+ s += s2;
}
+ else
+ {
#ifdef MY_CPU_AMD64
- s = "x64";
+ s += "x64";
#else
- s = "x86";
+ s += "x86";
#endif
+ }
}
#else
#ifdef MY_CPU_LE
- s = "LE";
+ s += "LE";
#elif defined(MY_CPU_BE)
- s = "BE";
+ s += "BE";
#endif
#endif
+
+ if (g_LargePagesMode)
+ s += " (LP)";
}
+void GetCpuFeatures(AString &s)
+{
+ s.Empty();
+
+ #ifdef _WIN32
+ const unsigned kNumFeatures_Extra = 32; // we check also for unknown features
+ const unsigned kNumFeatures = ARRAY_SIZE(k_PF) + kNumFeatures_Extra;
+ for (unsigned i = 0; i < kNumFeatures; i++)
+ {
+ if (IsProcessorFeaturePresent(i))
+ {
+ s.Add_Space_if_NotEmpty();
+ s += TypeToString2(k_PF, ARRAY_SIZE(k_PF), i);
+ }
+ }
+ #endif
+}
+
+
+#ifdef _WIN32
+#ifndef UNDER_CE
+
+typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
+
+static BOOL My_RtlGetVersion(OSVERSIONINFOEXW *vi)
+{
+ HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
+ if (!ntdll)
+ return FALSE;
+ Func_RtlGetVersion func = (Func_RtlGetVersion)GetProcAddress(ntdll, "RtlGetVersion");
+ if (!func)
+ return FALSE;
+ func(vi);
+ return TRUE;
+}
+
+#endif
+#endif
+
+
HRESULT Bench(
DECL_EXTERNAL_CODECS_LOC_VARS
IBenchPrintCallback *printCallback,
IBenchCallback *benchCallback,
+ // IBenchFreqCallback *freqCallback,
const CObjectVector<CProperty> &props,
UInt32 numIterations,
bool multiDict)
@@ -2454,8 +2767,16 @@ HRESULT Bench(
UInt32 numCPUs = 1;
UInt64 ramSize = (UInt64)(sizeof(size_t)) << 29;
+ NSystem::CProcessAffinity threadsInfo;
+ threadsInfo.InitST();
+
#ifndef _7ZIP_ST
- numCPUs = NSystem::GetNumberOfProcessors();
+
+ if (threadsInfo.Get() && threadsInfo.processAffinityMask != 0)
+ numCPUs = threadsInfo.GetNumProcessThreads();
+ else
+ numCPUs = NSystem::GetNumberOfProcessors();
+
#endif
bool ramSize_Defined = NSystem::GetRamSize(ramSize);
@@ -2477,7 +2798,7 @@ HRESULT Bench(
for (i = 0; i < props.Size(); i++)
{
const CProperty &property = props[i];
- UString name = property.Name;
+ UString name (property.Name);
name.MakeLower_Ascii();
if (name.IsEqualTo("file"))
@@ -2504,7 +2825,6 @@ HRESULT Bench(
if (printCallback)
{
printCallback->Print("file size =");
- // printCallback->Print(GetOemString(property.Value));
PrintNumber(*printCallback, len, 0);
printCallback->NewLine();
}
@@ -2523,14 +2843,14 @@ HRESULT Bench(
if (name.IsEqualTo("time"))
{
- RINOK(ParsePropToUInt32(L"", propVariant, testTime));
+ RINOK(ParsePropToUInt32(UString(), propVariant, testTime));
continue;
}
if (name.IsEqualTo("freq"))
{
UInt32 freq32 = 0;
- RINOK(ParsePropToUInt32(L"", propVariant, freq32));
+ RINOK(ParsePropToUInt32(UString(), propVariant, freq32));
if (freq32 == 0)
return E_INVALIDARG;
specifiedFreq = (UInt64)freq32 * 1000000;
@@ -2548,19 +2868,12 @@ HRESULT Bench(
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
UString s = name.Ptr(2);
- if (s == L"*")
+ if (s.IsEqualTo("*")
+ || s.IsEmpty() && propVariant.vt == VT_BSTR && StringsAreEqual_Ascii(propVariant.bstrVal, "*"))
{
multiThreadTests = true;
continue;
}
- if (s.IsEmpty() && propVariant.vt == VT_BSTR)
- {
- if (wcscmp(propVariant.bstrVal, L"*") == 0)
- {
- multiThreadTests = true;
- continue;
- }
- }
#ifndef _7ZIP_ST
RINOK(ParseMtProp(s, propVariant, numCPUs, numThreadsSpecified));
#endif
@@ -2573,10 +2886,62 @@ HRESULT Bench(
if (printCallback)
{
- AString s;
- GetCpuName(s);
- printCallback->Print(s);
- printCallback->NewLine();
+ #ifdef _WIN32
+ #ifndef UNDER_CE
+ {
+ AString s;
+ // OSVERSIONINFO vi;
+ OSVERSIONINFOEXW vi;
+ vi.dwOSVersionInfoSize = sizeof(vi);
+ // if (::GetVersionEx(&vi))
+ if (My_RtlGetVersion(&vi))
+ {
+ s += "Windows";
+ if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
+ s.Add_UInt32(vi.dwPlatformId);
+ s += " "; s.Add_UInt32(vi.dwMajorVersion);
+ s += "."; s.Add_UInt32(vi.dwMinorVersion);
+ s += " "; s.Add_UInt32(vi.dwBuildNumber);
+ // s += " "; s += GetAnsiString(vi.szCSDVersion);
+ }
+ printCallback->Print(s);
+ printCallback->NewLine();
+ }
+ #endif
+ #endif
+
+ {
+ AString s1, s2;
+ GetSysInfo(s1, s2);
+ if (!s1.IsEmpty() || !s2.IsEmpty())
+ {
+ printCallback->Print(s1);
+ if (s1 != s2 && !s2.IsEmpty())
+ {
+ printCallback->Print(" - ");
+ printCallback->Print(s2);
+ }
+ printCallback->NewLine();
+ }
+ }
+ {
+ AString s;
+ GetCpuFeatures(s);
+ if (!s.IsEmpty())
+ {
+ printCallback->Print(s);
+ printCallback->NewLine();
+ }
+ }
+ {
+ AString s;
+ GetCpuName(s);
+ if (!s.IsEmpty())
+ {
+ printCallback->Print(s);
+ printCallback->NewLine();
+ }
+ }
}
if (printCallback)
@@ -2586,7 +2951,7 @@ HRESULT Bench(
UInt64 complexInCommands = kComplexInCommands;
- if (printCallback /* || benchCallback */)
+ if (printCallback /* || freqCallback */)
{
UInt64 numMilCommands = 1 << 6;
if (specifiedFreq != 0)
@@ -2623,8 +2988,8 @@ HRESULT Bench(
}
}
/*
- if (benchCallback)
- benchCallback->AddCpuFreq(mipsVal);
+ if (freqCallback)
+ freqCallback->AddCpuFreq(mipsVal);
*/
if (jj >= 3)
@@ -2643,6 +3008,8 @@ HRESULT Bench(
printCallback->NewLine();
printCallback->NewLine();
PrintRequirements(*printCallback, "size: ", ramSize_Defined, ramSize, "CPU hardware threads:", numCPUs);
+ printCallback->Print(GetProcessThreadsInfo(threadsInfo));
+ printCallback->NewLine();
}
if (numThreadsSpecified < 1 || numThreadsSpecified > kNumThreadsMax)
@@ -2669,7 +3036,7 @@ HRESULT Bench(
kOldLzmaDictBits, printCallback, benchCallback, &benchProps);
}
- AString methodName = method.MethodName;
+ AString methodName (method.MethodName);
if (methodName.IsEqualTo_Ascii_NoCase("CRC"))
methodName = "crc32";
method.MethodName = methodName;
@@ -2688,26 +3055,34 @@ HRESULT Bench(
UInt32 complexity = 10000;
const UInt32 *checkSum = NULL;
{
- for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++)
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(g_Hash); i++)
{
const CBenchHash &h = g_Hash[i];
- AString s = h.Name;
- AString hProp;
- int propPos = s.Find(':');
+ AString benchMethod (h.Name);
+ AString benchProps;
+ int propPos = benchMethod.Find(':');
if (propPos >= 0)
{
- hProp = s.Ptr(propPos + 1);
- s.DeleteFrom(propPos);
+ benchProps = benchMethod.Ptr(propPos + 1);
+ benchMethod.DeleteFrom(propPos);
}
- if (AreSameMethodNames(s, methodName))
+ if (AreSameMethodNames(benchMethod, methodName))
{
- complexity = h.Complex;
- checkSum = &h.CheckSum;
- if (method.PropsString.IsEqualTo_Ascii_NoCase(hProp))
- break;
+ if (benchProps.IsEmpty()
+ || benchMethod.IsEqualTo_Ascii_NoCase("crc32") && benchProps == "8" && method.PropsString.IsEmpty()
+ || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps))
+ {
+ complexity = h.Complex;
+ checkSum = &h.CheckSum;
+ if (method.PropsString.IsEqualTo_Ascii_NoCase(benchProps))
+ break;
+ }
}
}
+ if (i == ARRAY_SIZE(g_Hash))
+ return E_NOTIMPL;
}
f.NewLine();
@@ -2852,6 +3227,7 @@ HRESULT Bench(
}
PrintRequirements(f, "usage:", true, GetBenchMemoryUsage(numThreads, dict, totalBenchMode), "Benchmark threads: ", numThreads);
+ f.NewLine();
f.NewLine();
@@ -2997,19 +3373,35 @@ HRESULT Bench(
bool needSetComplexity = true;
if (!methodName.IsEqualTo_Ascii_NoCase("LZMA"))
{
- for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++)
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(g_Bench); i++)
{
const CBenchMethod &h = g_Bench[i];
- AString s = h.Name;
- if (AreSameMethodNames(h.Name, methodName))
+ AString benchMethod (h.Name);
+ AString benchProps;
+ int propPos = benchMethod.Find(':');
+ if (propPos >= 0)
{
- callback.BenchProps.EncComplex = h.EncComplex;
- callback.BenchProps.DecComplexCompr = h.DecComplexCompr;
- callback.BenchProps.DecComplexUnc = h.DecComplexUnc;;
- needSetComplexity = false;
- break;
+ benchProps = benchMethod.Ptr(propPos + 1);
+ benchMethod.DeleteFrom(propPos);
+ }
+
+ if (AreSameMethodNames(benchMethod, methodName))
+ {
+ if (benchProps.IsEmpty()
+ || benchProps == "x5" && method.PropsString.IsEmpty()
+ || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps))
+ {
+ callback.BenchProps.EncComplex = h.EncComplex;
+ callback.BenchProps.DecComplexCompr = h.DecComplexCompr;
+ callback.BenchProps.DecComplexUnc = h.DecComplexUnc;;
+ needSetComplexity = false;
+ break;
+ }
}
}
+ if (i == ARRAY_SIZE(g_Bench))
+ return E_NOTIMPL;
}
if (needSetComplexity)
callback.BenchProps.SetLzmaCompexity();
@@ -3040,7 +3432,7 @@ HRESULT Bench(
// method2 can have two different dictionary size properties.
// And last property is main.
NCOM::CPropVariant propVariant = (UInt32)pow;
- RINOK(method2.ParseMethodFromPROPVARIANT(L"d", propVariant));
+ RINOK(method2.ParseMethodFromPROPVARIANT((UString)"d", propVariant));
}
size_t uncompressedDataSize;
diff --git a/CPP/7zip/UI/Common/Bench.h b/CPP/7zip/UI/Common/Bench.h
index 7f9e05c..1990aab 100644
--- a/CPP/7zip/UI/Common/Bench.h
+++ b/CPP/7zip/UI/Common/Bench.h
@@ -3,6 +3,8 @@
#ifndef __7ZIP_BENCH_H
#define __7ZIP_BENCH_H
+#include "../../../Windows/System.h"
+
#include "../../Common/CreateCoder.h"
#include "../../UI/Common/Property.h"
@@ -43,13 +45,28 @@ struct IBenchPrintCallback
virtual HRESULT CheckBreak() = 0;
};
+/*
+struct IBenchFreqCallback
+{
+ virtual void AddCpuFreq(UInt64 freq) = 0;
+};
+*/
+
HRESULT Bench(
DECL_EXTERNAL_CODECS_LOC_VARS
IBenchPrintCallback *printCallback,
IBenchCallback *benchCallback,
+ // IBenchFreqCallback *freqCallback,
const CObjectVector<CProperty> &props,
UInt32 numIterations,
bool multiDict
);
+AString GetProcessThreadsInfo(const NWindows::NSystem::CProcessAffinity &ti);
+
+void GetSysInfo(AString &s1, AString &s2);
+void GetCpuName(AString &s);
+void GetCpuFeatures(AString &s);
+
+
#endif
diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h
index 9e74cd1..47485be 100644
--- a/CPP/7zip/UI/Common/DirItem.h
+++ b/CPP/7zip/UI/Common/DirItem.h
@@ -20,9 +20,18 @@ struct CDirItemsStat
UInt64 AltStreamsSize;
UInt64 NumErrors;
- // UInt64 GetTotalItems() const { return NumDirs + NumFiles + NumAltStreams; }
+ // UInt64 Get_NumItems() const { return NumDirs + NumFiles + NumAltStreams; }
+ UInt64 Get_NumDataItems() const { return NumFiles + NumAltStreams; }
UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; }
+
+ bool IsEmpty() const { return
+ 0 == NumDirs
+ && 0 == NumFiles
+ && 0 == NumAltStreams
+ && 0 == FilesSize
+ && 0 == AltStreamsSize
+ && 0 == NumErrors; }
CDirItemsStat():
NumDirs(0),
@@ -34,6 +43,30 @@ struct CDirItemsStat
{}
};
+
+struct CDirItemsStat2: public CDirItemsStat
+{
+ UInt64 Anti_NumDirs;
+ UInt64 Anti_NumFiles;
+ UInt64 Anti_NumAltStreams;
+
+ // UInt64 Get_NumItems() const { return Anti_NumDirs + Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumItems(); }
+ UInt64 Get_NumDataItems2() const { return Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumDataItems(); }
+
+ bool IsEmpty() const { return CDirItemsStat::IsEmpty()
+ && 0 == Anti_NumDirs
+ && 0 == Anti_NumFiles
+ && 0 == Anti_NumAltStreams; }
+
+ CDirItemsStat2():
+ Anti_NumDirs(0),
+ Anti_NumFiles(0),
+ Anti_NumAltStreams(0)
+ {}
+};
+
+
+
#define INTERFACE_IDirItemsCallback(x) \
virtual HRESULT ScanError(const FString &path, DWORD systemError) x; \
virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x; \
diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp
index c7dec1d..032e2ff 100644
--- a/CPP/7zip/UI/Common/EnumDirItems.cpp
+++ b/CPP/7zip/UI/Common/EnumDirItems.cpp
@@ -16,6 +16,7 @@
#endif
#include "EnumDirItems.h"
+#include "SortUtils.h"
using namespace NWindows;
using namespace NFile;
@@ -213,7 +214,8 @@ HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phy
{
RINOK(ScanProgress(phyPrefix));
- NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK);
+ NFind::CEnumerator enumerator;
+ enumerator.SetDirPrefix(phyPrefix);
for (unsigned ttt = 0; ; ttt++)
{
NFind::CFileInfo fi;
@@ -342,6 +344,7 @@ static HRESULT EnumerateAltStreams(
const NWildcard::CCensorNode &curNode,
int phyParent, int logParent, const FString &fullPath,
const UStringVector &addArchivePrefix, // prefix from curNode
+ bool addAllItems,
CDirItems &dirItems)
{
NFind::CStreamEnumerator enumerator(fullPath);
@@ -362,6 +365,10 @@ static HRESULT EnumerateAltStreams(
addArchivePrefixNew.Back() += reducedName;
if (curNode.CheckPathToRoot(false, addArchivePrefixNew, true))
continue;
+ if (!addAllItems)
+ if (!curNode.CheckPathToRoot(true, addArchivePrefixNew, true))
+ continue;
+
NFind::CFileInfo fi2 = fi;
fi2.Name += us2fs(reducedName);
fi2.Size = si.Size;
@@ -380,15 +387,27 @@ HRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi,
return S_OK;
const FString path = phyPrefix + fi.Name;
CByteBuffer &buf = dirItem.ReparseData;
+ DWORD res = 0;
if (NIO::GetReparseData(path, buf))
{
CReparseAttr attr;
- if (attr.Parse(buf, buf.Size()))
+ if (attr.Parse(buf, buf.Size(), res))
return S_OK;
+ // we ignore unknown reparse points
+ if (res != ERROR_INVALID_REPARSE_DATA)
+ res = 0;
+ }
+ else
+ {
+ res = ::GetLastError();
+ if (res == 0)
+ res = ERROR_INVALID_FUNCTION;
}
- DWORD res = ::GetLastError();
+
buf.Free();
- return AddError(path , res);
+ if (res == 0)
+ return S_OK;
+ return AddError(path, res);
}
#endif
@@ -412,6 +431,8 @@ static HRESULT EnumerateForItem(
}
int dirItemIndex = -1;
+ bool addAllSubStreams = false;
+
if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir()))
{
int secureIndex = -1;
@@ -426,6 +447,8 @@ static HRESULT EnumerateForItem(
dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
if (fi.IsDir())
enterToSubFolders2 = true;
+
+ addAllSubStreams = true;
}
#ifndef UNDER_CE
@@ -433,7 +456,9 @@ static HRESULT EnumerateForItem(
{
RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
phyPrefix + fi.Name,
- addArchivePrefixNew, dirItems));
+ addArchivePrefixNew,
+ addAllSubStreams,
+ dirItems));
}
if (dirItemIndex >= 0)
@@ -570,7 +595,7 @@ static HRESULT EnumerateDirItems(
#endif
*/
- fullPath = FCHAR_PATH_SEPARATOR;
+ fullPath = CHAR_PATH_SEPARATOR;
}
#if defined(_WIN32) && !defined(UNDER_CE)
else if (item.IsDriveItem())
@@ -642,7 +667,9 @@ static HRESULT EnumerateDirItems(
UStringVector pathParts;
pathParts.Add(fs2us(fi.Name));
RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
- fullPath, pathParts, dirItems));
+ fullPath, pathParts,
+ true, /* addAllSubStreams */
+ dirItems));
}
#endif
@@ -682,7 +709,7 @@ static HRESULT EnumerateDirItems(
{
{
if (nextNode.Name.IsEmpty())
- fullPath = FCHAR_PATH_SEPARATOR;
+ fullPath = CHAR_PATH_SEPARATOR;
#ifdef _WIN32
else if (NWildcard::IsDriveColonName(nextNode.Name))
fullPath.Add_PathSepar();
@@ -773,7 +800,9 @@ static HRESULT EnumerateDirItems(
#endif
#endif
- NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK);
+ NFind::CEnumerator enumerator;
+ enumerator.SetDirPrefix(phyPrefix);
+
for (unsigned ttt = 0; ; ttt++)
{
NFind::CFileInfo fi;
@@ -849,7 +878,8 @@ void CDirItems::FillFixedReparse()
continue;
CReparseAttr attr;
- if (!attr.Parse(item.ReparseData, item.ReparseData.Size()))
+ DWORD errorCode = 0;
+ if (!attr.Parse(item.ReparseData, item.ReparseData.Size(), errorCode))
continue;
if (attr.IsRelative())
continue;
@@ -896,3 +926,161 @@ void CDirItems::FillFixedReparse()
}
#endif
+
+
+
+static const char * const kCannotFindArchive = "Cannot find archive";
+
+HRESULT EnumerateDirItemsAndSort(
+ NWildcard::CCensor &censor,
+ NWildcard::ECensorPathMode censorPathMode,
+ const UString &addPathPrefix,
+ UStringVector &sortedPaths,
+ UStringVector &sortedFullPaths,
+ CDirItemsStat &st,
+ IDirItemsCallback *callback)
+{
+ FStringVector paths;
+
+ {
+ CDirItems dirItems;
+ dirItems.Callback = callback;
+ {
+ HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems);
+ st = dirItems.Stat;
+ RINOK(res);
+ }
+
+ FOR_VECTOR (i, dirItems.Items)
+ {
+ const CDirItem &dirItem = dirItems.Items[i];
+ if (!dirItem.IsDir())
+ paths.Add(dirItems.GetPhyPath(i));
+ }
+ }
+
+ if (paths.Size() == 0)
+ {
+ // return S_OK;
+ throw CMessagePathException(kCannotFindArchive);
+ }
+
+ UStringVector fullPaths;
+
+ unsigned i;
+
+ for (i = 0; i < paths.Size(); i++)
+ {
+ FString fullPath;
+ NFile::NDir::MyGetFullPathName(paths[i], fullPath);
+ fullPaths.Add(fs2us(fullPath));
+ }
+
+ CUIntVector indices;
+ SortFileNames(fullPaths, indices);
+ sortedPaths.ClearAndReserve(indices.Size());
+ sortedFullPaths.ClearAndReserve(indices.Size());
+
+ for (i = 0; i < indices.Size(); i++)
+ {
+ unsigned index = indices[i];
+ sortedPaths.AddInReserved(fs2us(paths[index]));
+ sortedFullPaths.AddInReserved(fullPaths[index]);
+ if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0)
+ throw CMessagePathException("Duplicate archive path:", sortedFullPaths[i]);
+ }
+
+ return S_OK;
+}
+
+
+
+
+#ifdef _WIN32
+
+// This code converts all short file names to long file names.
+
+static void ConvertToLongName(const UString &prefix, UString &name)
+{
+ if (name.IsEmpty() || DoesNameContainWildcard(name))
+ return;
+ NFind::CFileInfo fi;
+ const FString path (us2fs(prefix + name));
+ #ifndef UNDER_CE
+ if (NFile::NName::IsDevicePath(path))
+ return;
+ #endif
+ if (fi.Find(path))
+ name = fs2us(fi.Name);
+}
+
+static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items)
+{
+ FOR_VECTOR (i, items)
+ {
+ NWildcard::CItem &item = items[i];
+ if (item.Recursive || item.PathParts.Size() != 1)
+ continue;
+ if (prefix.IsEmpty() && item.IsDriveItem())
+ continue;
+ ConvertToLongName(prefix, item.PathParts.Front());
+ }
+}
+
+static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node)
+{
+ ConvertToLongNames(prefix, node.IncludeItems);
+ ConvertToLongNames(prefix, node.ExcludeItems);
+ unsigned i;
+ for (i = 0; i < node.SubNodes.Size(); i++)
+ {
+ UString &name = node.SubNodes[i].Name;
+ if (prefix.IsEmpty() && NWildcard::IsDriveColonName(name))
+ continue;
+ ConvertToLongName(prefix, name);
+ }
+ // mix folders with same name
+ for (i = 0; i < node.SubNodes.Size(); i++)
+ {
+ NWildcard::CCensorNode &nextNode1 = node.SubNodes[i];
+ for (unsigned j = i + 1; j < node.SubNodes.Size();)
+ {
+ const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];
+ if (nextNode1.Name.IsEqualTo_NoCase(nextNode2.Name))
+ {
+ nextNode1.IncludeItems += nextNode2.IncludeItems;
+ nextNode1.ExcludeItems += nextNode2.ExcludeItems;
+ node.SubNodes.Delete(j);
+ }
+ else
+ j++;
+ }
+ }
+ for (i = 0; i < node.SubNodes.Size(); i++)
+ {
+ NWildcard::CCensorNode &nextNode = node.SubNodes[i];
+ ConvertToLongNames(prefix + nextNode.Name + WCHAR_PATH_SEPARATOR, nextNode);
+ }
+}
+
+void ConvertToLongNames(NWildcard::CCensor &censor)
+{
+ FOR_VECTOR (i, censor.Pairs)
+ {
+ NWildcard::CPair &pair = censor.Pairs[i];
+ ConvertToLongNames(pair.Prefix, pair.Head);
+ }
+}
+
+#endif
+
+
+CMessagePathException::CMessagePathException(const char *a, const wchar_t *u)
+{
+ (*this) += a;
+ if (u)
+ {
+ Add_LF();
+ (*this) += u;
+ }
+}
diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h
index 15de340..6220500 100644
--- a/CPP/7zip/UI/Common/EnumDirItems.h
+++ b/CPP/7zip/UI/Common/EnumDirItems.h
@@ -18,4 +18,24 @@ HRESULT EnumerateItems(
const UString &addPathPrefix,
CDirItems &dirItems);
+
+struct CMessagePathException: public UString
+{
+ CMessagePathException(const char *a, const wchar_t *u = NULL);
+};
+
+
+HRESULT EnumerateDirItemsAndSort(
+ NWildcard::CCensor &censor,
+ NWildcard::ECensorPathMode pathMode,
+ const UString &addPathPrefix,
+ UStringVector &sortedPaths,
+ UStringVector &sortedFullPaths,
+ CDirItemsStat &st,
+ IDirItemsCallback *callback);
+
+#ifdef _WIN32
+void ConvertToLongNames(NWildcard::CCensor &censor);
+#endif
+
#endif
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp
index a0d109e..2cb2c9b 100644
--- a/CPP/7zip/UI/Common/Extract.cpp
+++ b/CPP/7zip/UI/Common/Extract.cpp
@@ -51,7 +51,7 @@ static HRESULT DecompressArchive(
replaceName = arc0.DefaultName;
}
- outDir.Replace(FSTRING_ANY_MASK, us2fs(Get_Correct_FsFile_Name(replaceName)));
+ outDir.Replace(FString("*"), us2fs(Get_Correct_FsFile_Name(replaceName)));
bool elimIsPossible = false;
UString elimPrefix; // only pure name without dir delimiter
@@ -156,7 +156,7 @@ static HRESULT DecompressArchive(
#endif
if (outDir.IsEmpty())
- outDir = FTEXT(".") FSTRING_PATH_SEPARATOR;
+ outDir = "." STRING_PATH_SEPARATOR;
/*
#ifdef _WIN32
else if (NName::IsAltPathPrefix(outDir)) {}
@@ -167,7 +167,7 @@ static HRESULT DecompressArchive(
HRESULT res = ::GetLastError();
if (res == S_OK)
res = E_FAIL;
- errorMessage.SetFromAscii("Can not create output directory: ");
+ errorMessage = "Can not create output directory: ";
errorMessage += fs2us(outDir);
return res;
}
@@ -197,6 +197,9 @@ static HRESULT DecompressArchive(
HRESULT result;
Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0;
+
+ CArchiveExtractCallback_Closer ecsCloser(ecs);
+
if (options.StdInMode)
{
result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs);
@@ -206,8 +209,11 @@ static HRESULT DecompressArchive(
}
else
result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs);
- if (result == S_OK && !options.StdInMode)
- result = ecs->SetDirsTimes();
+
+ HRESULT res2 = ecsCloser.Close();
+ if (result == S_OK)
+ result = res2;
+
return callback->ExtractResult(result);
}
@@ -279,7 +285,9 @@ HRESULT Extract(
CArchiveExtractCallback *ecs = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> ec(ecs);
bool multi = (numArcs > 1);
- ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode);
+ ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode,
+ false // keepEmptyDirParts
+ );
#ifndef _SFX
ecs->SetHashMethods(hash);
#endif
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
index d395232..13665de 100644
--- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
@@ -8,6 +8,15 @@
#include "ExtractingFilePath.h"
+bool g_PathTrailReplaceMode =
+ #ifdef _WIN32
+ true
+ #else
+ false
+ #endif
+ ;
+
+
static void ReplaceIncorrectChars(UString &s)
{
{
@@ -26,17 +35,42 @@ static void ReplaceIncorrectChars(UString &s)
}
}
- #ifdef _WIN32
+ if (g_PathTrailReplaceMode)
{
- for (unsigned i = s.Len(); i != 0;)
+ /*
+ // if (g_PathTrailReplaceMode == 1)
{
- wchar_t c = s[--i];
- if (c != '.' && c != ' ')
- break;
- s.ReplaceOneCharAtPos(i, '_');
+ if (!s.IsEmpty())
+ {
+ wchar_t c = s.Back();
+ if (c == '.' || c == ' ')
+ {
+ // s += (wchar_t)(0x9c); // STRING TERMINATOR
+ s += (wchar_t)'_';
+ }
+ }
+ }
+ else
+ */
+ {
+ unsigned i;
+ for (i = s.Len(); i != 0;)
+ {
+ wchar_t c = s[i - 1];
+ if (c != '.' && c != ' ')
+ break;
+ i--;
+ s.ReplaceOneCharAtPos(i, '_');
+ // s.ReplaceOneCharAtPos(i, (c == ' ' ? (wchar_t)(0x2423) : (wchar_t)0x00B7));
+ }
+ /*
+ if (g_PathTrailReplaceMode > 1 && i != s.Len())
+ {
+ s.DeleteFrom(i);
+ }
+ */
}
}
- #endif
}
#ifdef _WIN32
@@ -61,7 +95,7 @@ void Correct_AltStream_Name(UString &s)
s.ReplaceOneCharAtPos(i, '_');
}
if (s.IsEmpty())
- s = L'_';
+ s = '_';
}
static const unsigned g_ReservedWithNum_Index = 4;
@@ -112,6 +146,9 @@ static void CorrectUnsupportedName(UString &name)
static void Correct_PathPart(UString &s)
{
// "." and ".."
+ if (s.IsEmpty())
+ return;
+
if (s[0] == '.' && (s[1] == 0 || s[1] == '.' && s[2] == 0))
s.Empty();
#ifdef _WIN32
@@ -120,8 +157,8 @@ static void Correct_PathPart(UString &s)
#endif
}
-// static const wchar_t *k_EmptyReplaceName = L"[]";
-static const wchar_t k_EmptyReplaceName = L'_';
+// static const char * const k_EmptyReplaceName = "[]";
+static const char k_EmptyReplaceName = '_';
UString Get_Correct_FsFile_Name(const UString &name)
{
@@ -138,7 +175,7 @@ UString Get_Correct_FsFile_Name(const UString &name)
}
-void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
+void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir)
{
unsigned i = 0;
@@ -147,6 +184,7 @@ void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
#if defined(_WIN32) && !defined(UNDER_CE)
bool isDrive = false;
#endif
+
if (parts[0].IsEmpty())
{
i = 1;
@@ -157,7 +195,7 @@ void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
if (parts.Size() > 2 && parts[2] == L"?")
{
i = 3;
- if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3]))
+ if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3]))
{
isDrive = true;
i = 4;
@@ -176,16 +214,19 @@ void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
if (isDrive)
{
// we convert "c:name" to "c:\name", if absIsAllowed path.
- const UString &ds = parts[i - 1];
- if (ds.Len() != 2)
+ UString &ds = parts[i - 1];
+ if (ds.Len() > 2)
{
- UString s = ds.Ptr(2);
- parts.Insert(i, s);
+ parts.Insert(i, ds.Ptr(2));
+ ds.DeleteFrom(2);
}
}
#endif
}
+ if (i != 0)
+ keepAndReplaceEmptyPrefixes = false;
+
for (; i < parts.Size();)
{
UString &s = parts[i];
@@ -194,15 +235,17 @@ void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
if (s.IsEmpty())
{
- if (isDir || i != parts.Size() - 1)
- {
- parts.Delete(i);
- continue;
- }
+ if (!keepAndReplaceEmptyPrefixes)
+ if (isDir || i != parts.Size() - 1)
+ {
+ parts.Delete(i);
+ continue;
+ }
s = k_EmptyReplaceName;
}
else
{
+ keepAndReplaceEmptyPrefixes = false;
#ifdef _WIN32
CorrectUnsupportedName(s);
#endif
@@ -214,7 +257,7 @@ void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
if (!isDir)
{
if (parts.IsEmpty())
- parts.Add(k_EmptyReplaceName);
+ parts.Add((UString)k_EmptyReplaceName);
else
{
UString &s = parts.Back();
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h
index ce200b8..12eb0ba 100644
--- a/CPP/7zip/UI/Common/ExtractingFilePath.h
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.h
@@ -12,7 +12,19 @@ void Correct_AltStream_Name(UString &s);
// replaces unsuported characters, and replaces "." , ".." and "" to "[]"
UString Get_Correct_FsFile_Name(const UString &name);
-void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir);
+/*
+ Correct_FsPath() corrects path parts to prepare it for File System operations.
+ It also corrects empty path parts like "\\\\":
+ - frontal empty path parts : it removes them or changes them to "_"
+ - another empty path parts : it removes them
+ if (absIsAllowed && path is absolute) : it removes empty path parts after start absolute path prefix marker
+ else
+ {
+ if (!keepAndReplaceEmptyPrefixes) : it removes empty path parts
+ if ( keepAndReplaceEmptyPrefixes) : it changes each empty frontal path part to "_"
+ }
+*/
+void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir);
UString MakePathFromParts(const UStringVector &parts);
diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp
index 9d4747b..9c0a1d0 100644
--- a/CPP/7zip/UI/Common/HashCalc.cpp
+++ b/CPP/7zip/UI/Common/HashCalc.cpp
@@ -30,17 +30,13 @@ public:
~CHashMidBuf() { ::MidFree(_data); }
};
-static const char *k_DefaultHashMethod = "CRC32";
+static const char * const k_DefaultHashMethod = "CRC32";
HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods)
{
UStringVector names = hashMethods;
if (names.IsEmpty())
- {
- UString s;
- s.SetFromAscii(k_DefaultHashMethod);
- names.Add(s);
- }
+ names.Add(UString(k_DefaultHashMethod));
CRecordVector<CMethodId> ids;
CObjectVector<COneMethodInfo> methods;
diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h
index d98c577..77373b8 100644
--- a/CPP/7zip/UI/Common/HashCalc.h
+++ b/CPP/7zip/UI/Common/HashCalc.h
@@ -9,7 +9,6 @@
#include "../../Common/MethodProps.h"
#include "DirItem.h"
-#include "Property.h"
const unsigned k_HashCalc_DigestSize_Max = 64;
diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
index 9379152..d31e05f 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -81,7 +81,7 @@ using namespace NFile;
#define kFormatsFolderName FTEXT("Formats")
-static CFSTR kMainDll =
+static CFSTR const kMainDll =
// #ifdef _WIN32
FTEXT("7z.dll");
// #else
@@ -91,9 +91,9 @@ static CFSTR kMainDll =
#ifdef _WIN32
-static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");
-static LPCWSTR kProgramPathValue = L"Path";
-static LPCWSTR kProgramPath2Value = L"Path"
+static LPCTSTR const kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");
+static LPCWSTR const kProgramPathValue = L"Path";
+static LPCWSTR const kProgramPath2Value = L"Path"
#ifdef _WIN64
L"64";
#else
@@ -516,12 +516,11 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loaded
}
lib.CreateObject = (Func_CreateObject)lib.Lib.GetProc("CreateObject");
- if (lib.CreateObject)
{
unsigned startSize = Codecs.Size() + Hashers.Size();
res = LoadCodecs();
used = (startSize != Codecs.Size() + Hashers.Size());
- if (res == S_OK)
+ if (res == S_OK && lib.CreateObject)
{
startSize = Formats.Size();
res = LoadFormats();
@@ -539,7 +538,8 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loaded
HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix)
{
- NFile::NFind::CEnumerator enumerator(folderPrefix + FCHAR_ANY_MASK);
+ NFile::NFind::CEnumerator enumerator;
+ enumerator.SetDirPrefix(folderPrefix);
NFile::NFind::CFileInfo fi;
while (enumerator.Next(fi))
{
@@ -595,7 +595,7 @@ HRESULT CCodecs::Load()
const CArcInfo &arc = *g_Arcs[i];
CArcInfoEx item;
- item.Name.SetFromAscii(arc.Name);
+ item.Name = arc.Name;
item.CreateInArchive = arc.CreateInArchive;
item.IsArcFunc = arc.IsArc;
item.Flags = arc.Flags;
@@ -603,9 +603,9 @@ HRESULT CCodecs::Load()
{
UString e, ae;
if (arc.Ext)
- e.SetFromAscii(arc.Ext);
+ e = arc.Ext;
if (arc.AddExt)
- ae.SetFromAscii(arc.AddExt);
+ ae = arc.AddExt;
item.AddExts(e, ae);
}
@@ -866,7 +866,8 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
const CCodecLib &lib = Libs[ci.LibIndex];
if (lib.CreateDecoder)
return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder);
- return lib.CreateObject(&ci.Decoder, iid, (void **)coder);
+ if (lib.CreateObject)
+ return lib.CreateObject(&ci.Decoder, iid, (void **)coder);
}
return S_OK;
#else
@@ -888,7 +889,8 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
const CCodecLib &lib = Libs[ci.LibIndex];
if (lib.CreateEncoder)
return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder);
- return lib.CreateObject(&ci.Encoder, iid, (void **)coder);
+ if (lib.CreateObject)
+ return lib.CreateObject(&ci.Encoder, iid, (void **)coder);
}
return S_OK;
#else
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
index 968f0ca..9549269 100644
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -330,17 +330,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidPath:
{
- wchar_t sz[32];
+ char sz[32];
ConvertUInt32ToString(index + 1, sz);
- UString s = sz;
+ UString s(sz);
if (!item.Name.IsEmpty())
{
- s += L'.';
+ s += '.';
s += item.Name;
}
if (!item.Extension.IsEmpty())
{
- s += L'.';
+ s += '.';
s += item.Extension;
}
prop = s; break;
@@ -583,7 +583,7 @@ HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &pa
{
{
UString &s2 = parts[parts.Size() - 2];
- s2 += L':';
+ s2 += ':';
s2 += parts.Back();
}
parts.DeleteBack();
@@ -733,7 +733,7 @@ HRESULT CArc::GetDefaultItemPath(UInt32 index, UString &result) const
RINOK(Archive->GetProperty(index, kpidExtension, &prop));
if (prop.vt == VT_BSTR)
{
- result += L'.';
+ result += '.';
result += prop.bstrVal;
}
else if (prop.vt != VT_EMPTY)
@@ -857,7 +857,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
if (item.WriteToAltStreamIfColon || needFindAltStream)
{
- /* Good handler must support GetRawProps::GetParent for alt streams./
+ /* Good handler must support GetRawProps::GetParent for alt streams.
So the following code currently is not used */
int colon = FindAltStreamColon_in_Path(item.Path);
if (colon >= 0)
@@ -992,7 +992,7 @@ static void MakeCheckOrder(CCodecs *codecs,
int index = orderIndices[i];
if (index < 0)
continue;
- const CArcInfoEx &ai = codecs->Formats[index];
+ const CArcInfoEx &ai = codecs->Formats[(unsigned)index];
if (ai.SignatureOffset != 0)
{
orderIndices2.Add(index);
@@ -1020,10 +1020,11 @@ static void MakeCheckOrder(CCodecs *codecs,
#ifdef UNDER_CE
static const unsigned kNumHashBytes = 1;
- #define HASH_VAL(buf, pos) ((buf)[pos])
+ #define HASH_VAL(buf) ((buf)[0])
#else
static const unsigned kNumHashBytes = 2;
- #define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8))
+ // #define HASH_VAL(buf) ((buf)[0] | ((UInt32)(buf)[1] << 8))
+ #define HASH_VAL(buf) GetUi16(buf)
#endif
@@ -2294,7 +2295,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
int index = orderIndices[i];
if (index < 0)
continue;
- const CArcInfoEx &ai = op.codecs->Formats[index];
+ const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index];
bool isDifficult = false;
// if (ai.Version < 0x91F) // we don't use parser with old DLL (before 9.31)
if (!ai.NewInterface)
@@ -2317,7 +2318,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
continue;
}
thereAreHandlersForSearch = true;
- UInt32 v = HASH_VAL(sig, 0);
+ UInt32 v = HASH_VAL(sig);
unsigned sigIndex = arc2sig[(unsigned)index] + k;
prevs[sigIndex] = hash[v];
hash[v] = (Byte)sigIndex;
@@ -2326,7 +2327,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
if (isDifficult)
{
difficultFormats.Add(index);
- difficultBools[index] = true;
+ difficultBools[(unsigned)index] = true;
}
}
@@ -2440,6 +2441,9 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
}
+ if (bytesInBuf <= (size_t)posInBuf)
+ break;
+
bool useOffsetCallback = false;
if (openCallback_Offset)
{
@@ -2489,17 +2493,19 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
scanSize++;
const Byte *buf = byteBuffer + (size_t)posInBuf;
+ const Byte *bufLimit = buf + scanSize;
size_t ppp = 0;
if (!needCheckStartOpen)
{
- for (; ppp < scanSize && hash[HASH_VAL(buf, ppp)] == 0xFF; ppp++);
+ for (; buf < bufLimit && hash[HASH_VAL(buf)] == 0xFF; buf++);
+ ppp = buf - (byteBuffer + (size_t)posInBuf);
pos += ppp;
- if (ppp == scanSize)
+ if (buf == bufLimit)
continue;
}
- UInt32 v = HASH_VAL(buf, ppp);
+ UInt32 v = HASH_VAL(buf);
bool nextNeedCheckStartOpen = true;
unsigned i = hash[v];
unsigned indexOfDifficult = 0;
@@ -2539,7 +2545,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
const CByteBuffer &sig = ai.Signatures[sigIndex];
if (ppp + sig.Size() > availSize
- || !TestSignature(buf + ppp, sig, sig.Size()))
+ || !TestSignature(buf, sig, sig.Size()))
continue;
// printf("\nSignature OK: %10S %8x %5d", (const wchar_t *)ai.Name, (int)pos, (int)(pos - prevPos));
// prevPos = pos;
@@ -2946,10 +2952,10 @@ HRESULT CArc::OpenStream(const COpenOptions &op)
#ifdef _SFX
#ifdef _WIN32
- static const char *k_ExeExt = ".exe";
+ #define k_ExeExt ".exe"
static const unsigned k_ExeExt_Len = 4;
#else
- static const char *k_ExeExt = "";
+ #define k_ExeExt ""
static const unsigned k_ExeExt_Len = 0;
#endif
@@ -3012,10 +3018,10 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op)
if (ai.IsSplit())
continue;
UString path3 = path2;
- path3 += L'.';
+ path3 += '.';
path3 += ai.GetMainExt(); // "7z" for SFX.
Path = path3;
- Path.AddAscii(".001");
+ Path += ".001";
bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));
if (!isOk)
{
diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h
index 0395987..033cb96 100644
--- a/CPP/7zip/UI/Common/OpenArchive.h
+++ b/CPP/7zip/UI/Common/OpenArchive.h
@@ -414,4 +414,23 @@ struct CArchiveLink
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
+
+struct CDirPathSortPair
+{
+ unsigned Len;
+ unsigned Index;
+
+ void SetNumSlashes(const FChar *s);
+
+ int Compare(const CDirPathSortPair &a) const
+ {
+ // We need sorting order where parent items will be after child items
+ if (Len < a.Len) return 1;
+ if (Len > a.Len) return -1;
+ if (Index < a.Index) return -1;
+ if (Index > a.Index) return 1;
+ return 0;
+ }
+};
+
#endif
diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
index 9633248..bb9c89f 100644
--- a/CPP/7zip/UI/Common/PropIDUtils.cpp
+++ b/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -19,12 +19,16 @@
using namespace NWindows;
-static const char g_WinAttribChars[16 + 1] = "RHS8DAdNTsLCOnE_";
+static const unsigned kNumWinAtrribFlags = 21;
+static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU";
+
/*
+FILE_ATTRIBUTE_
+
0 READONLY
1 HIDDEN
2 SYSTEM
-
+3 (Volume label - obsolete)
4 DIRECTORY
5 ARCHIVE
6 DEVICE
@@ -34,12 +38,19 @@ static const char g_WinAttribChars[16 + 1] = "RHS8DAdNTsLCOnE_";
10 REPARSE_POINT
11 COMPRESSED
12 OFFLINE
-13 NOT_CONTENT_INDEXED
+13 NOT_CONTENT_INDEXED (I - Win10 attrib/Explorer)
14 ENCRYPTED
-
-16 VIRTUAL
+15 INTEGRITY_STREAM (V - ReFS Win8/Win2012)
+16 VIRTUAL (reserved)
+17 NO_SCRUB_DATA (X - ReFS Win8/Win2012 attrib)
+18 RECALL_ON_OPEN or EA
+19 PINNED
+20 UNPINNED
+21 STRICTLY_SEQUENTIAL
+22 RECALL_ON_DATA_ACCESS
*/
+
static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };
#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-';
@@ -65,36 +76,68 @@ static void ConvertPosixAttribToString(char *s, UInt32 a) throw()
}
}
+
void ConvertWinAttribToString(char *s, UInt32 wa) throw()
{
- for (int i = 0; i < 16; i++)
- if ((wa & (1 << i)) && i != 7)
- *s++ = g_WinAttribChars[i];
- *s = 0;
+ /*
+ some programs store posix attributes in high 16 bits.
+ p7zip - stores additional 0x8000 flag marker.
+ macos - stores additional 0x4000 flag marker.
+ info-zip - no additional marker.
+ */
+
+ bool isPosix = ((wa & 0xF0000000) != 0);
+
+ UInt32 posix = 0;
+ if (isPosix)
+ {
+ posix = wa >> 16;
+ wa &= (UInt32)0x3FFF;
+ }
- // we support p7zip trick that stores posix attributes in high 16 bits, and 0x8000 flag
- // we also support ZIP archives created in Unix, that store posix attributes in high 16 bits without 0x8000 flag
+ for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
+ {
+ UInt32 flag = (1 << i);
+ if ((wa & flag) != 0)
+ {
+ char c = g_WinAttribChars[i];
+ if (c != '.')
+ {
+ wa &= ~flag;
+ // if (i != 7) // we can disable N (NORMAL) printing
+ *s++ = c;
+ }
+ }
+ }
- // if (wa & 0x8000)
- if ((wa >> 16) != 0)
+ if (wa != 0)
{
*s++ = ' ';
- ConvertPosixAttribToString(s, wa >> 16);
+ ConvertUInt32ToHex8Digits(wa, s);
+ s += strlen(s);
+ }
+
+ *s = 0;
+
+ if (isPosix)
+ {
+ *s++ = ' ';
+ ConvertPosixAttribToString(s, posix);
}
}
-void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID propID, bool full) throw()
+
+void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID propID, int level) throw()
{
*dest = 0;
if (prop.vt == VT_FILETIME)
{
- FILETIME localFileTime;
- if ((prop.filetime.dwHighDateTime == 0 &&
- prop.filetime.dwLowDateTime == 0) ||
- !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime))
+ const FILETIME &ft = prop.filetime;
+ if ((ft.dwHighDateTime == 0 &&
+ ft.dwLowDateTime == 0))
return;
- ConvertFileTimeToString(localFileTime, dest, true, full);
+ ConvertUtcFileTimeToString(prop.filetime, dest, level);
return;
}
@@ -158,7 +201,7 @@ void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID pr
ConvertPropVariantToShortString(prop, dest);
}
-void ConvertPropertyToString(UString &dest, const PROPVARIANT &prop, PROPID propID, bool full)
+void ConvertPropertyToString2(UString &dest, const PROPVARIANT &prop, PROPID propID, int level)
{
if (prop.vt == VT_BSTR)
{
@@ -166,8 +209,8 @@ void ConvertPropertyToString(UString &dest, const PROPVARIANT &prop, PROPID prop
return;
}
char temp[64];
- ConvertPropertyToShortString(temp, prop, propID, full);
- dest.SetFromAscii(temp);
+ ConvertPropertyToShortString2(temp, prop, propID, level);
+ dest = temp;
}
static inline unsigned GetHex(unsigned v)
@@ -181,7 +224,6 @@ static inline void AddHexToString(AString &res, unsigned v)
{
res += (char)GetHex(v >> 4);
res += (char)GetHex(v & 0xF);
- res += ' ';
}
/*
@@ -226,6 +268,14 @@ struct CSecID2Name
const char *sz;
};
+static int FindPairIndex(const CSecID2Name * pairs, unsigned num, UInt32 id)
+{
+ for (unsigned i = 0; i < num; i++)
+ if (pairs[i].n == id)
+ return i;
+ return -1;
+}
+
static const CSecID2Name sid_32_Names[] =
{
{ 544, "Administrators" },
@@ -316,22 +366,22 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
if (v0 == 32 && num == 2)
{
UInt32 v1 = Get32(p + 12);
- for (unsigned i = 0; i < ARRAY_SIZE(sid_32_Names); i++)
- if (sid_32_Names[i].n == v1)
- {
- s += sid_32_Names[i].sz;
- return;
- }
+ int index = FindPairIndex(sid_32_Names, ARRAY_SIZE(sid_32_Names), v1);
+ if (index >= 0)
+ {
+ s += sid_32_Names[(unsigned)index].sz;
+ return;
+ }
}
if (v0 == 21 && num == 5)
{
UInt32 v4 = Get32(p + 8 + 4 * 4);
- for (unsigned i = 0; i < ARRAY_SIZE(sid_21_Names); i++)
- if (sid_21_Names[i].n == v4)
- {
- s += sid_21_Names[i].sz;
- return;
- }
+ int index = FindPairIndex(sid_21_Names, ARRAY_SIZE(sid_21_Names), v4);
+ if (index >= 0)
+ {
+ s += sid_21_Names[(unsigned)index].sz;
+ return;
+ }
}
if (v0 == 80 && num == 6)
{
@@ -349,13 +399,9 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
}
}
- char sz[16];
s += "S-1-";
if (p[2] == 0 && p[3] == 0)
- {
- ConvertUInt32ToString(authority, sz);
- s += sz;
- }
+ s.Add_UInt32(authority);
else
{
s += "0x";
@@ -365,8 +411,7 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
for (UInt32 i = 0; i < num; i++)
{
s += '-';
- ConvertUInt32ToString(Get32(p + 8 + i * 4), sz);
- s += sz;
+ s.Add_UInt32(Get32(p + 8 + i * 4));
}
}
@@ -381,20 +426,13 @@ static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos)
ParseSid(s, p + pos, size - pos, sidSize);
}
-static void AddUInt32ToString(AString &s, UInt32 val)
-{
- char sz[16];
- ConvertUInt32ToString(val, sz);
- s += sz;
-}
-
static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset)
{
UInt32 control = Get16(p + 2);
if ((flags & control) == 0)
return;
UInt32 pos = Get32(p + offset);
- s += ' ';
+ s.Add_Space();
s += strName;
if (pos >= size)
return;
@@ -405,7 +443,7 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName
if (Get16(p) != 2) // revision
return;
UInt32 num = Get32(p + 4);
- AddUInt32ToString(s, num);
+ s.Add_UInt32(num);
/*
UInt32 aclSize = Get16(p + 2);
@@ -428,7 +466,7 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName
size -= 8;
UInt32 sidSize = 0;
- s += ' ';
+ s.Add_Space();
ParseSid(s, p, size, sidSize);
if (sidSize == 0)
return;
@@ -470,12 +508,12 @@ void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s)
return;
}
ParseOwner(s, data, size, Get32(data + 4));
- s += ' ';
+ s.Add_Space();
ParseOwner(s, data, size, Get32(data + 8));
ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12);
ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16);
- s += ' ';
- AddUInt32ToString(s, size);
+ s.Add_Space();
+ s.Add_UInt32(size);
// s += '\n';
// s += Data_To_Hex(data, size);
}
@@ -529,18 +567,45 @@ bool CheckNtSecure(const Byte *data, UInt32 size) throw()
#endif
+
+
+// IO_REPARSE_TAG_*
+
+static const CSecID2Name k_ReparseTags[] =
+{
+ { 0xA0000003, "MOUNT_POINT" },
+ { 0xC0000004, "HSM" },
+ { 0x80000005, "DRIVE_EXTENDER" },
+ { 0x80000006, "HSM2" },
+ { 0x80000007, "SIS" },
+ { 0x80000008, "WIM" },
+ { 0x80000009, "CSV" },
+ { 0x8000000A, "DFS" },
+ { 0x8000000B, "FILTER_MANAGER" },
+ { 0xA000000C, "SYMLINK" },
+ { 0xA0000010, "IIS_CACHE" },
+ { 0x80000012, "DFSR" },
+ { 0x80000013, "DEDUP" },
+ { 0xC0000014, "APPXSTRM" },
+ { 0x80000014, "NFS" },
+ { 0x80000015, "FILE_PLACEHOLDER" },
+ { 0x80000016, "DFM" },
+ { 0x80000017, "WOF" }
+};
+
bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
{
s.Empty();
NFile::CReparseAttr attr;
- if (attr.Parse(data, size))
+ DWORD errorCode = 0;
+ if (attr.Parse(data, size, errorCode))
{
if (!attr.IsSymLink())
- s.AddAscii("Junction: ");
+ s += "Junction: ";
s += attr.GetPath();
if (!attr.IsOkNamePair())
{
- s.AddAscii(" : ");
+ s += " : ";
s += attr.PrintName;
}
return true;
@@ -555,19 +620,48 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
if (Get16(data + 6) != 0) // padding
return false;
- char hex[16];
- ConvertUInt32ToHex8Digits(tag, hex);
- s.AddAscii(hex);
- s.Add_Space();
+ /*
+ #define _my_IO_REPARSE_TAG_DEDUP (0x80000013L)
+ if (tag == _my_IO_REPARSE_TAG_DEDUP)
+ {
+ }
+ */
- data += 8;
+ {
+ int index = FindPairIndex(k_ReparseTags, ARRAY_SIZE(k_ReparseTags), tag);
+ if (index >= 0)
+ s += k_ReparseTags[(unsigned)index].sz;
+ else
+ {
+ s += "REPARSE:";
+ char hex[16];
+ ConvertUInt32ToHex8Digits(tag, hex);
+ s += hex;
+ }
+ }
+
+ s += ":";
+ s.Add_UInt32(len);
- for (UInt32 i = 0; i < len; i++)
+ if (len != 0)
{
- unsigned b = ((const Byte *)data)[i];
- s += (wchar_t)GetHex((b >> 4) & 0xF);
- s += (wchar_t)GetHex(b & 0xF);
+ s.Add_Space();
+
+ data += 8;
+
+ for (UInt32 i = 0; i < len; i++)
+ {
+ if (i >= 8)
+ {
+ s += "...";
+ break;
+ }
+ unsigned b = data[i];
+ s += (char)GetHex((b >> 4) & 0xF);
+ s += (char)GetHex(b & 0xF);
+ }
}
+
return true;
}
diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h
index fef4b7d..e94e6d7 100644
--- a/CPP/7zip/UI/Common/PropIDUtils.h
+++ b/CPP/7zip/UI/Common/PropIDUtils.h
@@ -6,8 +6,8 @@
#include "../../../Common/MyString.h"
// provide at least 64 bytes for buffer including zero-end
-void ConvertPropertyToShortString(char *dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true) throw();
-void ConvertPropertyToString(UString &dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true);
+void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0) throw();
+void ConvertPropertyToString2(UString &dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0);
bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s);
void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s);
diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
index 57723e4..fc1eede 100644
--- a/CPP/7zip/UI/Common/Update.cpp
+++ b/CPP/7zip/UI/Common/Update.cpp
@@ -4,7 +4,6 @@
#include "Update.h"
-#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#include "../../../Windows/DLL.h"
@@ -30,16 +29,19 @@
#include "TempFiles.h"
#include "UpdateCallback.h"
-static const char *kUpdateIsNotSupoorted =
+static const char * const kUpdateIsNotSupoorted =
"update operations are not supported for this archive";
+static const char * const kUpdateIsNotSupoorted_MultiVol =
+ "Updating for multivolume archives is not implemented";
+
using namespace NWindows;
using namespace NCOM;
using namespace NFile;
using namespace NDir;
using namespace NName;
-static CFSTR kTempFolderPrefix = FTEXT("7zE");
+static CFSTR const kTempFolderPrefix = FTEXT("7zE");
void CUpdateErrorInfo::SetFromLastError(const char *message)
@@ -60,7 +62,8 @@ static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path)
NFind::CFileInfo fileInfo;
FString pathPrefix = path + FCHAR_PATH_SEPARATOR;
{
- NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK);
+ NFind::CEnumerator enumerator;
+ enumerator.SetDirPrefix(pathPrefix);
while (enumerator.Next(fileInfo))
{
if (fileInfo.IsDir())
@@ -156,7 +159,7 @@ bool COutMultiVolStream::SetMTime(const FILETIME *mTime)
STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
while (size > 0)
{
@@ -164,9 +167,8 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr
{
CAltStreamInfo altStream;
- FChar temp[16];
- ConvertUInt32ToString(_streamIndex + 1, temp);
- FString name = temp;
+ FString name;
+ name.Add_UInt32(_streamIndex + 1);
while (name.Len() < 3)
name.InsertAtFront(FTEXT('0'));
name.Insert(0, Prefix);
@@ -218,7 +220,7 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr
_length = _absPos;
if (_offsetPos > altStream.RealSize)
altStream.RealSize = _offsetPos;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize += realProcessed;
if (altStream.Pos == volSize)
{
@@ -243,7 +245,7 @@ STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *n
case STREAM_SEEK_END: _absPos = _length + offset; break;
}
_offsetPos = _absPos;
- if (newPosition != NULL)
+ if (newPosition)
*newPosition = _absPos;
_streamIndex = 0;
return S_OK;
@@ -316,7 +318,7 @@ UString CArchivePath::GetFinalPath() const
UString path = GetPathWithoutExt();
if (!BaseExtension.IsEmpty())
{
- path += L'.';
+ path += '.';
path += BaseExtension;
}
return path;
@@ -327,7 +329,7 @@ UString CArchivePath::GetFinalVolPath() const
UString path = GetPathWithoutExt();
if (!BaseExtension.IsEmpty())
{
- path += L'.';
+ path += '.';
path += VolExtension;
}
return path;
@@ -339,17 +341,17 @@ FString CArchivePath::GetTempPath() const
path += us2fs(Name);
if (!BaseExtension.IsEmpty())
{
- path += FTEXT('.');
+ path += '.';
path += us2fs(BaseExtension);
}
- path.AddAscii(".tmp");
+ path += ".tmp";
path += TempPostfix;
return path;
}
-static const wchar_t *kDefaultArcType = L"7z";
-static const wchar_t *kDefaultArcExt = L"7z";
-static const char *kSFXExtension =
+static const char * const kDefaultArcType = "7z";
+static const char * const kDefaultArcExt = "7z";
+static const char * const kSFXExtension =
#ifdef _WIN32
"exe";
#else
@@ -398,7 +400,7 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)
}
UString ext = typeExt;
if (SfxMode)
- ext.SetFromAscii(kSFXExtension);
+ ext = kSFXExtension;
ArchivePath.BaseExtension = ext;
ArchivePath.VolExtension = typeExt;
ArchivePath.ParseFromPath(arcPath, ArcNameMode);
@@ -412,19 +414,43 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)
return true;
}
+
struct CUpdateProduceCallbackImp: public IUpdateProduceCallback
{
const CObjectVector<CArcItem> *_arcItems;
IUpdateCallbackUI *_callback;
+ CDirItemsStat *_stat;
+
+ CUpdateProduceCallbackImp(
+ const CObjectVector<CArcItem> *a,
+ CDirItemsStat *stat,
+ IUpdateCallbackUI *callback):
+ _arcItems(a),
+ _stat(stat),
+ _callback(callback) {}
- CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a,
- IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {}
virtual HRESULT ShowDeleteFile(unsigned arcIndex);
};
+
HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(unsigned arcIndex)
{
const CArcItem &ai = (*_arcItems)[arcIndex];
+ {
+ CDirItemsStat &stat = *_stat;
+ if (ai.IsDir)
+ stat.NumDirs++;
+ else if (ai.IsAltStream)
+ {
+ stat.NumAltStreams++;
+ stat.AltStreamsSize += ai.Size;
+ }
+ else
+ {
+ stat.NumFiles++;
+ stat.FilesSize += ai.Size;
+ }
+ }
return _callback->ShowDeleteFile(ai.Name, ai.IsDir);
}
@@ -562,6 +588,8 @@ static HRESULT Compress(
UStringVector newNames;
+ CArcToDoStat stat2;
+
if (options.RenamePairs.Size() != 0)
{
FOR_VECTOR (i, arcItems)
@@ -595,7 +623,7 @@ static HRESULT Compress(
if (rp.GetNewPath(false, mainName, dest))
{
needRename = true;
- dest += L':';
+ dest += ':';
dest += ai.Name.Ptr(colonPos + 1);
break;
}
@@ -620,23 +648,94 @@ static HRESULT Compress(
{
CRecordVector<CUpdatePair> updatePairs;
GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!
- CUpdateProduceCallbackImp upCallback(&arcItems, callback);
+ CUpdateProduceCallbackImp upCallback(&arcItems, &stat2.DeleteData, callback);
UpdateProduce(updatePairs, actionSet, updatePairs2, isUpdatingItself ? &upCallback : NULL);
}
{
- UInt32 numItems = 0;
FOR_VECTOR (i, updatePairs2)
- if (updatePairs2[i].NewData)
- numItems++;
- RINOK(callback->SetNumItems(numItems));
+ {
+ const CUpdatePair2 &up = updatePairs2[i];
+
+ // 17.01: anti-item is (up.NewData && (p.UseArcProps in most cases))
+
+ if (up.NewData && !up.UseArcProps)
+ {
+ if (up.ExistOnDisk())
+ {
+ CDirItemsStat2 &stat = stat2.NewData;
+ const CDirItem &di = dirItems.Items[up.DirIndex];
+ if (di.IsDir())
+ {
+ if (up.IsAnti)
+ stat.Anti_NumDirs++;
+ else
+ stat.NumDirs++;
+ }
+ else if (di.IsAltStream)
+ {
+ if (up.IsAnti)
+ stat.Anti_NumAltStreams++;
+ else
+ {
+ stat.NumAltStreams++;
+ stat.AltStreamsSize += di.Size;
+ }
+ }
+ else
+ {
+ if (up.IsAnti)
+ stat.Anti_NumFiles++;
+ else
+ {
+ stat.NumFiles++;
+ stat.FilesSize += di.Size;
+ }
+ }
+ }
+ }
+ else if (up.ArcIndex >= 0)
+ {
+ CDirItemsStat2 &stat = *(up.NewData ? &stat2.NewData : &stat2.OldData);
+ const CArcItem &ai = arcItems[up.ArcIndex];
+ if (ai.IsDir)
+ {
+ if (up.IsAnti)
+ stat.Anti_NumDirs++;
+ else
+ stat.NumDirs++;
+ }
+ else if (ai.IsAltStream)
+ {
+ if (up.IsAnti)
+ stat.Anti_NumAltStreams++;
+ else
+ {
+ stat.NumAltStreams++;
+ stat.AltStreamsSize += ai.Size;
+ }
+ }
+ else
+ {
+ if (up.IsAnti)
+ stat.Anti_NumFiles++;
+ else
+ {
+ stat.NumFiles++;
+ stat.FilesSize += ai.Size;
+ }
+ }
+ }
+ }
+ RINOK(callback->SetNumItems(stat2));
}
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
updateCallbackSpec->ShareForWrite = options.OpenShareForWrite;
+ updateCallbackSpec->StopAfterOpenError = options.StopAfterOpenError;
updateCallbackSpec->StdInMode = options.StdInMode;
updateCallbackSpec->Callback = callback;
@@ -698,9 +797,8 @@ static HRESULT Compress(
{
if (i > 0)
{
- FChar s[16];
- ConvertUInt32ToString(i, s);
- archivePath.TempPostfix = s;
+ archivePath.TempPostfix.Empty();
+ archivePath.TempPostfix.Add_UInt32(i);
}
realPath = archivePath.GetTempPath();
}
@@ -734,7 +832,7 @@ static HRESULT Compress(
outStream = outSeekStream;
volStreamSpec->Sizes = options.VolumesSizes;
volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath());
- volStreamSpec->Prefix += FTEXT('.');
+ volStreamSpec->Prefix += '.';
volStreamSpec->TempFiles = &tempFiles;
volStreamSpec->Init();
@@ -742,7 +840,7 @@ static HRESULT Compress(
updateCallbackSpec->VolumesSizes = volumesSizes;
updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
if (!archivePath.VolExtension.IsEmpty())
- updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;
+ updateCallbackSpec->VolExt = UString('.') + archivePath.VolExtension;
*/
}
@@ -948,36 +1046,6 @@ static HRESULT EnumerateInArchiveItems(
#endif
-struct CRefSortPair
-{
- unsigned Len;
- unsigned Index;
-};
-
-#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
-
-static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, void *)
-{
- RINOZ(-MyCompare(a1->Len, a2->Len));
- return MyCompare(a1->Index, a2->Index);
-}
-
-static unsigned GetNumSlashes(const FChar *s)
-{
- for (unsigned numSlashes = 0;;)
- {
- FChar c = *s++;
- if (c == 0)
- return numSlashes;
- if (IS_PATH_SEPAR(c))
- numSlashes++;
- }
-}
-
-#ifdef _WIN32
-void ConvertToLongNames(NWildcard::CCensor &censor);
-#endif
-
HRESULT UpdateArchive(
CCodecs *codecs,
const CObjectVector<COpenType> &types,
@@ -1025,7 +1093,7 @@ HRESULT UpdateArchive(
if (options.SfxMode)
{
CProperty property;
- property.Name.SetFromAscii("rsfx");
+ property.Name = "rsfx";
options.MethodMode.Properties.Add(property);
if (options.SfxModule.IsEmpty())
{
@@ -1058,7 +1126,15 @@ HRESULT UpdateArchive(
!options.SetArcPath(codecs, cmdArcPath2))
return E_NOTIMPL;
}
- const UString arcPath = options.ArchivePath.GetFinalPath();
+
+ UString arcPath = options.ArchivePath.GetFinalPath();
+
+ if (!options.VolumesSizes.IsEmpty())
+ {
+ arcPath = options.ArchivePath.GetFinalVolPath();
+ arcPath += '.';
+ arcPath += "001";
+ }
if (cmdArcPath2.IsEmpty())
{
@@ -1084,8 +1160,23 @@ HRESULT UpdateArchive(
throw "there is no such archive";
if (fi.IsDevice)
return E_NOTIMPL;
+
+ if (!options.StdOutMode && options.UpdateArchiveItself)
+ if (fi.IsReadOnly())
+ {
+ errorInfo.SystemError = ERROR_ACCESS_DENIED;
+ errorInfo.Message = "The file is read-only";
+ errorInfo.FileNames.Add(arcPath);
+ return errorInfo.Get_HRESULT_Error();
+ }
+
if (options.VolumesSizes.Size() > 0)
+ {
+ errorInfo.FileNames.Add(us2fs(arcPath));
+ errorInfo.SystemError = (DWORD)E_NOTIMPL;
+ errorInfo.Message = kUpdateIsNotSupoorted_MultiVol;
return E_NOTIMPL;
+ }
CObjectVector<COpenType> types2;
// change it.
if (options.MethodMode.Type_Defined)
@@ -1122,7 +1213,7 @@ HRESULT UpdateArchive(
if (arcLink.VolumePaths.Size() > 1)
{
errorInfo.SystemError = (DWORD)E_NOTIMPL;
- errorInfo.Message = "Updating for multivolume archives is not implemented";
+ errorInfo.Message = kUpdateIsNotSupoorted_MultiVol;
return E_NOTIMPL;
}
@@ -1147,7 +1238,7 @@ HRESULT UpdateArchive(
if (options.MethodMode.Type.FormatIndex < 0)
{
- options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArcType);
+ options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType((UString)kDefaultArcType);
if (options.MethodMode.Type.FormatIndex < 0)
return E_NOTIMPL;
}
@@ -1218,7 +1309,7 @@ HRESULT UpdateArchive(
{
NFind::CFileInfo fi;
FString prefix = us2fs(censor.Pairs[0].Prefix);
- prefix += FTEXT('.');
+ prefix += '.';
// UString prefix = censor.Pairs[0].Prefix;
/*
if (prefix.Back() == WCHAR_PATH_SEPARATOR)
@@ -1353,7 +1444,7 @@ HRESULT UpdateArchive(
if (options.StdOutMode)
{
- name.SetFromAscii("stdout");
+ name = "stdout";
isUpdating = thereIsInArchive;
}
else
@@ -1399,9 +1490,13 @@ HRESULT UpdateArchive(
CArchivePath &ap = options.Commands[0].ArchivePath;
const FString &tempPath = ap.GetTempPath();
+ // DWORD attrib = 0;
if (thereIsInArchive)
+ {
+ // attrib = NFind::GetFileAttrib(us2fs(arcPath));
if (!DeleteFileAlways(us2fs(arcPath)))
return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));
+ }
if (!MyMoveFile(tempPath, us2fs(arcPath)))
{
@@ -1409,6 +1504,15 @@ HRESULT UpdateArchive(
errorInfo.FileNames.Add(us2fs(arcPath));
return errorInfo.Get_HRESULT_Error();
}
+
+ /*
+ if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
+ {
+ DWORD attrib2 = NFind::GetFileAttrib(us2fs(arcPath));
+ if (attrib2 != INVALID_FILE_ATTRIBUTES)
+ NDir::SetFileAttrib(us2fs(arcPath), attrib2 | FILE_ATTRIBUTE_READONLY);
+ }
+ */
}
catch(...)
{
@@ -1461,10 +1565,10 @@ HRESULT UpdateArchive(
for (i = 0; i < fullPaths.Size(); i++)
{
- UString arcPath2 = fs2us(fullPaths[i]);
- UString fileName = ExtractFileNameFromPath(arcPath2);
- AString path = GetAnsiString(arcPath2);
- AString name = GetAnsiString(fileName);
+ const UString arcPath2 = fs2us(fullPaths[i]);
+ const UString fileName = ExtractFileNameFromPath(arcPath2);
+ const AString path (GetAnsiString(arcPath2));
+ const AString name (GetAnsiString(fileName));
// Warning!!! MAPISendDocuments function changes Current directory
// fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
@@ -1479,7 +1583,7 @@ HRESULT UpdateArchive(
m.nFileCount = 1;
m.lpFiles = &f;
- const AString addr = GetAnsiString(options.EMailAddress);
+ const AString addr (GetAnsiString(options.EMailAddress));
MapiRecipDesc rec;
if (!addr.IsEmpty())
{
@@ -1498,7 +1602,7 @@ HRESULT UpdateArchive(
if (options.DeleteAfterCompressing)
{
- CRecordVector<CRefSortPair> pairs;
+ CRecordVector<CDirPathSortPair> pairs;
FStringVector foldersNames;
unsigned i;
@@ -1506,20 +1610,30 @@ HRESULT UpdateArchive(
for (i = 0; i < dirItems.Items.Size(); i++)
{
const CDirItem &dirItem = dirItems.Items[i];
- FString phyPath = dirItems.GetPhyPath(i);
+ const FString phyPath = dirItems.GetPhyPath(i);
if (dirItem.IsDir())
{
- CRefSortPair pair;
+ CDirPathSortPair pair;
pair.Index = i;
- pair.Len = GetNumSlashes(phyPath);
+ pair.SetNumSlashes(phyPath);
pairs.Add(pair);
}
else
{
if (processedItems[i] != 0 || dirItem.Size == 0)
{
- RINOK(callback->DeletingAfterArchiving(phyPath, false));
- DeleteFileAlways(phyPath);
+ NFind::CFileInfo fileInfo;
+ if (fileInfo.Find(phyPath))
+ {
+ // maybe we must exclude also files with archive name: "a a.7z * -sdel"
+ if (fileInfo.Size == dirItem.Size
+ && CompareFileTime(&fileInfo.MTime, &dirItem.MTime) == 0
+ && CompareFileTime(&fileInfo.CTime, &dirItem.CTime) == 0)
+ {
+ RINOK(callback->DeletingAfterArchiving(phyPath, false));
+ DeleteFileAlways(phyPath);
+ }
+ }
}
else
{
@@ -1534,11 +1648,11 @@ HRESULT UpdateArchive(
}
}
- pairs.Sort(CompareRefSortPair, NULL);
+ pairs.Sort2();
for (i = 0; i < pairs.Size(); i++)
{
- FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
+ const FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
if (NFind::DoesDirExist(phyPath))
{
RINOK(callback->DeletingAfterArchiving(phyPath, true));
diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h
index 4e3fb2a..45b02d7 100644
--- a/CPP/7zip/UI/Common/Update.h
+++ b/CPP/7zip/UI/Common/Update.h
@@ -92,6 +92,7 @@ struct CUpdateOptions
FString SfxModule;
bool OpenShareForWrite;
+ bool StopAfterOpenError;
bool StdInMode;
UString StdInFileName;
@@ -127,6 +128,7 @@ struct CUpdateOptions
EMailMode(false),
EMailRemoveAfter(false),
OpenShareForWrite(false),
+ StopAfterOpenError(false),
ArcNameMode(k_ArcNameMode_Smart),
PathMode(NWildcard::k_RelatPath),
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp
index ab36f82..9c165fe 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -51,8 +51,11 @@ CArchiveUpdateCallback::CArchiveUpdateCallback():
ArcItems(NULL),
UpdatePairs(NULL),
NewNames(NULL),
+ CommentIndex(-1),
+ Comment(NULL),
ShareForWrite(false),
+ StopAfterOpenError(false),
StdInMode(false),
KeepOriginalItemNames(false),
@@ -300,7 +303,7 @@ static UString GetRelativePath(const UString &to, const UString &from)
unsigned k;
for (k = i + 1; k < partsFrom.Size(); k++)
- s += L".." WSTRING_PATH_SEPARATOR;
+ s += ".." STRING_PATH_SEPARATOR;
for (k = i; k < partsTo.Size(); k++)
{
@@ -344,7 +347,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
// if (di.IsDir())
{
CReparseAttr attr;
- if (attr.Parse(di.ReparseData, di.ReparseData.Size()))
+ DWORD errorCode = 0;
+ if (attr.Parse(di.ReparseData, di.ReparseData.Size(), errorCode))
{
UString simpleName = attr.GetPath();
if (attr.IsRelative())
@@ -396,6 +400,11 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
}
else if (propID == kpidPath && up.NewNameIndex >= 0)
prop = (*NewNames)[up.NewNameIndex];
+ else if (propID == kpidComment
+ && CommentIndex >= 0
+ && (unsigned)CommentIndex == index
+ && Comment)
+ prop = *Comment;
else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem)
{
// we can generate new ShortName here;
@@ -505,7 +514,12 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
#endif
if (!inStreamSpec->OpenShared(path, ShareForWrite))
{
- return Callback->OpenFileError(path, ::GetLastError());
+ DWORD error = ::GetLastError();
+ HRESULT hres = Callback->OpenFileError(path, error);
+ if (StopAfterOpenError)
+ if (hres == S_OK || hres == S_FALSE)
+ return HRESULT_FROM_WIN32(error);
+ return hres;
}
if (StoreHardLinks)
@@ -690,13 +704,13 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
{
COM_TRY_BEGIN
- FChar temp[16];
+ char temp[16];
ConvertUInt32ToString(index + 1, temp);
- FString res = temp;
+ FString res (temp);
while (res.Len() < 2)
res.InsertAtFront(FTEXT('0'));
FString fileName = VolName;
- fileName += FTEXT('.');
+ fileName += '.';
fileName += res;
fileName += VolExt;
COutFileStream *streamSpec = new COutFileStream;
diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h
index 81f5ed6..1b5d1ee 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.h
+++ b/CPP/7zip/UI/Common/UpdateCallback.h
@@ -15,6 +15,18 @@
#include "OpenArchive.h"
+struct CArcToDoStat
+{
+ CDirItemsStat2 NewData;
+ CDirItemsStat2 OldData;
+ CDirItemsStat2 DeleteData;
+
+ UInt64 Get_NumDataItems_Total() const
+ {
+ return NewData.Get_NumDataItems2() + OldData.Get_NumDataItems2();
+ }
+};
+
#define INTERFACE_IUpdateCallbackUI(x) \
virtual HRESULT WriteSfx(const wchar_t *name, UInt64 size) x; \
virtual HRESULT SetTotal(UInt64 size) x; \
@@ -22,7 +34,7 @@
virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \
virtual HRESULT CheckBreak() x; \
/* virtual HRESULT Finalize() x; */ \
- virtual HRESULT SetNumItems(UInt64 numItems) x; \
+ virtual HRESULT SetNumItems(const CArcToDoStat &stat) x; \
virtual HRESULT GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) x; \
virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \
virtual HRESULT ReadingFileError(const FString &path, DWORD systemError) x; \
@@ -120,8 +132,11 @@ public:
const CObjectVector<CArcItem> *ArcItems;
const CRecordVector<CUpdatePair2> *UpdatePairs;
const UStringVector *NewNames;
+ int CommentIndex;
+ const UString *Comment;
bool ShareForWrite;
+ bool StopAfterOpenError;
bool StdInMode;
bool KeepOriginalItemNames;
diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp
index 10864b2..5153671 100644
--- a/CPP/7zip/UI/Common/UpdatePair.cpp
+++ b/CPP/7zip/UI/Common/UpdatePair.cpp
@@ -38,14 +38,13 @@ static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time
throw 4191618;
}
-static const char *k_Duplicate_inArc_Message = "Duplicate filename in archive:";
-static const char *k_Duplicate_inDir_Message = "Duplicate filename on disk:";
-static const char *k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):";
+static const char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:";
+static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:";
+static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):";
static void ThrowError(const char *message, const UString &s1, const UString &s2)
{
- UString m;
- m.SetFromAscii(message);
+ UString m (message);
m.Add_LF(); m += s1;
m.Add_LF(); m += s2;
throw m;
diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp
index 4f28a1e..c025ac4 100644
--- a/CPP/7zip/UI/Common/UpdateProduce.cpp
+++ b/CPP/7zip/UI/Common/UpdateProduce.cpp
@@ -6,7 +6,7 @@
using namespace NUpdateArchive;
-static const char *kUpdateActionSetCollision = "Internal collision in update action set";
+static const char * const kUpdateActionSetCollision = "Internal collision in update action set";
void UpdateProduce(
const CRecordVector<CUpdatePair> &updatePairs,
diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h
index d349fae..4c16b61 100644
--- a/CPP/7zip/UI/Common/ZipRegistry.h
+++ b/CPP/7zip/UI/Common/ZipRegistry.h
@@ -48,9 +48,14 @@ namespace NCompression
UString Options;
UString EncryptionMethod;
+ void Reset_BlockLogSize()
+ {
+ BlockLogSize = (UInt32)(Int32)-1;
+ }
+
void ResetForLevelChange()
{
- BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1);
+ BlockLogSize = NumThreads = Level = Dictionary = Order = (UInt32)(Int32)-1;
Method.Empty();
// Options.Empty();
// EncryptionMethod.Empty();
diff --git a/CPP/7zip/UI/Console/Console.manifest b/CPP/7zip/UI/Console/Console.manifest
new file mode 100644
index 0000000..77ecaad
--- /dev/null
+++ b/CPP/7zip/UI/Console/Console.manifest
@@ -0,0 +1,13 @@
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7z" type="win32"></assemblyIdentity>
+<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+<security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false">
+</requestedExecutionLevel></requestedPrivileges></security></trustInfo>
+<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application>
+<!-- Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+<!-- Win 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+<!-- Win 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+<!-- Win 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+<!-- Win 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+</application></compatibility>
+</assembly> \ No newline at end of file
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
index cc82770..bdf9549 100644
--- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
@@ -32,7 +32,7 @@ static HRESULT CheckBreak2()
return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
}
-static const char *kError = "ERROR: ";
+static const char * const kError = "ERROR: ";
void CExtractScanConsole::StartScanning()
@@ -60,8 +60,9 @@ HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError)
if (_se)
{
- *_se << endl << kError << NError::MyFormatMessage(systemError) << endl <<
- fs2us(path) << endl << endl;
+ *_se << endl << kError << NError::MyFormatMessage(systemError) << endl;
+ _se->NormalizePrint_UString(fs2us(path));
+ *_se << endl << endl;
_se->Flush();
}
return HRESULT_FROM_WIN32(systemError);
@@ -95,6 +96,16 @@ void PrintSize_bytes_Smart(AString &s, UInt64 val)
s += ')';
}
+void PrintSize_bytes_Smart_comma(AString &s, UInt64 val)
+{
+ if (val == (UInt64)(Int64)-1)
+ return;
+ s += ", ";
+ PrintSize_bytes_Smart(s, val);
+}
+
+
+
void Print_DirItemsStat(AString &s, const CDirItemsStat &st)
{
if (st.NumDirs != 0)
@@ -103,17 +114,48 @@ void Print_DirItemsStat(AString &s, const CDirItemsStat &st)
s += ", ";
}
Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? "file" : "files");
- s += ", ";
- PrintSize_bytes_Smart(s, st.FilesSize);
+ PrintSize_bytes_Smart_comma(s, st.FilesSize);
if (st.NumAltStreams != 0)
{
s.Add_LF();
Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams");
- s += ", ";
- PrintSize_bytes_Smart(s, st.AltStreamsSize);
+ PrintSize_bytes_Smart_comma(s, st.AltStreamsSize);
}
}
+
+void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st)
+{
+ Print_DirItemsStat(s, (CDirItemsStat &)st);
+ bool needLF = true;
+ if (st.Anti_NumDirs != 0)
+ {
+ if (needLF)
+ s.Add_LF();
+ needLF = false;
+ Print_UInt64_and_String(s, st.Anti_NumDirs, st.Anti_NumDirs == 1 ? "anti-folder" : "anti-folders");
+ }
+ if (st.Anti_NumFiles != 0)
+ {
+ if (needLF)
+ s.Add_LF();
+ else
+ s += ", ";
+ needLF = false;
+ Print_UInt64_and_String(s, st.Anti_NumFiles, st.Anti_NumFiles == 1 ? "anti-file" : "anti-files");
+ }
+ if (st.Anti_NumAltStreams != 0)
+ {
+ if (needLF)
+ s.Add_LF();
+ else
+ s += ", ";
+ needLF = false;
+ Print_UInt64_and_String(s, st.Anti_NumAltStreams, "anti-alternate-streams");
+ }
+}
+
+
void CExtractScanConsole::PrintStat(const CDirItemsStat &st)
{
if (_so)
@@ -138,33 +180,33 @@ static NSynchronization::CCriticalSection g_CriticalSection;
#endif
-static const char *kTestString = "T";
-static const char *kExtractString = "-";
-static const char *kSkipString = ".";
+static const char * const kTestString = "T";
+static const char * const kExtractString = "-";
+static const char * const kSkipString = ".";
-// static const char *kCantAutoRename = "can not create file with auto name\n";
-// static const char *kCantRenameFile = "can not rename existing file\n";
-// static const char *kCantDeleteOutputFile = "can not delete output file ";
+// static const char * const kCantAutoRename = "can not create file with auto name\n";
+// static const char * const kCantRenameFile = "can not rename existing file\n";
+// static const char * const kCantDeleteOutputFile = "can not delete output file ";
-static const char *kMemoryExceptionMessage = "Can't allocate required memory!";
+static const char * const kMemoryExceptionMessage = "Can't allocate required memory!";
-static const char *kExtracting = "Extracting archive: ";
-static const char *kTesting = "Testing archive: ";
+static const char * const kExtracting = "Extracting archive: ";
+static const char * const kTesting = "Testing archive: ";
-static const char *kEverythingIsOk = "Everything is Ok";
-static const char *kNoFiles = "No files to process";
+static const char * const kEverythingIsOk = "Everything is Ok";
+static const char * const kNoFiles = "No files to process";
-static const char *kUnsupportedMethod = "Unsupported Method";
-static const char *kCrcFailed = "CRC Failed";
-static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";
-static const char *kDataError = "Data Error";
-static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";
-static const char *kUnavailableData = "Unavailable data";
-static const char *kUnexpectedEnd = "Unexpected end of data";
-static const char *kDataAfterEnd = "There are some data after the end of the payload data";
-static const char *kIsNotArc = "Is not archive";
-static const char *kHeadersError = "Headers Error";
-static const char *kWrongPassword = "Wrong password";
+static const char * const kUnsupportedMethod = "Unsupported Method";
+static const char * const kCrcFailed = "CRC Failed";
+static const char * const kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";
+static const char * const kDataError = "Data Error";
+static const char * const kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";
+static const char * const kUnavailableData = "Unavailable data";
+static const char * const kUnexpectedEnd = "Unexpected end of data";
+static const char * const kDataAfterEnd = "There are some data after the end of the payload data";
+static const char * const kIsNotArc = "Is not archive";
+static const char * const kHeadersError = "Headers Error";
+static const char * const kWrongPassword = "Wrong password";
static const char * const k_ErrorFlagsMessages[] =
{
@@ -206,12 +248,14 @@ STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue)
return CheckBreak2();
}
-static const char *kTab = " ";
+static const char * const kTab = " ";
static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size)
{
- *_so << kTab << "Path: " << path << endl;
- if (size)
+ *_so << kTab << "Path: ";
+ _so->NormalizePrint_wstr(path);
+ *_so << endl;
+ if (size && *size != (UInt64)(Int64)-1)
{
AString s;
PrintSize_bytes_Smart(s, *size);
@@ -220,10 +264,8 @@ static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIM
if (ft)
{
char temp[64];
- FILETIME locTime;
- if (FileTimeToLocalFileTime(ft, &locTime))
- if (ConvertFileTimeToString(locTime, temp, true, true))
- *_so << kTab << "Modified: " << temp << endl;
+ if (ConvertUtcFileTimeToString(*ft, temp, kTimestampPrintLevel_SEC))
+ *_so << kTab << "Modified: " << temp << endl;
}
}
@@ -256,6 +298,8 @@ STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break;
case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break;
case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break;
+ case NUserAnswerMode::kEof: return E_ABORT;
+ case NUserAnswerMode::kError: return E_FAIL;
default: return E_FAIL;
}
@@ -299,7 +343,10 @@ STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int3
_tempU.Empty();
if (name)
+ {
_tempU = name;
+ _so->Normalize_UString(_tempU);
+ }
_so->PrintUString(_tempU, _tempA);
if (position)
*_so << " <" << *position << ">";
@@ -388,10 +435,8 @@ void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest)
dest += s;
else
{
- char temp[16];
- ConvertUInt32ToString(opRes, temp);
dest += "Error #";
- dest += temp;
+ dest.Add_UInt32(opRes);
}
}
@@ -422,7 +467,10 @@ STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encr
*_se << s;
if (!_currentName.IsEmpty())
- *_se << " : " << _currentName;
+ {
+ *_se << " : ";
+ _se->NormalizePrint_UString(_currentName);
+ }
*_se << endl;
_se->Flush();
}
@@ -474,7 +522,11 @@ HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode)
ClosePercents_for_so();
if (_so)
- *_so << endl << (testMode ? kTesting : kExtracting) << name << endl;
+ {
+ *_so << endl << (testMode ? kTesting : kExtracting);
+ _so->NormalizePrint_wstr(name);
+ *_so << endl;
+ }
if (NeedPercents())
_percent.Command = "Open";
@@ -524,22 +576,23 @@ void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags)
void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType)
{
s.Add_LF();
- s.AddAscii(pre);
- s.AddAscii(" as [");
+ s += pre;
+ s += " as [";
s += arcType;
- s.AddAscii("] archive");
+ s += "] archive";
}
void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc)
{
const CArcErrorInfo &er = arc.ErrorInfo;
- UString s = L"WARNING:\n";
- s += arc.Path;
+ *_so << "WARNING:\n";
+ _so->NormalizePrint_UString(arc.Path);
+ UString s;
if (arc.FormatIndex == er.ErrorFormatIndex)
{
s.Add_LF();
- s.AddAscii("The archive is open with offset");
+ s += "The archive is open with offset";
}
else
{
@@ -580,7 +633,10 @@ HRESULT CExtractCallbackConsole::OpenResult(
{
*_se << endl;
if (level != 0)
- *_se << arc.Path << endl;
+ {
+ _se->NormalizePrint_UString(arc.Path);
+ *_se << endl;
+ }
}
if (errorFlags != 0)
@@ -614,7 +670,10 @@ HRESULT CExtractCallbackConsole::OpenResult(
{
*_so << endl;
if (level != 0)
- *_so << arc.Path << endl;
+ {
+ _so->NormalizePrint_UString(arc.Path);
+ *_so << endl;
+ }
}
if (warningFlags != 0)
@@ -669,7 +728,9 @@ HRESULT CExtractCallbackConsole::OpenResult(
_so->Flush();
if (_se)
{
- *_se << kError << name << endl;
+ *_se << kError;
+ _se->NormalizePrint_wstr(name);
+ *_se << endl;
HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
RINOK(res);
if (result == S_FALSE)
diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp
index 863c5e5..ec8e6dc 100644
--- a/CPP/7zip/UI/Console/HashCon.cpp
+++ b/CPP/7zip/UI/Console/HashCon.cpp
@@ -7,9 +7,9 @@
#include "ConsoleClose.h"
#include "HashCon.h"
-static const wchar_t *kEmptyFileAlias = L"[Content]";
+static const char * const kEmptyFileAlias = "[Content]";
-static const char *kScanningMessage = "Scanning";
+static const char * const kScanningMessage = "Scanning";
static HRESULT CheckBreak2()
{
@@ -168,7 +168,7 @@ HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb)
if (PrintSize)
{
_s.Add_Space();
- const AString s2 = "Size";
+ const AString s2 ("Size");
AddSpaces_if_Positive(_s, (int)kSizeField_Len - (int)s2.Len());
_s += s2;
}
@@ -269,7 +269,7 @@ HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBun
if (_fileName.IsEmpty())
*_so << kEmptyFileAlias;
else
- *_so << _fileName;
+ _so->NormalizePrint_UString(_fileName);
}
*_so << endl;
}
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
index 77168c9..ebcabb6 100644
--- a/CPP/7zip/UI/Console/List.cpp
+++ b/CPP/7zip/UI/Console/List.cpp
@@ -128,14 +128,14 @@ static const char * const kPropIdToName[] =
static const char kEmptyAttribChar = '.';
-static const char *kListing = "Listing archive: ";
+static const char * const kListing = "Listing archive: ";
-static const char *kString_Files = "files";
-static const char *kString_Dirs = "folders";
-static const char *kString_AltStreams = "alternate streams";
-static const char *kString_Streams = "streams";
+static const char * const kString_Files = "files";
+static const char * const kString_Dirs = "folders";
+static const char * const kString_AltStreams = "alternate streams";
+static const char * const kString_Streams = "streams";
-static const char *kError = "ERROR: ";
+static const char * const kError = "ERROR: ";
static void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, char *s)
{
@@ -417,9 +417,8 @@ static void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UStr
nameU = name;
else
{
- char s[16];
- ConvertUInt32ToString(propID, s);
- nameA = s;
+ nameA.Empty();
+ nameA.Add_UInt32(propID);
}
}
@@ -429,7 +428,7 @@ void CFieldPrinter::AddProp(const wchar_t *name, PROPID propID, bool isRawProp)
f.PropID = propID;
f.IsRawProp = isRawProp;
GetPropName(propID, name, f.NameA, f.NameU);
- f.NameU.AddAscii(" = ");
+ f.NameU += " = ";
if (!f.NameA.IsEmpty())
f.NameA += " = ";
else
@@ -499,10 +498,7 @@ static void PrintTime(char *dest, const FILETIME *ft)
*dest = 0;
if (ft->dwLowDateTime == 0 && ft->dwHighDateTime == 0)
return;
- FILETIME locTime;
- if (!FileTimeToLocalFileTime(ft, &locTime))
- throw 20121211;
- ConvertFileTimeToString(locTime, dest, true, true);
+ ConvertUtcFileTimeToString(*ft, dest, kTimestampPrintLevel_SEC);
}
#ifndef _SFX
@@ -564,7 +560,7 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)
{
if (!techMode)
g_StdOut << temp;
- g_StdOut.PrintUString(FilePath, TempAString);
+ g_StdOut.NormalizePrint_UString(FilePath, TempWString, TempAString);
if (techMode)
g_StdOut << MY_ENDL;
continue;
@@ -675,9 +671,10 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)
else if (prop.vt == VT_BSTR)
{
TempWString.SetFromBstr(prop.bstrVal);
+ // do we need multi-line support here ?
+ g_StdOut.Normalize_UString(TempWString);
if (techMode)
{
- // replace CR/LF here.
g_StdOut.PrintUString(TempWString, TempAString);
}
else
@@ -686,7 +683,7 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)
else
{
char s[64];
- ConvertPropertyToShortString(s, prop, f.PropID);
+ ConvertPropertyToShortString2(s, prop, f.PropID);
if (techMode)
g_StdOut << s;
else
@@ -819,25 +816,81 @@ static void PrintPropNameAndNumber_Signed(CStdOutStream &so, PROPID propID, Int6
so << val << endl;
}
-static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val)
+
+static void UString_Replace_CRLF_to_LF(UString &s)
+{
+ // s.Replace(L"\r\n", L"\n");
+ wchar_t *src = s.GetBuf();
+ wchar_t *dest = src;
+ for (;;)
+ {
+ wchar_t c = *src++;
+ if (c == 0)
+ break;
+ if (c == '\r' && *src == '\n')
+ {
+ src++;
+ c = '\n';
+ }
+ *dest++ = c;
+ }
+ s.ReleaseBuf_SetEnd((unsigned)(dest - s.GetBuf()));
+}
+
+
+static void PrintPropVal_MultiLine(CStdOutStream &so, const wchar_t *val)
{
- so << name << " = " << val << endl;
+ UString s = val;
+ if (s.Find(L'\n') >= 0)
+ {
+ so << endl;
+ so << "{";
+ so << endl;
+ UString_Replace_CRLF_to_LF(s);
+ so.Normalize_UString__LF_Allowed(s);
+ so << s;
+ so << endl;
+ so << "}";
+ }
+ else
+ {
+ so.Normalize_UString(s);
+ so << s;
+ }
+ so << endl;
+}
+
+
+static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val, bool multiLine)
+{
+ so << name << " = ";
+ if (multiLine)
+ {
+ PrintPropVal_MultiLine(so, val);
+ return;
+ }
+ UString s = val;
+ so.Normalize_UString(s);
+ so << s;
+ so << endl;
}
static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop)
{
UString s;
- ConvertPropertyToString(s, prop, propID);
+ ConvertPropertyToString2(s, prop, propID);
if (!s.IsEmpty())
{
AString nameA;
UString nameU;
GetPropName(propID, name, nameA, nameU);
if (!nameA.IsEmpty())
- PrintPropPair(so, nameA, s);
+ so << nameA;
else
- so << nameU << " = " << s << endl;
+ so << nameU;
+ so << " = ";
+ PrintPropVal_MultiLine(so, s);
}
}
@@ -866,11 +919,11 @@ static void ErrorInfo_Print(CStdOutStream &so, const CArcErrorInfo &er)
{
PrintErrorFlags(so, "ERRORS:", er.GetErrorFlags());
if (!er.ErrorMessage.IsEmpty())
- PrintPropPair(so, "ERROR", er.ErrorMessage);
+ PrintPropPair(so, "ERROR", er.ErrorMessage, true);
PrintErrorFlags(so, "WARNINGS:", er.GetWarningFlags());
if (!er.WarningMessage.IsEmpty())
- PrintPropPair(so, "WARNING", er.WarningMessage);
+ PrintPropPair(so, "WARNING", er.WarningMessage, true);
}
HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink)
@@ -881,7 +934,7 @@ HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const
const CArcErrorInfo &er = arc.ErrorInfo;
so << "--\n";
- PrintPropPair(so, "Path", arc.Path);
+ PrintPropPair(so, "Path", arc.Path, false);
if (er.ErrorFormatIndex >= 0)
{
if (er.ErrorFormatIndex == arc.FormatIndex)
@@ -889,7 +942,7 @@ HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const
else
PrintArcTypeError(so, codecs->GetFormatNamePtr(er.ErrorFormatIndex), true);
}
- PrintPropPair(so, "Type", codecs->GetFormatNamePtr(arc.FormatIndex));
+ PrintPropPair(so, "Type", codecs->GetFormatNamePtr(arc.FormatIndex), false);
ErrorInfo_Print(so, er);
@@ -947,7 +1000,8 @@ HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const
{
if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
{
- so << arcLink.NonOpen_ArcPath << endl;
+ so.NormalizePrint_UString(arcLink.NonOpen_ArcPath);
+ so << endl;
PrintArcTypeError(so, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);
}
else
@@ -1018,15 +1072,18 @@ HRESULT ListArchives(CCodecs *codecs,
errorCode = ERROR_FILE_NOT_FOUND;
lastError = HRESULT_FROM_WIN32(lastError);;
g_StdOut.Flush();
- *g_ErrStream << endl << kError << NError::MyFormatMessage(errorCode) <<
- endl << arcPath << endl << endl;
+ *g_ErrStream << endl << kError << NError::MyFormatMessage(errorCode) << endl;
+ g_ErrStream->NormalizePrint_UString(arcPath);
+ *g_ErrStream << endl << endl;
numErrors++;
continue;
}
if (fi.IsDir())
{
g_StdOut.Flush();
- *g_ErrStream << endl << kError << arcPath << " is not a file" << endl << endl;
+ *g_ErrStream << endl << kError;
+ g_ErrStream->NormalizePrint_UString(arcPath);
+ *g_ErrStream << " is not a file" << endl << endl;
numErrors++;
continue;
}
@@ -1065,7 +1122,9 @@ HRESULT ListArchives(CCodecs *codecs,
if (enableHeaders)
{
- g_StdOut << endl << kListing << arcPath << endl << endl;
+ g_StdOut << endl << kListing;
+ g_StdOut.NormalizePrint_UString(arcPath);
+ g_StdOut << endl << endl;
}
HRESULT result = arcLink.Open_Strict(options, &openCallback);
@@ -1075,7 +1134,9 @@ HRESULT ListArchives(CCodecs *codecs,
if (result == E_ABORT)
return result;
g_StdOut.Flush();
- *g_ErrStream << endl << kError << arcPath << " : ";
+ *g_ErrStream << endl << kError;
+ g_ErrStream->NormalizePrint_UString(arcPath);
+ *g_ErrStream << " : ";
if (result == S_FALSE)
{
Print_OpenArchive_Error(*g_ErrStream, codecs, arcLink);
@@ -1259,7 +1320,7 @@ HRESULT ListArchives(CCodecs *codecs,
if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
{
g_StdOut << "----------\n";
- PrintPropPair(g_StdOut, "Path", arcLink.NonOpen_ArcPath);
+ PrintPropPair(g_StdOut, "Path", arcLink.NonOpen_ArcPath, false);
PrintArcTypeError(g_StdOut, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);
}
}
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
index f54e9c3..8f2825c 100644
--- a/CPP/7zip/UI/Console/Main.cpp
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -10,10 +10,6 @@
#include "../../../../C/CpuArch.h"
-#if defined( _7ZIP_LARGE_PAGES)
-#include "../../../../C/Alloc.h"
-#endif
-
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/CommandLineParser.h"
@@ -25,10 +21,6 @@
#include "../../../Windows/ErrorMsg.h"
-#ifdef _WIN32
-#include "../../../Windows/MemoryLock.h"
-#endif
-
#include "../../../Windows/TimeUtils.h"
#include "../Common/ArchiveCommandLine.h"
@@ -64,6 +56,8 @@ using namespace NCommandLineParser;
HINSTANCE g_hInstance = 0;
#endif
+extern bool g_LargePagesMode;
+
extern CStdOutStream *g_StdStream;
extern CStdOutStream *g_ErrStream;
@@ -73,24 +67,19 @@ extern const CCodecInfo *g_Codecs[];
extern unsigned g_NumHashers;
extern const CHasherInfo *g_Hashers[];
-static const char *kCopyrightString = "\n7-Zip"
-#ifndef EXTERNAL_CODECS
-#ifdef PROG_VARIANT_R
-" (r)"
-#else
-" (a)"
-#endif
-#endif
-
-#ifdef MY_CPU_64BIT
-" [64]"
-#elif defined MY_CPU_32BIT
-" [32]"
-#endif
+static const char * const kCopyrightString = "\n7-Zip"
+ #ifndef EXTERNAL_CODECS
+ #ifdef PROG_VARIANT_R
+ " (r)"
+ #else
+ " (a)"
+ #endif
+ #endif
-" " MY_VERSION_COPYRIGHT_DATE "\n\n";
+ " " MY_VERSION_CPU
+ " : " MY_COPYRIGHT_DATE "\n\n";
-static const char *kHelpString =
+static const char * const kHelpString =
"Usage: 7z"
#ifndef EXTERNAL_CODECS
#ifdef PROG_VARIANT_R
@@ -100,7 +89,6 @@ static const char *kHelpString =
#endif
#endif
" <command> [<switches>...] <archive_name> [<file_names>...]\n"
- " [<@listfiles...>]\n"
"\n"
"<Commands>\n"
" a : Add files to archive\n"
@@ -117,6 +105,7 @@ static const char *kHelpString =
"\n"
"<Switches>\n"
" -- : Stop switches parsing\n"
+ " @listfile : set path to listfile that contains file names\n"
" -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n"
" -ax[r[-|0]]{@listfile|!wildcard} : eXclude archives\n"
" -ao{a|s|t|u} : set Overwrite mode\n"
@@ -128,6 +117,7 @@ static const char *kHelpString =
" -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n"
" -m{Parameters} : set compression Method\n"
" -mmt[N] : set number of CPU threads\n"
+ " -mx[N] : set compression level: -mx1 (fastest) ... -mx9 (ultra)\n"
" -o{Directory} : set Output directory\n"
#ifndef _NO_CRYPTO
" -p{Password} : set Password\n"
@@ -152,6 +142,7 @@ static const char *kHelpString =
" -spe : eliminate duplication of root folder for extract command\n"
" -spf : use fully qualified file paths\n"
" -ssc[-] : set sensitive case mode\n"
+ " -sse : stop archive creating, if it can't open some input file\n"
" -ssw : compress shared files\n"
" -stl : set archive timestamp from the most recently modified file\n"
" -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)\n"
@@ -166,13 +157,13 @@ static const char *kHelpString =
// ---------------------------
// exception messages
-static const char *kEverythingIsOk = "Everything is Ok";
-static const char *kUserErrorMessage = "Incorrect command line";
-static const char *kNoFormats = "7-Zip cannot find the code that works with archives.";
-static const char *kUnsupportedArcTypeMessage = "Unsupported archive type";
-// static const char *kUnsupportedUpdateArcType = "Can't create archive for that type";
+static const char * const kEverythingIsOk = "Everything is Ok";
+static const char * const kUserErrorMessage = "Incorrect command line";
+static const char * const kNoFormats = "7-Zip cannot find the code that works with archives.";
+static const char * const kUnsupportedArcTypeMessage = "Unsupported archive type";
+// static const char * const kUnsupportedUpdateArcType = "Can't create archive for that type";
-static CFSTR kDefaultSfxModule = FTEXT("7zCon.sfx");
+#define kDefaultSfxModule "7zCon.sfx"
static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code)
{
@@ -204,9 +195,9 @@ static void ShowCopyrightAndHelp(CStdOutStream *so, bool needHelp)
}
-static void PrintStringRight(CStdOutStream &so, const AString &s, unsigned size)
+static void PrintStringRight(CStdOutStream &so, const char *s, unsigned size)
{
- unsigned len = s.Len();
+ unsigned len = MyStringLen(s);
for (unsigned i = len; i < size; i++)
so << ' ';
so << s;
@@ -245,7 +236,8 @@ static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so)
{
FOR_VECTOR(i, pc.Paths)
{
- so << pc.Paths[i] << " : ";
+ so.NormalizePrint_UString(pc.Paths[i]);
+ so << " : ";
so << NError::MyFormatMessage(pc.Codes[i]) << endl;
}
so << "----------------" << endl;
@@ -279,7 +271,7 @@ static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
UString message;
if (!errorInfo.Message.IsEmpty())
{
- message.AddAscii(errorInfo.Message);
+ message += errorInfo.Message.Ptr();
message.Add_LF();
}
{
@@ -384,11 +376,14 @@ static void PrintMemUsage(const char *s, UInt64 val)
*g_StdStream << " " << s << " Memory =";
PrintNum(SHIFT_SIZE_VALUE(val, 20), 7);
*g_StdStream << " MB";
+ if (g_LargePagesMode)
+ *g_StdStream << " (LP)";
}
EXTERN_C_BEGIN
typedef BOOL (WINAPI *Func_GetProcessMemoryInfo)(HANDLE Process,
PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb);
+typedef BOOL (WINAPI *Func_QueryProcessCycleTime)(HANDLE Process, PULONG64 CycleTime);
EXTERN_C_END
#endif
@@ -415,6 +410,8 @@ static void PrintStat()
PROCESS_MEMORY_COUNTERS m;
memset(&m, 0, sizeof(m));
BOOL memDefined = FALSE;
+ BOOL cycleDefined = FALSE;
+ ULONG64 cycleTime = 0;
{
/* NT 4.0: GetProcessMemoryInfo() in Psapi.dll
Win7: new function K32GetProcessMemoryInfo() in kernel32.dll
@@ -425,8 +422,9 @@ static void PrintStat()
// memDefined = GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m));
*/
+ HMODULE kern = ::GetModuleHandleW(L"kernel32.dll");
Func_GetProcessMemoryInfo my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)
- ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "K32GetProcessMemoryInfo");
+ ::GetProcAddress(kern, "K32GetProcessMemoryInfo");
if (!my_GetProcessMemoryInfo)
{
HMODULE lib = LoadLibraryW(L"Psapi.dll");
@@ -436,6 +434,11 @@ static void PrintStat()
if (my_GetProcessMemoryInfo)
memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m));
// FreeLibrary(lib);
+
+ Func_QueryProcessCycleTime my_QueryProcessCycleTime = (Func_QueryProcessCycleTime)
+ ::GetProcAddress(kern, "QueryProcessCycleTime");
+ if (my_QueryProcessCycleTime)
+ cycleDefined = my_QueryProcessCycleTime(GetCurrentProcess(), &cycleTime);
}
#endif
@@ -448,6 +451,16 @@ static void PrintStat()
UInt64 totalTime = curTime - creationTime;
PrintTime("Kernel ", kernelTime, totalTime);
+
+ #ifndef UNDER_CE
+ if (cycleDefined)
+ {
+ *g_StdStream << " ";
+ PrintNum(cycleTime / 1000000, 22);
+ *g_StdStream << " MCycles";
+ }
+ #endif
+
PrintTime("User ", userTime, totalTime);
PrintTime("Process", kernelTime + userTime, totalTime);
@@ -470,6 +483,7 @@ static void PrintHexId(CStdOutStream &so, UInt64 id)
PrintStringRight(so, s, 8);
}
+
int Main2(
#ifndef _WIN32
int numArgs, char *args[]
@@ -488,20 +502,25 @@ int Main2(
GetArguments(numArgs, args, commandStrings);
#endif
- if (commandStrings.Size() == 1)
+ #ifndef UNDER_CE
+ if (commandStrings.Size() > 0)
+ commandStrings.Delete(0);
+ #endif
+
+ if (commandStrings.Size() == 0)
{
ShowCopyrightAndHelp(g_StdStream, true);
return 0;
}
- commandStrings.Delete(0);
-
CArcCmdLineOptions options;
CArcCmdLineParser parser;
parser.Parse1(commandStrings, options);
+ g_StdOut.IsTerminalMode = options.IsStdOutTerminal;
+ g_StdErr.IsTerminalMode = options.IsStdErrTerminal;
if (options.Number_for_Out != k_OutStream_stdout)
g_StdStream = (options.Number_for_Out == k_OutStream_stderr ? &g_StdErr : NULL);
@@ -519,20 +538,6 @@ int Main2(
return 0;
}
- #if defined(_WIN32) && !defined(UNDER_CE)
- NSecurity::EnablePrivilege_SymLink();
- #endif
-
- #ifdef _7ZIP_LARGE_PAGES
- if (options.LargePages)
- {
- SetLargePageSize();
- #if defined(_WIN32) && !defined(UNDER_CE)
- NSecurity::EnablePrivilege_LockMemory();
- #endif
- }
- #endif
-
if (options.EnableHeaders)
ShowCopyrightAndHelp(g_StdStream, false);
@@ -579,7 +584,7 @@ int Main2(
#ifdef EXTERNAL_CODECS
if (!codecs->MainDll_ErrorPath.IsEmpty())
{
- UString s = L"Can't load module ";
+ UString s ("Can't load module: ");
s += fs2us(codecs->MainDll_ErrorPath);
throw s;
}
@@ -639,7 +644,7 @@ int Main2(
so << endl << "Formats:" << endl;
- const char *kArcFlags = "KSNFMGOPBELH";
+ const char * const kArcFlags = "KSNFMGOPBELH";
const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags);
for (i = 0; i < codecs->Formats.Size(); i++)
@@ -673,9 +678,9 @@ int Main2(
s += ext.Ext;
if (!ext.AddExt.IsEmpty())
{
- s += L" (";
+ s += " (";
s += ext.AddExt;
- s += L')';
+ s += ')';
}
}
diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp
index 311c575..fdac643 100644
--- a/CPP/7zip/UI/Console/MainAr.cpp
+++ b/CPP/7zip/UI/Console/MainAr.cpp
@@ -24,12 +24,12 @@ extern int Main2(
#endif
);
-static const char *kException_CmdLine_Error_Message = "Command Line Error:";
-static const char *kExceptionErrorMessage = "ERROR:";
-static const char *kUserBreakMessage = "Break signaled";
-static const char *kMemoryExceptionMessage = "ERROR: Can't allocate required memory!";
-static const char *kUnknownExceptionMessage = "Unknown Error";
-static const char *kInternalExceptionMessage = "\n\nInternal Error #";
+static const char * const kException_CmdLine_Error_Message = "Command Line Error:";
+static const char * const kExceptionErrorMessage = "ERROR:";
+static const char * const kUserBreakMessage = "Break signaled";
+static const char * const kMemoryExceptionMessage = "ERROR: Can't allocate required memory!";
+static const char * const kUnknownExceptionMessage = "Unknown Error";
+static const char * const kInternalExceptionMessage = "\n\nInternal Error #";
static void FlushStreams()
{
@@ -79,7 +79,7 @@ int MY_CDECL main
PrintError(kUserBreakMessage);
return (NExitCode::kUserBreak);
}
- catch(const CArcCmdLineException &e)
+ catch(const CMessagePathException &e)
{
PrintError(kException_CmdLine_Error_Message);
if (g_ErrStream)
diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
index f1a1688..6e58c1f 100644
--- a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
@@ -32,13 +32,17 @@ HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *files, const UInt64 *b
if (bytes)
{
- _totalBytesDefined = true;
- // _totalBytes = *bytes;
+ // _totalBytesDefined = true;
+ _totalBytes = *bytes;
if (!files)
_percent.Total = *bytes;
}
else
- _totalBytesDefined = false;
+ {
+ // _totalBytesDefined = false;
+ if (!files)
+ _percent.Total = _totalBytes;
+ }
}
return CheckBreak2();
@@ -83,7 +87,7 @@ HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password)
if (!PasswordIsDefined)
{
ClosePercents();
- Password = GetPassword(_so);
+ RINOK(GetPassword_HRESULT(_so, Password));
PasswordIsDefined = true;
}
return StringToBstr(Password, password);
diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h
index fd07b98..b9270f8 100644
--- a/CPP/7zip/UI/Console/OpenCallbackConsole.h
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.h
@@ -18,9 +18,9 @@ protected:
CStdOutStream *_se;
bool _totalFilesDefined;
- bool _totalBytesDefined;
+ // bool _totalBytesDefined;
// UInt64 _totalFiles;
- // UInt64 _totalBytes;
+ UInt64 _totalBytes;
bool NeedPercents() const { return _percent._so != NULL; }
@@ -36,7 +36,8 @@ public:
COpenCallbackConsole():
_totalFilesDefined(false),
- _totalBytesDefined(false),
+ // _totalBytesDefined(false),
+ _totalBytes(0),
MultiArcMode(false)
#ifndef _NO_CRYPTO
diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp
index f94d827..20249ed 100644
--- a/CPP/7zip/UI/Console/PercentPrinter.cpp
+++ b/CPP/7zip/UI/Console/PercentPrinter.cpp
@@ -141,8 +141,9 @@ void CPercentPrinter::Print()
{
_s += ' ';
- StdOut_Convert_UString_to_AString(FileName, _temp);
- _temp.Replace('\n', ' ');
+ _tempU = FileName;
+ _so->Normalize_UString(_tempU);
+ StdOut_Convert_UString_to_AString(_tempU, _temp);
if (_s.Len() + _temp.Len() > MaxLen)
{
unsigned len = FileName.Len();
@@ -153,8 +154,9 @@ void CPercentPrinter::Print()
delta = 1;
len -= delta;
_tempU = FileName;
- _tempU.Delete(len / 2, FileName.Len() - len);
+ _tempU.Delete(len / 2, _tempU.Len() - len);
_tempU.Insert(len / 2, L" . ");
+ _so->Normalize_UString(_tempU);
StdOut_Convert_UString_to_AString(_tempU, _temp);
if (_s.Len() + _temp.Len() <= MaxLen)
break;
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
index d43a490..46ffaba 100644
--- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
@@ -23,15 +23,15 @@ static NSynchronization::CCriticalSection g_CriticalSection;
#define MT_LOCK
#endif
-static const wchar_t *kEmptyFileAlias = L"[Content]";
+static const wchar_t * const kEmptyFileAlias = L"[Content]";
-static const char *kOpenArchiveMessage = "Open archive: ";
-static const char *kCreatingArchiveMessage = "Creating archive: ";
-static const char *kUpdatingArchiveMessage = "Updating archive: ";
-static const char *kScanningMessage = "Scanning the drive:";
+static const char * const kOpenArchiveMessage = "Open archive: ";
+static const char * const kCreatingArchiveMessage = "Creating archive: ";
+static const char * const kUpdatingArchiveMessage = "Updating archive: ";
+static const char * const kScanningMessage = "Scanning the drive:";
-static const char *kError = "ERROR: ";
-static const char *kWarning = "WARNING: ";
+static const char * const kError = "ERROR: ";
+static const char * const kWarning = "WARNING: ";
static HRESULT CheckBreak2()
{
@@ -143,7 +143,9 @@ HRESULT CUpdateCallbackConsole::OpenResult(
_so->Flush();
if (_se)
{
- *_se << kError << name << endl;
+ *_se << kError;
+ _se->NormalizePrint_wstr(name);
+ *_se << endl;
HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
RINOK(res);
_se->Flush();
@@ -185,7 +187,9 @@ void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, b
*_se << endl << (isWarning ? kWarning : kError)
<< NError::MyFormatMessage(systemError)
- << endl << fs2us(path) << endl << endl;
+ << endl;
+ _se->NormalizePrint_UString(fs2us(path));
+ *_se << endl << endl;
_se->Flush();
}
}
@@ -241,6 +245,7 @@ static void PrintPropPair(AString &s, const char *name, UInt64 val)
void PrintSize_bytes_Smart(AString &s, UInt64 val);
void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
+void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st);
HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)
{
@@ -259,7 +264,7 @@ HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)
return S_OK;
}
-static const char *k_StdOut_ArcName = "StdOut";
+static const char * const k_StdOut_ArcName = "StdOut";
HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name)
{
@@ -280,8 +285,8 @@ HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
if (_so)
{
*_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage);
- if (name != 0)
- *_so << name;
+ if (name)
+ _so->NormalizePrint_wstr(name);
else
*_so << k_StdOut_ArcName;
*_so << endl << endl;
@@ -316,7 +321,7 @@ HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size)
{
*_so << "Write SFX: ";
*_so << name;
- AString s = " : ";
+ AString s (" : ");
PrintSize_bytes_Smart(s, size);
*_so << s << endl;
}
@@ -342,6 +347,7 @@ HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool
_tempA.Add_Space();
*_so << _tempA;
_tempU = fs2us(path);
+ _so->Normalize_UString(_tempU);
_so->PrintUString(_tempU, _tempA);
*_so << endl;
if (NeedFlush)
@@ -398,14 +404,31 @@ HRESULT CUpdateCallbackConsole::Finalize()
}
*/
-HRESULT CUpdateCallbackConsole::SetNumItems(UInt64 numItems)
+
+void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name)
+{
+ AString s;
+ Print_DirItemsStat2(s, stat);
+ *_so << name << ": " << s << endl;
+}
+
+HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat)
{
if (_so)
{
ClosePercents_for_so();
- AString s;
- PrintPropPair(s, "Items to compress", numItems);
- *_so << s << endl << endl;
+ if (!stat.DeleteData.IsEmpty())
+ {
+ *_so << endl;
+ PrintToDoStat(_so, stat.DeleteData, "Delete data from archive");
+ }
+ if (!stat.OldData.IsEmpty())
+ PrintToDoStat(_so, stat.OldData, "Keep old data in archive");
+ // if (!stat.NewData.IsEmpty())
+ {
+ PrintToDoStat(_so, stat.NewData, "Add new data to archive");
+ }
+ *_so << endl;
}
return S_OK;
}
@@ -457,7 +480,10 @@ HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *com
_tempU.Empty();
if (name)
+ {
_tempU = name;
+ _so->Normalize_UString(_tempU);
+ }
_so->PrintUString(_tempU, _tempA);
*_so << endl;
if (NeedFlush)
@@ -550,7 +576,9 @@ HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypt
AString s;
SetExtractErrorMessage(opRes, isEncrypted, s);
- *_se << s << " : " << endl << name << endl << endl;
+ *_se << s << " : " << endl;
+ _se->NormalizePrint_wstr(name);
+ *_se << endl << endl;
_se->Flush();
}
return S_OK;
@@ -622,7 +650,7 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined,
{
if (AskPassword)
{
- Password = GetPassword(_so);
+ RINOK(GetPassword_HRESULT(_so, Password));
PasswordIsDefined = true;
}
}
@@ -649,7 +677,7 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
if (!PasswordIsDefined)
{
{
- Password = GetPassword(_so);
+ RINOK(GetPassword_HRESULT(_so, Password))
PasswordIsDefined = true;
}
}
diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp
index d45e840..7bdafda 100644
--- a/CPP/7zip/UI/Console/UserInputUtils.cpp
+++ b/CPP/7zip/UI/Console/UserInputUtils.cpp
@@ -14,8 +14,8 @@ static const char kNoAll = 's';
static const char kAutoRenameAll = 'u';
static const char kQuit = 'q';
-static const char *kFirstQuestionMessage = "? ";
-static const char *kHelpQuestionMessage =
+static const char * const kFirstQuestionMessage = "? ";
+static const char * const kHelpQuestionMessage =
"(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? ";
// return true if pressed Quite;
@@ -31,9 +31,16 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
*outStream << kHelpQuestionMessage;
outStream->Flush();
}
- AString scannedString = g_StdIn.ScanStringUntilNewLine();
+ AString scannedString;
+ if (!g_StdIn.ScanAStringUntilNewLine(scannedString))
+ return NUserAnswerMode::kError;
+ if (g_StdIn.Error())
+ return NUserAnswerMode::kError;
scannedString.Trim();
- if (!scannedString.IsEmpty())
+ if (scannedString.IsEmpty() && g_StdIn.Eof())
+ return NUserAnswerMode::kEof;
+
+ if (scannedString.Len() == 1)
switch (::MyCharLower_Ascii(scannedString[0]))
{
case kYes: return NUserAnswerMode::kYes;
@@ -52,7 +59,7 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
#endif
#endif
-UString GetPassword(CStdOutStream *outStream)
+static bool GetPassword(CStdOutStream *outStream, UString &psw)
{
if (outStream)
{
@@ -72,19 +79,32 @@ UString GetPassword(CStdOutStream *outStream)
if (console != INVALID_HANDLE_VALUE && console != 0)
if (GetConsoleMode(console, &mode))
wasChanged = (SetConsoleMode(console, mode & ~ENABLE_ECHO_INPUT) != 0);
- UString res = g_StdIn.ScanUStringUntilNewLine();
+ bool res = g_StdIn.ScanUStringUntilNewLine(psw);
if (wasChanged)
SetConsoleMode(console, mode);
+
+ #else
+
+ bool res = g_StdIn.ScanUStringUntilNewLine(psw);
+
+ #endif
+
if (outStream)
{
*outStream << endl;
outStream->Flush();
}
+
return res;
-
- #else
-
- return g_StdIn.ScanUStringUntilNewLine();
-
- #endif
+}
+
+HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw)
+{
+ if (!GetPassword(outStream, psw))
+ return E_INVALIDARG;
+ if (g_StdIn.Error())
+ return E_FAIL;
+ if (g_StdIn.Eof() && psw.IsEmpty())
+ return E_ABORT;
+ return S_OK;
}
diff --git a/CPP/7zip/UI/Console/UserInputUtils.h b/CPP/7zip/UI/Console/UserInputUtils.h
index df2773d..ebe09c1 100644
--- a/CPP/7zip/UI/Console/UserInputUtils.h
+++ b/CPP/7zip/UI/Console/UserInputUtils.h
@@ -14,11 +14,14 @@ enum EEnum
kYesAll,
kNoAll,
kAutoRenameAll,
- kQuit
+ kQuit,
+ kEof,
+ kError
};
}
NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream);
-UString GetPassword(CStdOutStream *outStream);
+// bool GetPassword(CStdOutStream *outStream, UString &psw);
+HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw);
#endif
diff --git a/CPP/7zip/UI/Console/resource.rc b/CPP/7zip/UI/Console/resource.rc
index 20dfee1..8d721f5 100644
--- a/CPP/7zip/UI/Console/resource.rc
+++ b/CPP/7zip/UI/Console/resource.rc
@@ -1,3 +1,7 @@
#include "../../MyVersionInfo.rc"
-MY_VERSION_INFO_APP("7-Zip Console", "7z")
+MY_VERSION_INFO_APP("7-Zip Console" , "7z")
+
+#ifndef UNDER_CE
+1 24 MOVEABLE PURE "Console.manifest"
+#endif
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
index 703754f..d5c981c 100644
--- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
@@ -209,7 +209,7 @@ bool CBrowseDialog::OnInit()
if (!FilterDescription.IsEmpty())
s = FilterDescription;
else if (ShowAllFiles)
- s = L"*.*";
+ s = "*.*";
else
{
FOR_VECTOR (i, Filters)
@@ -468,11 +468,11 @@ bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, US
if (_topDirPrefix == path)
return false;
UString s = path;
- if (s.Back() == WCHAR_PATH_SEPARATOR)
+ if (IS_PATH_SEPAR(s.Back()))
s.DeleteBack();
if (s.IsEmpty())
return false;
- if (s.Back() == WCHAR_PATH_SEPARATOR)
+ if (IS_PATH_SEPAR(s.Back()))
return false;
int pos = s.ReverseFind_PathSepar();
parentPrefix.SetFrom(s, pos + 1);
@@ -531,7 +531,7 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected
#ifndef UNDER_CE
bool isDrive = false;
- if (pathPrefix.IsEmpty() || pathPrefix == kSuperPathPrefix)
+ if (pathPrefix.IsEmpty() || pathPrefix.IsEqualTo(kSuperPathPrefix))
{
isDrive = true;
FStringVector drives;
@@ -551,7 +551,8 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected
else
#endif
{
- CEnumerator enumerator(us2fs(pathPrefix + L'*'));
+ CEnumerator enumerator;
+ enumerator.SetDirPrefix(us2fs(pathPrefix));
for (;;)
{
bool found;
@@ -596,7 +597,7 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected
if (_showDots && _topDirPrefix != DirPrefix)
{
item.iItem = index;
- const UString itemName = L"..";
+ const UString itemName ("..");
if (selectedName.IsEmpty())
cursorIndex = index;
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
@@ -642,16 +643,14 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected
_list.InsertItem(&item);
wchar_t s[32];
{
- FILETIME ft;
s[0] = 0;
- if (FileTimeToLocalFileTime(&fi.MTime, &ft))
- ConvertFileTimeToString(ft, s,
+ ConvertUtcFileTimeToString(fi.MTime, s,
#ifndef UNDER_CE
- true
+ kTimestampPrintLevel_MIN
#else
- false
+ kTimestampPrintLevel_DAY
#endif
- , false);
+ );
_list.SetSubItem(index, subItem++, s);
}
{
@@ -780,8 +779,10 @@ void CBrowseDialog::OnItemEnter()
*/
return;
}
- UString s = DirPrefix + fs2us(file.Name) + WCHAR_PATH_SEPARATOR;
- HRESULT res = Reload(s, L"");
+ UString s = DirPrefix;
+ s += fs2us(file.Name);
+ s.Add_PathSepar();
+ HRESULT res = Reload(s, UString());
if (res != S_OK)
MessageBox_HResError(*this, res, s);
SetPathEditText();
@@ -853,17 +854,17 @@ bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path,
#else
// maybe we must use GetLastError in WinCE.
DWORD errorCode = CommDlgExtendedError();
- const wchar_t *errorMessage = NULL;
+ const char *errorMessage = NULL;
switch (errorCode)
{
case 0: return false; // cancel or close obn dialog
- case FNERR_INVALIDFILENAME: errorMessage = L"Invalid File Name"; break;
- default: errorMessage = L"Open Dialog Error";
+ case FNERR_INVALIDFILENAME: errorMessage = "Invalid File Name"; break;
+ default: errorMessage = "Open Dialog Error";
}
if (!errorMessage)
return false;
{
- UString s = errorMessage;
+ UString s (errorMessage);
s.Add_LF();
s += path;
MessageBox_Error_Global(owner, s);
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
index 1c3141c..6433e91 100644
--- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
@@ -335,20 +335,18 @@ void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileNam
s += msg;
else
{
- char temp[16];
- ConvertUInt32ToString(opRes, temp);
- s.AddAscii("Error #");
- s.AddAscii(temp);
+ s += "Error #";
+ s.Add_UInt32(opRes);
}
if (encrypted && opRes != NArchive::NExtract::NOperationResult::kWrongPassword)
{
- // s.AddAscii(" : ");
+ // s += " : ";
// AddLangString(s, IDS_EXTRACT_MSG_ENCRYPTED);
- s.AddAscii(" : ");
+ s += " : ";
AddLangString(s, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);
}
- s.AddAscii(" : ");
+ s += " : ";
s += fileName;
}
}
@@ -466,7 +464,7 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags)
continue;
if (f == kpv_ErrorFlags_EncryptedHeadersError)
{
- m.AddAscii(" : ");
+ m += " : ";
AddLangString(m, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);
}
if (!s.IsEmpty())
@@ -483,7 +481,7 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags)
ConvertUInt32ToHex(errorFlags, sz + 2);
if (!s.IsEmpty())
s.Add_LF();
- s.AddAscii(sz);
+ s += sz;
}
return s;
@@ -503,7 +501,7 @@ static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er)
if (warningFlags != 0)
{
s += GetNameOfProperty(kpidWarningFlags, L"Warnings");
- s.AddAscii(":");
+ s += ":";
s.Add_LF();
AddNewLineString(s, GetOpenArcErrorMessage(warningFlags));
}
@@ -511,7 +509,7 @@ static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er)
if (!er.WarningMessage.IsEmpty())
{
s += GetNameOfProperty(kpidWarning, L"Warning");
- s.AddAscii(": ");
+ s += ": ";
s += er.WarningMessage;
s.Add_LF();
}
@@ -519,9 +517,9 @@ static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er)
static UString GetBracedType(const wchar_t *type)
{
- UString s = L'[';
+ UString s ('[');
s += type;
- s += L']';
+ s += ']';
return s;
}
@@ -1009,7 +1007,7 @@ HRESULT CVirtFileSystem::FlushToDisk(bool closeLast)
{
_outFileStream.Release();
return E_FAIL;
- // MessageBoxMyError(UString(L"Can't create file ") + fs2us(tempFilePath));
+ // MessageBoxMyError(UString("Can't create file ") + fs2us(tempFilePath));
}
_fileIsOpen = true;
RINOK(WriteStream(_outFileStream, file.Data, (size_t)file.Size));
@@ -1027,7 +1025,7 @@ HRESULT CVirtFileSystem::FlushToDisk(bool closeLast)
_numFlushed++;
_fileIsOpen = false;
if (file.AttribDefined)
- NDir::SetFileAttrib(path, file.Attrib);
+ NDir::SetFileAttrib_PosixHighDetect(path, file.Attrib);
}
return S_OK;
}
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
index c5191d0..3f0180d 100644
--- a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
@@ -40,6 +40,12 @@ void COverwriteDialog::ReduceString(UString &s)
s.Delete(size / 2, s.Len() - size);
s.Insert(size / 2, L" ... ");
}
+ if (!s.IsEmpty() && s.Back() == ' ')
+ {
+ // s += (wchar_t)(0x2423);
+ s.InsertAtFront(L'\"');
+ s += L'\"';
+ }
}
void COverwriteDialog::SetFileInfoControl(int textID, int iconID,
@@ -66,13 +72,10 @@ void COverwriteDialog::SetFileInfoControl(int textID, int iconID,
if (fileInfo.TimeIsDefined)
{
- FILETIME localFileTime;
- if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))
- throw 4190402;
AddLangString(s, IDS_PROP_MTIME);
- s += L": ";
- wchar_t t[32];
- ConvertFileTimeToString(localFileTime, t);
+ s += ": ";
+ char t[32];
+ ConvertUtcFileTimeToString(fileInfo.Time, t);
s += t;
}
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
index 820e409..27d42b2 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
@@ -120,7 +120,7 @@ bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)
wchar_t s[64];
ConvertUInt64ToString(percentValue, s);
UString title = s;
- title += L"% ";
+ title += "% ";
SetText(title + _title);
#ifndef _SFX
AddToTitle(title + MainAddTitle);
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
index dd3b493..bdb2be3 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
@@ -217,7 +217,7 @@ void CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t
UString s;
if (name && *name != 0)
s += name;
- if (message && *message != 0 )
+ if (message && *message != 0)
{
if (!s.IsEmpty())
s.Add_LF();
@@ -232,11 +232,14 @@ void CProgressSync::AddError_Code_Name(DWORD systemError, const wchar_t *name)
{
UString s = NError::MyFormatMessage(systemError);
if (systemError == 0)
- s = L"Error";
+ s = "Error";
AddError_Message_Name(s, name);
}
-CProgressDialog::CProgressDialog(): _timer(0), CompressingMode(true), MainWindow(0)
+CProgressDialog::CProgressDialog():
+ _timer(0),
+ CompressingMode(true),
+ MainWindow(0)
{
_isDir = false;
@@ -828,8 +831,8 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
ConvertUInt64ToString(completedFiles, s);
if (IS_DEFINED_VAL(totalFiles))
{
- wcscat(s, L" / ");
- ConvertUInt64ToString(totalFiles, s + wcslen(s));
+ MyStringCat(s, L" / ");
+ ConvertUInt64ToString(totalFiles, s + MyStringLen(s));
}
if (_filesStr_Prev != s)
{
@@ -862,7 +865,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
{
_ratio_Prev = ratio;
ConvertUInt64ToString(ratio, s);
- wcscat(s, L"%");
+ MyStringCat(s, L"%");
SetItemText(IDT_PROGRESS_RATIO_VAL, s);
}
}
@@ -974,7 +977,9 @@ bool CProgressDialog::OnExternalCloseMessage()
::SendMessage(GetItem(IDCANCEL), BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0));
HideItem(IDB_PROGRESS_BACKGROUND);
HideItem(IDB_PAUSE);
-
+
+ ProcessWasFinished_GuiVirt();
+
bool thereAreMessages;
CProgressFinalMessage fm;
{
@@ -982,20 +987,22 @@ bool CProgressDialog::OnExternalCloseMessage()
thereAreMessages = !Sync.Messages.IsEmpty();
fm = Sync.FinalMessage;
}
+
if (!fm.ErrorMessage.Message.IsEmpty())
{
MessagesDisplayed = true;
if (fm.ErrorMessage.Title.IsEmpty())
- fm.ErrorMessage.Title = L"7-Zip";
+ fm.ErrorMessage.Title = "7-Zip";
MessageBoxW(*this, fm.ErrorMessage.Message, fm.ErrorMessage.Title, MB_ICONERROR);
}
else if (!thereAreMessages)
{
MessagesDisplayed = true;
+
if (!fm.OkMessage.Message.IsEmpty())
{
if (fm.OkMessage.Title.IsEmpty())
- fm.OkMessage.Title = L"7-Zip";
+ fm.OkMessage.Title = "7-Zip";
MessageBoxW(*this, fm.OkMessage.Message, fm.OkMessage.Title, MB_OK);
}
}
@@ -1050,8 +1057,8 @@ void CProgressDialog::SetTitleText()
{
char temp[32];
ConvertUInt64ToString(_prevPercentValue, temp);
- s.AddAscii(temp);
- s += L'%';
+ s += temp;
+ s += '%';
}
if (!_foreground)
{
@@ -1245,11 +1252,24 @@ void CProgressDialog::ProcessWasFinished()
}
+static THREAD_FUNC_DECL MyThreadFunction(void *param)
+{
+ CProgressThreadVirt *p = (CProgressThreadVirt *)param;
+ try
+ {
+ p->Process();
+ p->ThreadFinishedOK = true;
+ }
+ catch (...) { p->Result = E_FAIL; }
+ return 0;
+}
+
+
HRESULT CProgressThreadVirt::Create(const UString &title, HWND parentWindow)
{
NWindows::CThread thread;
RINOK(thread.Create(MyThreadFunction, this));
- ProgressDialog.Create(title, thread, parentWindow);
+ CProgressDialog::Create(title, thread, parentWindow);
return S_OK;
}
@@ -1265,7 +1285,7 @@ static void AddMessageToString(UString &dest, const UString &src)
void CProgressThreadVirt::Process()
{
- CProgressCloser closer(ProgressDialog);
+ CProgressCloser closer(*this);
UString m;
try { Result = ProcessVirt(); }
catch(const wchar_t *s) { m = s; }
@@ -1273,12 +1293,10 @@ void CProgressThreadVirt::Process()
catch(const char *s) { m = GetUnicodeString(s); }
catch(int v)
{
- wchar_t s[16];
- ConvertUInt32ToString(v, s);
- m = L"Error #";
- m += s;
+ m = "Error #";
+ m.Add_UInt32(v);
}
- catch(...) { m = L"Error"; }
+ catch(...) { m = "Error"; }
if (Result != E_ABORT)
{
if (m.IsEmpty() && Result != S_OK)
@@ -1295,7 +1313,7 @@ void CProgressThreadVirt::Process()
}
}
- CProgressSync &sync = ProgressDialog.Sync;
+ CProgressSync &sync = Sync;
NSynchronization::CCriticalSectionLock lock(sync._cs);
if (m.IsEmpty())
{
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h
index 0e2f2ce..5e916e6 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.h
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h
@@ -261,7 +261,18 @@ public:
INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0);
+
+ /* how it works:
+ 1) the working thread calls ProcessWasFinished()
+ that sends kCloseMessage message to CProgressDialog (GUI) thread
+ 2) CProgressDialog (GUI) thread receives kCloseMessage message and
+ calls ProcessWasFinished_GuiVirt();
+ So we can implement ProcessWasFinished_GuiVirt() and show special
+ results window in GUI thread with CProgressDialog as parent window
+ */
+
void ProcessWasFinished();
+ virtual void ProcessWasFinished_GuiVirt() {}
};
@@ -273,7 +284,8 @@ public:
~CProgressCloser() { _p->ProcessWasFinished(); }
};
-class CProgressThreadVirt
+
+class CProgressThreadVirt: public CProgressDialog
{
protected:
FStringVector ErrorPaths;
@@ -281,33 +293,59 @@ protected:
// error if any of HRESULT, ErrorMessage, ErrorPath
virtual HRESULT ProcessVirt() = 0;
- void Process();
public:
HRESULT Result;
bool ThreadFinishedOK; // if there is no fatal exception
- CProgressDialog ProgressDialog;
-
- static THREAD_FUNC_DECL MyThreadFunction(void *param)
- {
- CProgressThreadVirt *p = (CProgressThreadVirt *)param;
- try
- {
- p->Process();
- p->ThreadFinishedOK = true;
- }
- catch (...) { p->Result = E_FAIL; }
- return 0;
- }
+ void Process();
void AddErrorPath(const FString &path) { ErrorPaths.Add(path); }
HRESULT Create(const UString &title, HWND parentWindow = 0);
CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {}
CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; }
-
};
UString HResultToMessage(HRESULT errorCode);
+/*
+how it works:
+
+client code inherits CProgressThreadVirt and calls
+CProgressThreadVirt::Create()
+{
+ it creates new thread that calls CProgressThreadVirt::Process();
+ it creates modal progress dialog window with ProgressDialog.Create()
+}
+
+CProgressThreadVirt::Process()
+{
+ {
+ ProcessVirt(); // virtual function that must implement real work
+ }
+ if (exceptions) or FinalMessage.ErrorMessage.Message
+ {
+ set message to ProgressDialog.Sync.FinalMessage.ErrorMessage.Message
+ }
+ else if (FinalMessage.OkMessage.Message)
+ {
+ set message to ProgressDialog.Sync.FinalMessage.OkMessage
+ }
+
+ PostMsg(kCloseMessage);
+}
+
+
+CProgressDialog::OnExternalCloseMessage()
+{
+ if (ProgressDialog.Sync.FinalMessage)
+ {
+ WorkWasFinishedVirt();
+ Show (ProgressDialog.Sync.FinalMessage)
+ MessagesDisplayed = true;
+ }
+}
+
+*/
+
#endif
diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h
index 0b282b0..4666269 100644
--- a/CPP/7zip/UI/FileManager/resource.h
+++ b/CPP/7zip/UI/FileManager/resource.h
@@ -85,6 +85,8 @@
#define IDM_VIEW_TOOLBARS_LARGE_BUTTONS 752
#define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 753
+#define IDM_VIEW_TIME 761
+
#define IDS_BOOKMARK 801
#define IDM_OPTIONS 900
diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp
index 283713d..71c2a3b 100644
--- a/CPP/7zip/UI/GUI/ExtractDialog.cpp
+++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp
@@ -143,7 +143,7 @@ bool CExtractDialog::OnInit()
GetText(s);
if (!ArcPath.IsEmpty())
{
- s.AddAscii(" : ");
+ s += " : ";
s += ArcPath;
}
SetText(s);
@@ -409,10 +409,10 @@ void CExtractDialog::OnOK()
}
#ifndef NO_REGISTRY
-static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/extract.htm";
+#define kHelpTopic "fm/plugins/7-zip/extract.htm"
void CExtractDialog::OnHelp()
{
- ShowHelpWindow(NULL, kHelpTopic);
+ ShowHelpWindow(kHelpTopic);
CModalDialog::OnHelp();
}
#endif
diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp
index f3b08c2..37aa45b 100644
--- a/CPP/7zip/UI/GUI/ExtractGUI.cpp
+++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp
@@ -34,7 +34,7 @@ using namespace NWindows;
using namespace NFile;
using namespace NDir;
-static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path";
+static const wchar_t * const kIncorrectOutDir = L"Incorrect output directory path";
#ifndef _SFX
@@ -42,29 +42,19 @@ static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColo
{
AddLangString(s, resourceID);
if (addColon)
- s += L':';
+ s += ':';
s.Add_Space();
char sz[32];
ConvertUInt64ToString(value, sz);
- s.AddAscii(sz);
+ s += sz;
s.Add_LF();
}
static void AddSizePair(UString &s, UINT resourceID, UInt64 value)
{
- wchar_t sz[32];
AddLangString(s, resourceID);
- s += L": ";
- ConvertUInt64ToString(value, sz);
- s += MyFormatNew(IDS_FILE_SIZE, sz);
- // s += sz;
- if (value >= (1 << 20))
- {
- ConvertUInt64ToString(value >> 20, sz);
- s += L" (";
- s += sz;
- s += L" MB)";
- }
+ s += ": ";
+ AddSizeValue(s, value);
s.Add_LF();
}
@@ -83,16 +73,31 @@ public:
UStringVector *ArchivePathsFull;
const NWildcard::CCensorNode *WildcardCensor;
const CExtractOptions *Options;
+
#ifndef _SFX
CHashBundle *HashBundle;
+ virtual void ProcessWasFinished_GuiVirt();
#endif
+
CMyComPtr<IExtractCallbackUI> ExtractCallback;
UString Title;
+
+ CPropNameValPairs Pairs;
};
+
+#ifndef _SFX
+void CThreadExtracting::ProcessWasFinished_GuiVirt()
+{
+ if (HashBundle && !Pairs.IsEmpty())
+ ShowHashResults(Pairs, *this);
+}
+#endif
+
HRESULT CThreadExtracting::ProcessVirt()
{
CDecompressStat Stat;
+
#ifndef _SFX
if (HashBundle)
HashBundle->Init();
@@ -106,16 +111,23 @@ HRESULT CThreadExtracting::ProcessVirt()
HashBundle,
#endif
FinalMessage.ErrorMessage.Message, Stat);
+
#ifndef _SFX
- if (res == S_OK && Options->TestMode && ExtractCallbackSpec->IsOK())
+ if (res == S_OK && ExtractCallbackSpec->IsOK())
{
- UString s;
+ if (HashBundle)
+ {
+ AddValuePair(Pairs, IDS_ARCHIVES_COLON, Stat.NumArchives);
+ AddSizeValuePair(Pairs, IDS_PROP_PACKED_SIZE, Stat.PackSize);
+ AddHashBundleRes(Pairs, *HashBundle, UString());
+ }
+ else if (Options->TestMode)
+ {
+ UString s;
- AddValuePair(s, IDS_ARCHIVES_COLON, Stat.NumArchives, false);
- AddSizePair(s, IDS_PROP_PACKED_SIZE, Stat.PackSize);
+ AddValuePair(s, IDS_ARCHIVES_COLON, Stat.NumArchives, false);
+ AddSizePair(s, IDS_PROP_PACKED_SIZE, Stat.PackSize);
- if (!HashBundle)
- {
if (Stat.NumFolders != 0)
AddValuePair(s, IDS_PROP_FOLDERS, Stat.NumFolders);
AddValuePair(s, IDS_PROP_FILES, Stat.NumFiles);
@@ -126,24 +138,19 @@ HRESULT CThreadExtracting::ProcessVirt()
AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams);
AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize);
}
- }
-
- if (HashBundle)
- {
s.Add_LF();
- AddHashBundleRes(s, *HashBundle, UString());
+ AddLangString(s, IDS_MESSAGE_NO_ERRORS);
+ FinalMessage.OkMessage.Title = Title;
+ FinalMessage.OkMessage.Message = s;
}
-
- s.Add_LF();
- AddLangString(s, IDS_MESSAGE_NO_ERRORS);
-
- FinalMessage.OkMessage.Title = Title;
- FinalMessage.OkMessage.Message = s;
}
#endif
+
return res;
}
+
+
HRESULT ExtractGUI(
CCodecs *codecs,
const CObjectVector<COpenType> &formatIndices,
@@ -249,11 +256,11 @@ HRESULT ExtractGUI(
extracter.Title = title;
extracter.ExtractCallbackSpec = extractCallback;
- extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog;
+ extracter.ExtractCallbackSpec->ProgressDialog = &extracter;
extracter.ExtractCallback = extractCallback;
extracter.ExtractCallbackSpec->Init();
- extracter.ProgressDialog.CompressingMode = false;
+ extracter.CompressingMode = false;
extracter.ArchivePaths = &archivePaths;
extracter.ArchivePathsFull = &archivePathsFull;
@@ -263,10 +270,9 @@ HRESULT ExtractGUI(
extracter.HashBundle = hb;
#endif
- extracter.ProgressDialog.IconID = IDI_ICON;
+ extracter.IconID = IDI_ICON;
RINOK(extracter.Create(title, hwndParent));
- messageWasDisplayed = extracter.ThreadFinishedOK &
- extracter.ProgressDialog.MessagesDisplayed;
+ messageWasDisplayed = extracter.ThreadFinishedOK && extracter.MessagesDisplayed;
return extracter.Result;
}
diff --git a/CPP/7zip/UI/GUI/HashGUI.h b/CPP/7zip/UI/GUI/HashGUI.h
index 4fb0666..d6caa53 100644
--- a/CPP/7zip/UI/GUI/HashGUI.h
+++ b/CPP/7zip/UI/GUI/HashGUI.h
@@ -4,6 +4,7 @@
#define __HASH_GUI_H
#include "../Common/HashCalc.h"
+#include "../Common/Property.h"
HRESULT HashCalcGUI(
DECL_EXTERNAL_CODECS_LOC_VARS
@@ -11,6 +12,16 @@ HRESULT HashCalcGUI(
const CHashOptions &options,
bool &messageWasDisplayed);
+typedef CObjectVector<CProperty> CPropNameValPairs;
+
+void AddValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value);
+void AddSizeValue(UString &s, UInt64 value);
+void AddSizeValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value);
+
+void AddHashBundleRes(CPropNameValPairs &s, const CHashBundle &hb, const UString &firstFileName);
void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFileName);
+void ShowHashResults(const CPropNameValPairs &propPairs, HWND hwnd);
+void ShowHashResults(const CHashBundle &hb, const UString &firstFileName, HWND hwnd);
+
#endif
diff --git a/CPP/Build.mak b/CPP/Build.mak
index 1935ff0..28d5eca 100644
--- a/CPP/Build.mak
+++ b/CPP/Build.mak
@@ -15,11 +15,11 @@ O=O
!ENDIF
!IF "$(CPU)" == "AMD64"
-MY_ML = ml64 -Dx64
+MY_ML = ml64 -Dx64 -WX
!ELSEIF "$(CPU)" == "ARM"
-MY_ML = armasm
+MY_ML = armasm -WX
!ELSE
-MY_ML = ml
+MY_ML = ml -WX
!ENDIF
@@ -32,7 +32,9 @@ LFLAGS = $(LFLAGS) /ENTRY:mainACRTStartup
!IFNDEF NEW_COMPILER
LFLAGS = $(LFLAGS) -OPT:NOWIN98
!ENDIF
+!IF "$(CPU)" != "ARM" && "$(CPU)" != "ARM64"
CFLAGS = $(CFLAGS) -Gr
+!ENDIF
LIBS = $(LIBS) user32.lib advapi32.lib shell32.lib
!ENDIF
@@ -53,15 +55,22 @@ CFLAGS = $(CFLAGS) -MD
!ENDIF
!IFDEF NEW_COMPILER
-CFLAGS = $(CFLAGS) -GS- -Zc:forScope
+CFLAGS = $(CFLAGS) -GS- -Zc:forScope -Zc:wchar_t
!IFNDEF UNDER_CE
CFLAGS = $(CFLAGS) -MP2
+!IFNDEF CPU
+# CFLAGS = $(CFLAGS) -arch:IA32
+!ENDIF
!ENDIF
!ELSE
CFLAGS = $(CFLAGS)
!ENDIF
+!IF "$(CPU)" == "AMD64"
+CFLAGS_O1 = $(CFLAGS) -O1
+!ELSE
CFLAGS_O1 = $(CFLAGS) -O1
+!ENDIF
CFLAGS_O2 = $(CFLAGS) -O2
LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF
@@ -72,15 +81,31 @@ LFLAGS = $(LFLAGS) /LARGEADDRESSAWARE
!IFDEF DEF_FILE
LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE)
+!ELSE
+!IF defined(MY_FIXED) && "$(CPU)" != "ARM" && "$(CPU)" != "ARM64"
+LFLAGS = $(LFLAGS) /FIXED
+!ELSE
+LFLAGS = $(LFLAGS) /FIXED:NO
!ENDIF
+# /BASE:0x400000
+!ENDIF
+
+
+# !IF "$(CPU)" == "AMD64"
+
+!IFDEF SUB_SYS_VER
+
+MY_SUB_SYS_VER=5.02
-MY_SUB_SYS_VER=6.0
!IFDEF MY_CONSOLE
-# LFLAGS = $(LFLAGS) /SUBSYSTEM:console,$(MY_SUB_SYS_VER)
+LFLAGS = $(LFLAGS) /SUBSYSTEM:console,$(MY_SUB_SYS_VER)
!ELSE
-# LFLAGS = $(LFLAGS) /SUBSYSTEM:windows,$(MY_SUB_SYS_VER)
+LFLAGS = $(LFLAGS) /SUBSYSTEM:windows,$(MY_SUB_SYS_VER)
+!ENDIF
+
!ENDIF
+
PROGPATH = $O\$(PROG)
COMPL_O1 = $(CC) $(CFLAGS_O1) $**
@@ -92,10 +117,11 @@ COMPLB = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $<
# COMPLB_O2 = $(CC) $(CFLAGS_O2) -Yu"StdAfx.h" -Fp$O/a.pch $<
COMPLB_O2 = $(CC) $(CFLAGS_O2) $<
-CCOMPL_PCH = $(CC) $(CFLAGS_O2) -Yc"Precomp.h" -Fp$O/a.pch $**
-CCOMPL_USE = $(CC) $(CFLAGS_O2) -Yu"Precomp.h" -Fp$O/a.pch $**
-CCOMPL = $(CC) $(CFLAGS_O2) $**
-CCOMPLB = $(CC) $(CFLAGS_O2) $<
+CFLAGS_C_ALL = $(CFLAGS_O2) $(CFLAGS_C_SPEC)
+CCOMPL_PCH = $(CC) $(CFLAGS_C_ALL) -Yc"Precomp.h" -Fp$O/a.pch $**
+CCOMPL_USE = $(CC) $(CFLAGS_C_ALL) -Yu"Precomp.h" -Fp$O/a.pch $**
+CCOMPL = $(CC) $(CFLAGS_C_ALL) $**
+CCOMPLB = $(CC) $(CFLAGS_C_ALL) $<
all: $(PROGPATH)
diff --git a/CPP/Common/ComTry.h b/CPP/Common/ComTry.h
index b2b3029..e6b514d 100644
--- a/CPP/Common/ComTry.h
+++ b/CPP/Common/ComTry.h
@@ -10,7 +10,11 @@
#define COM_TRY_BEGIN try {
#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; }
- // catch(const CNewException &) { return E_OUTOFMEMORY; }
+/*
+#define COM_TRY_END } \
+ catch(const CNewException &) { return E_OUTOFMEMORY; } \
+ catch(...) { return HRESULT_FROM_WIN32(ERROR_NOACCESS); } \
+*/
// catch(const CSystemException &e) { return e.ErrorCode; }
// catch(...) { return E_FAIL; }
diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp
index 42edd8d..94aabce 100644
--- a/CPP/Common/CommandLineParser.cpp
+++ b/CPP/Common/CommandLineParser.cpp
@@ -4,20 +4,6 @@
#include "CommandLineParser.h"
-static bool IsString1PrefixedByString2_NoCase(const wchar_t *u, const char *a)
-{
- for (;;)
- {
- char c = *a;
- if (c == 0)
- return true;
- if ((unsigned char)MyCharLower_Ascii(c) != MyCharLower_Ascii(*u))
- return false;
- a++;
- u++;
- }
-}
-
namespace NCommandLineParser {
bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
@@ -44,7 +30,7 @@ bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
void SplitCommandLine(const UString &s, UStringVector &parts)
{
- UString sTemp = s;
+ UString sTemp (s);
sTemp.Trim();
parts.Clear();
for (;;)
@@ -59,18 +45,17 @@ void SplitCommandLine(const UString &s, UStringVector &parts)
}
-static const char *kStopSwitchParsing = "--";
+static const char * const kStopSwitchParsing = "--";
static bool inline IsItSwitchChar(wchar_t c)
{
return (c == '-');
}
-CParser::CParser(unsigned numSwitches):
- _numSwitches(numSwitches),
- _switches(0)
+CParser::CParser():
+ _switches(NULL),
+ StopSwitchIndex(-1)
{
- _switches = new CSwitchResult[numSwitches];
}
CParser::~CParser()
@@ -81,7 +66,7 @@ CParser::~CParser()
// if (s) contains switch then function updates switch structures
// out: true, if (s) is a switch
-bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
+bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches)
{
if (s.IsEmpty() || !IsItSwitchChar(s[0]))
return false;
@@ -90,13 +75,13 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
unsigned switchIndex = 0;
int maxLen = -1;
- for (unsigned i = 0; i < _numSwitches; i++)
+ for (unsigned i = 0; i < numSwitches; i++)
{
- const char *key = switchForms[i].Key;
+ const char * const key = switchForms[i].Key;
unsigned switchLen = MyStringLen(key);
if ((int)switchLen <= maxLen || pos + switchLen > s.Len())
continue;
- if (IsString1PrefixedByString2_NoCase((const wchar_t *)s + pos, key))
+ if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key))
{
switchIndex = i;
maxLen = switchLen;
@@ -161,8 +146,10 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
break;
case NSwitchType::kString:
- sw.PostStrings.Add((const wchar_t *)s + pos);
+ {
+ sw.PostStrings.Add(s.Ptr(pos));
return true;
+ }
}
if (pos != s.Len())
@@ -173,23 +160,30 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
return true;
}
-bool CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings)
+
+bool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings)
{
+ StopSwitchIndex = -1;
+ ErrorMessage.Empty();
ErrorLine.Empty();
- bool stopSwitch = false;
+ NonSwitchStrings.Clear();
+ delete []_switches;
+ _switches = NULL;
+ _switches = new CSwitchResult[numSwitches];
+
FOR_VECTOR (i, commandStrings)
{
const UString &s = commandStrings[i];
- if (!stopSwitch)
+ if (StopSwitchIndex < 0)
{
if (s.IsEqualTo(kStopSwitchParsing))
{
- stopSwitch = true;
+ StopSwitchIndex = NonSwitchStrings.Size();
continue;
}
if (!s.IsEmpty() && IsItSwitchChar(s[0]))
{
- if (ParseString(s, switchForms))
+ if (ParseString(s, switchForms, numSwitches))
continue;
ErrorLine = s;
return false;
diff --git a/CPP/Common/CommandLineParser.h b/CPP/Common/CommandLineParser.h
index 446619c..ec6336c 100644
--- a/CPP/Common/CommandLineParser.h
+++ b/CPP/Common/CommandLineParser.h
@@ -43,19 +43,19 @@ struct CSwitchResult
class CParser
{
- unsigned _numSwitches;
CSwitchResult *_switches;
- bool ParseString(const UString &s, const CSwitchForm *switchForms);
+ bool ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches);
public:
UStringVector NonSwitchStrings;
+ int StopSwitchIndex; // NonSwitchStrings[StopSwitchIndex+] are after "--"
AString ErrorMessage;
UString ErrorLine;
- CParser(unsigned numSwitches);
+ CParser();
~CParser();
- bool ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings);
- const CSwitchResult& operator[](size_t index) const { return _switches[index]; }
+ bool ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings);
+ const CSwitchResult& operator[](unsigned index) const { return _switches[index]; }
};
}
diff --git a/CPP/Common/Common.h b/CPP/Common/Common.h
index 1f99077..c1ecc7e 100644
--- a/CPP/Common/Common.h
+++ b/CPP/Common/Common.h
@@ -3,11 +3,41 @@
#ifndef __COMMON_COMMON_H
#define __COMMON_COMMON_H
+/*
+This file is included to all cpp files in 7-Zip.
+Each folder contains StdAfx.h file that includes "Common.h".
+So 7-Zip includes "Common.h" in both modes:
+ with precompiled StdAfx.h
+and
+ without precompiled StdAfx.h
+
+If you use 7-Zip code, you must include "Common.h" before other h files of 7-zip.
+If you don't need some things that are used in 7-Zip,
+you can change this h file or h files included in this file.
+*/
+
+// compiler pragmas to disable some warnings
#include "../../C/Compiler.h"
+// it's <windows.h> or code that defines windows things, if it's not _WIN32
#include "MyWindows.h"
+
+// NewHandler.h and NewHandler.cpp redefine operator new() to throw exceptions, if compiled with old MSVC compilers
#include "NewHandler.h"
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[1]))
+
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+
+/* There is BUG in MSVC 6.0 compiler for operator new[]:
+ It doesn't check overflow, when it calculates size in bytes for allocated array.
+ So we can use MY_ARRAY_NEW macro instead of new[] operator. */
+
+#if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64)
+ #define MY_ARRAY_NEW(p, T, size) p = new T[(size > (unsigned)0xFFFFFFFF / sizeof(T)) ? (unsigned)0xFFFFFFFF / sizeof(T) : size];
+#else
+ #define MY_ARRAY_NEW(p, T, size) p = new T[size];
+#endif
#endif
diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp
index d035115..da627ca 100644
--- a/CPP/Common/IntToString.cpp
+++ b/CPP/Common/IntToString.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../C/CpuArch.h"
+
#include "IntToString.h"
#define CONVERT_INT_TO_STR(charType, tempSize) \
@@ -46,6 +48,12 @@ void ConvertUInt64ToOct(UInt64 val, char *s) throw()
while (i);
}
+
+#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
+
+static inline char GetHexChar(unsigned t) { return GET_HEX_CHAR(t); }
+
+
void ConvertUInt32ToHex(UInt32 val, char *s) throw()
{
UInt32 v = val;
@@ -59,13 +67,14 @@ void ConvertUInt32ToHex(UInt32 val, char *s) throw()
s[i] = 0;
do
{
- unsigned t = (unsigned)((val & 0xF));
+ unsigned t = (unsigned)(val & 0xF);
val >>= 4;
- s[--i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+ s[--i] = GET_HEX_CHAR(t);
}
while (i);
}
+
void ConvertUInt64ToHex(UInt64 val, char *s) throw()
{
UInt64 v = val;
@@ -79,9 +88,9 @@ void ConvertUInt64ToHex(UInt64 val, char *s) throw()
s[i] = 0;
do
{
- unsigned t = (unsigned)((val & 0xF));
+ unsigned t = (unsigned)(val & 0xF);
val >>= 4;
- s[--i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+ s[--i] = GET_HEX_CHAR(t);
}
while (i);
}
@@ -93,7 +102,7 @@ void ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw()
{
unsigned t = val & 0xF;
val >>= 4;
- s[i] = (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))));
+ s[i] = GET_HEX_CHAR(t);;
}
}
@@ -144,3 +153,41 @@ void ConvertInt64ToString(Int64 val, wchar_t *s) throw()
}
ConvertUInt64ToString(val, s);
}
+
+
+static void ConvertByteToHex2Digits(unsigned v, char *s) throw()
+{
+ s[0] = GetHexChar(v >> 4);
+ s[1] = GetHexChar(v & 0xF);
+}
+
+static void ConvertUInt16ToHex4Digits(UInt32 val, char *s) throw()
+{
+ ConvertByteToHex2Digits(val >> 8, s);
+ ConvertByteToHex2Digits(val & 0xFF, s + 2);
+}
+
+char *RawLeGuidToString(const Byte *g, char *s) throw()
+{
+ ConvertUInt32ToHex8Digits(GetUi32(g ), s); s += 8; *s++ = '-';
+ ConvertUInt16ToHex4Digits(GetUi16(g + 4), s); s += 4; *s++ = '-';
+ ConvertUInt16ToHex4Digits(GetUi16(g + 6), s); s += 4; *s++ = '-';
+ for (unsigned i = 0; i < 8; i++)
+ {
+ if (i == 2)
+ *s++ = '-';
+ ConvertByteToHex2Digits(g[8 + i], s);
+ s += 2;
+ }
+ *s = 0;
+ return s;
+}
+
+char *RawLeGuidToString_Braced(const Byte *g, char *s) throw()
+{
+ *s++ = '{';
+ s = RawLeGuidToString(g, s);
+ *s++ = '}';
+ *s = 0;
+ return s;
+}
diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h
index 7750934..07b67c3 100644
--- a/CPP/Common/IntToString.h
+++ b/CPP/Common/IntToString.h
@@ -21,4 +21,8 @@ void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw();
void ConvertInt64ToString(Int64 value, char *s) throw();
void ConvertInt64ToString(Int64 value, wchar_t *s) throw();
+// use RawLeGuid only for RAW bytes that contain stored GUID as Little-endian.
+char *RawLeGuidToString(const Byte *guid, char *s) throw();
+char *RawLeGuidToString_Braced(const Byte *guid, char *s) throw();
+
#endif
diff --git a/CPP/Common/Lang.h b/CPP/Common/Lang.h
index 1288216..e95de68 100644
--- a/CPP/Common/Lang.h
+++ b/CPP/Common/Lang.h
@@ -15,7 +15,7 @@ class CLang
public:
CLang(): _text(0) {}
~CLang() { Clear(); }
- bool Open(CFSTR fileName, const wchar_t *id);
+ bool Open(CFSTR fileName, const char *id);
void Clear() throw();
const wchar_t *Get(UInt32 id) const throw();
};
diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp
index b4b84cf..f22680b 100644
--- a/CPP/Common/ListFileUtils.cpp
+++ b/CPP/Common/ListFileUtils.cpp
@@ -52,7 +52,7 @@ bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage
if (codePage == MY__CP_UTF16)
for (unsigned i = 0; i < num; i++)
{
- wchar_t c = GetUi16(buf + i * 2);
+ wchar_t c = GetUi16(buf + (size_t)i * 2);
if (c == 0)
return false;
p[i] = c;
@@ -60,7 +60,7 @@ bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage
else
for (unsigned i = 0; i < num; i++)
{
- wchar_t c = (wchar_t)GetBe16(buf + i * 2);
+ wchar_t c = (wchar_t)GetBe16(buf + (size_t)i * 2);
if (c == 0)
return false;
p[i] = c;
@@ -104,7 +104,7 @@ bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage
wchar_t c = u[i];
if (c == kGoodBOM || c == kBadBOM)
return false;
- if (c == L'\n' || c == 0xD)
+ if (c == '\n' || c == 0xD)
{
AddName(strings, s);
s.Empty();
diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h
index 2b5e946..ae320ee 100644
--- a/CPP/Common/MyBuffer.h
+++ b/CPP/Common/MyBuffer.h
@@ -5,6 +5,9 @@
#include "Defs.h"
+/* 7-Zip now uses CBuffer only as CByteBuffer.
+ So there is no need to use MY_ARRAY_NEW macro in CBuffer code. */
+
template <class T> class CBuffer
{
T *_items;
@@ -119,7 +122,7 @@ bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)
}
-typedef CBuffer<char> CCharBuffer;
+// typedef CBuffer<char> CCharBuffer;
// typedef CBuffer<wchar_t> CWCharBuffer;
typedef CBuffer<unsigned char> CByteBuffer;
@@ -129,7 +132,7 @@ template <class T> class CObjArray
protected:
T *_items;
private:
- // we disable constructors
+ // we disable copy
CObjArray(const CObjArray &buffer);
void operator=(const CObjArray &buffer);
public:
@@ -138,7 +141,14 @@ public:
delete []_items;
_items = 0;
}
- CObjArray(size_t size): _items(0) { if (size != 0) _items = new T[size]; }
+ CObjArray(size_t size): _items(0)
+ {
+ if (size != 0)
+ {
+ MY_ARRAY_NEW(_items, T, size)
+ // _items = new T[size];
+ }
+ }
CObjArray(): _items(0) {};
~CObjArray() { delete []_items; }
@@ -149,7 +159,8 @@ public:
{
delete []_items;
_items = 0;
- _items = new T[newSize];
+ MY_ARRAY_NEW(_items, T, newSize)
+ // _items = new T[newSize];
}
};
@@ -164,6 +175,7 @@ template <class T> class CObjArray2
T *_items;
unsigned _size;
+ // we disable copy
CObjArray2(const CObjArray2 &buffer);
void operator=(const CObjArray2 &buffer);
public:
@@ -216,7 +228,10 @@ public:
return;
T *newBuffer = NULL;
if (size != 0)
- newBuffer = new T[size];
+ {
+ MY_ARRAY_NEW(newBuffer, T, size)
+ // newBuffer = new T[size];
+ }
delete []_items;
_items = newBuffer;
_size = size;
diff --git a/CPP/Common/MyBuffer2.h b/CPP/Common/MyBuffer2.h
new file mode 100644
index 0000000..5cabd73
--- /dev/null
+++ b/CPP/Common/MyBuffer2.h
@@ -0,0 +1,45 @@
+// Common/MyBuffer2.h
+
+#ifndef __COMMON_MY_BUFFER2_H
+#define __COMMON_MY_BUFFER2_H
+
+#include "../../C/Alloc.h"
+
+#include "Defs.h"
+
+class CMidBuffer
+{
+ Byte *_data;
+ size_t _size;
+
+ CLASS_NO_COPY(CMidBuffer)
+
+public:
+ CMidBuffer(): _data(NULL), _size(0) {};
+ ~CMidBuffer() { ::MidFree(_data); }
+
+ void Free() { ::MidFree(_data); _data = NULL; _size = 0; }
+
+ bool IsAllocated() const { return _data != NULL; }
+ operator Byte *() { return _data; }
+ operator const Byte *() const { return _data; }
+ size_t Size() const { return _size; }
+
+ void AllocAtLeast(size_t size)
+ {
+ if (!_data || size > _size)
+ {
+ const size_t kMinSize = (size_t)1 << 16;
+ if (size < kMinSize)
+ size = kMinSize;
+ ::MidFree(_data);
+ _size = 0;
+ _data = 0;
+ _data = (Byte *)::MidAlloc(size);
+ if (_data)
+ _size = size;
+ }
+ }
+};
+
+#endif
diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h
index 3e3f8ce..ca49ead 100644
--- a/CPP/Common/MyCom.h
+++ b/CPP/Common/MyCom.h
@@ -4,7 +4,6 @@
#define __MY_COM_H
#include "MyWindows.h"
-#include "NewHandler.h"
#ifndef RINOK
#define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; }
@@ -158,7 +157,20 @@ private:
}
};
-//////////////////////////////////////////////////////////
+
+
+/*
+ If CMyUnknownImp doesn't use virtual destructor, the code size is smaller.
+ But if some class_1 derived from CMyUnknownImp
+ uses MY_ADDREF_RELEASE and IUnknown::Release()
+ and some another class_2 is derived from class_1,
+ then class_1 must use virtual destructor:
+ virtual ~class_1();
+ In that case, class_1::Release() calls correct destructor of class_2.
+
+ Also you can use virtual ~CMyUnknownImp(), if you want to disable warning
+ "class has virtual functions, but destructor is not virtual".
+*/
class CMyUnknownImp
{
@@ -166,9 +178,12 @@ public:
ULONG __m_RefCount;
CMyUnknownImp(): __m_RefCount(0) {}
- // virtual ~CMyUnknownImp() {};
+ // virtual
+ ~CMyUnknownImp() {}
};
+
+
#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \
(REFGUID iid, void **outObject) throw() { *outObject = NULL;
diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp
index 75b9326..bf62303 100644
--- a/CPP/Common/MyString.cpp
+++ b/CPP/Common/MyString.cpp
@@ -8,6 +8,8 @@
#include <ctype.h>
#endif
+#include "IntToString.h"
+
#if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING)
#include "StringConvert.h"
#endif
@@ -28,6 +30,10 @@ inline const char* MyStringGetNextCharPointer(const char *p) throw()
}
*/
+#define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, _size_)
+#define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, _size_)
+
+
int FindCharPosInString(const char *s, char c) throw()
{
for (const char *p = s;; p++)
@@ -52,7 +58,18 @@ int FindCharPosInString(const wchar_t *s, wchar_t c) throw()
}
/*
-void MyStringUpper_Ascii(wchar_t *s)
+void MyStringUpper_Ascii(char *s) throw()
+{
+ for (;;)
+ {
+ char c = *s;
+ if (c == 0)
+ return;
+ *s++ = MyCharUpper_Ascii(c);
+ }
+}
+
+void MyStringUpper_Ascii(wchar_t *s) throw()
{
for (;;)
{
@@ -282,6 +299,26 @@ bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw()
}
}
+bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw()
+{
+ for (;;)
+ {
+ unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true;
+ wchar_t c1 = *s1++; if (c1 != c2) return false;
+ }
+}
+
+bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw()
+{
+ for (;;)
+ {
+ char c2 = *s2++; if (c2 == 0) return true;
+ wchar_t c1 = *s1++;
+ if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))
+ return false;
+ }
+}
+
bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw()
{
for (;;)
@@ -345,8 +382,8 @@ void AString::ReAlloc(unsigned newLimit)
{
if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130220;
// MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1);
- char *newBuf = MY_STRING_NEW(char, newLimit + 1);
- memcpy(newBuf, _chars, (size_t)(_len + 1)); \
+ char *newBuf = MY_STRING_NEW_char(newLimit + 1);
+ memcpy(newBuf, _chars, (size_t)(_len + 1));
MY_STRING_DELETE(_chars);
_chars = newBuf;
_limit = newLimit;
@@ -356,7 +393,7 @@ void AString::ReAlloc2(unsigned newLimit)
{
if (newLimit >= k_Alloc_Len_Limit) throw 20130220;
// MY_STRING_REALLOC(_chars, char, newLimit + 1, 0);
- char *newBuf = MY_STRING_NEW(char, newLimit + 1);
+ char *newBuf = MY_STRING_NEW_char(newLimit + 1);
newBuf[0] = 0;
MY_STRING_DELETE(_chars);
_chars = newBuf;
@@ -366,7 +403,7 @@ void AString::ReAlloc2(unsigned newLimit)
void AString::SetStartLen(unsigned len)
{
_chars = 0;
- _chars = MY_STRING_NEW(char, len + 1);
+ _chars = MY_STRING_NEW_char(len + 1);
_len = len;
_limit = len;
}
@@ -393,7 +430,6 @@ void AString::Grow(unsigned n)
ReAlloc(next - 1);
}
-/*
AString::AString(unsigned num, const char *s)
{
unsigned len = MyStringLen(s);
@@ -403,7 +439,6 @@ AString::AString(unsigned num, const char *s)
memcpy(_chars, s, num);
_chars[num] = 0;
}
-*/
AString::AString(unsigned num, const AString &s)
{
@@ -421,7 +456,7 @@ AString::AString(const AString &s, char c)
unsigned len = s.Len();
memcpy(chars, s, len);
chars[len] = c;
- chars[len + 1] = 0;
+ chars[(size_t)len + 1] = 0;
}
AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2)
@@ -436,20 +471,23 @@ AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.
AString operator+(const AString &s1, const char *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); }
AString operator+(const char *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); }
+static const unsigned kStartStringCapacity = 4;
+
AString::AString()
{
_chars = 0;
- _chars = MY_STRING_NEW(char, 4);
+ _chars = MY_STRING_NEW_char(kStartStringCapacity);
_len = 0;
- _limit = 4 - 1;
+ _limit = kStartStringCapacity - 1;
_chars[0] = 0;
}
AString::AString(char c)
{
SetStartLen(1);
- _chars[0] = c;
- _chars[1] = 0;
+ char *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
}
AString::AString(const char *s)
@@ -468,14 +506,15 @@ AString &AString::operator=(char c)
{
if (1 > _limit)
{
- char *newBuf = MY_STRING_NEW(char, 1 + 1);
+ char *newBuf = MY_STRING_NEW_char(1 + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
_limit = 1;
}
_len = 1;
- _chars[0] = c;
- _chars[1] = 0;
+ char *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
return *this;
}
@@ -484,7 +523,7 @@ AString &AString::operator=(const char *s)
unsigned len = MyStringLen(s);
if (len > _limit)
{
- char *newBuf = MY_STRING_NEW(char, len + 1);
+ char *newBuf = MY_STRING_NEW_char(len + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
_limit = len;
@@ -501,7 +540,7 @@ AString &AString::operator=(const AString &s)
unsigned len = s._len;
if (len > _limit)
{
- char *newBuf = MY_STRING_NEW(char, len + 1);
+ char *newBuf = MY_STRING_NEW_char(len + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
_limit = len;
@@ -526,7 +565,7 @@ void AString::SetFromWStr_if_Ascii(const wchar_t *s)
}
if (len > _limit)
{
- char *newBuf = MY_STRING_NEW(char, len + 1);
+ char *newBuf = MY_STRING_NEW_char(len + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
_limit = len;
@@ -550,7 +589,7 @@ void AString::SetFromBstr_if_Ascii(BSTR s)
}
if (len > _limit)
{
- char *newBuf = MY_STRING_NEW(char, len + 1);
+ char *newBuf = MY_STRING_NEW_char(len + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
_limit = len;
@@ -577,6 +616,12 @@ AString &AString::operator+=(const char *s)
return *this;
}
+void AString::Add_OptSpaced(const char *s)
+{
+ Add_Space_if_NotEmpty();
+ (*this) += s;
+}
+
AString &AString::operator+=(const AString &s)
{
Grow(s._len);
@@ -585,11 +630,18 @@ AString &AString::operator+=(const AString &s)
return *this;
}
+void AString::Add_UInt32(UInt32 v)
+{
+ char sz[16];
+ ConvertUInt32ToString(v, sz);
+ (*this) += sz;
+}
+
void AString::SetFrom(const char *s, unsigned len) // no check
{
if (len > _limit)
{
- char *newBuf = MY_STRING_NEW(char, len + 1);
+ char *newBuf = MY_STRING_NEW_char(len + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
_limit = len;
@@ -694,7 +746,7 @@ void AString::TrimRight() throw()
unsigned i;
for (i = _len; i != 0; i--)
{
- char c = p[i - 1];
+ char c = p[(size_t)i - 1];
if (c != ' ' && c != '\n' && c != '\t')
break;
}
@@ -780,12 +832,13 @@ void AString::Replace(char oldChar, char newChar) throw()
return; // 0;
// unsigned number = 0;
int pos = 0;
+ char *chars = _chars;
while ((unsigned)pos < _len)
{
pos = Find(oldChar, pos);
if (pos < 0)
break;
- _chars[(unsigned)pos] = newChar;
+ chars[(unsigned)pos] = newChar;
pos++;
// number++;
}
@@ -895,7 +948,7 @@ void UString::ReAlloc(unsigned newLimit)
{
if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130221;
// MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1);
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, newLimit + 1);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1);
wmemcpy(newBuf, _chars, _len + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
@@ -906,7 +959,7 @@ void UString::ReAlloc2(unsigned newLimit)
{
if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
// MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, newLimit + 1);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1);
newBuf[0] = 0;
MY_STRING_DELETE(_chars);
_chars = newBuf;
@@ -916,7 +969,7 @@ void UString::ReAlloc2(unsigned newLimit)
void UString::SetStartLen(unsigned len)
{
_chars = 0;
- _chars = MY_STRING_NEW(wchar_t, len + 1);
+ _chars = MY_STRING_NEW_wchar_t(len + 1);
_len = len;
_limit = len;
}
@@ -971,7 +1024,7 @@ UString::UString(const UString &s, wchar_t c)
unsigned len = s.Len();
wmemcpy(chars, s, len);
chars[len] = c;
- chars[len + 1] = 0;
+ chars[(size_t)len + 1] = 0;
}
UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2)
@@ -989,17 +1042,26 @@ UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyS
UString::UString()
{
_chars = 0;
- _chars = MY_STRING_NEW(wchar_t, 4);
+ _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity);
_len = 0;
- _limit = 4 - 1;
+ _limit = kStartStringCapacity - 1;
_chars[0] = 0;
}
UString::UString(wchar_t c)
{
SetStartLen(1);
- _chars[0] = c;
- _chars[1] = 0;
+ wchar_t *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
+}
+
+UString::UString(char c)
+{
+ SetStartLen(1);
+ wchar_t *chars = _chars;
+ chars[0] = (unsigned char)c;
+ chars[1] = 0;
}
UString::UString(const wchar_t *s)
@@ -1009,6 +1071,16 @@ UString::UString(const wchar_t *s)
wmemcpy(_chars, s, len + 1);
}
+UString::UString(const char *s)
+{
+ unsigned len = MyStringLen(s);
+ SetStartLen(len);
+ wchar_t *chars = _chars;
+ for (unsigned i = 0; i < len; i++)
+ chars[i] = (unsigned char)s[i];
+ chars[len] = 0;
+}
+
UString::UString(const UString &s)
{
SetStartLen(s._len);
@@ -1019,14 +1091,15 @@ UString &UString::operator=(wchar_t c)
{
if (1 > _limit)
{
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, 1 + 1);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
_limit = 1;
}
_len = 1;
- _chars[0] = c;
- _chars[1] = 0;
+ wchar_t *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
return *this;
}
@@ -1035,7 +1108,7 @@ UString &UString::operator=(const wchar_t *s)
unsigned len = MyStringLen(s);
if (len > _limit)
{
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
_limit = len;
@@ -1052,7 +1125,7 @@ UString &UString::operator=(const UString &s)
unsigned len = s._len;
if (len > _limit)
{
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
_limit = len;
@@ -1062,12 +1135,27 @@ UString &UString::operator=(const UString &s)
return *this;
}
+void UString::SetFrom(const wchar_t *s, unsigned len) // no check
+{
+ if (len > _limit)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ if (len != 0)
+ wmemcpy(_chars, s, len);
+ _chars[len] = 0;
+ _len = len;
+}
+
void UString::SetFromBstr(BSTR s)
{
unsigned len = ::SysStringLen(s);
if (len > _limit)
{
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
_limit = len;
@@ -1077,6 +1165,24 @@ void UString::SetFromBstr(BSTR s)
wmemcpy(_chars, s, len + 1);
}
+UString &UString::operator=(const char *s)
+{
+ unsigned len = MyStringLen(s);
+ if (len > _limit)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ wchar_t *chars = _chars;
+ for (unsigned i = 0; i < len; i++)
+ chars[i] = (unsigned char)s[i];
+ chars[len] = 0;
+ _len = len;
+ return *this;
+}
+
void UString::Add_Space() { operator+=(L' '); }
void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
@@ -1108,39 +1214,7 @@ UString &UString::operator+=(const UString &s)
return *this;
}
-void UString::SetFrom(const wchar_t *s, unsigned len) // no check
-{
- if (len > _limit)
- {
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
- MY_STRING_DELETE(_chars);
- _chars = newBuf;
- _limit = len;
- }
- if (len != 0)
- wmemcpy(_chars, s, len);
- _chars[len] = 0;
- _len = len;
-}
-
-void UString::SetFromAscii(const char *s)
-{
- unsigned len = MyStringLen(s);
- if (len > _limit)
- {
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
- MY_STRING_DELETE(_chars);
- _chars = newBuf;
- _limit = len;
- }
- wchar_t *chars = _chars;
- for (unsigned i = 0; i < len; i++)
- chars[i] = (unsigned char)s[i];
- chars[len] = 0;
- _len = len;
-}
-
-void UString::AddAscii(const char *s)
+UString &UString::operator+=(const char *s)
{
unsigned len = MyStringLen(s);
Grow(len);
@@ -1149,9 +1223,17 @@ void UString::AddAscii(const char *s)
chars[i] = (unsigned char)s[i];
chars[len] = 0;
_len += len;
+ return *this;
}
+void UString::Add_UInt32(UInt32 v)
+{
+ char sz[16];
+ ConvertUInt32ToString(v, sz);
+ (*this) += sz;
+}
+
int UString::Find(const wchar_t *s, unsigned startIndex) const throw()
{
@@ -1238,7 +1320,7 @@ void UString::TrimRight() throw()
unsigned i;
for (i = _len; i != 0; i--)
{
- wchar_t c = p[i - 1];
+ wchar_t c = p[(size_t)i - 1];
if (c != ' ' && c != '\n' && c != '\t')
break;
}
@@ -1324,12 +1406,13 @@ void UString::Replace(wchar_t oldChar, wchar_t newChar) throw()
return; // 0;
// unsigned number = 0;
int pos = 0;
+ wchar_t *chars = _chars;
while ((unsigned)pos < _len)
{
pos = Find(oldChar, pos);
if (pos < 0)
break;
- _chars[(unsigned)pos] = newChar;
+ chars[(unsigned)pos] = newChar;
pos++;
// number++;
}
@@ -1392,13 +1475,13 @@ void UString2::ReAlloc2(unsigned newLimit)
{
if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
// MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
- _chars = MY_STRING_NEW(wchar_t, newLimit + 1);
+ _chars = MY_STRING_NEW_wchar_t(newLimit + 1);
}
void UString2::SetStartLen(unsigned len)
{
_chars = 0;
- _chars = MY_STRING_NEW(wchar_t, len + 1);
+ _chars = MY_STRING_NEW_wchar_t(len + 1);
_len = len;
}
@@ -1407,8 +1490,9 @@ void UString2::SetStartLen(unsigned len)
UString2::UString2(wchar_t c)
{
SetStartLen(1);
- _chars[0] = c;
- _chars[1] = 0;
+ wchar_t *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
}
*/
@@ -1433,14 +1517,15 @@ UString2 &UString2::operator=(wchar_t c)
{
if (1 > _len)
{
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, 1 + 1);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
if (_chars)
MY_STRING_DELETE(_chars);
_chars = newBuf;
}
_len = 1;
- _chars[0] = c;
- _chars[1] = 0;
+ wchar_t *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
return *this;
}
*/
@@ -1450,7 +1535,7 @@ UString2 &UString2::operator=(const wchar_t *s)
unsigned len = MyStringLen(s);
if (len > _len)
{
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
if (_chars)
MY_STRING_DELETE(_chars);
_chars = newBuf;
@@ -1465,7 +1550,7 @@ void UString2::SetFromAscii(const char *s)
unsigned len = MyStringLen(s);
if (len > _len)
{
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
if (_chars)
MY_STRING_DELETE(_chars);
_chars = newBuf;
@@ -1484,7 +1569,7 @@ UString2 &UString2::operator=(const UString2 &s)
unsigned len = s._len;
if (len > _len)
{
- wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
if (_chars)
MY_STRING_DELETE(_chars);
_chars = newBuf;
@@ -1542,6 +1627,11 @@ AString fs2fas(CFSTR s)
return UnicodeStringToMultiByte(s, GetCurrentCodePage());
}
+FString fas2fs(const char *s)
+{
+ return MultiByteToUnicodeString(s, GetCurrentCodePage());
+}
+
FString fas2fs(const AString &s)
{
return MultiByteToUnicodeString(s, GetCurrentCodePage());
@@ -1551,9 +1641,14 @@ FString fas2fs(const AString &s)
#else
+UString fs2us(const FChar *s)
+{
+ return MultiByteToUnicodeString(s, GetCurrentCodePage());
+}
+
UString fs2us(const FString &s)
{
- return MultiByteToUnicodeString((AString)s, GetCurrentCodePage());
+ return MultiByteToUnicodeString(s, GetCurrentCodePage());
}
FString us2fs(const wchar_t *s)
diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h
index be848e4..f484ad2 100644
--- a/CPP/Common/MyString.h
+++ b/CPP/Common/MyString.h
@@ -14,6 +14,26 @@
#include "MyTypes.h"
#include "MyVector.h"
+
+#ifdef _MSC_VER
+ #ifdef _NATIVE_WCHAR_T_DEFINED
+ #define MY_NATIVE_WCHAR_T_DEFINED
+ #endif
+#else
+ #define MY_NATIVE_WCHAR_T_DEFINED
+#endif
+
+/*
+ native support for wchar_t:
+ _MSC_VER == 1600 : /Zc:wchar_t is not supported
+ _MSC_VER == 1310 (VS2003)
+ ? _MSC_VER == 1400 (VS2005) : wchar_t <- unsigned short
+ /Zc:wchar_t : wchar_t <- __wchar_t, _WCHAR_T_DEFINED and _NATIVE_WCHAR_T_DEFINED
+ _MSC_VER > 1400 (VS2008+)
+ /Zc:wchar_t[-]
+ /Zc:wchar_t is on by default
+*/
+
#ifdef _WIN32
#define IS_PATH_SEPAR(c) ((c) == '\\' || (c) == '/')
#else
@@ -60,6 +80,12 @@ inline void MyStringCopy(wchar_t *dest, const wchar_t *src)
while ((*dest++ = *src++) != 0);
}
+inline void MyStringCat(wchar_t *dest, const wchar_t *src)
+{
+ MyStringCopy(dest + MyStringLen(dest), src);
+}
+
+
/*
inline wchar_t *MyWcpCpy(wchar_t *dest, const wchar_t *src)
{
@@ -88,13 +114,15 @@ int FindCharPosInString(const wchar_t *s, wchar_t c) throw();
#define STRING_UNICODE_THROW throw()
#endif
-/*
+
inline char MyCharUpper_Ascii(char c)
{
if (c >= 'a' && c <= 'z')
- return (char)(c - 0x20);
+ return (char)((unsigned char)c - 0x20);
return c;
}
+
+/*
inline wchar_t MyCharUpper_Ascii(wchar_t c)
{
if (c >= 'a' && c <= 'z')
@@ -158,6 +186,7 @@ inline wchar_t MyCharLower(wchar_t c) throw()
// char *MyStringUpper(char *s) throw();
// char *MyStringLower(char *s) throw();
+// void MyStringUpper_Ascii(char *s) throw();
// void MyStringUpper_Ascii(wchar_t *s) throw();
void MyStringLower_Ascii(char *s) throw();
void MyStringLower_Ascii(wchar_t *s) throw();
@@ -168,8 +197,11 @@ bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();
bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();
bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();
+bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw();
+bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *u, const char *a) throw();
bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw();
+#define MyStringCompare(s1, s2) wcscmp(s1, s2)
int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw();
// int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw();
@@ -183,6 +215,33 @@ bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw();
#define MY_STRING_DELETE(_p_) delete []_p_;
// #define MY_STRING_DELETE(_p_) my_delete(_p_);
+
+#define FORBID_STRING_OPS_2(cls, t) \
+ void Find(t) const; \
+ void Find(t, unsigned startIndex) const; \
+ void ReverseFind(t) const; \
+ void InsertAtFront(t); \
+ void RemoveChar(t); \
+ void Replace(t, t); \
+
+#define FORBID_STRING_OPS(cls, t) \
+ explicit cls(t); \
+ explicit cls(const t *); \
+ cls &operator=(t); \
+ cls &operator=(const t *); \
+ cls &operator+=(t); \
+ cls &operator+=(const t *); \
+ FORBID_STRING_OPS_2(cls, t); \
+
+/*
+ cls &operator+(t); \
+ cls &operator+(const t *); \
+*/
+
+#define FORBID_STRING_OPS_AString(t) FORBID_STRING_OPS(AString, t)
+#define FORBID_STRING_OPS_UString(t) FORBID_STRING_OPS(UString, t)
+#define FORBID_STRING_OPS_UString2(t) FORBID_STRING_OPS(UString2, t)
+
class AString
{
char *_chars;
@@ -202,7 +261,7 @@ class AString
void Grow_1();
void Grow(unsigned n);
- // AString(unsigned num, const char *s);
+ AString(unsigned num, const char *s);
AString(unsigned num, const AString &s);
AString(const AString &s, char c); // it's for String + char
AString(const char *s1, unsigned num1, const char *s2, unsigned num2);
@@ -215,20 +274,24 @@ class AString
friend AString operator+(const char *s1, const AString &s2);
// ---------- forbidden functions ----------
- AString &operator+=(wchar_t c);
- AString &operator=(wchar_t c);
- AString(wchar_t c);
- void Find(wchar_t c) const;
- void Find(wchar_t c, unsigned startIndex) const;
- void ReverseFind(wchar_t c) const;
- void InsertAtFront(wchar_t c);
- void RemoveChar(wchar_t ch);
- void Replace(wchar_t oldChar, wchar_t newChar);
+
+ #ifdef MY_NATIVE_WCHAR_T_DEFINED
+ FORBID_STRING_OPS_AString(wchar_t)
+ #endif
+
+ FORBID_STRING_OPS_AString(signed char)
+ FORBID_STRING_OPS_AString(unsigned char)
+ FORBID_STRING_OPS_AString(short)
+ FORBID_STRING_OPS_AString(unsigned short)
+ FORBID_STRING_OPS_AString(int)
+ FORBID_STRING_OPS_AString(unsigned)
+ FORBID_STRING_OPS_AString(long)
+ FORBID_STRING_OPS_AString(unsigned long)
public:
- AString();
- AString(char c);
- AString(const char *s);
+ explicit AString();
+ explicit AString(char c);
+ explicit AString(const char *s);
AString(const AString &s);
~AString() { MY_STRING_DELETE(_chars); }
@@ -240,7 +303,7 @@ public:
const char *Ptr() const { return _chars; }
const char *Ptr(unsigned pos) const { return _chars + pos; }
const char *RightPtr(unsigned num) const { return _chars + _len - num; }
- char Back() const { return _chars[_len - 1]; }
+ char Back() const { return _chars[(size_t)_len - 1]; }
void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; }
@@ -292,16 +355,17 @@ public:
void Add_Space();
void Add_Space_if_NotEmpty();
+ void Add_OptSpaced(const char *s);
void Add_LF();
void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); }
AString &operator+=(const char *s);
AString &operator+=(const AString &s);
- void AddAscii(const char *s) { operator+=(s); }
+
+ void Add_UInt32(UInt32 v);
void SetFrom(const char *s, unsigned len); // no check
void SetFrom_CalcLen(const char *s, unsigned len);
- // void SetFromAscii(const char *s) { operator+=(s); }
AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }
AString Left(unsigned count) const { return AString(count, *this); }
@@ -444,28 +508,27 @@ class UString
// ---------- forbidden functions ----------
- UString &operator+=(char c);
- UString &operator+=(unsigned char c);
- UString &operator=(char c);
- UString &operator=(unsigned char c);
- UString(char c);
- UString(unsigned char c);
- void Find(char c) const;
- void Find(unsigned char c) const;
- void Find(char c, unsigned startIndex) const;
- void Find(unsigned char c, unsigned startIndex) const;
- void ReverseFind(char c) const;
- void ReverseFind(unsigned char c) const;
- void InsertAtFront(char c);
- void InsertAtFront(unsigned char c);
- void RemoveChar(char ch);
- void RemoveChar(unsigned char ch);
- void Replace(char oldChar, char newChar);
- void Replace(unsigned char oldChar, unsigned char newChar);
+ FORBID_STRING_OPS_UString(signed char)
+ FORBID_STRING_OPS_UString(unsigned char)
+ FORBID_STRING_OPS_UString(short)
+
+ #ifdef MY_NATIVE_WCHAR_T_DEFINED
+ FORBID_STRING_OPS_UString(unsigned short)
+ #endif
+
+ FORBID_STRING_OPS_UString(int)
+ FORBID_STRING_OPS_UString(unsigned)
+ FORBID_STRING_OPS_UString(long)
+ FORBID_STRING_OPS_UString(unsigned long)
+
+ FORBID_STRING_OPS_2(UString, char)
public:
UString();
- UString(wchar_t c);
+ explicit UString(wchar_t c);
+ explicit UString(char c);
+ explicit UString(const char *s);
+ // UString(const AString &s);
UString(const wchar_t *s);
UString(const UString &s);
~UString() { MY_STRING_DELETE(_chars); }
@@ -478,10 +541,12 @@ public:
const wchar_t *Ptr() const { return _chars; }
const wchar_t *Ptr(unsigned pos) const { return _chars + pos; }
const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; }
- wchar_t Back() const { return _chars[_len - 1]; }
+ wchar_t Back() const { return _chars[(size_t)_len - 1]; }
void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }
+ wchar_t *GetBuf() { return _chars; }
+
wchar_t *GetBuf(unsigned minLen)
{
if (minLen > _limit)
@@ -508,9 +573,13 @@ public:
}
UString &operator=(wchar_t c);
+ UString &operator=(char c) { return (*this)=((wchar_t)(unsigned char)c); }
UString &operator=(const wchar_t *s);
UString &operator=(const UString &s);
+ void SetFrom(const wchar_t *s, unsigned len); // no check
void SetFromBstr(BSTR s);
+ UString &operator=(const char *s);
+ UString &operator=(const AString &s) { return operator=(s.Ptr()); }
UString &operator+=(wchar_t c)
{
@@ -524,6 +593,8 @@ public:
return *this;
}
+ UString &operator+=(char c) { return (*this)+=((wchar_t)(unsigned char)c); }
+
void Add_Space();
void Add_Space_if_NotEmpty();
void Add_LF();
@@ -531,11 +602,10 @@ public:
UString &operator+=(const wchar_t *s);
UString &operator+=(const UString &s);
+ UString &operator+=(const char *s);
+ UString &operator+=(const AString &s) { return operator+=(s.Ptr()); }
- void SetFrom(const wchar_t *s, unsigned len); // no check
-
- void SetFromAscii(const char *s);
- void AddAscii(const char *s);
+ void Add_UInt32(UInt32 v);
UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }
UString Left(unsigned count) const { return UString(count, *this); }
@@ -630,6 +700,12 @@ void operator==(const UString &s1, wchar_t c2);
void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it
+void operator+(const AString &s1, const UString &s2);
+void operator+(const UString &s1, const AString &s2);
+
+void operator+(const UString &s1, const char *s2);
+void operator+(const char *s1, const UString &s2);
+
void operator+(const UString &s, char c);
void operator+(const UString &s, unsigned char c);
void operator+(char c, const UString &s);
@@ -662,15 +738,16 @@ class UString2
// ---------- forbidden functions ----------
- UString2 &operator=(char c);
- UString2 &operator=(unsigned char c);
+ FORBID_STRING_OPS_UString2(char)
+ FORBID_STRING_OPS_UString2(signed char)
+ FORBID_STRING_OPS_UString2(unsigned char)
+ FORBID_STRING_OPS_UString2(short)
+
UString2 &operator=(wchar_t c);
- UString2(char c);
- UString2(unsigned char c);
+ UString2(wchar_t c);
public:
UString2(): _chars(NULL), _len(0) {}
- // UString2(wchar_t c);
UString2(const wchar_t *s);
UString2(const UString2 &s);
~UString2() { if (_chars) MY_STRING_DELETE(_chars); }
@@ -682,6 +759,8 @@ public:
// operator const wchar_t *() const { return _chars; }
const wchar_t *GetRawPtr() const { return _chars; }
+ int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
+
wchar_t *GetBuf(unsigned minLen)
{
if (!_chars || minLen > _len)
@@ -754,6 +833,7 @@ typedef CObjectVector<CSysString> CSysStringVector;
#define fs2us(_x_) (_x_)
#define us2fs(_x_) (_x_)
+ FString fas2fs(const char *s);
FString fas2fs(const AString &s);
AString fs2fas(const FChar *s);
@@ -764,6 +844,7 @@ typedef CObjectVector<CSysString> CSysStringVector;
typedef char FChar;
typedef AString FString;
+ UString fs2us(const FChar *s);
UString fs2us(const FString &s);
FString us2fs(const wchar_t *s);
#define fas2fs(_x_) (_x_)
@@ -775,8 +856,10 @@ typedef CObjectVector<CSysString> CSysStringVector;
#define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR)
#define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR)
-#define FCHAR_ANY_MASK FTEXT('*')
-#define FSTRING_ANY_MASK FTEXT("*")
+
+// #define FCHAR_ANY_MASK FTEXT('*')
+// #define FSTRING_ANY_MASK FTEXT("*")
+
typedef const FChar *CFSTR;
typedef CObjectVector<FString> FStringVector;
diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h
index 4bc91d5..21125fa 100644
--- a/CPP/Common/MyVector.h
+++ b/CPP/Common/MyVector.h
@@ -22,7 +22,9 @@ class CRecordVector
if (_size == _capacity)
{
unsigned newCapacity = _capacity + (_capacity >> 2) + 1;
- T *p = new T[newCapacity];
+ T *p;
+ MY_ARRAY_NEW(p, T, newCapacity);
+ // p = new T[newCapacity];
if (_size != 0)
memcpy(p, _items, (size_t)_size * sizeof(T));
delete []_items;
@@ -54,7 +56,8 @@ public:
{
if (size != 0)
{
- _items = new T[size];
+ MY_ARRAY_NEW(_items, T, size)
+ // _items = new T[size];
_capacity = size;
}
}
@@ -63,7 +66,9 @@ public:
{
if (newCapacity > _capacity)
{
- T *p = new T[newCapacity];
+ T *p;
+ MY_ARRAY_NEW(p, T, newCapacity);
+ // p = new T[newCapacity];
if (_size != 0)
memcpy(p, _items, (size_t)_size * sizeof(T));
delete []_items;
@@ -80,7 +85,8 @@ public:
delete []_items;
_items = NULL;
_capacity = 0;
- _items = new T[newCapacity];
+ MY_ARRAY_NEW(_items, T, newCapacity)
+ // _items = new T[newCapacity];
_capacity = newCapacity;
}
}
@@ -95,7 +101,9 @@ public:
{
if (newSize > _capacity)
{
- T *p = new T[newSize];
+ T *p;
+ MY_ARRAY_NEW(p, T, newSize)
+ // p = new T[newSize];
if (_size != 0)
memcpy(p, _items, (size_t)_size * sizeof(T));
delete []_items;
@@ -230,8 +238,8 @@ public:
T& operator[](unsigned index) { return _items[index]; }
const T& Front() const { return _items[0]; }
T& Front() { return _items[0]; }
- const T& Back() const { return _items[_size - 1]; }
- T& Back() { return _items[_size - 1]; }
+ const T& Back() const { return _items[(size_t)_size - 1]; }
+ T& Back() { return _items[(size_t)_size - 1]; }
/*
void Swap(unsigned i, unsigned j)
@@ -370,7 +378,7 @@ public:
unsigned s = (k << 1);
if (s > size)
break;
- if (s < size && p[s + 1].Compare(p[s]) > 0)
+ if (s < size && p[(size_t)s + 1].Compare(p[s]) > 0)
s++;
if (temp.Compare(p[s]) >= 0)
break;
@@ -453,8 +461,8 @@ public:
T& operator[](unsigned index) { return *((T *)_v[index]); }
const T& Front() const { return operator[](0); }
T& Front() { return operator[](0); }
- const T& Back() const { return operator[](_v.Size() - 1); }
- T& Back() { return operator[](_v.Size() - 1); }
+ const T& Back() const { return *(T *)_v.Back(); }
+ T& Back() { return *(T *)_v.Back(); }
void MoveToFront(unsigned index) { _v.MoveToFront(index); }
@@ -521,7 +529,7 @@ public:
void DeleteBack()
{
- delete (T *)_v[_v.Size() - 1];
+ delete (T *)_v.Back();
_v.DeleteBack();
}
diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h
index 33145b1..cc78478 100644
--- a/CPP/Common/MyWindows.h
+++ b/CPP/Common/MyWindows.h
@@ -16,6 +16,7 @@
#include <stddef.h> // for wchar_t
#include <string.h>
+// #include <stdint.h> // for uintptr_t
#include "MyGuidDef.h"
@@ -44,6 +45,18 @@ typedef UINT32 ULONG;
#undef DWORD
typedef UINT32 DWORD;
+typedef long BOOL;
+
+#ifndef FALSE
+ #define FALSE 0
+ #define TRUE 1
+#endif
+
+// typedef size_t ULONG_PTR;
+typedef size_t DWORD_PTR;
+// typedef uintptr_t UINT_PTR;
+// typedef ptrdiff_t UINT_PTR;
+
typedef Int64 LONGLONG;
typedef UInt64 ULONGLONG;
@@ -71,6 +84,8 @@ typedef struct _FILETIME
typedef ULONG PROPID;
typedef LONG SCODE;
+#define ERROR_NEGATIVE_SEEK 131L
+
#define S_OK ((HRESULT)0x00000000L)
#define S_FALSE ((HRESULT)0x00000001L)
#define E_NOTIMPL ((HRESULT)0x80004001L)
diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp
index 2dfa289..18d2d18 100644
--- a/CPP/Common/NewHandler.cpp
+++ b/CPP/Common/NewHandler.cpp
@@ -10,7 +10,7 @@
#ifndef DEBUG_MEMORY_LEAK
-#ifdef _WIN32
+#ifdef _7ZIP_REDEFINE_OPERATOR_NEW
/*
void * my_new(size_t size)
diff --git a/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h
index f6ca552..9d20ee1 100644
--- a/CPP/Common/NewHandler.h
+++ b/CPP/Common/NewHandler.h
@@ -4,28 +4,29 @@
#define __COMMON_NEW_HANDLER_H
/*
-This file must be included before any code that uses operators "delete" or "new".
-Also you must compile and link "NewHandler.cpp", if you use MSVC 6.0.
-The operator "new" in MSVC 6.0 doesn't throw exception "bad_alloc".
-So we define another version of operator "new" that throws "CNewException" on failure.
+NewHandler.h and NewHandler.cpp allows to solve problem with compilers that
+don't throw exception in operator new().
-If you use compiler that throws exception in "new" operator (GCC or new version of MSVC),
-you can compile without "NewHandler.cpp". So standard exception "bad_alloc" will be used.
+This file must be included before any code that uses operators new() or delete()
+and you must compile and link "NewHandler.cpp", if you use some old MSVC compiler.
-It's still allowed to use redefined version of operator "new" from "NewHandler.cpp"
-with any compiler. 7-Zip's code can work with "bad_alloc" and "CNewException" exceptions.
-But if you use some additional code (outside of 7-Zip's code), you must check
-that redefined version of operator "new" (that throws CNewException) is not
-problem for your code.
+The operator new() in some MSVC versions doesn't throw exception std::bad_alloc.
+MSVC 6.0 (_MSC_VER == 1200) doesn't throw exception.
+The code produced by some another MSVC compilers also can be linked
+to library that doesn't throw exception.
+We suppose that code compiled with VS2015+ (_MSC_VER >= 1900) throws exception std::bad_alloc.
+For older _MSC_VER versions we redefine operator new() and operator delete().
+Our version of operator new() throws CNewException() exception on failure.
-Also we declare delete(void *p) throw() that creates smaller code.
+It's still allowed to use redefined version of operator new() from "NewHandler.cpp"
+with any compiler. 7-Zip's code can work with std::bad_alloc and CNewException() exceptions.
+But if you use some additional code (outside of 7-Zip's code), you must check
+that redefined version of operator new() is not problem for your code.
*/
#include <stddef.h>
-class CNewException {};
-
-#ifdef WIN32
+#ifdef _WIN32
// We can compile my_new and my_delete with _fastcall
/*
void * my_new(size_t size);
@@ -34,7 +35,19 @@ void my_delete(void *p) throw();
*/
#endif
-#ifdef _WIN32
+
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+ // If you want to use default operator new(), you can disable the following line
+ #define _7ZIP_REDEFINE_OPERATOR_NEW
+#endif
+
+
+#ifdef _7ZIP_REDEFINE_OPERATOR_NEW
+
+// std::bad_alloc can require additional DLL dependency.
+// So we don't define CNewException as std::bad_alloc here.
+
+class CNewException {};
void *
#ifdef _MSC_VER
@@ -48,6 +61,12 @@ __cdecl
#endif
operator delete(void *p) throw();
+#else
+
+#include <new>
+
+#define CNewException std::bad_alloc
+
#endif
/*
diff --git a/CPP/Common/StdInStream.cpp b/CPP/Common/StdInStream.cpp
index 0799c2c..f547b54 100644
--- a/CPP/Common/StdInStream.cpp
+++ b/CPP/Common/StdInStream.cpp
@@ -8,13 +8,11 @@
#include "StringConvert.h"
#include "UTFConvert.h"
-static const char kNewLineChar = '\n';
+// #define kEOFMessage "Unexpected end of input stream"
+// #define kReadErrorMessage "Error reading input stream"
+// #define kIllegalCharMessage "Illegal zero character in input stream"
-static const char *kEOFMessage = "Unexpected end of input stream";
-static const char *kReadErrorMessage ="Error reading input stream";
-static const char *kIllegalCharMessage = "Illegal character in input stream";
-
-static LPCTSTR kFileOpenMode = TEXT("r");
+#define kFileOpenMode TEXT("r")
extern int g_CodePage;
@@ -36,59 +34,56 @@ bool CStdInStream::Close() throw()
return !_streamIsOpen;
}
-AString CStdInStream::ScanStringUntilNewLine(bool allowEOF)
+bool CStdInStream::ScanAStringUntilNewLine(AString &s)
{
- AString s;
+ s.Empty();
for (;;)
{
int intChar = GetChar();
if (intChar == EOF)
- {
- if (allowEOF)
- break;
- throw kEOFMessage;
- }
+ return true;
char c = (char)intChar;
if (c == 0)
- throw kIllegalCharMessage;
- if (c == kNewLineChar)
- break;
+ return false;
+ if (c == '\n')
+ return true;
s += c;
}
- return s;
}
-UString CStdInStream::ScanUStringUntilNewLine()
+bool CStdInStream::ScanUStringUntilNewLine(UString &dest)
{
- AString s = ScanStringUntilNewLine(true);
+ dest.Empty();
+ AString s;
+ bool res = ScanAStringUntilNewLine(s);
int codePage = g_CodePage;
if (codePage == -1)
codePage = CP_OEMCP;
- UString dest;
if (codePage == CP_UTF8)
ConvertUTF8ToUnicode(s, dest);
else
- dest = MultiByteToUnicodeString(s, (UINT)codePage);
- return dest;
+ MultiByteToUnicodeString2(dest, s, (UINT)codePage);
+ return res;
}
-void CStdInStream::ReadToString(AString &resultString)
+/*
+bool CStdInStream::ReadToString(AString &resultString)
{
resultString.Empty();
- int c;
- while ((c = GetChar()) != EOF)
- resultString += (char)c;
-}
-
-bool CStdInStream::Eof() throw()
-{
- return (feof(_stream) != 0);
+ for (;;)
+ {
+ int intChar = GetChar();
+ if (intChar == EOF)
+ return !Error();
+ char c = (char)intChar;
+ if (c == 0)
+ return false;
+ resultString += c;
+ }
}
+*/
int CStdInStream::GetChar()
{
- int c = fgetc(_stream); // getc() doesn't work in BeOS?
- if (c == EOF && !Eof())
- throw kReadErrorMessage;
- return c;
+ return fgetc(_stream); // getc() doesn't work in BeOS?
}
diff --git a/CPP/Common/StdInStream.h b/CPP/Common/StdInStream.h
index c017d0a..20f9ce3 100644
--- a/CPP/Common/StdInStream.h
+++ b/CPP/Common/StdInStream.h
@@ -20,11 +20,16 @@ public:
bool Open(LPCTSTR fileName) throw();
bool Close() throw();
- AString ScanStringUntilNewLine(bool allowEOF = false);
- void ReadToString(AString &resultString);
- UString ScanUStringUntilNewLine();
+ // returns:
+ // false, if ZERO character in stream
+ // true, if EOF or '\n'
+ bool ScanAStringUntilNewLine(AString &s);
+ bool ScanUStringUntilNewLine(UString &s);
+ // bool ReadToString(AString &resultString);
+
+ bool Eof() const throw() { return (feof(_stream) != 0); }
+ bool Error() const throw() { return (ferror(_stream) != 0); }
- bool Eof() throw();
int GetChar();
};
diff --git a/CPP/Common/StdOutStream.cpp b/CPP/Common/StdOutStream.cpp
index eec83bb..dc6d4bd 100644
--- a/CPP/Common/StdOutStream.cpp
+++ b/CPP/Common/StdOutStream.cpp
@@ -9,9 +9,7 @@
#include "StringConvert.h"
#include "UTFConvert.h"
-static const char kNewLineChar = '\n';
-
-static const char *kFileOpenMode = "wt";
+#define kFileOpenMode "wt"
extern int g_CodePage;
@@ -44,7 +42,7 @@ bool CStdOutStream::Flush() throw()
CStdOutStream & endl(CStdOutStream & outStream) throw()
{
- return outStream << kNewLineChar;
+ return outStream << '\n';
}
CStdOutStream & CStdOutStream::operator<<(const wchar_t *s)
@@ -77,6 +75,65 @@ void CStdOutStream::PrintUString(const UString &s, AString &temp)
*this << (const char *)temp;
}
+
+static const wchar_t kReplaceChar = '_';
+
+void CStdOutStream::Normalize_UString__LF_Allowed(UString &s)
+{
+ unsigned len = s.Len();
+ wchar_t *d = s.GetBuf();
+
+ if (IsTerminalMode)
+ for (unsigned i = 0; i < len; i++)
+ {
+ wchar_t c = d[i];
+ if (c <= 13 && c >= 7 && c != '\n')
+ d[i] = kReplaceChar;
+ }
+}
+
+void CStdOutStream::Normalize_UString(UString &s)
+{
+ unsigned len = s.Len();
+ wchar_t *d = s.GetBuf();
+
+ if (IsTerminalMode)
+ for (unsigned i = 0; i < len; i++)
+ {
+ wchar_t c = d[i];
+ if (c <= 13 && c >= 7)
+ d[i] = kReplaceChar;
+ }
+ else
+ for (unsigned i = 0; i < len; i++)
+ {
+ wchar_t c = d[i];
+ if (c == '\n')
+ d[i] = kReplaceChar;
+ }
+}
+
+void CStdOutStream::NormalizePrint_UString(const UString &s, UString &tempU, AString &tempA)
+{
+ tempU = s;
+ Normalize_UString(tempU);
+ PrintUString(tempU, tempA);
+}
+
+void CStdOutStream::NormalizePrint_UString(const UString &s)
+{
+ NormalizePrint_wstr(s);
+}
+
+void CStdOutStream::NormalizePrint_wstr(const wchar_t *s)
+{
+ UString tempU = s;
+ Normalize_UString(tempU);
+ AString tempA;
+ PrintUString(tempU, tempA);
+}
+
+
CStdOutStream & CStdOutStream::operator<<(Int32 number) throw()
{
char s[32];
diff --git a/CPP/Common/StdOutStream.h b/CPP/Common/StdOutStream.h
index 45738b2..475954c 100644
--- a/CPP/Common/StdOutStream.h
+++ b/CPP/Common/StdOutStream.h
@@ -13,7 +13,9 @@ class CStdOutStream
FILE *_stream;
bool _streamIsOpen;
public:
- CStdOutStream(): _stream(0), _streamIsOpen(false) {};
+ bool IsTerminalMode;
+
+ CStdOutStream(): _stream(0), _streamIsOpen(false), IsTerminalMode(false) {};
CStdOutStream(FILE *stream): _stream(stream), _streamIsOpen(false) {};
~CStdOutStream() { Close(); }
@@ -50,6 +52,13 @@ public:
CStdOutStream & operator<<(const wchar_t *s);
void PrintUString(const UString &s, AString &temp);
+
+ void Normalize_UString__LF_Allowed(UString &s);
+ void Normalize_UString(UString &s);
+
+ void NormalizePrint_UString(const UString &s, UString &tempU, AString &tempA);
+ void NormalizePrint_UString(const UString &s);
+ void NormalizePrint_wstr(const wchar_t *s);
};
CStdOutStream & endl(CStdOutStream & outStream) throw();
diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp
index ae66d14..b8f33cd 100644
--- a/CPP/Common/StringConvert.cpp
+++ b/CPP/Common/StringConvert.cpp
@@ -291,6 +291,12 @@ UString MultiByteToUnicodeString(const AString &src, UINT codePage)
return dest;
}
+UString MultiByteToUnicodeString(const char *src, UINT codePage)
+{
+ return MultiByteToUnicodeString(AString(src), codePage);
+}
+
+
void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage)
{
bool defaultCharWasUsed;
diff --git a/CPP/Common/StringConvert.h b/CPP/Common/StringConvert.h
index 7f387b1..05a2155 100644
--- a/CPP/Common/StringConvert.h
+++ b/CPP/Common/StringConvert.h
@@ -6,72 +6,83 @@
#include "MyString.h"
#include "MyWindows.h"
-UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP);
+UString MultiByteToUnicodeString(const AString &src, UINT codePage = CP_ACP);
+UString MultiByteToUnicodeString(const char *src, UINT codePage = CP_ACP);
// optimized versions that work faster for ASCII strings
-void MultiByteToUnicodeString2(UString &dest, const AString &srcString, UINT codePage = CP_ACP);
+void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage = CP_ACP);
// void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
-void UnicodeStringToMultiByte2(AString &dest, const UString &srcString, UINT codePage);
-
-AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
-AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP);
-
-inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString)
- { return unicodeString; }
-inline const UString& GetUnicodeString(const UString &unicodeString)
- { return unicodeString; }
-inline UString GetUnicodeString(const AString &ansiString)
- { return MultiByteToUnicodeString(ansiString); }
-inline UString GetUnicodeString(const AString &multiByteString, UINT codePage)
- { return MultiByteToUnicodeString(multiByteString, codePage); }
-inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT)
- { return unicodeString; }
-inline const UString& GetUnicodeString(const UString &unicodeString, UINT)
- { return unicodeString; }
-
-inline const char* GetAnsiString(const char* ansiString)
- { return ansiString; }
-inline const AString& GetAnsiString(const AString &ansiString)
- { return ansiString; }
-inline AString GetAnsiString(const UString &unicodeString)
- { return UnicodeStringToMultiByte(unicodeString); }
-
-inline const char* GetOemString(const char* oemString)
- { return oemString; }
-inline const AString& GetOemString(const AString &oemString)
- { return oemString; }
-inline AString GetOemString(const UString &unicodeString)
- { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); }
+void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage);
+AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
+AString UnicodeStringToMultiByte(const UString &src, UINT codePage = CP_ACP);
+
+inline const wchar_t* GetUnicodeString(const wchar_t *u) { return u; }
+inline const UString& GetUnicodeString(const UString &u) { return u; }
+
+inline UString GetUnicodeString(const AString &a) { return MultiByteToUnicodeString(a); }
+inline UString GetUnicodeString(const char *a) { return MultiByteToUnicodeString(a); }
+
+inline UString GetUnicodeString(const AString &a, UINT codePage)
+ { return MultiByteToUnicodeString(a, codePage); }
+inline UString GetUnicodeString(const char *a, UINT codePage)
+ { return MultiByteToUnicodeString(a, codePage); }
+
+inline const wchar_t* GetUnicodeString(const wchar_t *u, UINT) { return u; }
+inline const UString& GetUnicodeString(const UString &u, UINT) { return u; }
+
+inline const char* GetAnsiString(const char *a) { return a; }
+inline const AString& GetAnsiString(const AString &a) { return a; }
+
+inline AString GetAnsiString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); }
+inline AString GetAnsiString(const UString &u) { return UnicodeStringToMultiByte(u); }
+
+/*
+inline const char* GetOemString(const char* oem)
+ { return oem; }
+inline const AString& GetOemString(const AString &oem)
+ { return oem; }
+*/
+const char* GetOemString(const char* oem);
+const AString& GetOemString(const AString &oem);
+inline AString GetOemString(const UString &u)
+ { return UnicodeStringToMultiByte(u, CP_OEMCP); }
#ifdef _UNICODE
- inline const wchar_t* GetSystemString(const wchar_t* unicodeString)
- { return unicodeString;}
- inline const UString& GetSystemString(const UString &unicodeString)
- { return unicodeString;}
- inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */)
- { return unicodeString;}
- inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */)
- { return unicodeString;}
- inline UString GetSystemString(const AString &multiByteString, UINT codePage)
- { return MultiByteToUnicodeString(multiByteString, codePage);}
- inline UString GetSystemString(const AString &multiByteString)
- { return MultiByteToUnicodeString(multiByteString);}
+ inline const wchar_t* GetSystemString(const wchar_t *u) { return u;}
+ inline const UString& GetSystemString(const UString &u) { return u;}
+ inline const wchar_t* GetSystemString(const wchar_t *u, UINT /* codePage */) { return u;}
+ inline const UString& GetSystemString(const UString &u, UINT /* codePage */) { return u;}
+
+ inline UString GetSystemString(const AString &a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); }
+ inline UString GetSystemString(const char *a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); }
+ inline UString GetSystemString(const AString &a) { return MultiByteToUnicodeString(a); }
+ inline UString GetSystemString(const char *a) { return MultiByteToUnicodeString(a); }
#else
- inline const char* GetSystemString(const char *ansiString)
- { return ansiString; }
- inline const AString& GetSystemString(const AString &multiByteString, UINT)
- { return multiByteString; }
- inline const char * GetSystemString(const char *multiByteString, UINT)
- { return multiByteString; }
- inline AString GetSystemString(const UString &unicodeString)
- { return UnicodeStringToMultiByte(unicodeString); }
- inline AString GetSystemString(const UString &unicodeString, UINT codePage)
- { return UnicodeStringToMultiByte(unicodeString, codePage); }
+ inline const char* GetSystemString(const char *a) { return a; }
+ inline const AString& GetSystemString(const AString &a) { return a; }
+ inline const char* GetSystemString(const char *a, UINT) { return a; }
+ inline const AString& GetSystemString(const AString &a, UINT) { return a; }
+
+ inline AString GetSystemString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); }
+ inline AString GetSystemString(const UString &u) { return UnicodeStringToMultiByte(u); }
+ inline AString GetSystemString(const UString &u, UINT codePage) { return UnicodeStringToMultiByte(u, codePage); }
+
+
+
+ /*
+ inline AString GetSystemString(const wchar_t *u)
+ {
+ UString s;
+ s = u;
+ return UnicodeStringToMultiByte(s);
+ }
+ */
+
#endif
#ifndef UNDER_CE
-AString SystemStringToOemString(const CSysString &srcString);
+AString SystemStringToOemString(const CSysString &src);
#endif
#endif
diff --git a/CPP/Common/TextConfig.cpp b/CPP/Common/TextConfig.cpp
index f6b7008..f54aa3f 100644
--- a/CPP/Common/TextConfig.cpp
+++ b/CPP/Common/TextConfig.cpp
@@ -61,7 +61,7 @@ bool GetTextConfig(const AString &s, CObjectVector<CTextConfigPair> &pairs)
break;
CTextConfigPair pair;
unsigned finishPos;
- AString temp = GetIDString(((const char *)s) + pos, finishPos);
+ const AString temp (GetIDString(((const char *)s) + pos, finishPos));
if (!ConvertUTF8ToUnicode(temp, pair.ID))
return false;
if (finishPos == 0)
@@ -107,15 +107,15 @@ bool GetTextConfig(const AString &s, CObjectVector<CTextConfigPair> &pairs)
return true;
}
-int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const UString &id) throw()
+int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const char *id) throw()
{
FOR_VECTOR (i, pairs)
- if (pairs[i].ID == id)
+ if (pairs[i].ID.IsEqualTo(id))
return i;
return -1;
}
-UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const UString &id)
+UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const char *id)
{
int index = FindTextConfigItem(pairs, id);
if (index < 0)
diff --git a/CPP/Common/TextConfig.h b/CPP/Common/TextConfig.h
index fd9605c..c39e363 100644
--- a/CPP/Common/TextConfig.h
+++ b/CPP/Common/TextConfig.h
@@ -13,7 +13,7 @@ struct CTextConfigPair
bool GetTextConfig(const AString &text, CObjectVector<CTextConfigPair> &pairs);
-int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const UString &id) throw();
-UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const UString &id);
+int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const char *id) throw();
+UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const char *id);
#endif
diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp
index 4967b69..43e4baa 100644
--- a/CPP/Common/Wildcard.cpp
+++ b/CPP/Common/Wildcard.cpp
@@ -22,16 +22,18 @@ bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2)
int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW
{
if (g_CaseSensitive)
- return wcscmp(s1, s2);
+ return MyStringCompare(s1, s2);
return MyStringCompareNoCase(s1, s2);
}
#ifndef USE_UNICODE_FSTRING
int CompareFileNames(const char *s1, const char *s2)
{
+ const UString u1 = fs2us(s1);
+ const UString u2 = fs2us(s2);
if (g_CaseSensitive)
- return wcscmp(fs2us(s1), fs2us(s2));
- return MyStringCompareNoCase(fs2us(s1), fs2us(s2));
+ return MyStringCompare(u1, u2);
+ return MyStringCompareNoCase(u1, u2);
}
#endif
@@ -120,24 +122,16 @@ void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &na
name = p;
}
+/*
UString ExtractDirPrefixFromPath(const UString &path)
{
- const wchar_t *start = path;
- const wchar_t *p = start + path.Len();
- for (; p != start; p--)
- if (IsPathSepar(*(p - 1)))
- break;
- return path.Left((unsigned)(p - start));
+ return path.Left(path.ReverseFind_PathSepar() + 1));
}
+*/
UString ExtractFileNameFromPath(const UString &path)
{
- const wchar_t *start = path;
- const wchar_t *p = start + path.Len();
- for (; p != start; p--)
- if (IsPathSepar(*(p - 1)))
- break;
- return p;
+ return UString(path.Ptr(path.ReverseFind_PathSepar() + 1));
}
@@ -425,7 +419,7 @@ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive, bo
return;
bool forFile = true;
bool forFolder = true;
- UString path2 = path;
+ UString path2 (path);
if (IsPathSepar(path.Back()))
{
path2.DeleteBack();
@@ -612,7 +606,7 @@ void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &pat
{
// we create universal item, if we skip all parts as prefix (like \ or L:\ )
pathParts.Clear();
- pathParts.Add(L"*");
+ pathParts.Add(UString("*"));
forFile = true;
wildcardMatching = true;
recursive = false;
diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h
index 2ed7298..6e5f013 100644
--- a/CPP/Common/Wildcard.h
+++ b/CPP/Common/Wildcard.h
@@ -139,7 +139,7 @@ public:
}
void AddPreItem_Wildcard()
{
- AddPreItem(true, L"*", false, true);
+ AddPreItem(true, UString("*"), false, true);
}
};
diff --git a/CPP/Common/XzCrc64Init.cpp b/CPP/Common/XzCrc64Init.cpp
new file mode 100644
index 0000000..1eae72a
--- /dev/null
+++ b/CPP/Common/XzCrc64Init.cpp
@@ -0,0 +1,7 @@
+// XzCrc64Init.cpp
+
+#include "StdAfx.h"
+
+#include "../../C/XzCrc64.h"
+
+static struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;
diff --git a/CPP/Windows/Control/Dialog.cpp b/CPP/Windows/Control/Dialog.cpp
index c8a09ed..8e61a2b 100644
--- a/CPP/Windows/Control/Dialog.cpp
+++ b/CPP/Windows/Control/Dialog.cpp
@@ -72,6 +72,7 @@ bool CDialog::OnButtonClicked(int buttonID, HWND /* buttonHWND */)
{
case IDOK: OnOK(); break;
case IDCANCEL: OnCancel(); break;
+ case IDCLOSE: OnClose(); break;
case IDHELP: OnHelp(); break;
default: return false;
}
diff --git a/CPP/Windows/Control/Dialog.h b/CPP/Windows/Control/Dialog.h
index b160958..f9c3442 100644
--- a/CPP/Windows/Control/Dialog.h
+++ b/CPP/Windows/Control/Dialog.h
@@ -105,6 +105,7 @@ public:
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
virtual void OnOK() {};
virtual void OnCancel() {};
+ virtual void OnClose() {}
virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */) { return false; }
virtual bool OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { return false; }
@@ -133,6 +134,7 @@ public:
#endif
virtual void OnOK() { Destroy(); }
virtual void OnCancel() { Destroy(); }
+ virtual void OnClose() { Destroy(); }
};
class CModalDialog: public CDialog
@@ -147,6 +149,7 @@ public:
bool End(INT_PTR result) { return BOOLToBool(::EndDialog(_window, result)); }
virtual void OnOK() { End(IDOK); }
virtual void OnCancel() { End(IDCANCEL); }
+ virtual void OnClose() { End(IDCLOSE); }
};
class CDialogChildControl: public NWindows::CWindow
diff --git a/CPP/Windows/Control/PropertyPage.cpp b/CPP/Windows/Control/PropertyPage.cpp
index 6d940c8..48947c0 100644
--- a/CPP/Windows/Control/PropertyPage.cpp
+++ b/CPP/Windows/Control/PropertyPage.cpp
@@ -115,7 +115,7 @@ INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndPare
sheet.dwFlags = PSH_PROPSHEETPAGE;
sheet.hwndParent = hwndParent;
sheet.hInstance = g_hInstance;
- AString titleA = GetSystemString(title);
+ AString titleA (GetSystemString(title));
sheet.pszCaption = titleA;
sheet.nPages = pagesInfo.Size();
sheet.nStartPage = 0;
diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp
index 988b66f..efee379 100644
--- a/CPP/Windows/DLL.cpp
+++ b/CPP/Windows/DLL.cpp
@@ -97,12 +97,11 @@ FString GetModuleDirPrefix()
{
int pos = s.ReverseFind_PathSepar();
if (pos >= 0)
- {
s.DeleteFrom(pos + 1);
- return s;
- }
}
- return FTEXT(".") FSTRING_PATH_SEPARATOR;
+ if (s.IsEmpty())
+ s = "." STRING_PATH_SEPARATOR;
+ return s;
}
#endif
diff --git a/CPP/Windows/ErrorMsg.cpp b/CPP/Windows/ErrorMsg.cpp
index c252afd..6434ec2 100644
--- a/CPP/Windows/ErrorMsg.cpp
+++ b/CPP/Windows/ErrorMsg.cpp
@@ -53,8 +53,8 @@ UString MyFormatMessage(DWORD errorCode)
s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
}
s[8] = 0;
- m.AddAscii("Error #");
- m.AddAscii(s);
+ m += "Error #";
+ m += s;
}
else if (m.Len() >= 2
&& m[m.Len() - 1] == 0x0A
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
index 6b70a47..124569e 100644
--- a/CPP/Windows/FileDir.cpp
+++ b/CPP/Windows/FileDir.cpp
@@ -128,6 +128,15 @@ bool SetFileAttrib(CFSTR path, DWORD attrib)
return false;
}
+
+bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
+{
+ if ((attrib & 0xF0000000) != 0)
+ attrib &= 0x3FFF;
+ return SetFileAttrib(path, attrib);
+}
+
+
bool RemoveDir(CFSTR path)
{
#ifndef _UNICODE
@@ -345,7 +354,7 @@ bool CreateComplexDir(CFSTR _path)
#endif
- FString path = _path;
+ FString path (_path);
int pos = path.ReverseFind_PathSepar();
if (pos >= 0 && (unsigned)pos == path.Len() - 1)
@@ -355,7 +364,7 @@ bool CreateComplexDir(CFSTR _path)
path.DeleteBack();
}
- const FString path2 = path;
+ const FString path2 (path);
pos = path.Len();
for (;;)
@@ -452,11 +461,11 @@ bool RemoveDirWithSubItems(const FString &path)
if (needRemoveSubItems)
{
- FString s = path;
+ FString s (path);
s.Add_PathSepar();
- unsigned prefixSize = s.Len();
- s += FCHAR_ANY_MASK;
- NFind::CEnumerator enumerator(s);
+ const unsigned prefixSize = s.Len();
+ NFind::CEnumerator enumerator;
+ enumerator.SetDirPrefix(s);
NFind::CFileInfo fi;
while (enumerator.Next(fi))
{
@@ -580,18 +589,18 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu
path = prefix;
if (addRandom)
{
- FChar s[16];
- UInt32 value = d;
+ char s[16];
+ UInt32 val = d;
unsigned k;
for (k = 0; k < 8; k++)
{
- unsigned t = value & 0xF;
- value >>= 4;
- s[k] = (FChar)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+ unsigned t = val & 0xF;
+ val >>= 4;
+ s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
}
s[k] = '\0';
if (outFile)
- path += FChar('.');
+ path += '.';
path += s;
UInt32 step = GetTickCount() + 2;
if (step == 0)
@@ -600,7 +609,7 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu
}
addRandom = true;
if (outFile)
- path += FTEXT(".tmp");
+ path += ".tmp";
if (NFind::DoesFileOrDirExist(path))
{
SetLastError(ERROR_ALREADY_EXISTS);
@@ -658,12 +667,27 @@ bool CTempFile::Remove()
bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore)
{
+ // DWORD attrib = 0;
if (deleteDestBefore)
+ {
if (NFind::DoesFileExist(name))
+ {
+ // attrib = NFind::GetFileAttrib(name);
if (!DeleteFileAlways(name))
return false;
+ }
+ }
DisableDeleting();
return MyMoveFile(_path, name);
+
+ /*
+ if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
+ {
+ DWORD attrib2 = NFind::GetFileAttrib(name);
+ if (attrib2 != INVALID_FILE_ATTRIBUTES)
+ SetFileAttrib(name, attrib2 | FILE_ATTRIBUTE_READONLY);
+ }
+ */
}
bool CTempDir::Create(CFSTR prefix)
diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h
index 35f6957..8d2b56a 100644
--- a/CPP/Windows/FileDir.h
+++ b/CPP/Windows/FileDir.h
@@ -15,7 +15,20 @@ bool GetWindowsDir(FString &path);
bool GetSystemDir(FString &path);
bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);
+
+
bool SetFileAttrib(CFSTR path, DWORD attrib);
+
+/*
+ Some programs store posix attributes in high 16 bits of windows attributes field.
+ Also some programs use additional flag markers: 0x8000 or 0x4000.
+ SetFileAttrib_PosixHighDetect() tries to detect posix field, and it extracts only attribute
+ bits that are related to current system only.
+*/
+
+bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib);
+
+
bool MyMoveFile(CFSTR existFileName, CFSTR newFileName);
#ifndef UNDER_CE
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp
index 2ab189d..8c6255b 100644
--- a/CPP/Windows/FileFind.cpp
+++ b/CPP/Windows/FileFind.cpp
@@ -227,7 +227,7 @@ bool CStreamInfo::IsMainStream() const throw()
UString CStreamInfo::GetReducedName() const
{
// remove ":$DATA" postfix, but keep postfix, if Name is "::$DATA"
- UString s = Name;
+ UString s (Name);
if (s.Len() > 6 + 1 && StringsAreEqualNoCase_Ascii(s.RightPtr(6), ":$DATA"))
s.DeleteFrom(s.Len() - 6);
return s;
@@ -453,7 +453,7 @@ bool CFileInfo::Find(CFSTR path)
if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0)
{
UString streamName = fs2us(path + (unsigned)colonPos);
- FString filePath = path;
+ FString filePath (path);
filePath.DeleteFrom(colonPos);
/* we allow both cases:
name:stream
@@ -462,7 +462,7 @@ bool CFileInfo::Find(CFSTR path)
const unsigned kPostfixSize = 6;
if (streamName.Len() <= kPostfixSize
|| !StringsAreEqualNoCase_Ascii(streamName.RightPtr(kPostfixSize), ":$DATA"))
- streamName += L":$DATA";
+ streamName += ":$DATA";
bool isOk = true;
@@ -559,9 +559,9 @@ bool CFileInfo::Find(CFSTR path)
{
if (NName::FindSepar(path + prefixSize) < 0)
{
- FString s = path;
+ FString s (path);
s.Add_PathSepar();
- s += FCHAR_ANY_MASK;
+ s += '*'; // CHAR_ANY_MASK
bool isOK = false;
if (finder.FindFirst(s, *this))
@@ -618,6 +618,12 @@ bool DoesFileOrDirExist(CFSTR name)
}
+void CEnumerator::SetDirPrefix(const FString &dirPrefix)
+{
+ _wildcard = dirPrefix;
+ _wildcard += '*';
+}
+
bool CEnumerator::NextAny(CFileInfo &fi)
{
if (_findFile.IsHandleAllocated())
diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h
index fc1f387..77d8dc3 100644
--- a/CPP/Windows/FileFind.h
+++ b/CPP/Windows/FileFind.h
@@ -134,7 +134,7 @@ class CEnumerator
bool NextAny(CFileInfo &fileInfo);
public:
- CEnumerator(const FString &wildcard): _wildcard(wildcard) {}
+ void SetDirPrefix(const FString &dirPrefix);
bool Next(CFileInfo &fileInfo);
bool Next(CFileInfo &fileInfo, bool &found);
};
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h
index af4785f..e31bc20 100644
--- a/CPP/Windows/FileIO.h
+++ b/CPP/Windows/FileIO.h
@@ -45,7 +45,11 @@ struct CReparseAttr
UString PrintName;
CReparseAttr(): Tag(0), Flags(0) {}
- bool Parse(const Byte *p, size_t size);
+
+ // Parse()
+ // returns true and (errorCode = 0), if (correct MOUNT_POINT or SYMLINK)
+ // returns false and (errorCode = ERROR_REPARSE_TAG_MISMATCH), if not (MOUNT_POINT or SYMLINK)
+ bool Parse(const Byte *p, size_t size, DWORD &errorCode);
bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction
bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; }
@@ -171,7 +175,12 @@ public:
bool OpenReparse(CFSTR fileName)
{
- return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING,
+ // 17.02 fix: to support Windows XP compatibility junctions:
+ // we use Create() with (desiredAccess = 0) instead of Open() with GENERIC_READ
+ return
+ Create(fileName, 0,
+ // Open(fileName,
+ FILE_SHARE_READ, OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS);
}
diff --git a/CPP/Windows/FileLink.cpp b/CPP/Windows/FileLink.cpp
index f4c7081..b5e47e7 100644
--- a/CPP/Windows/FileLink.cpp
+++ b/CPP/Windows/FileLink.cpp
@@ -74,7 +74,7 @@ static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31);
#define Set16(p, v) SetUi16(p, v)
#define Set32(p, v) SetUi32(p, v)
-static const wchar_t *k_LinkPrefix = L"\\??\\";
+static const wchar_t * const k_LinkPrefix = L"\\??\\";
static const unsigned k_LinkPrefix_Size = 4;
static const bool IsLinkPrefix(const wchar_t *s)
@@ -83,7 +83,7 @@ static const bool IsLinkPrefix(const wchar_t *s)
}
/*
-static const wchar_t *k_VolumePrefix = L"Volume{";
+static const wchar_t * const k_VolumePrefix = L"Volume{";
static const bool IsVolumeName(const wchar_t *s)
{
return IsString1PrefixedByString2(s, k_VolumePrefix);
@@ -194,8 +194,9 @@ static void GetString(const Byte *p, unsigned len, UString &res)
res.ReleaseBuf_SetLen(i);
}
-bool CReparseAttr::Parse(const Byte *p, size_t size)
+bool CReparseAttr::Parse(const Byte *p, size_t size, DWORD &errorCode)
{
+ errorCode = ERROR_INVALID_REPARSE_DATA;
if (size < 8)
return false;
Tag = Get32(p);
@@ -209,8 +210,10 @@ bool CReparseAttr::Parse(const Byte *p, size_t size)
*/
if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT &&
Tag != _my_IO_REPARSE_TAG_SYMLINK)
- // return true;
+ {
+ errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID
return false;
+ }
if (Get16(p + 6) != 0) // padding
return false;
@@ -247,6 +250,7 @@ bool CReparseAttr::Parse(const Byte *p, size_t size)
GetString(p + subOffs, subLen >> 1, SubsName);
GetString(p + printOffs, printLen >> 1, PrintName);
+ errorCode = 0;
return true;
}
@@ -332,7 +336,7 @@ bool CReparseAttr::IsVolume() const
UString CReparseAttr::GetPath() const
{
- UString s = SubsName;
+ UString s (SubsName);
if (IsLinkPrefix(s))
{
s.ReplaceOneCharAtPos(1, '\\');
@@ -376,7 +380,7 @@ bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMA
static bool CreatePrefixDirOfFile(CFSTR path)
{
- FString path2 = path;
+ FString path2 (path);
int pos = path2.ReverseFind_PathSepar();
if (pos < 0)
return true;
diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp
index 773b834..2a227dc 100644
--- a/CPP/Windows/FileName.cpp
+++ b/CPP/Windows/FileName.cpp
@@ -87,8 +87,8 @@ bool IsAltPathPrefix(CFSTR s) throw()
#if defined(_WIN32) && !defined(UNDER_CE)
-const wchar_t *kSuperPathPrefix = L"\\\\?\\";
-static const wchar_t *kSuperUncPrefix = L"\\\\?\\UNC\\";
+const char * const kSuperPathPrefix = "\\\\?\\";
+static const char * const kSuperUncPrefix = "\\\\?\\UNC\\";
#define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3]))
#define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3]))
@@ -109,7 +109,7 @@ bool IsDevicePath(CFSTR s) throw()
/*
// actually we don't know the way to open device file in WinCE.
unsigned len = MyStringLen(s);
- if (len < 5 || len > 5 || memcmp(s, FTEXT("DSK"), 3 * sizeof(FChar)) != 0)
+ if (len < 5 || len > 5 || !IsString1PrefixedByString2(s, "DSK"))
return false;
if (s[4] != ':')
return false;
@@ -123,7 +123,7 @@ bool IsDevicePath(CFSTR s) throw()
unsigned len = MyStringLen(s);
if (len == 6 && s[5] == ':')
return true;
- if (len < 18 || len > 22 || memcmp(s + kDevicePathPrefixSize, FTEXT("PhysicalDrive"), 13 * sizeof(FChar)) != 0)
+ if (len < 18 || len > 22 || !IsString1PrefixedByString2(s + kDevicePathPrefixSize, "PhysicalDrive"))
return false;
for (unsigned i = 17; i < len; i++)
if (s[i] < '0' || s[i] > '9')
@@ -191,14 +191,12 @@ bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }
bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
#endif // USE_UNICODE_FSTRING
-/*
-bool IsDrivePath_SuperAllowed(CFSTR s)
+bool IsDrivePath_SuperAllowed(CFSTR s) throw()
{
if (IsSuperPath(s))
s += kSuperPathPrefixSize;
return IsDrivePath(s);
}
-*/
bool IsDriveRootPath_SuperAllowed(CFSTR s) throw()
{
@@ -212,7 +210,7 @@ bool IsAbsolutePath(const wchar_t *s) throw()
return IS_SEPAR(s[0]) || IsDrivePath2(s);
}
-int FindAltStreamColon(CFSTR path)
+int FindAltStreamColon(CFSTR path) throw()
{
unsigned i = 0;
if (IsDrivePath2(path))
@@ -274,7 +272,7 @@ static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s)
return kSuperPathPrefixSize + pos + 1;
}
-unsigned GetRootPrefixSize(CFSTR s)
+unsigned GetRootPrefixSize(CFSTR s) throw()
{
if (IS_DEVICE_PATH(s))
return kDevicePathPrefixSize;
@@ -285,7 +283,7 @@ unsigned GetRootPrefixSize(CFSTR s)
#endif // USE_UNICODE_FSTRING
-static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s)
+static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw()
{
// Network path: we look "server\path\" as root prefix
int pos = FindSepar(s);
@@ -297,7 +295,7 @@ static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s)
return pos + pos2 + 2;
}
-static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s)
+static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw()
{
if (IsDrivePath(s))
return kDrivePrefixSize;
@@ -309,7 +307,7 @@ static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s)
return (size == 0) ? 0 : 2 + size;
}
-static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s)
+static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()
{
if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
{
@@ -628,7 +626,7 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
unsigned fixedSizeStart = 0;
unsigned fixedSize = 0;
- const wchar_t *superMarker = NULL;
+ const char *superMarker = NULL;
if (IsSuperPath(curDir))
{
fixedSize = GetRootPrefixSize_Of_SuperPath(curDir);
diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h
index e2720ff..1e47098 100644
--- a/CPP/Windows/FileName.h
+++ b/CPP/Windows/FileName.h
@@ -23,7 +23,7 @@ bool IsAltPathPrefix(CFSTR s) throw(); /* name: */
#if defined(_WIN32) && !defined(UNDER_CE)
-extern const wchar_t *kSuperPathPrefix; /* \\?\ */
+extern const char * const kSuperPathPrefix; /* \\?\ */
const unsigned kDevicePathPrefixSize = 4;
const unsigned kSuperPathPrefixSize = 4;
const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4;
@@ -42,7 +42,7 @@ unsigned GetNetworkServerPrefixSize(CFSTR s) throw();
bool IsNetworkShareRootPath(CFSTR s) throw(); /* \\?\UNC\SERVER\share or \\SERVER\share or with slash */
-// bool IsDrivePath_SuperAllowed(CFSTR s) throw(); // first chars are drive chars like "a:\" or "\\?\a:\"
+bool IsDrivePath_SuperAllowed(CFSTR s) throw(); // first chars are drive chars like "a:\" or "\\?\a:\"
bool IsDriveRootPath_SuperAllowed(CFSTR s) throw(); // exact drive root path "a:\" or "\\?\a:\"
bool IsDrivePath2(const wchar_t *s) throw(); // first 2 chars are drive chars like "a:"
@@ -71,7 +71,7 @@ unsigned GetRootPrefixSize(CFSTR s) throw();
#endif
-int FindAltStreamColon(CFSTR path);
+int FindAltStreamColon(CFSTR path) throw();
#endif // _WIN32
diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp
index 7a2cfd5..3cd82e5 100644
--- a/CPP/Windows/MemoryLock.cpp
+++ b/CPP/Windows/MemoryLock.cpp
@@ -67,6 +67,31 @@ bool EnablePrivilege(LPCTSTR privilegeName, bool enable)
return res;
}
+
+
+typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
+
+/*
+ We suppose that Window 10 works incorrectly with "Large Pages" at:
+ - Windows 10 1703 (15063)
+ - Windows 10 1709 (16299)
+*/
+
+unsigned Get_LargePages_RiskLevel()
+{
+ OSVERSIONINFOEXW vi;
+ HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
+ if (!ntdll)
+ return 0;
+ Func_RtlGetVersion func = (Func_RtlGetVersion)GetProcAddress(ntdll, "RtlGetVersion");
+ if (!func)
+ return 0;
+ func(&vi);
+ return (vi.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && vi.dwMajorVersion + vi.dwMinorVersion == 10
+ && vi.dwBuildNumber <= 16299) ? 1 : 0;
+}
+
#endif
}}
diff --git a/CPP/Windows/MemoryLock.h b/CPP/Windows/MemoryLock.h
index 1336fe5..d82910f 100644
--- a/CPP/Windows/MemoryLock.h
+++ b/CPP/Windows/MemoryLock.h
@@ -31,6 +31,8 @@ inline void EnablePrivilege_SymLink()
// Do we need to set SE_BACKUP_NAME ?
}
+unsigned Get_LargePages_RiskLevel();
+
#endif
}}
diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
index 6b3f20b..6d9fb48 100644
--- a/CPP/Windows/PropVariant.cpp
+++ b/CPP/Windows/PropVariant.cpp
@@ -91,7 +91,7 @@ CPropVariant& CPropVariant::operator=(BSTR bstrSrc)
return *this;
}
-static const char *kMemException = "out of memory";
+static const char * const kMemException = "out of memory";
CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
{
diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h
index 0304565..f2eaba2 100644
--- a/CPP/Windows/PropVariant.h
+++ b/CPP/Windows/PropVariant.h
@@ -80,6 +80,8 @@ public:
CPropVariant& operator=(const UString &s);
CPropVariant& operator=(const UString2 &s);
CPropVariant& operator=(const char *s);
+ CPropVariant& operator=(const AString &s)
+ { return (*this)=(const char *)s; }
CPropVariant& operator=(bool bSrc) throw();
CPropVariant& operator=(Byte value) throw();
diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp
index 1501a49..c5ac212 100644
--- a/CPP/Windows/PropVariantConv.cpp
+++ b/CPP/Windows/PropVariantConv.cpp
@@ -9,21 +9,24 @@
#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; }
-bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) throw()
+bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw()
{
+ *s = 0;
+ FILETIME ft;
+ if (!FileTimeToLocalFileTime(&utc, &ft))
+ return false;
+
SYSTEMTIME st;
if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))
- {
- *s = 0;
return false;
- }
- unsigned val = st.wYear;
- if (val >= 10000)
- {
- *s++ = (char)('0' + val / 10000);
- val %= 10000;
- }
+
{
+ unsigned val = st.wYear;
+ if (val >= 10000)
+ {
+ *s++ = (char)('0' + val / 10000);
+ val %= 10000;
+ }
s[3] = (char)('0' + val % 10); val /= 10;
s[2] = (char)('0' + val % 10); val /= 10;
s[1] = (char)('0' + val % 10);
@@ -32,40 +35,66 @@ bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool
}
UINT_TO_STR_2('-', st.wMonth);
UINT_TO_STR_2('-', st.wDay);
- if (includeTime)
+
+ if (level > kTimestampPrintLevel_DAY)
{
UINT_TO_STR_2(' ', st.wHour);
UINT_TO_STR_2(':', st.wMinute);
- if (includeSeconds)
+
+ if (level >= kTimestampPrintLevel_SEC)
{
UINT_TO_STR_2(':', st.wSecond);
- /*
- *s++ = '.';
- unsigned val = st.wMilliseconds;
- s[2] = (char)('0' + val % 10); val /= 10;
- s[1] = (char)('0' + val % 10);
- s[0] = (char)('0' + val / 10);
- s += 3;
- */
+
+ if (level > kTimestampPrintLevel_SEC)
+ {
+ *s++ = '.';
+ /*
+ {
+ unsigned val = st.wMilliseconds;
+ s[2] = (char)('0' + val % 10); val /= 10;
+ s[1] = (char)('0' + val % 10);
+ s[0] = (char)('0' + val / 10);
+ s += 3;
+ }
+ *s++ = ' ';
+ */
+
+ {
+ unsigned numDigits = 7;
+ UInt32 val = (UInt32)((((UInt64)ft.dwHighDateTime << 32) + ft.dwLowDateTime) % 10000000);
+ for (unsigned i = numDigits; i != 0;)
+ {
+ i--;
+ s[i] = (char)('0' + val % 10); val /= 10;
+ }
+ if (numDigits > (unsigned)level)
+ numDigits = (unsigned)level;
+ s += numDigits;
+ }
+ }
}
}
+
*s = 0;
return true;
}
-void ConvertFileTimeToString(const FILETIME &ft, wchar_t *dest, bool includeTime, bool includeSeconds) throw()
+
+bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw()
{
char s[32];
- ConvertFileTimeToString(ft, s, includeTime, includeSeconds);
+ bool res = ConvertUtcFileTimeToString(ft, s, level);
for (unsigned i = 0;; i++)
{
unsigned char c = s[i];
dest[i] = c;
if (c == 0)
- return;
+ break;
}
+ return res;
}
+
void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw()
{
*dest = 0;
@@ -77,7 +106,7 @@ void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw(
case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
- case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return;
+ case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return;
// case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
@@ -98,7 +127,7 @@ void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) thr
case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
- case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return;
+ case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return;
// case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
diff --git a/CPP/Windows/PropVariantConv.h b/CPP/Windows/PropVariantConv.h
index 3e8297d..3e24569 100644
--- a/CPP/Windows/PropVariantConv.h
+++ b/CPP/Windows/PropVariantConv.h
@@ -6,8 +6,15 @@
#include "../Common/MyTypes.h"
// provide at least 32 bytes for buffer including zero-end
-bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true) throw();
-void ConvertFileTimeToString(const FILETIME &ft, wchar_t *s, bool includeTime = true, bool includeSeconds = true) throw();
+
+#define kTimestampPrintLevel_DAY -3
+// #define kTimestampPrintLevel_HOUR -2
+#define kTimestampPrintLevel_MIN -1
+#define kTimestampPrintLevel_SEC 0
+#define kTimestampPrintLevel_NTFS 7
+
+bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw();
+bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw();
// provide at least 32 bytes for buffer including zero-end
// don't send VT_BSTR to these functions
diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp
index 71ca17f..0146621 100644
--- a/CPP/Windows/Registry.cpp
+++ b/CPP/Windows/Registry.cpp
@@ -152,7 +152,7 @@ LONG CKey::SetValue(LPCWSTR name, LPCWSTR value)
MYASSERT(value != NULL);
MYASSERT(_object != NULL);
if (g_IsNT)
- return RegSetValueExW(_object, name, NULL, REG_SZ,
+ return RegSetValueExW(_object, name, 0, REG_SZ,
(const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t)));
return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name),
value == 0 ? 0 : (LPCSTR)GetSystemString(value));
diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp
index b3df199..fde29ac 100644
--- a/CPP/Windows/Shell.cpp
+++ b/CPP/Windows/Shell.cpp
@@ -153,8 +153,8 @@ bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */,
MessageBoxW(0, L"yes", L"", 0);
*/
/*
- UString s = L"all files";
- s += L" (*.*)";
+ UString s = "all files";
+ s += " (*.*)";
return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true);
*/
return false;
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
index 5d894d1..c6f8275 100644
--- a/CPP/Windows/System.cpp
+++ b/CPP/Windows/System.cpp
@@ -11,12 +11,42 @@
namespace NWindows {
namespace NSystem {
+UInt32 CountAffinity(DWORD_PTR mask)
+{
+ UInt32 num = 0;
+ for (unsigned i = 0; i < sizeof(mask) * 8; i++)
+ num += (UInt32)((mask >> i) & 1);
+ return num;
+}
+
#ifdef _WIN32
+BOOL CProcessAffinity::Get()
+{
+ #ifndef UNDER_CE
+ return GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask);
+ #else
+ return FALSE;
+ #endif
+}
+
+
UInt32 GetNumberOfProcessors()
{
+ // We need to know how many threads we can use.
+ // By default the process is assigned to one group.
+ // So we get the number of logical processors (threads)
+ // assigned to current process in the current group.
+ // Group size can be smaller than total number logical processors, for exammple, 2x36
+
+ CProcessAffinity pa;
+
+ if (pa.Get() && pa.processAffinityMask != 0)
+ return pa.GetNumProcessThreads();
+
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
+ // the number of logical processors in the current group
return (UInt32)systemInfo.dwNumberOfProcessors;
}
diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h
index 845362f..bc28f47 100644
--- a/CPP/Windows/System.h
+++ b/CPP/Windows/System.h
@@ -8,6 +8,29 @@
namespace NWindows {
namespace NSystem {
+UInt32 CountAffinity(DWORD_PTR mask);
+
+struct CProcessAffinity
+{
+ // UInt32 numProcessThreads;
+ // UInt32 numSysThreads;
+ DWORD_PTR processAffinityMask;
+ DWORD_PTR systemAffinityMask;
+
+ void InitST()
+ {
+ // numProcessThreads = 1;
+ // numSysThreads = 1;
+ processAffinityMask = 1;
+ systemAffinityMask = 1;
+ }
+
+ UInt32 GetNumProcessThreads() const { return CountAffinity(processAffinityMask); }
+ UInt32 GetNumSystemThreads() const { return CountAffinity(systemAffinityMask); }
+
+ BOOL Get();
+};
+
UInt32 GetNumberOfProcessors();
bool GetRamSize(UInt64 &size); // returns false, if unknown ram size
diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp
index 32f3108..3fc02bc 100644
--- a/CPP/Windows/TimeUtils.cpp
+++ b/CPP/Windows/TimeUtils.cpp
@@ -115,16 +115,26 @@ bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw()
return true;
}
+UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw()
+{
+ return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond;
+}
+
void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw()
{
- UInt64 v = (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond;
+ UInt64 v = UnixTimeToFileTime64(unixTime);
ft.dwLowDateTime = (DWORD)v;
ft.dwHighDateTime = (DWORD)(v >> 32);
}
+UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw()
+{
+ return (UInt64)(kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond;
+}
+
bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw()
{
- if (unixTime > kNumSecondsInFileTime - kUnixTimeOffset)
+ if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset))
{
ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1;
return false;
@@ -144,7 +154,7 @@ bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw()
Int64 FileTimeToUnixTime64(const FILETIME &ft) throw()
{
UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
- return (Int64)(winTime / kNumTimeQuantumsInSecond) - kUnixTimeOffset;
+ return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset;
}
bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw()
diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h
index 011d2f5..b0092f8 100644
--- a/CPP/Windows/TimeUtils.h
+++ b/CPP/Windows/TimeUtils.h
@@ -11,10 +11,18 @@ namespace NTime {
bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) throw();
bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) throw();
+
+// UInt32 Unix Time : for dates 1970-2106
+UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw();
void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) throw();
+
+// Int64 Unix Time : negative values for dates before 1970
+UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw();
bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime) throw();
+
bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw();
Int64 FileTimeToUnixTime64(const FILETIME &ft) throw();
+
bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,
unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw();
void GetCurUtcFileTime(FILETIME &ft) throw();
diff --git a/DOC/Methods.txt b/DOC/Methods.txt
index 3ca9057..11adcb0 100644
--- a/DOC/Methods.txt
+++ b/DOC/Methods.txt
@@ -1,8 +1,8 @@
7-Zip method IDs for 7z and xz archives
---------------------------------------
-Version: 16.03
-Date: 2016-09-27
+Version: 17.01
+Date: 2017-05-27
Each compression or crypto method in 7z is associated with unique binary value (ID).
The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes).
@@ -122,9 +122,17 @@ List of defined IDs
F7 - External codecs (that are not included to 7-Zip)
0x xx - reserved
- 10 xx - reserved (LZHAM)
- 11 xx - reserved (Zstd)
+ 10 xx - reserved (LZHAM)
+ 01 - LZHAM
+
+ 11 xx - reserved (Tino Reichardt)
+ 01 - ZSTD
+ 02 - BROTLI
+ 04 - LZ4
+ 05 - LZ5
+ 06 - LIZARD
+
06.. - Crypto
diff --git a/DOC/lzma-history.txt b/DOC/lzma-history.txt
index 603a9e8..c53e3bd 100644
--- a/DOC/lzma-history.txt
+++ b/DOC/lzma-history.txt
@@ -1,6 +1,67 @@
HISTORY of the LZMA SDK
-----------------------
+18.05 2018-04-30
+-------------------------
+- The speed for LZMA/LZMA2 compressing was increased
+ by 8% for fastest/fast compression levels and
+ by 3% for normal/maximum compression levels.
+- Previous versions of 7-Zip could work incorrectly in "Large memory pages" mode in
+ Windows 10 because of some BUG with "Large Pages" in Windows 10.
+ Now 7-Zip doesn't use "Large Pages" on Windows 10 up to revision 1709 (16299).
+- The BUG was fixed in Lzma2Enc.c
+ Lzma2Enc_Encode2() function worked incorretly,
+ if (inStream == NULL) and the number of block threads is more than 1.
+
+
+18.03 beta 2018-03-04
+-------------------------
+- Asm\x86\LzmaDecOpt.asm: new optimized LZMA decoder written in asm
+ for x64 with about 30% higher speed than main version of LZMA decoder written in C.
+- The speed for single-thread LZMA/LZMA2 decoder written in C was increased by 3%.
+- 7-Zip now can use multi-threading for 7z/LZMA2 decoding,
+ if there are multiple independent data chunks in LZMA2 stream.
+- 7-Zip now can use multi-threading for xz decoding,
+ if there are multiple blocks in xz stream.
+
+
+18.01 2019-01-28
+-------------------------
+- The BUG in 17.01 - 18.00 beta was fixed:
+ XzDec.c : random block unpacking and XzUnpacker_IsBlockFinished()
+ didn't work correctly for xz archives without checksum (CRC).
+
+
+18.00 beta 2019-01-10
+-------------------------
+- The BUG in xz encoder was fixed:
+ There was memory leak of 16 KB for each file compressed with
+ xz compression method, if additional filter was used.
+
+
+17.01 beta 2017-08-28
+-------------------------
+- Minor speed optimization for LZMA2 (xz and 7z) multi-threading compression.
+ 7-Zip now uses additional memory buffers for multi-block LZMA2 compression.
+ CPU utilization was slightly improved.
+- 7-zip now creates multi-block xz archives by default. Block size can be
+ specified with -ms[Size]{m|g} switch.
+- xz decoder now can unpack random block from multi-block xz archives.
+- 7-Zip command line: @listfile now doesn't work after -- switch.
+ Use -i@listfile before -- switch instead.
+- The BUGs were fixed:
+ 7-Zip 17.00 beta crashed for commands that write anti-item to 7z archive.
+
+
+17.00 beta 2017-04-29
+-------------------------
+- NewHandler.h / NewHandler.cpp:
+ now it redefines operator new() only for old MSVC compilers (_MSC_VER < 1900).
+- C/7zTypes.h : the names of variables in interface structures were changed (vt).
+- Some bugs were fixed. 7-Zip could crash in some cases.
+- Some internal changes in code.
+
+
16.04 2016-10-04
-------------------------
- The bug was fixed in DllSecur.c.
diff --git a/DOC/lzma-sdk.txt b/DOC/lzma-sdk.txt
index 86fef24..01521e9 100644
--- a/DOC/lzma-sdk.txt
+++ b/DOC/lzma-sdk.txt
@@ -1,4 +1,4 @@
-LZMA SDK 16.04
+LZMA SDK 18.05
--------------
LZMA SDK provides the documentation, samples, header files,
diff --git a/DOC/lzma.txt b/DOC/lzma.txt
index f9a80ae..1f92142 100644
--- a/DOC/lzma.txt
+++ b/DOC/lzma.txt
@@ -33,7 +33,7 @@ If you want to use old interfaces you can download previous version of LZMA SDK
from sourceforge.net site.
To use ANSI-C LZMA Decoder you need the following files:
-1) LzmaDec.h + LzmaDec.c + Types.h
+1) LzmaDec.h + LzmaDec.c + 7zTypes.h + Precomp.h + Compiler.h
Look example code:
C/Util/Lzma/LzmaUtil.c
@@ -70,7 +70,7 @@ You can use p = p; operator to disable compiler warnings.
Single-call Decompressing
-------------------------
When to use: RAM->RAM decompressing
-Compile files: LzmaDec.h + LzmaDec.c + Types.h
+Compile files: LzmaDec.h + LzmaDec.c + 7zTypes.h
Compile defines: no defines
Memory Requirements:
- Input buffer: compressed size
@@ -124,7 +124,7 @@ Multi-call State Decompressing (zlib-like interface)
----------------------------------------------------
When to use: file->file decompressing
-Compile files: LzmaDec.h + LzmaDec.c + Types.h
+Compile files: LzmaDec.h + LzmaDec.c + 7zTypes.h
Memory Requirements:
- Buffer for input stream: any size (for example, 16 KB)
@@ -167,7 +167,7 @@ How To compress data
--------------------
Compile files:
- Types.h
+ 7zTypes.h
Threads.h
LzmaEnc.h
LzmaEnc.c