aboutsummaryrefslogtreecommitdiff
path: root/C
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--C/7zArcIn.c6
-rw-r--r--C/7zCrc.c508
-rw-r--r--C/7zCrc.h5
-rw-r--r--C/7zCrcOpt.c244
-rw-r--r--C/7zDec.c46
-rw-r--r--C/7zTypes.h14
-rw-r--r--C/7zVersion.h10
-rw-r--r--C/7zip_gcc_c.mak4
-rw-r--r--C/Aes.c56
-rw-r--r--C/AesOpt.c225
-rw-r--r--C/Alloc.c174
-rw-r--r--C/Alloc.h15
-rw-r--r--C/Asm_c.mak12
-rw-r--r--C/Blake2.h111
-rw-r--r--C/Blake2s.c2693
-rw-r--r--C/Bra.c325
-rw-r--r--C/Bra.h36
-rw-r--r--C/Compiler.h91
-rw-r--r--C/CpuArch.c94
-rw-r--r--C/CpuArch.h144
-rw-r--r--C/DllSecur.c18
-rw-r--r--C/HuffEnc.c4
-rw-r--r--C/LzFind.c127
-rw-r--r--C/LzFind.h5
-rw-r--r--C/LzFindMt.c58
-rw-r--r--C/LzFindMt.h9
-rw-r--r--C/Lzma2Dec.c6
-rw-r--r--C/LzmaEnc.c26
-rw-r--r--C/MtCoder.c8
-rw-r--r--C/MtDec.c18
-rw-r--r--C/Ppmd7.c33
-rw-r--r--C/Ppmd7Dec.c24
-rw-r--r--C/Ppmd7Enc.c17
-rw-r--r--C/Ppmd7aDec.c24
-rw-r--r--C/Ppmd8.c33
-rw-r--r--C/Ppmd8Dec.c22
-rw-r--r--C/Ppmd8Enc.c17
-rw-r--r--C/Precomp.h123
-rw-r--r--C/Sha1.c52
-rw-r--r--C/Sha1Opt.c132
-rw-r--r--C/Sha256.c52
-rw-r--r--C/Sha256Opt.c127
-rw-r--r--C/SwapBytes.c63
-rw-r--r--C/Threads.c53
-rw-r--r--C/Threads.h20
-rw-r--r--C/Util/7z/7z.dsp8
-rw-r--r--C/Util/7z/7zMain.c45
-rw-r--r--C/Util/7z/Precomp.h13
-rw-r--r--C/Util/7z/makefile8
-rw-r--r--C/Util/7zipInstall/7zipInstall.c32
-rw-r--r--C/Util/7zipInstall/Precomp.h13
-rw-r--r--C/Util/7zipInstall/makefile9
-rw-r--r--C/Util/7zipInstall/resource.rc5
-rw-r--r--C/Util/7zipUninstall/7zipUninstall.c75
-rw-r--r--C/Util/7zipUninstall/Precomp.h13
-rw-r--r--C/Util/7zipUninstall/resource.rc5
-rw-r--r--C/Util/Lzma/Precomp.h13
-rw-r--r--C/Util/LzmaLib/Precomp.h13
-rw-r--r--C/Util/LzmaLib/makefile7
-rw-r--r--C/Util/SfxSetup/Precomp.h13
-rw-r--r--C/Util/SfxSetup/SfxSetup.c17
-rw-r--r--C/Util/SfxSetup/makefile8
-rw-r--r--C/Xxh64.c327
-rw-r--r--C/Xxh64.h50
-rw-r--r--C/Xz.c4
-rw-r--r--C/Xz.h7
-rw-r--r--C/XzCrc64.c122
-rw-r--r--C/XzCrc64.h8
-rw-r--r--C/XzCrc64Opt.c254
-rw-r--r--C/XzDec.c84
-rw-r--r--C/XzEnc.c60
-rw-r--r--C/XzIn.c10
-rw-r--r--C/ZstdDec.c4064
-rw-r--r--C/ZstdDec.h173
-rw-r--r--C/var_clang_arm64.mak1
-rw-r--r--CPP/7zip/7zip.mak8
-rw-r--r--CPP/7zip/7zip_gcc.mak77
-rw-r--r--CPP/7zip/Archive/7z/7zCompressionMode.h17
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.cpp14
-rw-r--r--CPP/7zip/Archive/7z/7zEncode.cpp34
-rw-r--r--CPP/7zip/Archive/7z/7zExtract.cpp5
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.cpp16
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.h6
-rw-r--r--CPP/7zip/Archive/7z/7zHandlerOut.cpp72
-rw-r--r--CPP/7zip/Archive/7z/7zHeader.h5
-rw-r--r--CPP/7zip/Archive/7z/7zIn.cpp45
-rw-r--r--CPP/7zip/Archive/7z/7zIn.h25
-rw-r--r--CPP/7zip/Archive/7z/7zItem.h2
-rw-r--r--CPP/7zip/Archive/7z/7zOut.cpp309
-rw-r--r--CPP/7zip/Archive/7z/7zOut.h52
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.cpp307
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.h23
-rw-r--r--CPP/7zip/Archive/ApfsHandler.cpp92
-rw-r--r--CPP/7zip/Archive/ApmHandler.cpp170
-rw-r--r--CPP/7zip/Archive/ArHandler.cpp49
-rw-r--r--CPP/7zip/Archive/ArjHandler.cpp221
-rw-r--r--CPP/7zip/Archive/AvbHandler.cpp596
-rw-r--r--CPP/7zip/Archive/Base64Handler.cpp31
-rw-r--r--CPP/7zip/Archive/Bz2Handler.cpp84
-rw-r--r--CPP/7zip/Archive/Cab/CabBlockInStream.cpp128
-rw-r--r--CPP/7zip/Archive/Cab/CabBlockInStream.h31
-rw-r--r--CPP/7zip/Archive/Cab/CabHandler.cpp235
-rw-r--r--CPP/7zip/Archive/Cab/CabIn.cpp33
-rw-r--r--CPP/7zip/Archive/Chm/ChmHandler.cpp106
-rw-r--r--CPP/7zip/Archive/Chm/ChmIn.cpp78
-rw-r--r--CPP/7zip/Archive/Chm/ChmIn.h10
-rw-r--r--CPP/7zip/Archive/ComHandler.cpp16
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2.cpp12
-rw-r--r--CPP/7zip/Archive/Common/FindSignature.cpp42
-rw-r--r--CPP/7zip/Archive/Common/InStreamWithCRC.h7
-rw-r--r--CPP/7zip/Archive/Common/MultiStream.h4
-rw-r--r--CPP/7zip/Archive/Common/OutStreamWithSha1.cpp11
-rw-r--r--CPP/7zip/Archive/Common/OutStreamWithSha1.h30
-rw-r--r--CPP/7zip/Archive/CpioHandler.cpp143
-rw-r--r--CPP/7zip/Archive/DmgHandler.cpp1841
-rw-r--r--CPP/7zip/Archive/ElfHandler.cpp94
-rw-r--r--CPP/7zip/Archive/ExtHandler.cpp49
-rw-r--r--CPP/7zip/Archive/FatHandler.cpp73
-rw-r--r--CPP/7zip/Archive/GptHandler.cpp127
-rw-r--r--CPP/7zip/Archive/GzHandler.cpp124
-rw-r--r--CPP/7zip/Archive/HandlerCont.cpp77
-rw-r--r--CPP/7zip/Archive/HandlerCont.h14
-rw-r--r--CPP/7zip/Archive/HfsHandler.cpp80
-rw-r--r--CPP/7zip/Archive/HfsHandler.h11
-rw-r--r--CPP/7zip/Archive/IArchive.h50
-rw-r--r--CPP/7zip/Archive/Icons/zst.icobin0 -> 3638 bytes
-rw-r--r--CPP/7zip/Archive/IhexHandler.cpp162
-rw-r--r--CPP/7zip/Archive/Iso/IsoHandler.cpp60
-rw-r--r--CPP/7zip/Archive/Iso/IsoIn.cpp54
-rw-r--r--CPP/7zip/Archive/Iso/IsoIn.h8
-rw-r--r--CPP/7zip/Archive/Iso/IsoItem.h4
-rw-r--r--CPP/7zip/Archive/LvmHandler.cpp1107
-rw-r--r--CPP/7zip/Archive/LzhHandler.cpp118
-rw-r--r--CPP/7zip/Archive/LzmaHandler.cpp87
-rw-r--r--CPP/7zip/Archive/MbrHandler.cpp136
-rw-r--r--CPP/7zip/Archive/MslzHandler.cpp29
-rw-r--r--CPP/7zip/Archive/Nsis/NsisHandler.cpp15
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.cpp10
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.h2
-rw-r--r--CPP/7zip/Archive/NtfsHandler.cpp208
-rw-r--r--CPP/7zip/Archive/PeHandler.cpp7
-rw-r--r--CPP/7zip/Archive/PpmdHandler.cpp20
-rw-r--r--CPP/7zip/Archive/Rar/Rar5Handler.cpp1414
-rw-r--r--CPP/7zip/Archive/Rar/Rar5Handler.h162
-rw-r--r--CPP/7zip/Archive/Rar/RarHandler.h5
-rw-r--r--CPP/7zip/Archive/RpmHandler.cpp38
-rw-r--r--CPP/7zip/Archive/SparseHandler.cpp9
-rw-r--r--CPP/7zip/Archive/SplitHandler.cpp2
-rw-r--r--CPP/7zip/Archive/SquashfsHandler.cpp204
-rw-r--r--CPP/7zip/Archive/SwfHandler.cpp38
-rw-r--r--CPP/7zip/Archive/Tar/TarHandler.cpp145
-rw-r--r--CPP/7zip/Archive/Tar/TarHandler.h3
-rw-r--r--CPP/7zip/Archive/Tar/TarHandlerOut.cpp4
-rw-r--r--CPP/7zip/Archive/Tar/TarIn.cpp20
-rw-r--r--CPP/7zip/Archive/Tar/TarIn.h2
-rw-r--r--CPP/7zip/Archive/Tar/TarItem.h4
-rw-r--r--CPP/7zip/Archive/Tar/TarOut.cpp2
-rw-r--r--CPP/7zip/Archive/Tar/TarUpdate.cpp48
-rw-r--r--CPP/7zip/Archive/Udf/UdfHandler.cpp49
-rw-r--r--CPP/7zip/Archive/Udf/UdfIn.cpp2
-rw-r--r--CPP/7zip/Archive/UefiHandler.cpp119
-rw-r--r--CPP/7zip/Archive/VhdHandler.cpp27
-rw-r--r--CPP/7zip/Archive/VhdxHandler.cpp38
-rw-r--r--CPP/7zip/Archive/VmdkHandler.cpp4
-rw-r--r--CPP/7zip/Archive/Wim/WimHandler.cpp30
-rw-r--r--CPP/7zip/Archive/Wim/WimHandler.h14
-rw-r--r--CPP/7zip/Archive/Wim/WimHandlerOut.cpp101
-rw-r--r--CPP/7zip/Archive/Wim/WimIn.cpp148
-rw-r--r--CPP/7zip/Archive/Wim/WimIn.h18
-rw-r--r--CPP/7zip/Archive/XarHandler.cpp1065
-rw-r--r--CPP/7zip/Archive/XzHandler.cpp107
-rw-r--r--CPP/7zip/Archive/ZHandler.cpp37
-rw-r--r--CPP/7zip/Archive/Zip/ZipAddCommon.cpp83
-rw-r--r--CPP/7zip/Archive/Zip/ZipAddCommon.h6
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandler.cpp201
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandlerOut.cpp26
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.cpp6
-rw-r--r--CPP/7zip/Archive/Zip/ZipItem.cpp14
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.cpp332
-rw-r--r--CPP/7zip/Archive/ZstdHandler.cpp1147
-rw-r--r--CPP/7zip/Asm.mak9
-rw-r--r--CPP/7zip/Bundles/Alone/Alone.dsp114
-rw-r--r--CPP/7zip/Bundles/Alone/makefile18
-rw-r--r--CPP/7zip/Bundles/Alone/makefile.gcc65
-rw-r--r--CPP/7zip/Bundles/Alone2/makefile2
-rw-r--r--CPP/7zip/Bundles/Alone2/makefile.gcc12
-rw-r--r--CPP/7zip/Bundles/Alone7z/Alone.dsp47
-rw-r--r--CPP/7zip/Bundles/Alone7z/makefile5
-rw-r--r--CPP/7zip/Bundles/Alone7z/makefile.gcc23
-rw-r--r--CPP/7zip/Bundles/Fm/FM.dsp24
-rw-r--r--CPP/7zip/Bundles/Fm/makefile2
-rw-r--r--CPP/7zip/Bundles/Format7z/makefile1
-rw-r--r--CPP/7zip/Bundles/Format7zF/Arc.mak5
-rw-r--r--CPP/7zip/Bundles/Format7zF/Arc_gcc.mak34
-rw-r--r--CPP/7zip/Bundles/Format7zF/Format7z.dsp68
-rw-r--r--CPP/7zip/Bundles/Format7zF/makefile2
-rw-r--r--CPP/7zip/Bundles/Format7zF/makefile.gcc8
-rw-r--r--CPP/7zip/Bundles/Format7zF/resource.rc3
-rw-r--r--CPP/7zip/Bundles/Format7zR/makefile1
-rw-r--r--CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp2
-rw-r--r--CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp4
-rw-r--r--CPP/7zip/Bundles/LzmaCon/makefile1
-rw-r--r--CPP/7zip/Bundles/LzmaCon/makefile.gcc19
-rw-r--r--CPP/7zip/Bundles/SFXCon/SFXCon.dsp12
-rw-r--r--CPP/7zip/Bundles/SFXCon/makefile3
-rw-r--r--CPP/7zip/Bundles/SFXCon/makefile.gcc6
-rw-r--r--CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp2
-rw-r--r--CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp14
-rw-r--r--CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp3
-rw-r--r--CPP/7zip/Bundles/SFXSetup/makefile3
-rw-r--r--CPP/7zip/Bundles/SFXWin/SFXWin.dsp14
-rw-r--r--CPP/7zip/Bundles/SFXWin/SfxWin.cpp30
-rw-r--r--CPP/7zip/Bundles/SFXWin/makefile3
-rw-r--r--CPP/7zip/Common/CWrappers.cpp4
-rw-r--r--CPP/7zip/Common/FilePathAutoRename.cpp10
-rw-r--r--CPP/7zip/Common/FileStreams.cpp129
-rw-r--r--CPP/7zip/Common/FileStreams.h29
-rw-r--r--CPP/7zip/Common/InBuffer.cpp18
-rw-r--r--CPP/7zip/Common/InBuffer.h2
-rw-r--r--CPP/7zip/Common/MemBlocks.cpp6
-rw-r--r--CPP/7zip/Common/MemBlocks.h6
-rw-r--r--CPP/7zip/Common/MethodProps.cpp2
-rw-r--r--CPP/7zip/Common/MultiOutStream.cpp34
-rw-r--r--CPP/7zip/Common/OutBuffer.h42
-rw-r--r--CPP/7zip/Common/OutMemStream.h2
-rw-r--r--CPP/7zip/Compress/BZip2Crc.cpp3
-rw-r--r--CPP/7zip/Compress/BZip2Decoder.cpp98
-rw-r--r--CPP/7zip/Compress/BZip2Decoder.h3
-rw-r--r--CPP/7zip/Compress/Bcj2Coder.cpp18
-rw-r--r--CPP/7zip/Compress/BitlDecoder.cpp21
-rw-r--r--CPP/7zip/Compress/BitlDecoder.h65
-rw-r--r--CPP/7zip/Compress/BitmDecoder.h6
-rw-r--r--CPP/7zip/Compress/BranchMisc.cpp18
-rw-r--r--CPP/7zip/Compress/BranchMisc.h14
-rw-r--r--CPP/7zip/Compress/BranchRegister.cpp39
-rw-r--r--CPP/7zip/Compress/DeflateDecoder.cpp117
-rw-r--r--CPP/7zip/Compress/DeflateDecoder.h29
-rw-r--r--CPP/7zip/Compress/DeflateEncoder.cpp8
-rw-r--r--CPP/7zip/Compress/DeltaFilter.cpp6
-rw-r--r--CPP/7zip/Compress/HuffmanDecoder.h581
-rw-r--r--CPP/7zip/Compress/ImplodeDecoder.cpp66
-rw-r--r--CPP/7zip/Compress/ImplodeDecoder.h8
-rw-r--r--CPP/7zip/Compress/LzfseDecoder.cpp26
-rw-r--r--CPP/7zip/Compress/LzhDecoder.cpp104
-rw-r--r--CPP/7zip/Compress/LzhDecoder.h33
-rw-r--r--CPP/7zip/Compress/LzmaDecoder.cpp1
-rw-r--r--CPP/7zip/Compress/LzmsDecoder.cpp71
-rw-r--r--CPP/7zip/Compress/LzmsDecoder.h72
-rw-r--r--CPP/7zip/Compress/Lzx.h4
-rw-r--r--CPP/7zip/Compress/LzxDecoder.cpp1576
-rw-r--r--CPP/7zip/Compress/LzxDecoder.h249
-rw-r--r--CPP/7zip/Compress/PpmdDecoder.cpp1
-rw-r--r--CPP/7zip/Compress/PpmdZip.cpp17
-rw-r--r--CPP/7zip/Compress/PpmdZip.h11
-rw-r--r--CPP/7zip/Compress/QuantumDecoder.cpp372
-rw-r--r--CPP/7zip/Compress/QuantumDecoder.h143
-rw-r--r--CPP/7zip/Compress/Rar1Decoder.h11
-rw-r--r--CPP/7zip/Compress/Rar2Decoder.cpp155
-rw-r--r--CPP/7zip/Compress/Rar2Decoder.h103
-rw-r--r--CPP/7zip/Compress/Rar3Decoder.cpp38
-rw-r--r--CPP/7zip/Compress/Rar3Decoder.h66
-rw-r--r--CPP/7zip/Compress/Rar3Vm.cpp6
-rw-r--r--CPP/7zip/Compress/Rar5Decoder.cpp2059
-rw-r--r--CPP/7zip/Compress/Rar5Decoder.h251
-rw-r--r--CPP/7zip/Compress/XpressDecoder.cpp388
-rw-r--r--CPP/7zip/Compress/XpressDecoder.h7
-rw-r--r--CPP/7zip/Compress/XzDecoder.cpp1
-rw-r--r--CPP/7zip/Compress/XzEncoder.cpp2
-rw-r--r--CPP/7zip/Compress/ZDecoder.cpp32
-rw-r--r--CPP/7zip/Compress/ZDecoder.h12
-rw-r--r--CPP/7zip/Compress/ZlibDecoder.cpp111
-rw-r--r--CPP/7zip/Compress/ZlibDecoder.h21
-rw-r--r--CPP/7zip/Compress/ZstdDecoder.cpp437
-rw-r--r--CPP/7zip/Compress/ZstdDecoder.h98
-rw-r--r--CPP/7zip/Crc.mak2
-rw-r--r--CPP/7zip/Crc64.mak2
-rw-r--r--CPP/7zip/Crypto/7zAes.cpp16
-rw-r--r--CPP/7zip/Crypto/MyAes.cpp28
-rw-r--r--CPP/7zip/GuiCommon.rc41
-rw-r--r--CPP/7zip/Guid.txt4
-rw-r--r--CPP/7zip/IDecl.h2
-rw-r--r--CPP/7zip/IStream.h47
-rw-r--r--CPP/7zip/LzmaDec.mak2
-rw-r--r--CPP/7zip/UI/Agent/Agent.cpp10
-rw-r--r--CPP/7zip/UI/Agent/AgentOut.cpp81
-rw-r--r--CPP/7zip/UI/Agent/AgentProxy.cpp16
-rw-r--r--CPP/7zip/UI/Client7z/Client7z.cpp45
-rw-r--r--CPP/7zip/UI/Client7z/Client7z.dsp4
-rw-r--r--CPP/7zip/UI/Client7z/makefile1
-rw-r--r--CPP/7zip/UI/Common/ArchiveCommandLine.cpp134
-rw-r--r--CPP/7zip/UI/Common/ArchiveCommandLine.h7
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.cpp177
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.h39
-rw-r--r--CPP/7zip/UI/Common/ArchiveName.cpp4
-rw-r--r--CPP/7zip/UI/Common/ArchiveOpenCallback.cpp17
-rw-r--r--CPP/7zip/UI/Common/ArchiveOpenCallback.h1
-rw-r--r--CPP/7zip/UI/Common/Bench.cpp188
-rw-r--r--CPP/7zip/UI/Common/CompressCall.cpp8
-rw-r--r--CPP/7zip/UI/Common/CompressCall2.cpp2
-rw-r--r--CPP/7zip/UI/Common/DirItem.h3
-rw-r--r--CPP/7zip/UI/Common/EnumDirItems.cpp4
-rw-r--r--CPP/7zip/UI/Common/Extract.cpp21
-rw-r--r--CPP/7zip/UI/Common/Extract.h3
-rw-r--r--CPP/7zip/UI/Common/HashCalc.cpp164
-rw-r--r--CPP/7zip/UI/Common/HashCalc.h13
-rw-r--r--CPP/7zip/UI/Common/LoadCodecs.cpp4
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.cpp21
-rw-r--r--CPP/7zip/UI/Common/PropIDUtils.cpp89
-rw-r--r--CPP/7zip/UI/Common/PropIDUtils.h6
-rw-r--r--CPP/7zip/UI/Common/SetProperties.cpp2
-rw-r--r--CPP/7zip/UI/Common/Update.cpp26
-rw-r--r--CPP/7zip/UI/Common/UpdateCallback.cpp25
-rw-r--r--CPP/7zip/UI/Common/UpdateProduce.cpp4
-rw-r--r--CPP/7zip/UI/Common/ZipRegistry.cpp22
-rw-r--r--CPP/7zip/UI/Common/ZipRegistry.h3
-rw-r--r--CPP/7zip/UI/Console/Console.dsp12
-rw-r--r--CPP/7zip/UI/Console/Console.mak3
-rw-r--r--CPP/7zip/UI/Console/ExtractCallbackConsole.cpp116
-rw-r--r--CPP/7zip/UI/Console/ExtractCallbackConsole.h31
-rw-r--r--CPP/7zip/UI/Console/HashCon.cpp2
-rw-r--r--CPP/7zip/UI/Console/List.cpp123
-rw-r--r--CPP/7zip/UI/Console/Main.cpp95
-rw-r--r--CPP/7zip/UI/Console/MainAr.cpp3
-rw-r--r--CPP/7zip/UI/Console/PercentPrinter.cpp4
-rw-r--r--CPP/7zip/UI/Console/UpdateCallbackConsole.cpp12
-rw-r--r--CPP/7zip/UI/Console/UserInputUtils.cpp1
-rw-r--r--CPP/7zip/UI/Console/makefile.gcc11
-rw-r--r--CPP/7zip/UI/Explorer/ContextMenu.cpp16
-rw-r--r--CPP/7zip/UI/Explorer/ContextMenu.h2
-rw-r--r--CPP/7zip/UI/Explorer/DllExportsExplorer.cpp4
-rw-r--r--CPP/7zip/UI/Explorer/Explorer.dsp8
-rw-r--r--CPP/7zip/UI/Explorer/MyExplorerCommand.h2
-rw-r--r--CPP/7zip/UI/Explorer/MyMessages.cpp9
-rw-r--r--CPP/7zip/UI/Explorer/RegistryContextMenu.cpp36
-rw-r--r--CPP/7zip/UI/Explorer/makefile4
-rw-r--r--CPP/7zip/UI/Far/Far.cpp6
-rw-r--r--CPP/7zip/UI/Far/FarPlugin.h22
-rw-r--r--CPP/7zip/UI/Far/FarUtils.cpp14
-rw-r--r--CPP/7zip/UI/Far/FarUtils.h10
-rw-r--r--CPP/7zip/UI/Far/OverwriteDialogFar.cpp2
-rw-r--r--CPP/7zip/UI/Far/Plugin.cpp34
-rw-r--r--CPP/7zip/UI/Far/Plugin.h2
-rw-r--r--CPP/7zip/UI/Far/PluginWrite.cpp5
-rw-r--r--CPP/7zip/UI/Far/makefile3
-rw-r--r--CPP/7zip/UI/FileManager/AltStreamsFolder.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/App.cpp1
-rw-r--r--CPP/7zip/UI/FileManager/App.h12
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog.cpp58
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog2.cpp1834
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog2.h10
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog2.rc32
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog2Res.h9
-rw-r--r--CPP/7zip/UI/FileManager/EditPage.rc4
-rw-r--r--CPP/7zip/UI/FileManager/ExtractCallback.cpp176
-rw-r--r--CPP/7zip/UI/FileManager/ExtractCallback.h133
-rw-r--r--CPP/7zip/UI/FileManager/FM.cpp108
-rw-r--r--CPP/7zip/UI/FileManager/FM.dsp32
-rw-r--r--CPP/7zip/UI/FileManager/FM.mak5
-rw-r--r--CPP/7zip/UI/FileManager/FSDrives.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/FSFolder.cpp14
-rw-r--r--CPP/7zip/UI/FileManager/FSFolderCopy.cpp65
-rw-r--r--CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/FoldersPage.rc2
-rw-r--r--CPP/7zip/UI/FileManager/FoldersPage2.rc13
-rw-r--r--CPP/7zip/UI/FileManager/LangPage.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/LangPage.rc6
-rw-r--r--CPP/7zip/UI/FileManager/LangUtils.cpp23
-rw-r--r--CPP/7zip/UI/FileManager/MemDialog.cpp218
-rw-r--r--CPP/7zip/UI/FileManager/MemDialog.h48
-rw-r--r--CPP/7zip/UI/FileManager/MemDialog.rc49
-rw-r--r--CPP/7zip/UI/FileManager/MemDialogRes.h13
-rw-r--r--CPP/7zip/UI/FileManager/MenuPage.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/MenuPage.rc4
-rw-r--r--CPP/7zip/UI/FileManager/MenuPage2.rc12
-rw-r--r--CPP/7zip/UI/FileManager/MyCom2.h11
-rw-r--r--CPP/7zip/UI/FileManager/MyLoadMenu.cpp48
-rw-r--r--CPP/7zip/UI/FileManager/OverwriteDialog.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/Panel.cpp13
-rw-r--r--CPP/7zip/UI/FileManager/Panel.h5
-rw-r--r--CPP/7zip/UI/FileManager/PanelCopy.cpp6
-rw-r--r--CPP/7zip/UI/FileManager/PanelFolderChange.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/PanelItemOpen.cpp134
-rw-r--r--CPP/7zip/UI/FileManager/PanelItems.cpp19
-rw-r--r--CPP/7zip/UI/FileManager/PanelListNotify.cpp90
-rw-r--r--CPP/7zip/UI/FileManager/PanelMenu.cpp36
-rw-r--r--CPP/7zip/UI/FileManager/PanelOperations.cpp20
-rw-r--r--CPP/7zip/UI/FileManager/PanelSplitFile.cpp8
-rw-r--r--CPP/7zip/UI/FileManager/PasswordDialog.rc4
-rw-r--r--CPP/7zip/UI/FileManager/PluginLoader.h4
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.cpp11
-rw-r--r--CPP/7zip/UI/FileManager/RegistryAssociations.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/RootFolder.cpp22
-rw-r--r--CPP/7zip/UI/FileManager/SettingsPage.cpp121
-rw-r--r--CPP/7zip/UI/FileManager/SettingsPage.h8
-rw-r--r--CPP/7zip/UI/FileManager/SettingsPage.rc4
-rw-r--r--CPP/7zip/UI/FileManager/SettingsPage2.rc36
-rw-r--r--CPP/7zip/UI/FileManager/SettingsPageRes.h6
-rw-r--r--CPP/7zip/UI/FileManager/StdAfx.h16
-rw-r--r--CPP/7zip/UI/FileManager/SysIconUtils.cpp1
-rw-r--r--CPP/7zip/UI/FileManager/SystemPage.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/SystemPage.rc12
-rw-r--r--CPP/7zip/UI/FileManager/TextPairs.cpp6
-rw-r--r--CPP/7zip/UI/FileManager/VerCtrl.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/makefile2
-rw-r--r--CPP/7zip/UI/FileManager/resource.h4
-rw-r--r--CPP/7zip/UI/FileManager/resource.rc6
-rw-r--r--CPP/7zip/UI/FileManager/resourceGui.h8
-rw-r--r--CPP/7zip/UI/FileManager/resourceGui.rc9
-rw-r--r--CPP/7zip/UI/GUI/BenchmarkDialog.cpp29
-rw-r--r--CPP/7zip/UI/GUI/CompressDialog.cpp64
-rw-r--r--CPP/7zip/UI/GUI/CompressDialog.rc2
-rw-r--r--CPP/7zip/UI/GUI/CompressDialogRes.h2
-rw-r--r--CPP/7zip/UI/GUI/CompressOptionsDialog.rc69
-rw-r--r--CPP/7zip/UI/GUI/ExtractGUI.cpp2
-rw-r--r--CPP/7zip/UI/GUI/GUI.cpp24
-rw-r--r--CPP/7zip/UI/GUI/GUI.dsp24
-rw-r--r--CPP/7zip/UI/GUI/UpdateGUI.cpp4
-rw-r--r--CPP/7zip/UI/GUI/makefile4
-rw-r--r--CPP/7zip/UI/GUI/resource.rc1
-rw-r--r--CPP/7zip/cmpl_gcc_arm.mak3
-rw-r--r--CPP/7zip/var_clang_arm64.mak8
-rw-r--r--CPP/7zip/var_clang_x64.mak1
-rw-r--r--CPP/7zip/var_clang_x86.mak1
-rw-r--r--CPP/7zip/var_gcc_arm.mak34
-rw-r--r--CPP/7zip/var_gcc_x64.mak1
-rw-r--r--CPP/7zip/var_gcc_x86.mak1
-rw-r--r--CPP/7zip/var_mac_arm64.mak2
-rw-r--r--CPP/7zip/warn_gcc.mak3
-rw-r--r--CPP/Build.mak23
-rw-r--r--CPP/Common/AutoPtr.h33
-rw-r--r--CPP/Common/CommandLineParser.cpp40
-rw-r--r--CPP/Common/Common.h299
-rw-r--r--CPP/Common/Common0.h330
-rw-r--r--CPP/Common/CrcReg.cpp23
-rw-r--r--CPP/Common/DynamicBuffer.h12
-rw-r--r--CPP/Common/IntToString.cpp231
-rw-r--r--CPP/Common/IntToString.h30
-rw-r--r--CPP/Common/ListFileUtils.cpp14
-rw-r--r--CPP/Common/MyBuffer.h19
-rw-r--r--CPP/Common/MyBuffer2.h39
-rw-r--r--CPP/Common/MyCom.h153
-rw-r--r--CPP/Common/MyGuidDef.h4
-rw-r--r--CPP/Common/MyMap.cpp4
-rw-r--r--CPP/Common/MyString.cpp70
-rw-r--r--CPP/Common/MyString.h20
-rw-r--r--CPP/Common/MyTypes.h5
-rw-r--r--CPP/Common/MyVector.h34
-rw-r--r--CPP/Common/MyWindows.cpp6
-rw-r--r--CPP/Common/MyWindows.h11
-rw-r--r--CPP/Common/MyXml.cpp117
-rw-r--r--CPP/Common/MyXml.h4
-rw-r--r--CPP/Common/NewHandler.cpp50
-rw-r--r--CPP/Common/NewHandler.h23
-rw-r--r--CPP/Common/Random.cpp4
-rw-r--r--CPP/Common/Random.h2
-rw-r--r--CPP/Common/StdInStream.cpp12
-rw-r--r--CPP/Common/StdOutStream.cpp120
-rw-r--r--CPP/Common/StdOutStream.h17
-rw-r--r--CPP/Common/StringConvert.cpp52
-rw-r--r--CPP/Common/StringToInt.cpp215
-rw-r--r--CPP/Common/StringToInt.h16
-rw-r--r--CPP/Common/TextConfig.cpp13
-rw-r--r--CPP/Common/UTFConvert.cpp8
-rw-r--r--CPP/Common/Xxh64Reg.cpp97
-rw-r--r--CPP/Windows/Control/Dialog.cpp1
-rw-r--r--CPP/Windows/Control/Dialog.h19
-rw-r--r--CPP/Windows/Control/PropertyPage.cpp4
-rw-r--r--CPP/Windows/DLL.cpp9
-rw-r--r--CPP/Windows/FileDir.cpp26
-rw-r--r--CPP/Windows/FileFind.cpp177
-rw-r--r--CPP/Windows/FileFind.h19
-rw-r--r--CPP/Windows/FileIO.cpp125
-rw-r--r--CPP/Windows/FileIO.h76
-rw-r--r--CPP/Windows/FileLink.cpp17
-rw-r--r--CPP/Windows/FileName.cpp8
-rw-r--r--CPP/Windows/FileSystem.cpp27
-rw-r--r--CPP/Windows/MemoryLock.cpp3
-rw-r--r--CPP/Windows/ProcessUtils.cpp2
-rw-r--r--CPP/Windows/PropVariant.cpp2
-rw-r--r--CPP/Windows/PropVariantConv.cpp104
-rw-r--r--CPP/Windows/PropVariantConv.h9
-rw-r--r--CPP/Windows/Registry.cpp15
-rw-r--r--CPP/Windows/SecurityUtils.h2
-rw-r--r--CPP/Windows/Shell.cpp26
-rw-r--r--CPP/Windows/Shell.h1
-rw-r--r--CPP/Windows/StdAfx.h1
-rw-r--r--CPP/Windows/Synchronization.h5
-rw-r--r--CPP/Windows/System.cpp78
-rw-r--r--CPP/Windows/System.h2
-rw-r--r--CPP/Windows/SystemInfo.cpp225
-rw-r--r--CPP/Windows/TimeUtils.cpp90
491 files changed, 32182 insertions, 9934 deletions
diff --git a/C/7zArcIn.c b/C/7zArcIn.c
index 43fa7c2..23f2949 100644
--- a/C/7zArcIn.c
+++ b/C/7zArcIn.c
@@ -1,5 +1,5 @@
1/* 7zArcIn.c -- 7z Input functions 1/* 7zArcIn.c -- 7z Input functions
22023-05-11 : Igor Pavlov : Public domain */ 22023-09-07 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -301,7 +301,7 @@ static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v)
301 301
302static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) 302static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
303{ 303{
304 Byte b = 0; 304 unsigned b = 0;
305 unsigned m = 0; 305 unsigned m = 0;
306 UInt32 sum = 0; 306 UInt32 sum = 0;
307 for (; numItems != 0; numItems--) 307 for (; numItems != 0; numItems--)
@@ -312,7 +312,7 @@ static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
312 m = 8; 312 m = 8;
313 } 313 }
314 m--; 314 m--;
315 sum += ((b >> m) & 1); 315 sum += (UInt32)((b >> m) & 1);
316 } 316 }
317 return sum; 317 return sum;
318} 318}
diff --git a/C/7zCrc.c b/C/7zCrc.c
index c995a8b..6e2db9e 100644
--- a/C/7zCrc.c
+++ b/C/7zCrc.c
@@ -1,93 +1,96 @@
1/* 7zCrc.c -- CRC32 calculation and init 1/* 7zCrc.c -- CRC32 calculation and init
22023-04-02 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
6#include "7zCrc.h" 6#include "7zCrc.h"
7#include "CpuArch.h" 7#include "CpuArch.h"
8 8
9#define kCrcPoly 0xEDB88320 9// for debug:
10// #define __ARM_FEATURE_CRC32 1
10 11
11#ifdef MY_CPU_LE 12#ifdef __ARM_FEATURE_CRC32
12 #define CRC_NUM_TABLES 8 13// #pragma message("__ARM_FEATURE_CRC32")
13#else 14#define Z7_CRC_HW_FORCE
14 #define CRC_NUM_TABLES 9 15#endif
15 16
16 UInt32 Z7_FASTCALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); 17// #define Z7_CRC_DEBUG_BE
17 UInt32 Z7_FASTCALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table); 18#ifdef Z7_CRC_DEBUG_BE
19#undef MY_CPU_LE
20#define MY_CPU_BE
18#endif 21#endif
19 22
20#ifndef MY_CPU_BE 23#ifdef Z7_CRC_HW_FORCE
21 UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); 24 #define Z7_CRC_NUM_TABLES_USE 1
22 UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); 25#else
26#ifdef Z7_CRC_NUM_TABLES
27 #define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES
28#else
29 #define Z7_CRC_NUM_TABLES_USE 12
30#endif
23#endif 31#endif
24 32
25/* 33#if Z7_CRC_NUM_TABLES_USE < 1
26extern 34 #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
27CRC_FUNC g_CrcUpdateT4; 35#endif
28CRC_FUNC g_CrcUpdateT4;
29*/
30extern
31CRC_FUNC g_CrcUpdateT8;
32CRC_FUNC g_CrcUpdateT8;
33extern
34CRC_FUNC g_CrcUpdateT0_32;
35CRC_FUNC g_CrcUpdateT0_32;
36extern
37CRC_FUNC g_CrcUpdateT0_64;
38CRC_FUNC g_CrcUpdateT0_64;
39extern
40CRC_FUNC g_CrcUpdate;
41CRC_FUNC g_CrcUpdate;
42
43UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
44
45UInt32 Z7_FASTCALL CrcUpdate(UInt32 v, const void *data, size_t size)
46{
47 return g_CrcUpdate(v, data, size, g_CrcTable);
48}
49 36
50UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size) 37#if defined(MY_CPU_LE) || (Z7_CRC_NUM_TABLES_USE == 1)
51{ 38 #define Z7_CRC_NUM_TABLES_TOTAL Z7_CRC_NUM_TABLES_USE
52 return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; 39#else
53} 40 #define Z7_CRC_NUM_TABLES_TOTAL (Z7_CRC_NUM_TABLES_USE + 1)
41#endif
54 42
55#if CRC_NUM_TABLES < 4 \ 43#ifndef Z7_CRC_HW_FORCE
56 || (CRC_NUM_TABLES == 4 && defined(MY_CPU_BE)) \ 44
45#if Z7_CRC_NUM_TABLES_USE == 1 \
57 || (!defined(MY_CPU_LE) && !defined(MY_CPU_BE)) 46 || (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
58#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) 47#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
59UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table); 48#define Z7_CRC_UPDATE_T1_FUNC_NAME CrcUpdateGT1
60UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) 49static UInt32 Z7_FASTCALL Z7_CRC_UPDATE_T1_FUNC_NAME(UInt32 v, const void *data, size_t size)
61{ 50{
51 const UInt32 *table = g_CrcTable;
62 const Byte *p = (const Byte *)data; 52 const Byte *p = (const Byte *)data;
63 const Byte *pEnd = p + size; 53 const Byte *lim = p + size;
64 for (; p != pEnd; p++) 54 for (; p != lim; p++)
65 v = CRC_UPDATE_BYTE_2(v, *p); 55 v = CRC_UPDATE_BYTE_2(v, *p);
66 return v; 56 return v;
67} 57}
68#endif 58#endif
69 59
60
61#if Z7_CRC_NUM_TABLES_USE != 1
62#ifndef MY_CPU_BE
63 #define FUNC_NAME_LE_2(s) CrcUpdateT ## s
64 #define FUNC_NAME_LE_1(s) FUNC_NAME_LE_2(s)
65 #define FUNC_NAME_LE FUNC_NAME_LE_1(Z7_CRC_NUM_TABLES_USE)
66 UInt32 Z7_FASTCALL FUNC_NAME_LE (UInt32 v, const void *data, size_t size, const UInt32 *table);
67#endif
68#ifndef MY_CPU_LE
69 #define FUNC_NAME_BE_2(s) CrcUpdateT1_BeT ## s
70 #define FUNC_NAME_BE_1(s) FUNC_NAME_BE_2(s)
71 #define FUNC_NAME_BE FUNC_NAME_BE_1(Z7_CRC_NUM_TABLES_USE)
72 UInt32 Z7_FASTCALL FUNC_NAME_BE (UInt32 v, const void *data, size_t size, const UInt32 *table);
73#endif
74#endif
75
76#endif // Z7_CRC_HW_FORCE
77
70/* ---------- hardware CRC ---------- */ 78/* ---------- hardware CRC ---------- */
71 79
72#ifdef MY_CPU_LE 80#ifdef MY_CPU_LE
73 81
74#if defined(MY_CPU_ARM_OR_ARM64) 82#if defined(MY_CPU_ARM_OR_ARM64)
75
76// #pragma message("ARM*") 83// #pragma message("ARM*")
77 84
78 #if defined(_MSC_VER) 85 #if (defined(__clang__) && (__clang_major__ >= 3)) \
79 #if defined(MY_CPU_ARM64) 86 || defined(__GNUC__) && (__GNUC__ >= 6) && defined(MY_CPU_ARM64) \
80 #if (_MSC_VER >= 1910) 87 || defined(__GNUC__) && (__GNUC__ >= 8)
81 #ifndef __clang__
82 #define USE_ARM64_CRC
83 #include <intrin.h>
84 #endif
85 #endif
86 #endif
87 #elif (defined(__clang__) && (__clang_major__ >= 3)) \
88 || (defined(__GNUC__) && (__GNUC__ > 4))
89 #if !defined(__ARM_FEATURE_CRC32) 88 #if !defined(__ARM_FEATURE_CRC32)
89// #pragma message("!defined(__ARM_FEATURE_CRC32)")
90Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
90 #define __ARM_FEATURE_CRC32 1 91 #define __ARM_FEATURE_CRC32 1
92Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
93 #define Z7_ARM_FEATURE_CRC32_WAS_SET
91 #if defined(__clang__) 94 #if defined(__clang__)
92 #if defined(MY_CPU_ARM64) 95 #if defined(MY_CPU_ARM64)
93 #define ATTRIB_CRC __attribute__((__target__("crc"))) 96 #define ATTRIB_CRC __attribute__((__target__("crc")))
@@ -96,100 +99,120 @@ UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UI
96 #endif 99 #endif
97 #else 100 #else
98 #if defined(MY_CPU_ARM64) 101 #if defined(MY_CPU_ARM64)
102#if !defined(Z7_GCC_VERSION) || (Z7_GCC_VERSION >= 60000)
99 #define ATTRIB_CRC __attribute__((__target__("+crc"))) 103 #define ATTRIB_CRC __attribute__((__target__("+crc")))
104#endif
100 #else 105 #else
106#if !defined(Z7_GCC_VERSION) || (__GNUC__ >= 8)
107#if defined(__ARM_FP) && __GNUC__ >= 8
108// for -mfloat-abi=hard: similar to <arm_acle.h>
109 #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc+simd")))
110#else
101 #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc"))) 111 #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc")))
112#endif
113#endif
102 #endif 114 #endif
103 #endif 115 #endif
104 #endif 116 #endif
105 #if defined(__ARM_FEATURE_CRC32) 117 #if defined(__ARM_FEATURE_CRC32)
106 #define USE_ARM64_CRC 118 // #pragma message("<arm_acle.h>")
119/*
120arm_acle.h (GGC):
121 before Nov 17, 2017:
122#ifdef __ARM_FEATURE_CRC32
123
124 Nov 17, 2017: gcc10.0 (gcc 9.2.0) checked"
125#if __ARM_ARCH >= 8
126#pragma GCC target ("arch=armv8-a+crc")
127
128 Aug 22, 2019: GCC 8.4?, 9.2.1, 10.1:
129#ifdef __ARM_FEATURE_CRC32
130#ifdef __ARM_FP
131#pragma GCC target ("arch=armv8-a+crc+simd")
132#else
133#pragma GCC target ("arch=armv8-a+crc")
134#endif
135*/
136#if defined(__ARM_ARCH) && __ARM_ARCH < 8
137#if defined(Z7_GCC_VERSION) && (__GNUC__ == 8) && (Z7_GCC_VERSION < 80400) \
138 || defined(Z7_GCC_VERSION) && (__GNUC__ == 9) && (Z7_GCC_VERSION < 90201) \
139 || defined(Z7_GCC_VERSION) && (__GNUC__ == 10) && (Z7_GCC_VERSION < 100100)
140Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
141// #pragma message("#define __ARM_ARCH 8")
142#undef __ARM_ARCH
143#define __ARM_ARCH 8
144Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
145#endif
146#endif
147 #define Z7_CRC_HW_USE
107 #include <arm_acle.h> 148 #include <arm_acle.h>
108 #endif 149 #endif
150 #elif defined(_MSC_VER)
151 #if defined(MY_CPU_ARM64)
152 #if (_MSC_VER >= 1910)
153 #ifdef __clang__
154 // #define Z7_CRC_HW_USE
155 // #include <arm_acle.h>
156 #else
157 #define Z7_CRC_HW_USE
158 #include <intrin.h>
159 #endif
160 #endif
161 #endif
109 #endif 162 #endif
110 163
111#else 164#else // non-ARM*
112
113// no hardware CRC
114
115// #define USE_CRC_EMU
116
117#ifdef USE_CRC_EMU
118
119#pragma message("ARM64 CRC emulation")
120
121Z7_FORCE_INLINE
122UInt32 __crc32b(UInt32 v, UInt32 data)
123{
124 const UInt32 *table = g_CrcTable;
125 v = CRC_UPDATE_BYTE_2(v, (Byte)data);
126 return v;
127}
128 165
129Z7_FORCE_INLINE 166// #define Z7_CRC_HW_USE // for debug : we can test HW-branch of code
130UInt32 __crc32w(UInt32 v, UInt32 data) 167#ifdef Z7_CRC_HW_USE
131{ 168#include "7zCrcEmu.h"
132 const UInt32 *table = g_CrcTable; 169#endif
133 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
134 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
135 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
136 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
137 return v;
138}
139 170
140Z7_FORCE_INLINE 171#endif // non-ARM*
141UInt32 __crc32d(UInt32 v, UInt64 data)
142{
143 const UInt32 *table = g_CrcTable;
144 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
145 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
146 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
147 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
148 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
149 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
150 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
151 v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
152 return v;
153}
154 172
155#endif // USE_CRC_EMU
156 173
157#endif // defined(MY_CPU_ARM64) && defined(MY_CPU_LE)
158 174
175#if defined(Z7_CRC_HW_USE)
159 176
177// #pragma message("USE ARM HW CRC")
160 178
161#if defined(USE_ARM64_CRC) || defined(USE_CRC_EMU) 179#ifdef MY_CPU_64BIT
180 #define CRC_HW_WORD_TYPE UInt64
181 #define CRC_HW_WORD_FUNC __crc32d
182#else
183 #define CRC_HW_WORD_TYPE UInt32
184 #define CRC_HW_WORD_FUNC __crc32w
185#endif
162 186
163#define T0_32_UNROLL_BYTES (4 * 4) 187#define CRC_HW_UNROLL_BYTES (sizeof(CRC_HW_WORD_TYPE) * 4)
164#define T0_64_UNROLL_BYTES (4 * 8)
165 188
166#ifndef ATTRIB_CRC 189#ifdef ATTRIB_CRC
167#define ATTRIB_CRC 190 ATTRIB_CRC
168#endif 191#endif
169// #pragma message("USE ARM HW CRC") 192Z7_NO_INLINE
170 193#ifdef Z7_CRC_HW_FORCE
171ATTRIB_CRC 194 UInt32 Z7_FASTCALL CrcUpdate
172UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table); 195#else
173ATTRIB_CRC 196 static UInt32 Z7_FASTCALL CrcUpdate_HW
174UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table) 197#endif
198 (UInt32 v, const void *data, size_t size)
175{ 199{
176 const Byte *p = (const Byte *)data; 200 const Byte *p = (const Byte *)data;
177 UNUSED_VAR(table); 201 for (; size != 0 && ((unsigned)(ptrdiff_t)p & (CRC_HW_UNROLL_BYTES - 1)) != 0; size--)
178
179 for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_32_UNROLL_BYTES - 1)) != 0; size--)
180 v = __crc32b(v, *p++); 202 v = __crc32b(v, *p++);
181 203 if (size >= CRC_HW_UNROLL_BYTES)
182 if (size >= T0_32_UNROLL_BYTES)
183 { 204 {
184 const Byte *lim = p + size; 205 const Byte *lim = p + size;
185 size &= (T0_32_UNROLL_BYTES - 1); 206 size &= CRC_HW_UNROLL_BYTES - 1;
186 lim -= size; 207 lim -= size;
187 do 208 do
188 { 209 {
189 v = __crc32w(v, *(const UInt32 *)(const void *)(p)); 210 v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));
190 v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4; 211 v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));
191 v = __crc32w(v, *(const UInt32 *)(const void *)(p)); 212 p += 2 * sizeof(CRC_HW_WORD_TYPE);
192 v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4; 213 v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));
214 v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));
215 p += 2 * sizeof(CRC_HW_WORD_TYPE);
193 } 216 }
194 while (p != lim); 217 while (p != lim);
195 } 218 }
@@ -200,46 +223,86 @@ UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const
200 return v; 223 return v;
201} 224}
202 225
203ATTRIB_CRC 226#ifdef Z7_ARM_FEATURE_CRC32_WAS_SET
204UInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table); 227Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
205ATTRIB_CRC 228#undef __ARM_FEATURE_CRC32
206UInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table) 229Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
230#undef Z7_ARM_FEATURE_CRC32_WAS_SET
231#endif
232
233#endif // defined(Z7_CRC_HW_USE)
234#endif // MY_CPU_LE
235
236
237
238#ifndef Z7_CRC_HW_FORCE
239
240#if defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
241/*
242typedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_WITH_TABLE_FUNC)
243 (UInt32 v, const void *data, size_t size, const UInt32 *table);
244Z7_CRC_UPDATE_WITH_TABLE_FUNC g_CrcUpdate;
245*/
246static unsigned g_Crc_Algo;
247#if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
248static unsigned g_Crc_Be;
249#endif
250#endif // defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
251
252
253
254Z7_NO_INLINE
255#ifdef Z7_CRC_HW_USE
256 static UInt32 Z7_FASTCALL CrcUpdate_Base
257#else
258 UInt32 Z7_FASTCALL CrcUpdate
259#endif
260 (UInt32 crc, const void *data, size_t size)
207{ 261{
208 const Byte *p = (const Byte *)data; 262#if Z7_CRC_NUM_TABLES_USE == 1
209 UNUSED_VAR(table); 263 return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);
264#else // Z7_CRC_NUM_TABLES_USE != 1
265#ifdef Z7_CRC_UPDATE_T1_FUNC_NAME
266 if (g_Crc_Algo == 1)
267 return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);
268#endif
210 269
211 for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_64_UNROLL_BYTES - 1)) != 0; size--) 270#ifdef MY_CPU_LE
212 v = __crc32b(v, *p++); 271 return FUNC_NAME_LE(crc, data, size, g_CrcTable);
272#elif defined(MY_CPU_BE)
273 return FUNC_NAME_BE(crc, data, size, g_CrcTable);
274#else
275 if (g_Crc_Be)
276 return FUNC_NAME_BE(crc, data, size, g_CrcTable);
277 else
278 return FUNC_NAME_LE(crc, data, size, g_CrcTable);
279#endif
280#endif // Z7_CRC_NUM_TABLES_USE != 1
281}
213 282
214 if (size >= T0_64_UNROLL_BYTES)
215 {
216 const Byte *lim = p + size;
217 size &= (T0_64_UNROLL_BYTES - 1);
218 lim -= size;
219 do
220 {
221 v = __crc32d(v, *(const UInt64 *)(const void *)(p));
222 v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;
223 v = __crc32d(v, *(const UInt64 *)(const void *)(p));
224 v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;
225 }
226 while (p != lim);
227 }
228
229 for (; size != 0; size--)
230 v = __crc32b(v, *p++);
231 283
232 return v; 284#ifdef Z7_CRC_HW_USE
285Z7_NO_INLINE
286UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size)
287{
288 if (g_Crc_Algo == 0)
289 return CrcUpdate_HW(crc, data, size);
290 return CrcUpdate_Base(crc, data, size);
233} 291}
292#endif
234 293
235#undef T0_32_UNROLL_BYTES 294#endif // !defined(Z7_CRC_HW_FORCE)
236#undef T0_64_UNROLL_BYTES
237 295
238#endif // defined(USE_ARM64_CRC) || defined(USE_CRC_EMU)
239 296
240#endif // MY_CPU_LE 297
298UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size)
299{
300 return CrcUpdate(CRC_INIT_VAL, data, size) ^ CRC_INIT_VAL;
301}
241 302
242 303
304MY_ALIGN(64)
305UInt32 g_CrcTable[256 * Z7_CRC_NUM_TABLES_TOTAL];
243 306
244 307
245void Z7_FASTCALL CrcGenerateTable(void) 308void Z7_FASTCALL CrcGenerateTable(void)
@@ -247,94 +310,111 @@ void Z7_FASTCALL CrcGenerateTable(void)
247 UInt32 i; 310 UInt32 i;
248 for (i = 0; i < 256; i++) 311 for (i = 0; i < 256; i++)
249 { 312 {
313#if defined(Z7_CRC_HW_FORCE)
314 g_CrcTable[i] = __crc32b(i, 0);
315#else
316 #define kCrcPoly 0xEDB88320
250 UInt32 r = i; 317 UInt32 r = i;
251 unsigned j; 318 unsigned j;
252 for (j = 0; j < 8; j++) 319 for (j = 0; j < 8; j++)
253 r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); 320 r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
254 g_CrcTable[i] = r; 321 g_CrcTable[i] = r;
322#endif
255 } 323 }
256 for (i = 256; i < 256 * CRC_NUM_TABLES; i++) 324 for (i = 256; i < 256 * Z7_CRC_NUM_TABLES_USE; i++)
257 { 325 {
258 const UInt32 r = g_CrcTable[(size_t)i - 256]; 326 const UInt32 r = g_CrcTable[(size_t)i - 256];
259 g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); 327 g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
260 } 328 }
261 329
262 #if CRC_NUM_TABLES < 4 330#if !defined(Z7_CRC_HW_FORCE) && \
263 g_CrcUpdate = CrcUpdateT1; 331 (defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME) || defined(MY_CPU_BE))
264 #elif defined(MY_CPU_LE) 332
265 // g_CrcUpdateT4 = CrcUpdateT4; 333#if Z7_CRC_NUM_TABLES_USE <= 1
266 #if CRC_NUM_TABLES < 8 334 g_Crc_Algo = 1;
267 g_CrcUpdate = CrcUpdateT4; 335#else // Z7_CRC_NUM_TABLES_USE <= 1
268 #else // CRC_NUM_TABLES >= 8 336
269 g_CrcUpdateT8 = CrcUpdateT8; 337#if defined(MY_CPU_LE)
270 /* 338 g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
271 #ifdef MY_CPU_X86_OR_AMD64 339#else // !defined(MY_CPU_LE)
272 if (!CPU_Is_InOrder())
273 #endif
274 */
275 g_CrcUpdate = CrcUpdateT8;
276 #endif
277 #else
278 { 340 {
279 #ifndef MY_CPU_BE 341#ifndef MY_CPU_BE
280 UInt32 k = 0x01020304; 342 UInt32 k = 0x01020304;
281 const Byte *p = (const Byte *)&k; 343 const Byte *p = (const Byte *)&k;
282 if (p[0] == 4 && p[1] == 3) 344 if (p[0] == 4 && p[1] == 3)
283 { 345 g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
284 #if CRC_NUM_TABLES < 8
285 // g_CrcUpdateT4 = CrcUpdateT4;
286 g_CrcUpdate = CrcUpdateT4;
287 #else // CRC_NUM_TABLES >= 8
288 g_CrcUpdateT8 = CrcUpdateT8;
289 g_CrcUpdate = CrcUpdateT8;
290 #endif
291 }
292 else if (p[0] != 1 || p[1] != 2) 346 else if (p[0] != 1 || p[1] != 2)
293 g_CrcUpdate = CrcUpdateT1; 347 g_Crc_Algo = 1;
294 else 348 else
295 #endif // MY_CPU_BE 349#endif // MY_CPU_BE
296 { 350 {
297 for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) 351 for (i = 256 * Z7_CRC_NUM_TABLES_TOTAL - 1; i >= 256; i--)
298 { 352 {
299 const UInt32 x = g_CrcTable[(size_t)i - 256]; 353 const UInt32 x = g_CrcTable[(size_t)i - 256];
300 g_CrcTable[i] = Z7_BSWAP32(x); 354 g_CrcTable[i] = Z7_BSWAP32(x);
301 } 355 }
302 #if CRC_NUM_TABLES <= 4 356#if defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
303 g_CrcUpdate = CrcUpdateT1; 357 g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
304 #elif CRC_NUM_TABLES <= 8 358#endif
305 // g_CrcUpdateT4 = CrcUpdateT1_BeT4; 359#if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
306 g_CrcUpdate = CrcUpdateT1_BeT4; 360 g_Crc_Be = 1;
307 #else // CRC_NUM_TABLES > 8 361#endif
308 g_CrcUpdateT8 = CrcUpdateT1_BeT8;
309 g_CrcUpdate = CrcUpdateT1_BeT8;
310 #endif
311 } 362 }
312 } 363 }
313 #endif // CRC_NUM_TABLES < 4 364#endif // !defined(MY_CPU_LE)
314 365
315 #ifdef MY_CPU_LE 366#ifdef MY_CPU_LE
316 #ifdef USE_ARM64_CRC 367#ifdef Z7_CRC_HW_USE
317 if (CPU_IsSupported_CRC32()) 368 if (CPU_IsSupported_CRC32())
318 { 369 g_Crc_Algo = 0;
319 g_CrcUpdateT0_32 = CrcUpdateT0_32; 370#endif // Z7_CRC_HW_USE
320 g_CrcUpdateT0_64 = CrcUpdateT0_64; 371#endif // MY_CPU_LE
321 g_CrcUpdate = 372
322 #if defined(MY_CPU_ARM) 373#endif // Z7_CRC_NUM_TABLES_USE <= 1
323 CrcUpdateT0_32; 374#endif // g_Crc_Algo was declared
324 #else 375}
325 CrcUpdateT0_64; 376
326 #endif 377Z7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo)
327 } 378{
328 #endif 379 if (algo == 0)
329 380 return &CrcUpdate;
330 #ifdef USE_CRC_EMU 381
331 g_CrcUpdateT0_32 = CrcUpdateT0_32; 382#if defined(Z7_CRC_HW_USE)
332 g_CrcUpdateT0_64 = CrcUpdateT0_64; 383 if (algo == sizeof(CRC_HW_WORD_TYPE) * 8)
333 g_CrcUpdate = CrcUpdateT0_64; 384 {
334 #endif 385#ifdef Z7_CRC_HW_FORCE
386 return &CrcUpdate;
387#else
388 if (g_Crc_Algo == 0)
389 return &CrcUpdate_HW;
390#endif
391 }
392#endif
393
394#ifndef Z7_CRC_HW_FORCE
395 if (algo == Z7_CRC_NUM_TABLES_USE)
396 return
397 #ifdef Z7_CRC_HW_USE
398 &CrcUpdate_Base;
399 #else
400 &CrcUpdate;
335 #endif 401 #endif
402#endif
403
404 return NULL;
336} 405}
337 406
338#undef kCrcPoly 407#undef kCrcPoly
339#undef CRC64_NUM_TABLES 408#undef Z7_CRC_NUM_TABLES_USE
409#undef Z7_CRC_NUM_TABLES_TOTAL
340#undef CRC_UPDATE_BYTE_2 410#undef CRC_UPDATE_BYTE_2
411#undef FUNC_NAME_LE_2
412#undef FUNC_NAME_LE_1
413#undef FUNC_NAME_LE
414#undef FUNC_NAME_BE_2
415#undef FUNC_NAME_BE_1
416#undef FUNC_NAME_BE
417
418#undef CRC_HW_UNROLL_BYTES
419#undef CRC_HW_WORD_FUNC
420#undef CRC_HW_WORD_TYPE
diff --git a/C/7zCrc.h b/C/7zCrc.h
index 4afaeae..3e6d408 100644
--- a/C/7zCrc.h
+++ b/C/7zCrc.h
@@ -1,5 +1,5 @@
1/* 7zCrc.h -- CRC32 calculation 1/* 7zCrc.h -- CRC32 calculation
22023-04-02 : Igor Pavlov : Public domain */ 22024-01-22 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_7Z_CRC_H 4#ifndef ZIP7_INC_7Z_CRC_H
5#define ZIP7_INC_7Z_CRC_H 5#define ZIP7_INC_7Z_CRC_H
@@ -20,7 +20,8 @@ void Z7_FASTCALL CrcGenerateTable(void);
20UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size); 20UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size);
21UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size); 21UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size);
22 22
23typedef UInt32 (Z7_FASTCALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); 23typedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_FUNC)(UInt32 v, const void *data, size_t size);
24Z7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo);
24 25
25EXTERN_C_END 26EXTERN_C_END
26 27
diff --git a/C/7zCrcOpt.c b/C/7zCrcOpt.c
index 9c64929..9408017 100644
--- a/C/7zCrcOpt.c
+++ b/C/7zCrcOpt.c
@@ -1,117 +1,199 @@
1/* 7zCrcOpt.c -- CRC32 calculation 1/* 7zCrcOpt.c -- CRC32 calculation (optimized functions)
22023-04-02 : Igor Pavlov : Public domain */ 22023-12-07 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
6#include "CpuArch.h" 6#include "CpuArch.h"
7 7
8#if !defined(Z7_CRC_NUM_TABLES) || Z7_CRC_NUM_TABLES > 1
9
10// for debug only : define Z7_CRC_DEBUG_BE to test big-endian code in little-endian cpu
11// #define Z7_CRC_DEBUG_BE
12#ifdef Z7_CRC_DEBUG_BE
13#undef MY_CPU_LE
14#define MY_CPU_BE
15#endif
16
17// the value Z7_CRC_NUM_TABLES_USE must be defined to same value as in 7zCrc.c
18#ifdef Z7_CRC_NUM_TABLES
19#define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES
20#else
21#define Z7_CRC_NUM_TABLES_USE 12
22#endif
23
24#if Z7_CRC_NUM_TABLES_USE % 4 || \
25 Z7_CRC_NUM_TABLES_USE < 4 * 1 || \
26 Z7_CRC_NUM_TABLES_USE > 4 * 6
27 #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
28#endif
29
30
8#ifndef MY_CPU_BE 31#ifndef MY_CPU_BE
9 32
10#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) 33#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
11 34
12UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); 35#define Q(n, d) \
13UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) 36 ( (table + ((n) * 4 + 3) * 0x100)[(Byte)(d)] \
14{ 37 ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \
15 const Byte *p = (const Byte *)data; 38 ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \
16 for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) 39 ^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] )
17 v = CRC_UPDATE_BYTE_2(v, *p); 40
18 for (; size >= 4; size -= 4, p += 4) 41#define R(a) *((const UInt32 *)(const void *)p + (a))
19 { 42
20 v ^= *(const UInt32 *)(const void *)p; 43#define CRC_FUNC_PRE_LE2(step) \
21 v = 44UInt32 Z7_FASTCALL CrcUpdateT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)
22 (table + 0x300)[((v ) & 0xFF)]
23 ^ (table + 0x200)[((v >> 8) & 0xFF)]
24 ^ (table + 0x100)[((v >> 16) & 0xFF)]
25 ^ (table + 0x000)[((v >> 24))];
26 }
27 for (; size > 0; size--, p++)
28 v = CRC_UPDATE_BYTE_2(v, *p);
29 return v;
30}
31 45
32UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); 46#define CRC_FUNC_PRE_LE(step) \
33UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) 47 CRC_FUNC_PRE_LE2(step); \
48 CRC_FUNC_PRE_LE2(step)
49
50CRC_FUNC_PRE_LE(Z7_CRC_NUM_TABLES_USE)
34{ 51{
35 const Byte *p = (const Byte *)data; 52 const Byte *p = (const Byte *)data;
36 for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) 53 const Byte *lim;
54 for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)
37 v = CRC_UPDATE_BYTE_2(v, *p); 55 v = CRC_UPDATE_BYTE_2(v, *p);
38 for (; size >= 8; size -= 8, p += 8) 56 lim = p + size;
57 if (size >= Z7_CRC_NUM_TABLES_USE)
39 { 58 {
40 UInt32 d; 59 lim -= Z7_CRC_NUM_TABLES_USE;
41 v ^= *(const UInt32 *)(const void *)p; 60 do
42 v = 61 {
43 (table + 0x700)[((v ) & 0xFF)] 62 v ^= R(0);
44 ^ (table + 0x600)[((v >> 8) & 0xFF)] 63 {
45 ^ (table + 0x500)[((v >> 16) & 0xFF)] 64#if Z7_CRC_NUM_TABLES_USE == 1 * 4
46 ^ (table + 0x400)[((v >> 24))]; 65 v = Q(0, v);
47 d = *((const UInt32 *)(const void *)p + 1); 66#else
48 v ^= 67#define U2(r, op) \
49 (table + 0x300)[((d ) & 0xFF)] 68 { d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }
50 ^ (table + 0x200)[((d >> 8) & 0xFF)] 69 UInt32 d, x;
51 ^ (table + 0x100)[((d >> 16) & 0xFF)] 70 U2(1, =)
52 ^ (table + 0x000)[((d >> 24))]; 71#if Z7_CRC_NUM_TABLES_USE >= 3 * 4
72#define U(r) U2(r, ^=)
73 U(2)
74#if Z7_CRC_NUM_TABLES_USE >= 4 * 4
75 U(3)
76#if Z7_CRC_NUM_TABLES_USE >= 5 * 4
77 U(4)
78#if Z7_CRC_NUM_TABLES_USE >= 6 * 4
79 U(5)
80#if Z7_CRC_NUM_TABLES_USE >= 7 * 4
81#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
82#endif
83#endif
84#endif
85#endif
86#endif
87#undef U
88#undef U2
89 v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);
90#endif
91 }
92 p += Z7_CRC_NUM_TABLES_USE;
93 }
94 while (p <= lim);
95 lim += Z7_CRC_NUM_TABLES_USE;
53 } 96 }
54 for (; size > 0; size--, p++) 97 for (; p < lim; p++)
55 v = CRC_UPDATE_BYTE_2(v, *p); 98 v = CRC_UPDATE_BYTE_2(v, *p);
56 return v; 99 return v;
57} 100}
58 101
102#undef CRC_UPDATE_BYTE_2
103#undef R
104#undef Q
105#undef CRC_FUNC_PRE_LE
106#undef CRC_FUNC_PRE_LE2
107
59#endif 108#endif
60 109
61 110
111
112
62#ifndef MY_CPU_LE 113#ifndef MY_CPU_LE
63 114
64#define CRC_UINT32_SWAP(v) Z7_BSWAP32(v) 115#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[((crc) >> 24) ^ (b)] ^ ((crc) << 8))
65 116
66#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8)) 117#define Q(n, d) \
118 ( (table + ((n) * 4 + 0) * 0x100)[((d)) & 0xFF] \
119 ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \
120 ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \
121 ^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] )
67 122
68UInt32 Z7_FASTCALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) 123#ifdef Z7_CRC_DEBUG_BE
69{ 124 #define R(a) GetBe32a((const UInt32 *)(const void *)p + (a))
70 const Byte *p = (const Byte *)data; 125#else
71 table += 0x100; 126 #define R(a) *((const UInt32 *)(const void *)p + (a))
72 v = CRC_UINT32_SWAP(v); 127#endif
73 for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) 128
74 v = CRC_UPDATE_BYTE_2_BE(v, *p); 129
75 for (; size >= 4; size -= 4, p += 4) 130#define CRC_FUNC_PRE_BE2(step) \
76 { 131UInt32 Z7_FASTCALL CrcUpdateT1_BeT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)
77 v ^= *(const UInt32 *)(const void *)p;
78 v =
79 (table + 0x000)[((v ) & 0xFF)]
80 ^ (table + 0x100)[((v >> 8) & 0xFF)]
81 ^ (table + 0x200)[((v >> 16) & 0xFF)]
82 ^ (table + 0x300)[((v >> 24))];
83 }
84 for (; size > 0; size--, p++)
85 v = CRC_UPDATE_BYTE_2_BE(v, *p);
86 return CRC_UINT32_SWAP(v);
87}
88 132
89UInt32 Z7_FASTCALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table) 133#define CRC_FUNC_PRE_BE(step) \
134 CRC_FUNC_PRE_BE2(step); \
135 CRC_FUNC_PRE_BE2(step)
136
137CRC_FUNC_PRE_BE(Z7_CRC_NUM_TABLES_USE)
90{ 138{
91 const Byte *p = (const Byte *)data; 139 const Byte *p = (const Byte *)data;
140 const Byte *lim;
92 table += 0x100; 141 table += 0x100;
93 v = CRC_UINT32_SWAP(v); 142 v = Z7_BSWAP32(v);
94 for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) 143 for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)
95 v = CRC_UPDATE_BYTE_2_BE(v, *p); 144 v = CRC_UPDATE_BYTE_2_BE(v, *p);
96 for (; size >= 8; size -= 8, p += 8) 145 lim = p + size;
146 if (size >= Z7_CRC_NUM_TABLES_USE)
97 { 147 {
98 UInt32 d; 148 lim -= Z7_CRC_NUM_TABLES_USE;
99 v ^= *(const UInt32 *)(const void *)p; 149 do
100 v = 150 {
101 (table + 0x400)[((v ) & 0xFF)] 151 v ^= R(0);
102 ^ (table + 0x500)[((v >> 8) & 0xFF)] 152 {
103 ^ (table + 0x600)[((v >> 16) & 0xFF)] 153#if Z7_CRC_NUM_TABLES_USE == 1 * 4
104 ^ (table + 0x700)[((v >> 24))]; 154 v = Q(0, v);
105 d = *((const UInt32 *)(const void *)p + 1); 155#else
106 v ^= 156#define U2(r, op) \
107 (table + 0x000)[((d ) & 0xFF)] 157 { d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }
108 ^ (table + 0x100)[((d >> 8) & 0xFF)] 158 UInt32 d, x;
109 ^ (table + 0x200)[((d >> 16) & 0xFF)] 159 U2(1, =)
110 ^ (table + 0x300)[((d >> 24))]; 160#if Z7_CRC_NUM_TABLES_USE >= 3 * 4
161#define U(r) U2(r, ^=)
162 U(2)
163#if Z7_CRC_NUM_TABLES_USE >= 4 * 4
164 U(3)
165#if Z7_CRC_NUM_TABLES_USE >= 5 * 4
166 U(4)
167#if Z7_CRC_NUM_TABLES_USE >= 6 * 4
168 U(5)
169#if Z7_CRC_NUM_TABLES_USE >= 7 * 4
170#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
171#endif
172#endif
173#endif
174#endif
175#endif
176#undef U
177#undef U2
178 v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);
179#endif
180 }
181 p += Z7_CRC_NUM_TABLES_USE;
182 }
183 while (p <= lim);
184 lim += Z7_CRC_NUM_TABLES_USE;
111 } 185 }
112 for (; size > 0; size--, p++) 186 for (; p < lim; p++)
113 v = CRC_UPDATE_BYTE_2_BE(v, *p); 187 v = CRC_UPDATE_BYTE_2_BE(v, *p);
114 return CRC_UINT32_SWAP(v); 188 return Z7_BSWAP32(v);
115} 189}
116 190
191#undef CRC_UPDATE_BYTE_2_BE
192#undef R
193#undef Q
194#undef CRC_FUNC_PRE_BE
195#undef CRC_FUNC_PRE_BE2
196
197#endif
198#undef Z7_CRC_NUM_TABLES_USE
117#endif 199#endif
diff --git a/C/7zDec.c b/C/7zDec.c
index 96c6035..c9b4064 100644
--- a/C/7zDec.c
+++ b/C/7zDec.c
@@ -1,5 +1,5 @@
1/* 7zDec.c -- Decoding from 7z folder 1/* 7zDec.c -- Decoding from 7z folder
22023-04-02 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -51,6 +51,7 @@
51 51
52#ifndef Z7_NO_METHODS_FILTERS 52#ifndef Z7_NO_METHODS_FILTERS
53#define k_Delta 3 53#define k_Delta 3
54#define k_RISCV 0xb
54#define k_BCJ 0x3030103 55#define k_BCJ 0x3030103
55#define k_PPC 0x3030205 56#define k_PPC 0x3030205
56#define k_IA64 0x3030401 57#define k_IA64 0x3030401
@@ -362,6 +363,7 @@ static SRes CheckSupportedFolder(const CSzFolder *f)
362 case k_IA64: 363 case k_IA64:
363 case k_SPARC: 364 case k_SPARC:
364 case k_ARM: 365 case k_ARM:
366 case k_RISCV:
365 #endif 367 #endif
366 #ifdef Z7_USE_FILTER_ARM64 368 #ifdef Z7_USE_FILTER_ARM64
367 case k_ARM64: 369 case k_ARM64:
@@ -535,10 +537,10 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
535 } 537 }
536 } 538 }
537 } 539 }
538 #if defined(Z7_USE_BRANCH_FILTER) 540#if defined(Z7_USE_BRANCH_FILTER)
539 else if (ci == 1) 541 else if (ci == 1)
540 { 542 {
541 #if !defined(Z7_NO_METHODS_FILTERS) 543#if !defined(Z7_NO_METHODS_FILTERS)
542 if (coder->MethodID == k_Delta) 544 if (coder->MethodID == k_Delta)
543 { 545 {
544 if (coder->PropsSize != 1) 546 if (coder->PropsSize != 1)
@@ -550,22 +552,43 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
550 } 552 }
551 continue; 553 continue;
552 } 554 }
553 #endif 555#endif
554 556
555 #ifdef Z7_USE_FILTER_ARM64 557#ifdef Z7_USE_FILTER_ARM64
556 if (coder->MethodID == k_ARM64) 558 if (coder->MethodID == k_ARM64)
557 { 559 {
558 UInt32 pc = 0; 560 UInt32 pc = 0;
559 if (coder->PropsSize == 4) 561 if (coder->PropsSize == 4)
562 {
560 pc = GetUi32(propsData + coder->PropsOffset); 563 pc = GetUi32(propsData + coder->PropsOffset);
564 if (pc & 3)
565 return SZ_ERROR_UNSUPPORTED;
566 }
561 else if (coder->PropsSize != 0) 567 else if (coder->PropsSize != 0)
562 return SZ_ERROR_UNSUPPORTED; 568 return SZ_ERROR_UNSUPPORTED;
563 z7_BranchConv_ARM64_Dec(outBuffer, outSize, pc); 569 z7_BranchConv_ARM64_Dec(outBuffer, outSize, pc);
564 continue; 570 continue;
565 } 571 }
566 #endif 572#endif
567 573
568 #if !defined(Z7_NO_METHODS_FILTERS) || defined(Z7_USE_FILTER_ARMT) 574#if !defined(Z7_NO_METHODS_FILTERS)
575 if (coder->MethodID == k_RISCV)
576 {
577 UInt32 pc = 0;
578 if (coder->PropsSize == 4)
579 {
580 pc = GetUi32(propsData + coder->PropsOffset);
581 if (pc & 1)
582 return SZ_ERROR_UNSUPPORTED;
583 }
584 else if (coder->PropsSize != 0)
585 return SZ_ERROR_UNSUPPORTED;
586 z7_BranchConv_RISCV_Dec(outBuffer, outSize, pc);
587 continue;
588 }
589#endif
590
591#if !defined(Z7_NO_METHODS_FILTERS) || defined(Z7_USE_FILTER_ARMT)
569 { 592 {
570 if (coder->PropsSize != 0) 593 if (coder->PropsSize != 0)
571 return SZ_ERROR_UNSUPPORTED; 594 return SZ_ERROR_UNSUPPORTED;
@@ -579,7 +602,8 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
579 z7_BranchConvSt_X86_Dec(outBuffer, outSize, 0, &state); // pc = 0 602 z7_BranchConvSt_X86_Dec(outBuffer, outSize, 0, &state); // pc = 0
580 break; 603 break;
581 } 604 }
582 CASE_BRA_CONV(PPC) 605 case k_PPC: Z7_BRANCH_CONV_DEC_2(BranchConv_PPC)(outBuffer, outSize, 0); break; // pc = 0;
606 // CASE_BRA_CONV(PPC)
583 CASE_BRA_CONV(IA64) 607 CASE_BRA_CONV(IA64)
584 CASE_BRA_CONV(SPARC) 608 CASE_BRA_CONV(SPARC)
585 CASE_BRA_CONV(ARM) 609 CASE_BRA_CONV(ARM)
@@ -592,9 +616,9 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
592 } 616 }
593 continue; 617 continue;
594 } 618 }
595 #endif 619#endif
596 } // (c == 1) 620 } // (c == 1)
597 #endif 621#endif // Z7_USE_BRANCH_FILTER
598 else 622 else
599 return SZ_ERROR_UNSUPPORTED; 623 return SZ_ERROR_UNSUPPORTED;
600 } 624 }
diff --git a/C/7zTypes.h b/C/7zTypes.h
index 1fcb247..5b77420 100644
--- a/C/7zTypes.h
+++ b/C/7zTypes.h
@@ -1,5 +1,5 @@
1/* 7zTypes.h -- Basic types 1/* 7zTypes.h -- Basic types
22023-04-02 : Igor Pavlov : Public domain */ 22024-01-24 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_7Z_TYPES_H 4#ifndef ZIP7_7Z_TYPES_H
5#define ZIP7_7Z_TYPES_H 5#define ZIP7_7Z_TYPES_H
@@ -530,20 +530,20 @@ struct ISzAlloc
530#define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL(ptr, type, m) 530#define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL(ptr, type, m)
531*/ 531*/
532#if defined (__clang__) || defined(__GNUC__) 532#if defined (__clang__) || defined(__GNUC__)
533#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL \ 533#define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \
534 _Pragma("GCC diagnostic push") \ 534 _Pragma("GCC diagnostic push") \
535 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") 535 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
536#define Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL \ 536#define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL \
537 _Pragma("GCC diagnostic pop") 537 _Pragma("GCC diagnostic pop")
538#else 538#else
539#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL 539#define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL
540#define Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL 540#define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL
541#endif 541#endif
542 542
543#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(ptr, type, m, p) \ 543#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(ptr, type, m, p) \
544 Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL \ 544 Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \
545 type *p = Z7_CONTAINER_FROM_VTBL(ptr, type, m); \ 545 type *p = Z7_CONTAINER_FROM_VTBL(ptr, type, m); \
546 Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL 546 Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL
547 547
548#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(type) \ 548#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(type) \
549 Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(pp, type, vt, p) 549 Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(pp, type, vt, p)
diff --git a/C/7zVersion.h b/C/7zVersion.h
index 7549239..72b915a 100644
--- a/C/7zVersion.h
+++ b/C/7zVersion.h
@@ -1,7 +1,7 @@
1#define MY_VER_MAJOR 23 1#define MY_VER_MAJOR 24
2#define MY_VER_MINOR 01 2#define MY_VER_MINOR 05
3#define MY_VER_BUILD 0 3#define MY_VER_BUILD 0
4#define MY_VERSION_NUMBERS "23.01" 4#define MY_VERSION_NUMBERS "24.05"
5#define MY_VERSION MY_VERSION_NUMBERS 5#define MY_VERSION MY_VERSION_NUMBERS
6 6
7#ifdef MY_CPU_NAME 7#ifdef MY_CPU_NAME
@@ -10,12 +10,12 @@
10 #define MY_VERSION_CPU MY_VERSION 10 #define MY_VERSION_CPU MY_VERSION
11#endif 11#endif
12 12
13#define MY_DATE "2023-06-20" 13#define MY_DATE "2024-05-14"
14#undef MY_COPYRIGHT 14#undef MY_COPYRIGHT
15#undef MY_VERSION_COPYRIGHT_DATE 15#undef MY_VERSION_COPYRIGHT_DATE
16#define MY_AUTHOR_NAME "Igor Pavlov" 16#define MY_AUTHOR_NAME "Igor Pavlov"
17#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" 17#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
18#define MY_COPYRIGHT_CR "Copyright (c) 1999-2023 Igor Pavlov" 18#define MY_COPYRIGHT_CR "Copyright (c) 1999-2024 Igor Pavlov"
19 19
20#ifdef USE_COPYRIGHT_CR 20#ifdef USE_COPYRIGHT_CR
21 #define MY_COPYRIGHT MY_COPYRIGHT_CR 21 #define MY_COPYRIGHT MY_COPYRIGHT_CR
diff --git a/C/7zip_gcc_c.mak b/C/7zip_gcc_c.mak
index f19a99b..195d23d 100644
--- a/C/7zip_gcc_c.mak
+++ b/C/7zip_gcc_c.mak
@@ -22,8 +22,8 @@ CFLAGS_BASE_LIST = -c
22# for ASM file 22# for ASM file
23# CFLAGS_BASE_LIST = -S 23# CFLAGS_BASE_LIST = -S
24 24
25FLAGS_FLTO =
26FLAGS_FLTO = -flto 25FLAGS_FLTO = -flto
26FLAGS_FLTO =
27 27
28CFLAGS_BASE = $(MY_ARCH_2) -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \ 28CFLAGS_BASE = $(MY_ARCH_2) -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \
29 -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE 29 -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
@@ -329,7 +329,7 @@ endif
329 329
330ifdef IS_ARM64 330ifdef IS_ARM64
331$O/LzmaDecOpt.o: ../../../Asm/arm64/LzmaDecOpt.S ../../../Asm/arm64/7zAsm.S 331$O/LzmaDecOpt.o: ../../../Asm/arm64/LzmaDecOpt.S ../../../Asm/arm64/7zAsm.S
332 $(CC) $(CFLAGS) $< 332 $(CC) $(CFLAGS) $(ASM_FLAGS) $<
333endif 333endif
334 334
335$O/LzmaDec.o: ../../LzmaDec.c 335$O/LzmaDec.o: ../../LzmaDec.c
diff --git a/C/Aes.c b/C/Aes.c
index bcaafab..abc5d24 100644
--- a/C/Aes.c
+++ b/C/Aes.c
@@ -1,5 +1,5 @@
1/* Aes.c -- AES encryption / decryption 1/* Aes.c -- AES encryption / decryption
22023-04-02 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -13,7 +13,9 @@ AES_CODE_FUNC g_AesCtr_Code;
13UInt32 g_Aes_SupportedFunctions_Flags; 13UInt32 g_Aes_SupportedFunctions_Flags;
14#endif 14#endif
15 15
16MY_ALIGN(64)
16static UInt32 T[256 * 4]; 17static UInt32 T[256 * 4];
18MY_ALIGN(64)
17static const Byte Sbox[256] = { 19static const Byte Sbox[256] = {
18 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 20 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
19 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 21 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
@@ -33,7 +35,9 @@ static const Byte Sbox[256] = {
33 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; 35 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
34 36
35 37
38MY_ALIGN(64)
36static UInt32 D[256 * 4]; 39static UInt32 D[256 * 4];
40MY_ALIGN(64)
37static Byte InvS[256]; 41static Byte InvS[256];
38 42
39#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF) 43#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF)
@@ -54,24 +58,54 @@ static Byte InvS[256];
54// #define Z7_SHOW_AES_STATUS 58// #define Z7_SHOW_AES_STATUS
55 59
56#ifdef MY_CPU_X86_OR_AMD64 60#ifdef MY_CPU_X86_OR_AMD64
57 #define USE_HW_AES 61
58#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) 62 #if defined(__INTEL_COMPILER)
59 #if defined(__clang__) 63 #if (__INTEL_COMPILER >= 1110)
60 #if (__clang_major__ >= 8) // fix that check
61 #define USE_HW_AES
62 #endif
63 #elif defined(__GNUC__)
64 #if (__GNUC__ >= 6) // fix that check
65 #define USE_HW_AES 64 #define USE_HW_AES
65 #if (__INTEL_COMPILER >= 1900)
66 #define USE_HW_VAES
67 #endif
66 #endif 68 #endif
69 #elif defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
70 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400)
71 #define USE_HW_AES
72 #if defined(__clang__) && (__clang_major__ >= 8) \
73 || defined(__GNUC__) && (__GNUC__ >= 8)
74 #define USE_HW_VAES
75 #endif
67 #elif defined(_MSC_VER) 76 #elif defined(_MSC_VER)
68 #if _MSC_VER >= 1910 77 #define USE_HW_AES
78 #define USE_HW_VAES
79 #endif
80
81#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)
82
83 #if defined(__ARM_FEATURE_AES) \
84 || defined(__ARM_FEATURE_CRYPTO)
85 #define USE_HW_AES
86 #else
87 #if defined(MY_CPU_ARM64) \
88 || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
89 || defined(Z7_MSC_VER_ORIGINAL)
90 #if defined(__ARM_FP) && \
91 ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
92 || defined(__GNUC__) && (__GNUC__ >= 6) \
93 ) \
94 || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
95 #if defined(MY_CPU_ARM64) \
96 || !defined(Z7_CLANG_VERSION) \
97 || defined(__ARM_NEON) && \
98 (Z7_CLANG_VERSION < 170000 || \
99 Z7_CLANG_VERSION > 170001)
69 #define USE_HW_AES 100 #define USE_HW_AES
70 #endif 101 #endif
102 #endif
103 #endif
71 #endif 104 #endif
72#endif 105#endif
73 106
74#ifdef USE_HW_AES 107#ifdef USE_HW_AES
108// #pragma message("=== Aes.c USE_HW_AES === ")
75#ifdef Z7_SHOW_AES_STATUS 109#ifdef Z7_SHOW_AES_STATUS
76#include <stdio.h> 110#include <stdio.h>
77#define PRF(x) x 111#define PRF(x) x
@@ -136,6 +170,7 @@ void AesGenTables(void)
136 #endif 170 #endif
137 171
138 #ifdef MY_CPU_X86_OR_AMD64 172 #ifdef MY_CPU_X86_OR_AMD64
173 #ifdef USE_HW_VAES
139 if (CPU_IsSupported_VAES_AVX2()) 174 if (CPU_IsSupported_VAES_AVX2())
140 { 175 {
141 PRF(printf("\n===vaes avx2\n")); 176 PRF(printf("\n===vaes avx2\n"));
@@ -146,6 +181,7 @@ void AesGenTables(void)
146 #endif 181 #endif
147 } 182 }
148 #endif 183 #endif
184 #endif
149 } 185 }
150 #endif 186 #endif
151 187
diff --git a/C/AesOpt.c b/C/AesOpt.c
index cfa6413..58769ea 100644
--- a/C/AesOpt.c
+++ b/C/AesOpt.c
@@ -1,5 +1,5 @@
1/* AesOpt.c -- AES optimized code for x86 AES hardware instructions 1/* AesOpt.c -- AES optimized code for x86 AES hardware instructions
22023-04-02 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -15,8 +15,8 @@
15 #define USE_INTEL_VAES 15 #define USE_INTEL_VAES
16 #endif 16 #endif
17 #endif 17 #endif
18 #elif defined(__clang__) && (__clang_major__ > 3 || __clang_major__ == 3 && __clang_minor__ >= 8) \ 18 #elif defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
19 || defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4) 19 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400)
20 #define USE_INTEL_AES 20 #define USE_INTEL_AES
21 #if !defined(__AES__) 21 #if !defined(__AES__)
22 #define ATTRIB_AES __attribute__((__target__("aes"))) 22 #define ATTRIB_AES __attribute__((__target__("aes")))
@@ -35,27 +35,37 @@
35 #define USE_INTEL_VAES 35 #define USE_INTEL_VAES
36 #endif 36 #endif
37 #endif 37 #endif
38 #ifndef USE_INTEL_AES
39 #define Z7_USE_AES_HW_STUB
40 #endif
41 #ifndef USE_INTEL_VAES
42 #define Z7_USE_VAES_HW_STUB
43 #endif
38 #endif 44 #endif
39 45
40#ifndef ATTRIB_AES 46 #ifndef USE_INTEL_AES
41 #define ATTRIB_AES 47 // #define Z7_USE_AES_HW_STUB // for debug
42#endif 48 #endif
43#ifndef ATTRIB_VAES 49 #ifndef USE_INTEL_VAES
44 #define ATTRIB_VAES 50 // #define Z7_USE_VAES_HW_STUB // for debug
45#endif 51 #endif
46 52
47 53
48#ifdef USE_INTEL_AES 54#ifdef USE_INTEL_AES
49 55
50#include <wmmintrin.h> 56#include <wmmintrin.h>
51 57
52#ifndef USE_INTEL_VAES 58#if !defined(USE_INTEL_VAES) && defined(Z7_USE_VAES_HW_STUB)
53#define AES_TYPE_keys UInt32 59#define AES_TYPE_keys UInt32
54#define AES_TYPE_data Byte 60#define AES_TYPE_data Byte
55// #define AES_TYPE_keys __m128i 61// #define AES_TYPE_keys __m128i
56// #define AES_TYPE_data __m128i 62// #define AES_TYPE_data __m128i
57#endif 63#endif
58 64
65#ifndef ATTRIB_AES
66 #define ATTRIB_AES
67#endif
68
59#define AES_FUNC_START(name) \ 69#define AES_FUNC_START(name) \
60 void Z7_FASTCALL name(UInt32 *ivAes, Byte *data8, size_t numBlocks) 70 void Z7_FASTCALL name(UInt32 *ivAes, Byte *data8, size_t numBlocks)
61 // void Z7_FASTCALL name(__m128i *p, __m128i *data, size_t numBlocks) 71 // void Z7_FASTCALL name(__m128i *p, __m128i *data, size_t numBlocks)
@@ -69,8 +79,6 @@ AES_FUNC_START (name)
69#define MM_OP_m(op, src) MM_OP(op, m, src) 79#define MM_OP_m(op, src) MM_OP(op, m, src)
70 80
71#define MM_XOR( dest, src) MM_OP(_mm_xor_si128, dest, src) 81#define MM_XOR( dest, src) MM_OP(_mm_xor_si128, dest, src)
72#define AVX_XOR(dest, src) MM_OP(_mm256_xor_si256, dest, src)
73
74 82
75AES_FUNC_START2 (AesCbc_Encode_HW) 83AES_FUNC_START2 (AesCbc_Encode_HW)
76{ 84{
@@ -139,11 +147,6 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
139#define XOR_data_M1(reg, ii) MM_XOR (reg, data[ii- 1]) 147#define XOR_data_M1(reg, ii) MM_XOR (reg, data[ii- 1])
140#endif 148#endif
141 149
142#define AVX_DECLARE_VAR(reg, ii) __m256i reg;
143#define AVX_LOAD_data( reg, ii) reg = ((const __m256i *)(const void *)data)[ii];
144#define AVX_STORE_data( reg, ii) ((__m256i *)(void *)data)[ii] = reg;
145#define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, (((const __m256i *)(const void *)(data - 1))[ii]))
146
147#define MM_OP_key(op, reg) MM_OP(op, reg, key); 150#define MM_OP_key(op, reg) MM_OP(op, reg, key);
148 151
149#define AES_DEC( reg, ii) MM_OP_key (_mm_aesdec_si128, reg) 152#define AES_DEC( reg, ii) MM_OP_key (_mm_aesdec_si128, reg)
@@ -152,27 +155,13 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
152#define AES_ENC_LAST( reg, ii) MM_OP_key (_mm_aesenclast_si128, reg) 155#define AES_ENC_LAST( reg, ii) MM_OP_key (_mm_aesenclast_si128, reg)
153#define AES_XOR( reg, ii) MM_OP_key (_mm_xor_si128, reg) 156#define AES_XOR( reg, ii) MM_OP_key (_mm_xor_si128, reg)
154 157
155
156#define AVX_AES_DEC( reg, ii) MM_OP_key (_mm256_aesdec_epi128, reg)
157#define AVX_AES_DEC_LAST( reg, ii) MM_OP_key (_mm256_aesdeclast_epi128, reg)
158#define AVX_AES_ENC( reg, ii) MM_OP_key (_mm256_aesenc_epi128, reg)
159#define AVX_AES_ENC_LAST( reg, ii) MM_OP_key (_mm256_aesenclast_epi128, reg)
160#define AVX_AES_XOR( reg, ii) MM_OP_key (_mm256_xor_si256, reg)
161
162#define CTR_START(reg, ii) MM_OP (_mm_add_epi64, ctr, one) reg = ctr; 158#define CTR_START(reg, ii) MM_OP (_mm_add_epi64, ctr, one) reg = ctr;
163#define CTR_END( reg, ii) MM_XOR (data[ii], reg) 159#define CTR_END( reg, ii) MM_XOR (data[ii], reg)
164 160
165#define AVX_CTR_START(reg, ii) MM_OP (_mm256_add_epi64, ctr2, two) reg = _mm256_xor_si256(ctr2, key);
166#define AVX_CTR_END( reg, ii) AVX_XOR (((__m256i *)(void *)data)[ii], reg)
167
168#define WOP_KEY(op, n) { \ 161#define WOP_KEY(op, n) { \
169 const __m128i key = w[n]; \ 162 const __m128i key = w[n]; \
170 WOP(op); } 163 WOP(op); }
171 164
172#define AVX_WOP_KEY(op, n) { \
173 const __m256i key = w[n]; \
174 WOP(op); }
175
176 165
177#define WIDE_LOOP_START \ 166#define WIDE_LOOP_START \
178 dataEnd = data + numBlocks; \ 167 dataEnd = data + numBlocks; \
@@ -190,6 +179,40 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
190 for (; data < dataEnd; data++) 179 for (; data < dataEnd; data++)
191 180
192 181
182
183#ifdef USE_INTEL_VAES
184
185#define AVX_XOR(dest, src) MM_OP(_mm256_xor_si256, dest, src)
186#define AVX_DECLARE_VAR(reg, ii) __m256i reg;
187#define AVX_LOAD_data( reg, ii) reg = ((const __m256i *)(const void *)data)[ii];
188#define AVX_STORE_data( reg, ii) ((__m256i *)(void *)data)[ii] = reg;
189/*
190AVX_XOR_data_M1() needs unaligned memory load
191if (we don't use _mm256_loadu_si256() here)
192{
193 Most compilers with enabled optimizations generate fused AVX (LOAD + OP)
194 instruction that can load unaligned data.
195 But GCC and CLANG without -O2 or -O1 optimizations can generate separated
196 LOAD-ALIGNED (vmovdqa) instruction that will fail on execution.
197}
198Note: some compilers generate more instructions, if we use _mm256_loadu_si256() here.
199v23.02: we use _mm256_loadu_si256() here, because we need compatibility with any compiler.
200*/
201#define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, _mm256_loadu_si256(&(((const __m256i *)(const void *)(data - 1))[ii])))
202// for debug only: the following code will fail on execution, if compiled by some compilers:
203// #define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, (((const __m256i *)(const void *)(data - 1))[ii]))
204
205#define AVX_AES_DEC( reg, ii) MM_OP_key (_mm256_aesdec_epi128, reg)
206#define AVX_AES_DEC_LAST( reg, ii) MM_OP_key (_mm256_aesdeclast_epi128, reg)
207#define AVX_AES_ENC( reg, ii) MM_OP_key (_mm256_aesenc_epi128, reg)
208#define AVX_AES_ENC_LAST( reg, ii) MM_OP_key (_mm256_aesenclast_epi128, reg)
209#define AVX_AES_XOR( reg, ii) MM_OP_key (_mm256_xor_si256, reg)
210#define AVX_CTR_START(reg, ii) MM_OP (_mm256_add_epi64, ctr2, two) reg = _mm256_xor_si256(ctr2, key);
211#define AVX_CTR_END( reg, ii) AVX_XOR (((__m256i *)(void *)data)[ii], reg)
212#define AVX_WOP_KEY(op, n) { \
213 const __m256i key = w[n]; \
214 WOP(op); }
215
193#define NUM_AES_KEYS_MAX 15 216#define NUM_AES_KEYS_MAX 15
194 217
195#define WIDE_LOOP_START_AVX(OP) \ 218#define WIDE_LOOP_START_AVX(OP) \
@@ -214,6 +237,9 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
214/* MSVC for x86: If we don't call _mm256_zeroupper(), and -arch:IA32 is not specified, 237/* MSVC for x86: If we don't call _mm256_zeroupper(), and -arch:IA32 is not specified,
215 MSVC still can insert vzeroupper instruction. */ 238 MSVC still can insert vzeroupper instruction. */
216 239
240#endif
241
242
217 243
218AES_FUNC_START2 (AesCbc_Decode_HW) 244AES_FUNC_START2 (AesCbc_Decode_HW)
219{ 245{
@@ -380,6 +406,9 @@ required that <immintrin.h> must be included before <avxintrin.h>.
380 #endif 406 #endif
381#endif // __clang__ && _MSC_VER 407#endif // __clang__ && _MSC_VER
382 408
409#ifndef ATTRIB_VAES
410 #define ATTRIB_VAES
411#endif
383 412
384#define VAES_FUNC_START2(name) \ 413#define VAES_FUNC_START2(name) \
385AES_FUNC_START (name); \ 414AES_FUNC_START (name); \
@@ -519,10 +548,18 @@ VAES_FUNC_START2 (AesCtr_Code_HW_256)
519 548
520/* no USE_INTEL_AES */ 549/* no USE_INTEL_AES */
521 550
551#if defined(Z7_USE_AES_HW_STUB)
552// We can compile this file with another C compiler,
553// or we can compile asm version.
554// So we can generate real code instead of this stub function.
555// #if defined(_MSC_VER)
522#pragma message("AES HW_SW stub was used") 556#pragma message("AES HW_SW stub was used")
557// #endif
523 558
559#if !defined(USE_INTEL_VAES) && defined(Z7_USE_VAES_HW_STUB)
524#define AES_TYPE_keys UInt32 560#define AES_TYPE_keys UInt32
525#define AES_TYPE_data Byte 561#define AES_TYPE_data Byte
562#endif
526 563
527#define AES_FUNC_START(name) \ 564#define AES_FUNC_START(name) \
528 void Z7_FASTCALL name(UInt32 *p, Byte *data, size_t numBlocks) \ 565 void Z7_FASTCALL name(UInt32 *p, Byte *data, size_t numBlocks) \
@@ -535,13 +572,16 @@ VAES_FUNC_START2 (AesCtr_Code_HW_256)
535AES_COMPAT_STUB (AesCbc_Encode) 572AES_COMPAT_STUB (AesCbc_Encode)
536AES_COMPAT_STUB (AesCbc_Decode) 573AES_COMPAT_STUB (AesCbc_Decode)
537AES_COMPAT_STUB (AesCtr_Code) 574AES_COMPAT_STUB (AesCtr_Code)
575#endif // Z7_USE_AES_HW_STUB
538 576
539#endif // USE_INTEL_AES 577#endif // USE_INTEL_AES
540 578
541 579
542#ifndef USE_INTEL_VAES 580#ifndef USE_INTEL_VAES
543 581#if defined(Z7_USE_VAES_HW_STUB)
582// #if defined(_MSC_VER)
544#pragma message("VAES HW_SW stub was used") 583#pragma message("VAES HW_SW stub was used")
584// #endif
545 585
546#define VAES_COMPAT_STUB(name) \ 586#define VAES_COMPAT_STUB(name) \
547 void Z7_FASTCALL name ## _256(UInt32 *p, Byte *data, size_t numBlocks); \ 587 void Z7_FASTCALL name ## _256(UInt32 *p, Byte *data, size_t numBlocks); \
@@ -550,36 +590,59 @@ AES_COMPAT_STUB (AesCtr_Code)
550 590
551VAES_COMPAT_STUB (AesCbc_Decode_HW) 591VAES_COMPAT_STUB (AesCbc_Decode_HW)
552VAES_COMPAT_STUB (AesCtr_Code_HW) 592VAES_COMPAT_STUB (AesCtr_Code_HW)
553 593#endif
554#endif // ! USE_INTEL_VAES 594#endif // ! USE_INTEL_VAES
555 595
556 596
597
598
557#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) 599#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)
558 600
559 #if defined(__clang__) 601 #if defined(__ARM_FEATURE_AES) \
560 #if (__clang_major__ >= 8) // fix that check 602 || defined(__ARM_FEATURE_CRYPTO)
603 #define USE_HW_AES
604 #else
605 #if defined(MY_CPU_ARM64) \
606 || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
607 || defined(Z7_MSC_VER_ORIGINAL)
608 #if defined(__ARM_FP) && \
609 ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
610 || defined(__GNUC__) && (__GNUC__ >= 6) \
611 ) \
612 || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
613 #if defined(MY_CPU_ARM64) \
614 || !defined(Z7_CLANG_VERSION) \
615 || defined(__ARM_NEON) && \
616 (Z7_CLANG_VERSION < 170000 || \
617 Z7_CLANG_VERSION > 170001)
561 #define USE_HW_AES 618 #define USE_HW_AES
562 #endif 619 #endif
563 #elif defined(__GNUC__)
564 #if (__GNUC__ >= 6) // fix that check
565 #define USE_HW_AES
566 #endif 620 #endif
567 #elif defined(_MSC_VER)
568 #if _MSC_VER >= 1910
569 #define USE_HW_AES
570 #endif 621 #endif
571 #endif 622 #endif
572 623
573#ifdef USE_HW_AES 624#ifdef USE_HW_AES
574 625
575// #pragma message("=== AES HW === ") 626// #pragma message("=== AES HW === ")
627// __ARM_FEATURE_CRYPTO macro is deprecated in favor of the finer grained feature macro __ARM_FEATURE_AES
576 628
577#if defined(__clang__) || defined(__GNUC__) 629#if defined(__clang__) || defined(__GNUC__)
630#if !defined(__ARM_FEATURE_AES) && \
631 !defined(__ARM_FEATURE_CRYPTO)
578 #ifdef MY_CPU_ARM64 632 #ifdef MY_CPU_ARM64
633#if defined(__clang__)
634 #define ATTRIB_AES __attribute__((__target__("crypto")))
635#else
579 #define ATTRIB_AES __attribute__((__target__("+crypto"))) 636 #define ATTRIB_AES __attribute__((__target__("+crypto")))
637#endif
580 #else 638 #else
639#if defined(__clang__)
640 #define ATTRIB_AES __attribute__((__target__("armv8-a,aes")))
641#else
581 #define ATTRIB_AES __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) 642 #define ATTRIB_AES __attribute__((__target__("fpu=crypto-neon-fp-armv8")))
643#endif
582 #endif 644 #endif
645#endif
583#else 646#else
584 // _MSC_VER 647 // _MSC_VER
585 // for arm32 648 // for arm32
@@ -590,12 +653,60 @@ VAES_COMPAT_STUB (AesCtr_Code_HW)
590 #define ATTRIB_AES 653 #define ATTRIB_AES
591#endif 654#endif
592 655
593#if defined(_MSC_VER) && defined(MY_CPU_ARM64) 656#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
594#include <arm64_neon.h> 657#include <arm64_neon.h>
595#else 658#else
659/*
660 clang-17.0.1: error : Cannot select: intrinsic %llvm.arm.neon.aese
661 clang
662 3.8.1 : __ARM_NEON : defined(__ARM_FEATURE_CRYPTO)
663 7.0.1 : __ARM_NEON : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_CRYPTO)
664 11.?.0 : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_CRYPTO)
665 13.0.1 : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_AES)
666 16 : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8
667*/
668#if defined(__clang__) && __clang_major__ < 16
669#if !defined(__ARM_FEATURE_AES) && \
670 !defined(__ARM_FEATURE_CRYPTO)
671// #pragma message("=== we set __ARM_FEATURE_CRYPTO 1 === ")
672 Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
673 #define Z7_ARM_FEATURE_CRYPTO_WAS_SET 1
674// #if defined(__clang__) && __clang_major__ < 13
675 #define __ARM_FEATURE_CRYPTO 1
676// #else
677 #define __ARM_FEATURE_AES 1
678// #endif
679 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
680#endif
681#endif // clang
682
683#if defined(__clang__)
684
685#if defined(__ARM_ARCH) && __ARM_ARCH < 8
686 Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
687// #pragma message("#define __ARM_ARCH 8")
688 #undef __ARM_ARCH
689 #define __ARM_ARCH 8
690 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
691#endif
692
693#endif // clang
694
596#include <arm_neon.h> 695#include <arm_neon.h>
696
697#if defined(Z7_ARM_FEATURE_CRYPTO_WAS_SET) && \
698 defined(__ARM_FEATURE_CRYPTO) && \
699 defined(__ARM_FEATURE_AES)
700Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
701 #undef __ARM_FEATURE_CRYPTO
702 #undef __ARM_FEATURE_AES
703 #undef Z7_ARM_FEATURE_CRYPTO_WAS_SET
704Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
705// #pragma message("=== we undefine __ARM_FEATURE_CRYPTO === ")
597#endif 706#endif
598 707
708#endif // Z7_MSC_VER_ORIGINAL
709
599typedef uint8x16_t v128; 710typedef uint8x16_t v128;
600 711
601#define AES_FUNC_START(name) \ 712#define AES_FUNC_START(name) \
@@ -620,7 +731,7 @@ AES_FUNC_START (name)
620 731
621AES_FUNC_START2 (AesCbc_Encode_HW) 732AES_FUNC_START2 (AesCbc_Encode_HW)
622{ 733{
623 v128 *p = (v128*)(void*)ivAes; 734 v128 * const p = (v128*)(void*)ivAes;
624 v128 *data = (v128*)(void*)data8; 735 v128 *data = (v128*)(void*)data8;
625 v128 m = *p; 736 v128 m = *p;
626 const v128 k0 = p[2]; 737 const v128 k0 = p[2];
@@ -639,7 +750,7 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
639 const v128 k_z0 = w[2]; 750 const v128 k_z0 = w[2];
640 for (; numBlocks != 0; numBlocks--, data++) 751 for (; numBlocks != 0; numBlocks--, data++)
641 { 752 {
642 MM_XOR_m (*data); 753 MM_XOR_m (*data)
643 AES_E_MC_m (k0) 754 AES_E_MC_m (k0)
644 AES_E_MC_m (k1) 755 AES_E_MC_m (k1)
645 AES_E_MC_m (k2) 756 AES_E_MC_m (k2)
@@ -660,7 +771,7 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
660 } 771 }
661 } 772 }
662 AES_E_m (k_z1) 773 AES_E_m (k_z1)
663 MM_XOR_m (k_z0); 774 MM_XOR_m (k_z0)
664 *data = m; 775 *data = m;
665 } 776 }
666 *p = m; 777 *p = m;
@@ -745,7 +856,7 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
745 while (w != p); 856 while (w != p);
746 WOP_KEY (AES_D, 1) 857 WOP_KEY (AES_D, 1)
747 WOP_KEY (AES_XOR, 0) 858 WOP_KEY (AES_XOR, 0)
748 MM_XOR (m0, iv); 859 MM_XOR (m0, iv)
749 WOP_M1 (XOR_data_M1) 860 WOP_M1 (XOR_data_M1)
750 iv = data[NUM_WAYS - 1]; 861 iv = data[NUM_WAYS - 1];
751 WOP (STORE_data) 862 WOP (STORE_data)
@@ -759,14 +870,14 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
759 AES_D_IMC_m (w[2]) 870 AES_D_IMC_m (w[2])
760 do 871 do
761 { 872 {
762 AES_D_IMC_m (w[1]); 873 AES_D_IMC_m (w[1])
763 AES_D_IMC_m (w[0]); 874 AES_D_IMC_m (w[0])
764 w -= 2; 875 w -= 2;
765 } 876 }
766 while (w != p); 877 while (w != p);
767 AES_D_m (w[1]); 878 AES_D_m (w[1])
768 MM_XOR_m (w[0]); 879 MM_XOR_m (w[0])
769 MM_XOR_m (iv); 880 MM_XOR_m (iv)
770 iv = *data; 881 iv = *data;
771 *data = m; 882 *data = m;
772 } 883 }
@@ -783,6 +894,12 @@ AES_FUNC_START2 (AesCtr_Code_HW)
783 const v128 *wEnd = p + ((size_t)*(const UInt32 *)(p + 1)) * 2; 894 const v128 *wEnd = p + ((size_t)*(const UInt32 *)(p + 1)) * 2;
784 const v128 *dataEnd; 895 const v128 *dataEnd;
785 uint64x2_t one = vdupq_n_u64(0); 896 uint64x2_t one = vdupq_n_u64(0);
897
898// the bug in clang:
899// __builtin_neon_vsetq_lane_i64(__s0, (int8x16_t)__s1, __p2);
900#if defined(__clang__) && (__clang_major__ <= 9)
901#pragma GCC diagnostic ignored "-Wvector-conversion"
902#endif
786 one = vsetq_lane_u64(1, one, 0); 903 one = vsetq_lane_u64(1, one, 0);
787 p += 2; 904 p += 2;
788 905
@@ -809,11 +926,11 @@ AES_FUNC_START2 (AesCtr_Code_HW)
809 { 926 {
810 const v128 *w = p; 927 const v128 *w = p;
811 v128 m; 928 v128 m;
812 CTR_START (m, 0); 929 CTR_START (m, 0)
813 do 930 do
814 { 931 {
815 AES_E_MC_m (w[0]); 932 AES_E_MC_m (w[0])
816 AES_E_MC_m (w[1]); 933 AES_E_MC_m (w[1])
817 w += 2; 934 w += 2;
818 } 935 }
819 while (w != wEnd); 936 while (w != wEnd);
diff --git a/C/Alloc.c b/C/Alloc.c
index d841bf2..63e1a12 100644
--- a/C/Alloc.c
+++ b/C/Alloc.c
@@ -1,5 +1,5 @@
1/* Alloc.c -- Memory allocation functions 1/* Alloc.c -- Memory allocation functions
22023-04-02 : Igor Pavlov : Public domain */ 22024-02-18 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -10,19 +10,18 @@
10 10
11#include "Alloc.h" 11#include "Alloc.h"
12 12
13#ifdef _WIN32 13#if defined(Z7_LARGE_PAGES) && defined(_WIN32) && \
14#ifdef Z7_LARGE_PAGES 14 (!defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0502) // < Win2003 (xp-64)
15#if defined(__clang__) || defined(__GNUC__) 15 #define Z7_USE_DYN_GetLargePageMinimum
16typedef void (*Z7_voidFunction)(void); 16#endif
17#define MY_CAST_FUNC (Z7_voidFunction) 17
18#elif defined(_MSC_VER) && _MSC_VER > 1920 18// for debug:
19#define MY_CAST_FUNC (void *) 19#if 0
20// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()' 20#if defined(__CHERI__) && defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)
21#else 21// #pragma message("=== Z7_ALLOC_NO_OFFSET_ALLOCATOR === ")
22#define MY_CAST_FUNC 22#define Z7_ALLOC_NO_OFFSET_ALLOCATOR
23#endif
23#endif 24#endif
24#endif // Z7_LARGE_PAGES
25#endif // _WIN32
26 25
27// #define SZ_ALLOC_DEBUG 26// #define SZ_ALLOC_DEBUG
28/* #define SZ_ALLOC_DEBUG */ 27/* #define SZ_ALLOC_DEBUG */
@@ -146,7 +145,9 @@ static void PrintAddr(void *p)
146#define PRINT_FREE(name, cnt, ptr) 145#define PRINT_FREE(name, cnt, ptr)
147#define Print(s) 146#define Print(s)
148#define PrintLn() 147#define PrintLn()
148#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
149#define PrintHex(v, align) 149#define PrintHex(v, align)
150#endif
150#define PrintAddr(p) 151#define PrintAddr(p)
151 152
152#endif 153#endif
@@ -246,9 +247,9 @@ void MidFree(void *address)
246#ifdef Z7_LARGE_PAGES 247#ifdef Z7_LARGE_PAGES
247 248
248#ifdef MEM_LARGE_PAGES 249#ifdef MEM_LARGE_PAGES
249 #define MY__MEM_LARGE_PAGES MEM_LARGE_PAGES 250 #define MY_MEM_LARGE_PAGES MEM_LARGE_PAGES
250#else 251#else
251 #define MY__MEM_LARGE_PAGES 0x20000000 252 #define MY_MEM_LARGE_PAGES 0x20000000
252#endif 253#endif
253 254
254extern 255extern
@@ -258,19 +259,23 @@ typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID);
258 259
259void SetLargePageSize(void) 260void SetLargePageSize(void)
260{ 261{
261 #ifdef Z7_LARGE_PAGES
262 SIZE_T size; 262 SIZE_T size;
263#ifdef Z7_USE_DYN_GetLargePageMinimum
264Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
265
263 const 266 const
264 Func_GetLargePageMinimum fn = 267 Func_GetLargePageMinimum fn =
265 (Func_GetLargePageMinimum) MY_CAST_FUNC GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), 268 (Func_GetLargePageMinimum) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
266 "GetLargePageMinimum"); 269 "GetLargePageMinimum");
267 if (!fn) 270 if (!fn)
268 return; 271 return;
269 size = fn(); 272 size = fn();
273#else
274 size = GetLargePageMinimum();
275#endif
270 if (size == 0 || (size & (size - 1)) != 0) 276 if (size == 0 || (size & (size - 1)) != 0)
271 return; 277 return;
272 g_LargePageSize = size; 278 g_LargePageSize = size;
273 #endif
274} 279}
275 280
276#endif // Z7_LARGE_PAGES 281#endif // Z7_LARGE_PAGES
@@ -292,7 +297,7 @@ void *BigAlloc(size_t size)
292 size2 = (size + ps) & ~ps; 297 size2 = (size + ps) & ~ps;
293 if (size2 >= size) 298 if (size2 >= size)
294 { 299 {
295 void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY__MEM_LARGE_PAGES, PAGE_READWRITE); 300 void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY_MEM_LARGE_PAGES, PAGE_READWRITE);
296 if (p) 301 if (p)
297 { 302 {
298 PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p) 303 PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p)
@@ -328,20 +333,7 @@ const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };
328const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; 333const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
329#endif 334#endif
330 335
331/* 336#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
332 uintptr_t : <stdint.h> C99 (optional)
333 : unsupported in VS6
334*/
335
336#ifdef _WIN32
337 typedef UINT_PTR UIntPtr;
338#else
339 /*
340 typedef uintptr_t UIntPtr;
341 */
342 typedef ptrdiff_t UIntPtr;
343#endif
344
345 337
346#define ADJUST_ALLOC_SIZE 0 338#define ADJUST_ALLOC_SIZE 0
347/* 339/*
@@ -352,14 +344,36 @@ const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
352 MyAlloc() can return address that is NOT multiple of sizeof(void *). 344 MyAlloc() can return address that is NOT multiple of sizeof(void *).
353*/ 345*/
354 346
355
356/* 347/*
357#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1)))) 348 uintptr_t : <stdint.h> C99 (optional)
349 : unsupported in VS6
358*/ 350*/
359#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1)))) 351typedef
352 #ifdef _WIN32
353 UINT_PTR
354 #elif 1
355 uintptr_t
356 #else
357 ptrdiff_t
358 #endif
359 MY_uintptr_t;
360
361#if 0 \
362 || (defined(__CHERI__) \
363 || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ > 8))
364// for 128-bit pointers (cheri):
365#define MY_ALIGN_PTR_DOWN(p, align) \
366 ((void *)((char *)(p) - ((size_t)(MY_uintptr_t)(p) & ((align) - 1))))
367#else
368#define MY_ALIGN_PTR_DOWN(p, align) \
369 ((void *)((((MY_uintptr_t)(p)) & ~((MY_uintptr_t)(align) - 1))))
370#endif
360 371
372#endif
361 373
362#if !defined(_WIN32) && defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) 374#if !defined(_WIN32) \
375 && (defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) \
376 || defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L))
363 #define USE_posix_memalign 377 #define USE_posix_memalign
364#endif 378#endif
365 379
@@ -399,14 +413,13 @@ static int posix_memalign(void **ptr, size_t align, size_t size)
399 413
400#define ALLOC_ALIGN_SIZE ((size_t)1 << 7) 414#define ALLOC_ALIGN_SIZE ((size_t)1 << 7)
401 415
402static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) 416void *z7_AlignedAlloc(size_t size)
403{ 417{
404 #ifndef USE_posix_memalign 418#ifndef USE_posix_memalign
405 419
406 void *p; 420 void *p;
407 void *pAligned; 421 void *pAligned;
408 size_t newSize; 422 size_t newSize;
409 UNUSED_VAR(pp)
410 423
411 /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned 424 /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
412 block to prevent cache line sharing with another allocated blocks */ 425 block to prevent cache line sharing with another allocated blocks */
@@ -431,10 +444,9 @@ static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
431 444
432 return pAligned; 445 return pAligned;
433 446
434 #else 447#else
435 448
436 void *p; 449 void *p;
437 UNUSED_VAR(pp)
438 if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size)) 450 if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size))
439 return NULL; 451 return NULL;
440 452
@@ -443,19 +455,37 @@ static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
443 455
444 return p; 456 return p;
445 457
446 #endif 458#endif
459}
460
461
462void z7_AlignedFree(void *address)
463{
464#ifndef USE_posix_memalign
465 if (address)
466 MyFree(((void **)address)[-1]);
467#else
468 free(address);
469#endif
470}
471
472
473static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
474{
475 UNUSED_VAR(pp)
476 return z7_AlignedAlloc(size);
447} 477}
448 478
449 479
450static void SzAlignedFree(ISzAllocPtr pp, void *address) 480static void SzAlignedFree(ISzAllocPtr pp, void *address)
451{ 481{
452 UNUSED_VAR(pp) 482 UNUSED_VAR(pp)
453 #ifndef USE_posix_memalign 483#ifndef USE_posix_memalign
454 if (address) 484 if (address)
455 MyFree(((void **)address)[-1]); 485 MyFree(((void **)address)[-1]);
456 #else 486#else
457 free(address); 487 free(address);
458 #endif 488#endif
459} 489}
460 490
461 491
@@ -463,16 +493,44 @@ const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree };
463 493
464 494
465 495
466#define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *))
467
468/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */ 496/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */
469#define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1] 497#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
470/* 498#if 1
471#define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1] 499 #define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *))
472*/ 500 #define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1]
501#else
502 // we can use this simplified code,
503 // if (CAlignOffsetAlloc::offset == (k * sizeof(void *))
504 #define REAL_BLOCK_PTR_VAR(p) (((void **)(p))[-1])
505#endif
506#endif
507
508
509#if 0
510#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
511#include <stdio.h>
512static void PrintPtr(const char *s, const void *p)
513{
514 const Byte *p2 = (const Byte *)&p;
515 unsigned i;
516 printf("%s %p ", s, p);
517 for (i = sizeof(p); i != 0;)
518 {
519 i--;
520 printf("%02x", p2[i]);
521 }
522 printf("\n");
523}
524#endif
525#endif
526
473 527
474static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) 528static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)
475{ 529{
530#if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR)
531 UNUSED_VAR(pp)
532 return z7_AlignedAlloc(size);
533#else
476 const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); 534 const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt);
477 void *adr; 535 void *adr;
478 void *pAligned; 536 void *pAligned;
@@ -501,6 +559,12 @@ static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)
501 pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr + 559 pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr +
502 alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset; 560 alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset;
503 561
562#if 0
563 printf("\nalignSize = %6x, offset=%6x, size=%8x \n", (unsigned)alignSize, (unsigned)p->offset, (unsigned)size);
564 PrintPtr("base", adr);
565 PrintPtr("alig", pAligned);
566#endif
567
504 PrintLn(); 568 PrintLn();
505 Print("- Aligned: "); 569 Print("- Aligned: ");
506 Print(" size="); PrintHex(size, 8); 570 Print(" size="); PrintHex(size, 8);
@@ -512,11 +576,16 @@ static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)
512 REAL_BLOCK_PTR_VAR(pAligned) = adr; 576 REAL_BLOCK_PTR_VAR(pAligned) = adr;
513 577
514 return pAligned; 578 return pAligned;
579#endif
515} 580}
516 581
517 582
518static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) 583static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address)
519{ 584{
585#if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR)
586 UNUSED_VAR(pp)
587 z7_AlignedFree(address);
588#else
520 if (address) 589 if (address)
521 { 590 {
522 const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); 591 const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt);
@@ -525,6 +594,7 @@ static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address)
525 PrintLn(); 594 PrintLn();
526 ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address)); 595 ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address));
527 } 596 }
597#endif
528} 598}
529 599
530 600
diff --git a/C/Alloc.h b/C/Alloc.h
index fac5b62..01bf6b7 100644
--- a/C/Alloc.h
+++ b/C/Alloc.h
@@ -1,5 +1,5 @@
1/* Alloc.h -- Memory allocation functions 1/* Alloc.h -- Memory allocation functions
22023-03-04 : Igor Pavlov : Public domain */ 22024-01-22 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_ALLOC_H 4#ifndef ZIP7_INC_ALLOC_H
5#define ZIP7_INC_ALLOC_H 5#define ZIP7_INC_ALLOC_H
@@ -22,6 +22,9 @@ void *MyAlloc(size_t size);
22void MyFree(void *address); 22void MyFree(void *address);
23void *MyRealloc(void *address, size_t size); 23void *MyRealloc(void *address, size_t size);
24 24
25void *z7_AlignedAlloc(size_t size);
26void z7_AlignedFree(void *p);
27
25#ifdef _WIN32 28#ifdef _WIN32
26 29
27#ifdef Z7_LARGE_PAGES 30#ifdef Z7_LARGE_PAGES
@@ -33,12 +36,14 @@ void MidFree(void *address);
33void *BigAlloc(size_t size); 36void *BigAlloc(size_t size);
34void BigFree(void *address); 37void BigFree(void *address);
35 38
39/* #define Z7_BIG_ALLOC_IS_ZERO_FILLED */
40
36#else 41#else
37 42
38#define MidAlloc(size) MyAlloc(size) 43#define MidAlloc(size) z7_AlignedAlloc(size)
39#define MidFree(address) MyFree(address) 44#define MidFree(address) z7_AlignedFree(address)
40#define BigAlloc(size) MyAlloc(size) 45#define BigAlloc(size) z7_AlignedAlloc(size)
41#define BigFree(address) MyFree(address) 46#define BigFree(address) z7_AlignedFree(address)
42 47
43#endif 48#endif
44 49
diff --git a/C/Asm_c.mak b/C/Asm_c.mak
new file mode 100644
index 0000000..9431816
--- /dev/null
+++ b/C/Asm_c.mak
@@ -0,0 +1,12 @@
1!IFDEF ASM_OBJS
2!IF "$(PLATFORM)" == "arm64"
3$(ASM_OBJS): ../../../Asm/arm64/$(*B).S
4 $(COMPL_ASM_CLANG)
5!ELSEIF "$(PLATFORM)" == "arm"
6$(ASM_OBJS): ../../../Asm/arm/$(*B).asm
7 $(COMPL_ASM)
8!ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips"
9$(ASM_OBJS): ../../../Asm/x86/$(*B).asm
10 $(COMPL_ASM)
11!ENDIF
12!ENDIF
diff --git a/C/Blake2.h b/C/Blake2.h
index 7235235..801ea7a 100644
--- a/C/Blake2.h
+++ b/C/Blake2.h
@@ -1,47 +1,104 @@
1/* Blake2.h -- BLAKE2 Hash 1/* Blake2.h -- BLAKE2sp Hash
22023-03-04 : Igor Pavlov : Public domain 22024-01-17 : Igor Pavlov : Public domain */
32015 : Samuel Neves : Public domain */
4 3
5#ifndef ZIP7_INC_BLAKE2_H 4#ifndef ZIP7_INC_BLAKE2_H
6#define ZIP7_INC_BLAKE2_H 5#define ZIP7_INC_BLAKE2_H
7 6
8#include "7zTypes.h" 7#include "7zTypes.h"
9 8
10EXTERN_C_BEGIN 9#if 0
10#include "Compiler.h"
11#include "CpuArch.h"
12#if defined(MY_CPU_X86_OR_AMD64)
13#if defined(__SSE2__) \
14 || defined(_MSC_VER) && _MSC_VER > 1200 \
15 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 30300) \
16 || defined(__clang__) \
17 || defined(__INTEL_COMPILER)
18#include <emmintrin.h> // SSE2
19#endif
11 20
12#define BLAKE2S_BLOCK_SIZE 64 21#if defined(__AVX2__) \
13#define BLAKE2S_DIGEST_SIZE 32 22 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
14#define BLAKE2SP_PARALLEL_DEGREE 8 23 || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \
24 || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \
25 || defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \
26 || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)
27#include <immintrin.h>
28#if defined(__clang__)
29#include <avxintrin.h>
30#include <avx2intrin.h>
31#endif
32#endif // avx2
33#endif // MY_CPU_X86_OR_AMD64
34#endif // 0
15 35
16typedef struct 36EXTERN_C_BEGIN
17{
18 UInt32 h[8];
19 UInt32 t[2];
20 UInt32 f[2];
21 Byte buf[BLAKE2S_BLOCK_SIZE];
22 UInt32 bufPos;
23 UInt32 lastNode_f1;
24 UInt32 dummy[2]; /* for sizeof(CBlake2s) alignment */
25} CBlake2s;
26
27/* You need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */
28/*
29void Blake2s_Init0(CBlake2s *p);
30void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size);
31void Blake2s_Final(CBlake2s *p, Byte *digest);
32*/
33 37
38#define Z7_BLAKE2S_BLOCK_SIZE 64
39#define Z7_BLAKE2S_DIGEST_SIZE 32
40#define Z7_BLAKE2SP_PARALLEL_DEGREE 8
41#define Z7_BLAKE2SP_NUM_STRUCT_WORDS 16
34 42
43#if 1 || defined(Z7_BLAKE2SP_USE_FUNCTIONS)
44typedef void (Z7_FASTCALL *Z7_BLAKE2SP_FUNC_COMPRESS)(UInt32 *states, const Byte *data, const Byte *end);
45typedef void (Z7_FASTCALL *Z7_BLAKE2SP_FUNC_INIT)(UInt32 *states);
46#endif
47
48// it's required that CBlake2sp is aligned for 32-bytes,
49// because the code can use unaligned access with sse and avx256.
50// but 64-bytes alignment can be better.
51MY_ALIGN(64)
35typedef struct 52typedef struct
36{ 53{
37 CBlake2s S[BLAKE2SP_PARALLEL_DEGREE]; 54 union
38 unsigned bufPos; 55 {
39} CBlake2sp; 56#if 0
57#if defined(MY_CPU_X86_OR_AMD64)
58#if defined(__SSE2__) \
59 || defined(_MSC_VER) && _MSC_VER > 1200 \
60 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 30300) \
61 || defined(__clang__) \
62 || defined(__INTEL_COMPILER)
63 __m128i _pad_align_128bit[4];
64#endif // sse2
65#if defined(__AVX2__) \
66 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
67 || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \
68 || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \
69 || defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \
70 || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)
71 __m256i _pad_align_256bit[2];
72#endif // avx2
73#endif // x86
74#endif // 0
40 75
76 void * _pad_align_ptr[8];
77 UInt32 _pad_align_32bit[16];
78 struct
79 {
80 unsigned cycPos;
81 unsigned _pad_unused;
82#if 1 || defined(Z7_BLAKE2SP_USE_FUNCTIONS)
83 Z7_BLAKE2SP_FUNC_COMPRESS func_Compress_Fast;
84 Z7_BLAKE2SP_FUNC_COMPRESS func_Compress_Single;
85 Z7_BLAKE2SP_FUNC_INIT func_Init;
86 Z7_BLAKE2SP_FUNC_INIT func_Final;
87#endif
88 } header;
89 } u;
90 // MY_ALIGN(64)
91 UInt32 states[Z7_BLAKE2SP_PARALLEL_DEGREE * Z7_BLAKE2SP_NUM_STRUCT_WORDS];
92 // MY_ALIGN(64)
93 UInt32 buf32[Z7_BLAKE2SP_PARALLEL_DEGREE * Z7_BLAKE2SP_NUM_STRUCT_WORDS * 2];
94} CBlake2sp;
41 95
96BoolInt Blake2sp_SetFunction(CBlake2sp *p, unsigned algo);
42void Blake2sp_Init(CBlake2sp *p); 97void Blake2sp_Init(CBlake2sp *p);
98void Blake2sp_InitState(CBlake2sp *p);
43void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size); 99void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size);
44void Blake2sp_Final(CBlake2sp *p, Byte *digest); 100void Blake2sp_Final(CBlake2sp *p, Byte *digest);
101void z7_Black2sp_Prepare(void);
45 102
46EXTERN_C_END 103EXTERN_C_END
47 104
diff --git a/C/Blake2s.c b/C/Blake2s.c
index 2a84b57..459e76b 100644
--- a/C/Blake2s.c
+++ b/C/Blake2s.c
@@ -1,250 +1,2645 @@
1/* Blake2s.c -- BLAKE2s and BLAKE2sp Hash 1/* Blake2s.c -- BLAKE2sp Hash
22023-03-04 : Igor Pavlov : Public domain 22024-01-29 : Igor Pavlov : Public domain
32015 : Samuel Neves : Public domain */ 32015-2019 : Samuel Neves : original code : CC0 1.0 Universal (CC0 1.0). */
4 4
5#include "Precomp.h" 5#include "Precomp.h"
6 6
7// #include <stdio.h>
7#include <string.h> 8#include <string.h>
8 9
9#include "Blake2.h" 10#include "Blake2.h"
10#include "CpuArch.h"
11#include "RotateDefs.h" 11#include "RotateDefs.h"
12#include "Compiler.h"
13#include "CpuArch.h"
14
15#if defined(__SSE2__)
16 #define Z7_BLAKE2S_USE_VECTORS
17#elif defined(MY_CPU_X86_OR_AMD64)
18 #if defined(_MSC_VER) && _MSC_VER > 1200 \
19 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 30300) \
20 || defined(__clang__) \
21 || defined(__INTEL_COMPILER)
22 #define Z7_BLAKE2S_USE_VECTORS
23 #endif
24#endif
25
26#ifdef Z7_BLAKE2S_USE_VECTORS
27
28#define Z7_BLAKE2SP_USE_FUNCTIONS
29
30// define Z7_BLAKE2SP_STRUCT_IS_NOT_ALIGNED, if CBlake2sp can be non aligned for 32-bytes.
31// #define Z7_BLAKE2SP_STRUCT_IS_NOT_ALIGNED
32
33// SSSE3 : for _mm_shuffle_epi8 (pshufb) that improves the performance for 5-15%.
34#if defined(__SSSE3__)
35 #define Z7_BLAKE2S_USE_SSSE3
36#elif defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1500) \
37 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40300) \
38 || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40000) \
39 || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 20300) \
40 || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1000)
41 #define Z7_BLAKE2S_USE_SSSE3
42#endif
43
44#ifdef Z7_BLAKE2S_USE_SSSE3
45/* SSE41 : for _mm_insert_epi32 (pinsrd)
46 it can slightly reduce code size and improves the performance in some cases.
47 it's used only for last 512-1024 bytes, if FAST versions (2 or 3) of vector algos are used.
48 it can be used for all blocks in another algos (4+).
49*/
50#if defined(__SSE4_1__)
51 #define Z7_BLAKE2S_USE_SSE41
52#elif defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1500) \
53 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40300) \
54 || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40000) \
55 || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 20300) \
56 || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1000)
57 #define Z7_BLAKE2S_USE_SSE41
58#endif
59#endif // SSSE3
60
61#if defined(__GNUC__) || defined(__clang__)
62 #if defined(Z7_BLAKE2S_USE_SSE41)
63 #define BLAKE2S_ATTRIB_128BIT __attribute__((__target__("sse4.1")))
64 #elif defined(Z7_BLAKE2S_USE_SSSE3)
65 #define BLAKE2S_ATTRIB_128BIT __attribute__((__target__("ssse3")))
66 #else
67 #define BLAKE2S_ATTRIB_128BIT __attribute__((__target__("sse2")))
68 #endif
69#endif
70
71
72#if defined(__AVX2__)
73 #define Z7_BLAKE2S_USE_AVX2
74#else
75 #if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
76 || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \
77 || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100)
78 #define Z7_BLAKE2S_USE_AVX2
79 #ifdef Z7_BLAKE2S_USE_AVX2
80 #define BLAKE2S_ATTRIB_AVX2 __attribute__((__target__("avx2")))
81 #endif
82 #elif defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \
83 || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)
84 #if (Z7_MSC_VER_ORIGINAL == 1900)
85 #pragma warning(disable : 4752) // found Intel(R) Advanced Vector Extensions; consider using /arch:AVX
86 #endif
87 #define Z7_BLAKE2S_USE_AVX2
88 #endif
89#endif
90
91#ifdef Z7_BLAKE2S_USE_SSE41
92#include <smmintrin.h> // SSE4.1
93#elif defined(Z7_BLAKE2S_USE_SSSE3)
94#include <tmmintrin.h> // SSSE3
95#else
96#include <emmintrin.h> // SSE2
97#endif
98
99#ifdef Z7_BLAKE2S_USE_AVX2
100#include <immintrin.h>
101#if defined(__clang__)
102#include <avxintrin.h>
103#include <avx2intrin.h>
104#endif
105#endif // avx2
106
107
108#if defined(__AVX512F__) && defined(__AVX512VL__)
109 // && defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL > 1930)
110 #define Z7_BLAKE2S_USE_AVX512_ALWAYS
111 // #pragma message ("=== Blake2s AVX512")
112#endif
12 113
13#define rotr32 rotrFixed
14 114
15#define BLAKE2S_NUM_ROUNDS 10 115#define Z7_BLAKE2S_USE_V128_FAST
16#define BLAKE2S_FINAL_FLAG (~(UInt32)0) 116// for speed optimization for small messages:
117// #define Z7_BLAKE2S_USE_V128_WAY2
17 118
119#ifdef Z7_BLAKE2S_USE_AVX2
120
121// for debug:
122// gather is slow
123// #define Z7_BLAKE2S_USE_GATHER
124
125 #define Z7_BLAKE2S_USE_AVX2_FAST
126// for speed optimization for small messages:
127// #define Z7_BLAKE2S_USE_AVX2_WAY2
128// #define Z7_BLAKE2S_USE_AVX2_WAY4
129#if defined(Z7_BLAKE2S_USE_AVX2_WAY2) || \
130 defined(Z7_BLAKE2S_USE_AVX2_WAY4)
131 #define Z7_BLAKE2S_USE_AVX2_WAY_SLOW
132#endif
133#endif
134
135 #define Z7_BLAKE2SP_ALGO_DEFAULT 0
136 #define Z7_BLAKE2SP_ALGO_SCALAR 1
137#ifdef Z7_BLAKE2S_USE_V128_FAST
138 #define Z7_BLAKE2SP_ALGO_V128_FAST 2
139#endif
140#ifdef Z7_BLAKE2S_USE_AVX2_FAST
141 #define Z7_BLAKE2SP_ALGO_V256_FAST 3
142#endif
143 #define Z7_BLAKE2SP_ALGO_V128_WAY1 4
144#ifdef Z7_BLAKE2S_USE_V128_WAY2
145 #define Z7_BLAKE2SP_ALGO_V128_WAY2 5
146#endif
147#ifdef Z7_BLAKE2S_USE_AVX2_WAY2
148 #define Z7_BLAKE2SP_ALGO_V256_WAY2 6
149#endif
150#ifdef Z7_BLAKE2S_USE_AVX2_WAY4
151 #define Z7_BLAKE2SP_ALGO_V256_WAY4 7
152#endif
153
154#endif // Z7_BLAKE2S_USE_VECTORS
155
156
157
158
159#define BLAKE2S_FINAL_FLAG (~(UInt32)0)
160#define NSW Z7_BLAKE2SP_NUM_STRUCT_WORDS
161#define SUPER_BLOCK_SIZE (Z7_BLAKE2S_BLOCK_SIZE * Z7_BLAKE2SP_PARALLEL_DEGREE)
162#define SUPER_BLOCK_MASK (SUPER_BLOCK_SIZE - 1)
163
164#define V_INDEX_0_0 0
165#define V_INDEX_1_0 1
166#define V_INDEX_2_0 2
167#define V_INDEX_3_0 3
168#define V_INDEX_0_1 4
169#define V_INDEX_1_1 5
170#define V_INDEX_2_1 6
171#define V_INDEX_3_1 7
172#define V_INDEX_0_2 8
173#define V_INDEX_1_2 9
174#define V_INDEX_2_2 10
175#define V_INDEX_3_2 11
176#define V_INDEX_0_3 12
177#define V_INDEX_1_3 13
178#define V_INDEX_2_3 14
179#define V_INDEX_3_3 15
180#define V_INDEX_4_0 0
181#define V_INDEX_5_0 1
182#define V_INDEX_6_0 2
183#define V_INDEX_7_0 3
184#define V_INDEX_7_1 4
185#define V_INDEX_4_1 5
186#define V_INDEX_5_1 6
187#define V_INDEX_6_1 7
188#define V_INDEX_6_2 8
189#define V_INDEX_7_2 9
190#define V_INDEX_4_2 10
191#define V_INDEX_5_2 11
192#define V_INDEX_5_3 12
193#define V_INDEX_6_3 13
194#define V_INDEX_7_3 14
195#define V_INDEX_4_3 15
196
197#define V(row, col) v[V_INDEX_ ## row ## _ ## col]
198
199#define k_Blake2s_IV_0 0x6A09E667UL
200#define k_Blake2s_IV_1 0xBB67AE85UL
201#define k_Blake2s_IV_2 0x3C6EF372UL
202#define k_Blake2s_IV_3 0xA54FF53AUL
203#define k_Blake2s_IV_4 0x510E527FUL
204#define k_Blake2s_IV_5 0x9B05688CUL
205#define k_Blake2s_IV_6 0x1F83D9ABUL
206#define k_Blake2s_IV_7 0x5BE0CD19UL
207
208#define KIV(n) (k_Blake2s_IV_## n)
209
210#ifdef Z7_BLAKE2S_USE_VECTORS
211MY_ALIGN(16)
18static const UInt32 k_Blake2s_IV[8] = 212static const UInt32 k_Blake2s_IV[8] =
19{ 213{
20 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 214 KIV(0), KIV(1), KIV(2), KIV(3), KIV(4), KIV(5), KIV(6), KIV(7)
21 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
22}; 215};
216#endif
23 217
24static const Byte k_Blake2s_Sigma[BLAKE2S_NUM_ROUNDS][16] = 218#define STATE_T(s) ((s) + 8)
25{ 219#define STATE_F(s) ((s) + 10)
26 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 220
27 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 221#ifdef Z7_BLAKE2S_USE_VECTORS
28 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
29 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
30 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
31 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
32 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
33 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
34 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
35 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
36};
37 222
223#define LOAD_128(p) _mm_load_si128 ((const __m128i *)(const void *)(p))
224#define LOADU_128(p) _mm_loadu_si128((const __m128i *)(const void *)(p))
225#ifdef Z7_BLAKE2SP_STRUCT_IS_NOT_ALIGNED
226 // here we use unaligned load and stores
227 // use this branch if CBlake2sp can be unaligned for 16 bytes
228 #define STOREU_128(p, r) _mm_storeu_si128((__m128i *)(void *)(p), r)
229 #define LOAD_128_FROM_STRUCT(p) LOADU_128(p)
230 #define STORE_128_TO_STRUCT(p, r) STOREU_128(p, r)
231#else
232 // here we use aligned load and stores
233 // use this branch if CBlake2sp is aligned for 16 bytes
234 #define STORE_128(p, r) _mm_store_si128((__m128i *)(void *)(p), r)
235 #define LOAD_128_FROM_STRUCT(p) LOAD_128(p)
236 #define STORE_128_TO_STRUCT(p, r) STORE_128(p, r)
237#endif
38 238
39static void Blake2s_Init0(CBlake2s *p) 239#endif // Z7_BLAKE2S_USE_VECTORS
240
241
242#if 0
243static void PrintState(const UInt32 *s, unsigned num)
244{
245 unsigned i;
246 printf("\n");
247 for (i = 0; i < num; i++)
248 printf(" %08x", (unsigned)s[i]);
249}
250static void PrintStates2(const UInt32 *s, unsigned x, unsigned y)
40{ 251{
41 unsigned i; 252 unsigned i;
42 for (i = 0; i < 8; i++) 253 for (i = 0; i < y; i++)
43 p->h[i] = k_Blake2s_IV[i]; 254 PrintState(s + i * x, x);
44 p->t[0] = 0; 255 printf("\n");
45 p->t[1] = 0;
46 p->f[0] = 0;
47 p->f[1] = 0;
48 p->bufPos = 0;
49 p->lastNode_f1 = 0;
50} 256}
257#endif
258
259
260#define REP8_MACRO(m) { m(0) m(1) m(2) m(3) m(4) m(5) m(6) m(7) }
261
262#define BLAKE2S_NUM_ROUNDS 10
263
264#if defined(Z7_BLAKE2S_USE_VECTORS)
265#define ROUNDS_LOOP(mac) \
266 { unsigned r; for (r = 0; r < BLAKE2S_NUM_ROUNDS; r++) mac(r) }
267#endif
268/*
269#define ROUNDS_LOOP_2(mac) \
270 { unsigned r; for (r = 0; r < BLAKE2S_NUM_ROUNDS; r += 2) { mac(r) mac(r + 1) } }
271*/
272#if 0 || 1 && !defined(Z7_BLAKE2S_USE_VECTORS)
273#define ROUNDS_LOOP_UNROLLED(m) \
274 { m(0) m(1) m(2) m(3) m(4) m(5) m(6) m(7) m(8) m(9) }
275#endif
276
277#define SIGMA_TABLE(M) \
278 M( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ), \
279 M( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ), \
280 M( 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 ), \
281 M( 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 ), \
282 M( 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 ), \
283 M( 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 ), \
284 M( 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 ), \
285 M( 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 ), \
286 M( 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 ), \
287 M( 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 )
288
289#define SIGMA_TABLE_MULT(m, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) \
290 { a0*m,a1*m,a2*m,a3*m,a4*m,a5*m,a6*m,a7*m,a8*m,a9*m,a10*m,a11*m,a12*m,a13*m,a14*m,a15*m }
291#define SIGMA_TABLE_MULT_4( a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) \
292 SIGMA_TABLE_MULT(4, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
293
294// MY_ALIGN(32)
295MY_ALIGN(16)
296static const Byte k_Blake2s_Sigma_4[BLAKE2S_NUM_ROUNDS][16] =
297 { SIGMA_TABLE(SIGMA_TABLE_MULT_4) };
298
299#define GET_SIGMA_PTR(p, index) \
300 ((const void *)((const Byte *)(const void *)(p) + (index)))
51 301
302#define GET_STATE_TABLE_PTR_FROM_BYTE_POS(s, pos) \
303 ((UInt32 *)(void *)((Byte *)(void *)(s) + (pos)))
52 304
53static void Blake2s_Compress(CBlake2s *p) 305
306#ifdef Z7_BLAKE2S_USE_VECTORS
307
308
309#if 0
310 // use loading constants from memory
311 // is faster for some compilers.
312 #define KK4(n) KIV(n), KIV(n), KIV(n), KIV(n)
313MY_ALIGN(64)
314static const UInt32 k_Blake2s_IV_WAY4[]=
54{ 315{
55 UInt32 m[16]; 316 KK4(0), KK4(1), KK4(2), KK4(3), KK4(4), KK4(5), KK4(6), KK4(7)
56 UInt32 v[16]; 317};
57 318 #define GET_128_IV_WAY4(i) LOAD_128(k_Blake2s_IV_WAY4 + 4 * (i))
319#else
320 // use constant generation:
321 #define GET_128_IV_WAY4(i) _mm_set1_epi32((Int32)KIV(i))
322#endif
323
324
325#ifdef Z7_BLAKE2S_USE_AVX2_WAY_SLOW
326#define GET_CONST_128_FROM_ARRAY32(k) \
327 _mm_set_epi32((Int32)(k)[3], (Int32)(k)[2], (Int32)(k)[1], (Int32)(k)[0])
328#endif
329
330
331#if 0
332#define k_r8 _mm_set_epi8(12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1)
333#define k_r16 _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2)
334#define k_inc _mm_set_epi32(0, 0, 0, Z7_BLAKE2S_BLOCK_SIZE)
335#define k_iv0_128 GET_CONST_128_FROM_ARRAY32(k_Blake2s_IV + 0)
336#define k_iv4_128 GET_CONST_128_FROM_ARRAY32(k_Blake2s_IV + 4)
337#else
338#if defined(Z7_BLAKE2S_USE_SSSE3) && \
339 !defined(Z7_BLAKE2S_USE_AVX512_ALWAYS)
340MY_ALIGN(16) static const Byte k_r8_arr [16] = { 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8 ,13, 14, 15, 12 };
341MY_ALIGN(16) static const Byte k_r16_arr[16] = { 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13 };
342#define k_r8 LOAD_128(k_r8_arr)
343#define k_r16 LOAD_128(k_r16_arr)
344#endif
345MY_ALIGN(16) static const UInt32 k_inc_arr[4] = { Z7_BLAKE2S_BLOCK_SIZE, 0, 0, 0 };
346#define k_inc LOAD_128(k_inc_arr)
347#define k_iv0_128 LOAD_128(k_Blake2s_IV + 0)
348#define k_iv4_128 LOAD_128(k_Blake2s_IV + 4)
349#endif
350
351
352#ifdef Z7_BLAKE2S_USE_AVX2_WAY_SLOW
353
354#ifdef Z7_BLAKE2S_USE_AVX2
355#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION < 80000)
356 #define MY_mm256_set_m128i(hi, lo) _mm256_insertf128_si256(_mm256_castsi128_si256(lo), (hi), 1)
357#else
358 #define MY_mm256_set_m128i _mm256_set_m128i
359#endif
360
361#define SET_FROM_128(a) MY_mm256_set_m128i(a, a)
362
363#ifndef Z7_BLAKE2S_USE_AVX512_ALWAYS
364MY_ALIGN(32) static const Byte k_r8_arr_256 [32] =
365{
366 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8 ,13, 14, 15, 12,
367 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8 ,13, 14, 15, 12
368};
369MY_ALIGN(32) static const Byte k_r16_arr_256[32] =
370{
371 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13,
372 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13
373};
374#define k_r8_256 LOAD_256(k_r8_arr_256)
375#define k_r16_256 LOAD_256(k_r16_arr_256)
376#endif
377
378// #define k_r8_256 SET_FROM_128(_mm_set_epi8(12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1))
379// #define k_r16_256 SET_FROM_128(_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2))
380// #define k_inc_256 SET_FROM_128(_mm_set_epi32(0, 0, 0, Z7_BLAKE2S_BLOCK_SIZE))
381// #define k_iv0_256 SET_FROM_128(GET_CONST_128_FROM_ARRAY32(k_Blake2s_IV + 0))
382#define k_iv4_256 SET_FROM_128(GET_CONST_128_FROM_ARRAY32(k_Blake2s_IV + 4))
383#endif // Z7_BLAKE2S_USE_AVX2_WAY_SLOW
384#endif
385
386
387/*
388IPC(TP) ports:
3891 p__5 : skl- : SSE : shufps : _mm_shuffle_ps
3902 p_15 : icl+
3911 p__5 : nhm-bdw : SSE : xorps : _mm_xor_ps
3923 p015 : skl+
393
3943 p015 : SSE2 : pxor : _mm_xor_si128
3952 p_15: snb-bdw : SSE2 : padd : _mm_add_epi32
3962 p0_5: mrm-wsm :
3973 p015 : skl+
398
3992 p_15 : ivb-,icl+ : SSE2 : punpcklqdq, punpckhqdq, punpckldq, punpckhdq
4002 p_15 : : SSE2 : pshufd : _mm_shuffle_epi32
4012 p_15 : : SSE2 : pshuflw : _mm_shufflelo_epi16
4022 p_15 : : SSE2 : psrldq :
4032 p_15 : : SSE3 : pshufb : _mm_shuffle_epi8
4042 p_15 : : SSE4 : pblendw : _mm_blend_epi16
4051 p__5 : hsw-skl : *
406
4071 p0 : SSE2 : pslld (i8) : _mm_slli_si128
4082 p01 : skl+ :
409
4102 p_15 : ivb- : SSE3 : palignr
4111 p__5 : hsw+
412
4132 p_15 + p23 : ivb-, icl+ : SSE4 : pinsrd : _mm_insert_epi32(xmm, m32, i8)
4141 p__5 + p23 : hsw-skl
4151 p_15 + p5 : ivb-, ice+ : SSE4 : pinsrd : _mm_insert_epi32(xmm, r32, i8)
4160.5 2*p5 : hsw-skl
417
4182 p23 : SSE2 : movd (m32)
4193 p23A : adl :
4201 p5: : SSE2 : movd (r32)
421*/
422
423#if 0 && defined(__XOP__)
424// we must debug and test __XOP__ instruction
425#include <x86intrin.h>
426#include <ammintrin.h>
427 #define LOAD_ROTATE_CONSTS
428 #define MM_ROR_EPI32(r, c) _mm_roti_epi32(r, -(c))
429 #define Z7_BLAKE2S_MM_ROR_EPI32_IS_SUPPORTED
430#elif 1 && defined(Z7_BLAKE2S_USE_AVX512_ALWAYS)
431 #define LOAD_ROTATE_CONSTS
432 #define MM_ROR_EPI32(r, c) _mm_ror_epi32(r, c)
433 #define Z7_BLAKE2S_MM_ROR_EPI32_IS_SUPPORTED
434#else
435
436// MSVC_1937+ uses "orps" instruction for _mm_or_si128().
437// But "orps" has low throughput: TP=1 for bdw-nhm.
438// So it can be better to use _mm_add_epi32()/"paddd" (TP=2 for bdw-nhm) instead of "xorps".
439// But "orps" is fast for modern cpus (skl+).
440// So we are default with "or" version:
441#if 0 || 0 && defined(Z7_MSC_VER_ORIGINAL) && Z7_MSC_VER_ORIGINAL > 1937
442 // minor optimization for some old cpus, if "xorps" is slow.
443 #define MM128_EPI32_OR_or_ADD _mm_add_epi32
444#else
445 #define MM128_EPI32_OR_or_ADD _mm_or_si128
446#endif
447
448 #define MM_ROR_EPI32_VIA_SHIFT(r, c)( \
449 MM128_EPI32_OR_or_ADD( \
450 _mm_srli_epi32((r), (c)), \
451 _mm_slli_epi32((r), 32-(c))))
452 #if defined(Z7_BLAKE2S_USE_SSSE3) || defined(Z7_BLAKE2S_USE_SSE41)
453 #define LOAD_ROTATE_CONSTS \
454 const __m128i r8 = k_r8; \
455 const __m128i r16 = k_r16;
456 #define MM_ROR_EPI32(r, c) ( \
457 ( 8==(c)) ? _mm_shuffle_epi8(r,r8) \
458 : (16==(c)) ? _mm_shuffle_epi8(r,r16) \
459 : MM_ROR_EPI32_VIA_SHIFT(r, c))
460 #else
461 #define LOAD_ROTATE_CONSTS
462 #define MM_ROR_EPI32(r, c) ( \
463 (16==(c)) ? _mm_shufflehi_epi16(_mm_shufflelo_epi16(r, 0xb1), 0xb1) \
464 : MM_ROR_EPI32_VIA_SHIFT(r, c))
465 #endif
466#endif
467
468/*
469we have 3 main ways to load 4 32-bit integers to __m128i:
470 1) SSE2: _mm_set_epi32()
471 2) SSE2: _mm_unpacklo_epi64() / _mm_unpacklo_epi32 / _mm_cvtsi32_si128()
472 3) SSE41: _mm_insert_epi32() and _mm_cvtsi32_si128()
473good compiler for _mm_set_epi32() generates these instructions:
474{
475 movd xmm, [m32]; vpunpckldq; vpunpckldq; vpunpcklqdq;
476}
477good new compiler generates one instruction
478{
479 for _mm_insert_epi32() : { pinsrd xmm, [m32], i }
480 for _mm_cvtsi32_si128() : { movd xmm, [m32] }
481}
482but vc2010 generates slow pair of instructions:
483{
484 for _mm_insert_epi32() : { mov r32, [m32]; pinsrd xmm, r32, i }
485 for _mm_cvtsi32_si128() : { mov r32, [m32]; movd xmm, r32 }
486}
487_mm_insert_epi32() (pinsrd) code reduces xmm register pressure
488in comparison with _mm_set_epi32() (movd + vpunpckld) code.
489Note that variant with "movd xmm, r32" can be more slow,
490but register pressure can be more important.
491So we can force to "pinsrd" always.
492*/
493// #if !defined(Z7_MSC_VER_ORIGINAL) || Z7_MSC_VER_ORIGINAL > 1600 || defined(MY_CPU_X86)
494#ifdef Z7_BLAKE2S_USE_SSE41
495 /* _mm_set_epi32() can be more effective for GCC and CLANG
496 _mm_insert_epi32() is more effective for MSVC */
497 #if 0 || 1 && defined(Z7_MSC_VER_ORIGINAL)
498 #define Z7_BLAKE2S_USE_INSERT_INSTRUCTION
499 #endif
500#endif // USE_SSE41
501// #endif
502
503#ifdef Z7_BLAKE2S_USE_INSERT_INSTRUCTION
504 // for SSE4.1
505#define MM_LOAD_EPI32_FROM_4_POINTERS(p0, p1, p2, p3) \
506 _mm_insert_epi32( \
507 _mm_insert_epi32( \
508 _mm_insert_epi32( \
509 _mm_cvtsi32_si128( \
510 *(const Int32 *)p0), \
511 *(const Int32 *)p1, 1), \
512 *(const Int32 *)p2, 2), \
513 *(const Int32 *)p3, 3)
514#elif 0 || 1 && defined(Z7_MSC_VER_ORIGINAL)
515/* MSVC 1400 implements _mm_set_epi32() via slow memory write/read.
516 Also _mm_unpacklo_epi32 is more effective for another MSVC compilers.
517 But _mm_set_epi32() is more effective for GCC and CLANG.
518 So we use _mm_unpacklo_epi32 for MSVC only */
519#define MM_LOAD_EPI32_FROM_4_POINTERS(p0, p1, p2, p3) \
520 _mm_unpacklo_epi64( \
521 _mm_unpacklo_epi32( _mm_cvtsi32_si128(*(const Int32 *)p0), \
522 _mm_cvtsi32_si128(*(const Int32 *)p1)), \
523 _mm_unpacklo_epi32( _mm_cvtsi32_si128(*(const Int32 *)p2), \
524 _mm_cvtsi32_si128(*(const Int32 *)p3)))
525#else
526#define MM_LOAD_EPI32_FROM_4_POINTERS(p0, p1, p2, p3) \
527 _mm_set_epi32( \
528 *(const Int32 *)p3, \
529 *(const Int32 *)p2, \
530 *(const Int32 *)p1, \
531 *(const Int32 *)p0)
532#endif
533
534#define SET_ROW_FROM_SIGMA_BASE(input, i0, i1, i2, i3) \
535 MM_LOAD_EPI32_FROM_4_POINTERS( \
536 GET_SIGMA_PTR(input, i0), \
537 GET_SIGMA_PTR(input, i1), \
538 GET_SIGMA_PTR(input, i2), \
539 GET_SIGMA_PTR(input, i3))
540
541#define SET_ROW_FROM_SIGMA(input, sigma_index) \
542 SET_ROW_FROM_SIGMA_BASE(input, \
543 sigma[(sigma_index) ], \
544 sigma[(sigma_index) + 2 * 1], \
545 sigma[(sigma_index) + 2 * 2], \
546 sigma[(sigma_index) + 2 * 3]) \
547
548
549#define ADD_128(a, b) _mm_add_epi32(a, b)
550#define XOR_128(a, b) _mm_xor_si128(a, b)
551
552#define D_ADD_128(dest, src) dest = ADD_128(dest, src)
553#define D_XOR_128(dest, src) dest = XOR_128(dest, src)
554#define D_ROR_128(dest, shift) dest = MM_ROR_EPI32(dest, shift)
555#define D_ADD_EPI64_128(dest, src) dest = _mm_add_epi64(dest, src)
556
557
558#define AXR(a, b, d, shift) \
559 D_ADD_128(a, b); \
560 D_XOR_128(d, a); \
561 D_ROR_128(d, shift);
562
563#define AXR2(a, b, c, d, input, sigma_index, shift1, shift2) \
564 a = _mm_add_epi32 (a, SET_ROW_FROM_SIGMA(input, sigma_index)); \
565 AXR(a, b, d, shift1) \
566 AXR(c, d, b, shift2)
567
568#define ROTATE_WORDS_TO_RIGHT(a, n) \
569 a = _mm_shuffle_epi32(a, _MM_SHUFFLE((3+n)&3, (2+n)&3, (1+n)&3, (0+n)&3));
570
571#define AXR4(a, b, c, d, input, sigma_index) \
572 AXR2(a, b, c, d, input, sigma_index, 16, 12) \
573 AXR2(a, b, c, d, input, sigma_index + 1, 8, 7) \
574
575#define RR2(a, b, c, d, input) \
576 { \
577 AXR4(a, b, c, d, input, 0) \
578 ROTATE_WORDS_TO_RIGHT(b, 1) \
579 ROTATE_WORDS_TO_RIGHT(c, 2) \
580 ROTATE_WORDS_TO_RIGHT(d, 3) \
581 AXR4(a, b, c, d, input, 8) \
582 ROTATE_WORDS_TO_RIGHT(b, 3) \
583 ROTATE_WORDS_TO_RIGHT(c, 2) \
584 ROTATE_WORDS_TO_RIGHT(d, 1) \
585 }
586
587
588/*
589Way1:
590per 64 bytes block:
59110 rounds * 4 iters * (7 + 2) = 360 cycles = if pslld TP=1
592 * (7 + 1) = 320 cycles = if pslld TP=2 (skl+)
593additional operations per 7_op_iter :
5944 movzx byte mem
5951 movd mem
5963 pinsrd mem
5971.5 pshufd
598*/
599
600static
601#if 0 || 0 && (defined(Z7_BLAKE2S_USE_V128_WAY2) || \
602 defined(Z7_BLAKE2S_USE_V256_WAY2))
603 Z7_NO_INLINE
604#else
605 Z7_FORCE_INLINE
606#endif
607#ifdef BLAKE2S_ATTRIB_128BIT
608 BLAKE2S_ATTRIB_128BIT
609#endif
610void
611Z7_FASTCALL
612Blake2s_Compress_V128_Way1(UInt32 * const s, const Byte * const input)
613{
614 __m128i a, b, c, d;
615 __m128i f0, f1;
616
617 LOAD_ROTATE_CONSTS
618 d = LOAD_128_FROM_STRUCT(STATE_T(s));
619 c = k_iv0_128;
620 a = f0 = LOAD_128_FROM_STRUCT(s);
621 b = f1 = LOAD_128_FROM_STRUCT(s + 4);
622 D_ADD_EPI64_128(d, k_inc);
623 STORE_128_TO_STRUCT (STATE_T(s), d);
624 D_XOR_128(d, k_iv4_128);
625
626#define RR(r) { const Byte * const sigma = k_Blake2s_Sigma_4[r]; \
627 RR2(a, b, c, d, input) }
628
629 ROUNDS_LOOP(RR)
630#undef RR
631
632 STORE_128_TO_STRUCT(s , XOR_128(f0, XOR_128(a, c)));
633 STORE_128_TO_STRUCT(s + 4, XOR_128(f1, XOR_128(b, d)));
634}
635
636
637static
638Z7_NO_INLINE
639#ifdef BLAKE2S_ATTRIB_128BIT
640 BLAKE2S_ATTRIB_128BIT
641#endif
642void
643Z7_FASTCALL
644Blake2sp_Compress2_V128_Way1(UInt32 *s_items, const Byte *data, const Byte *end)
645{
646 size_t pos = 0;
647 do
58 { 648 {
59 unsigned i; 649 UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);
650 Blake2s_Compress_V128_Way1(s, data);
651 data += Z7_BLAKE2S_BLOCK_SIZE;
652 pos += Z7_BLAKE2S_BLOCK_SIZE;
653 pos &= SUPER_BLOCK_MASK;
654 }
655 while (data != end);
656}
657
658
659#if defined(Z7_BLAKE2S_USE_V128_WAY2) || \
660 defined(Z7_BLAKE2S_USE_AVX2_WAY2)
661#if 1
662 #define Z7_BLAKE2S_CompressSingleBlock(s, data) \
663 Blake2sp_Compress2_V128_Way1(s, data, \
664 (const Byte *)(const void *)(data) + Z7_BLAKE2S_BLOCK_SIZE)
665#else
666 #define Z7_BLAKE2S_CompressSingleBlock Blake2s_Compress_V128_Way1
667#endif
668#endif
669
670
671#if (defined(Z7_BLAKE2S_USE_AVX2_WAY_SLOW) || \
672 defined(Z7_BLAKE2S_USE_V128_WAY2)) && \
673 !defined(Z7_BLAKE2S_USE_GATHER)
674#define AXR2_LOAD_INDEXES(sigma_index) \
675 const unsigned i0 = sigma[(sigma_index)]; \
676 const unsigned i1 = sigma[(sigma_index) + 2 * 1]; \
677 const unsigned i2 = sigma[(sigma_index) + 2 * 2]; \
678 const unsigned i3 = sigma[(sigma_index) + 2 * 3]; \
679
680#define SET_ROW_FROM_SIGMA_W(input) \
681 SET_ROW_FROM_SIGMA_BASE(input, i0, i1, i2, i3)
682#endif
683
684
685#ifdef Z7_BLAKE2S_USE_V128_WAY2
686
687#if 1 || !defined(Z7_BLAKE2S_USE_SSE41)
688/* we use SET_ROW_FROM_SIGMA_BASE, that uses
689 (SSE4) _mm_insert_epi32(), if Z7_BLAKE2S_USE_INSERT_INSTRUCTION is defined
690 (SSE2) _mm_set_epi32()
691 MSVC can be faster for this branch:
692*/
693#define AXR2_W(sigma_index, shift1, shift2) \
694 { \
695 AXR2_LOAD_INDEXES(sigma_index) \
696 a0 = _mm_add_epi32(a0, SET_ROW_FROM_SIGMA_W(data)); \
697 a1 = _mm_add_epi32(a1, SET_ROW_FROM_SIGMA_W(data + Z7_BLAKE2S_BLOCK_SIZE)); \
698 AXR(a0, b0, d0, shift1) \
699 AXR(a1, b1, d1, shift1) \
700 AXR(c0, d0, b0, shift2) \
701 AXR(c1, d1, b1, shift2) \
702 }
703#else
704/* we use interleaved _mm_insert_epi32():
705 GCC can be faster for this branch:
706*/
707#define AXR2_W_PRE_INSERT(sigma_index, i) \
708 { const unsigned ii = sigma[(sigma_index) + i * 2]; \
709 t0 = _mm_insert_epi32(t0, *(const Int32 *)GET_SIGMA_PTR(data, ii), i); \
710 t1 = _mm_insert_epi32(t1, *(const Int32 *)GET_SIGMA_PTR(data, Z7_BLAKE2S_BLOCK_SIZE + ii), i); \
711 }
712#define AXR2_W(sigma_index, shift1, shift2) \
713 { __m128i t0, t1; \
714 { const unsigned ii = sigma[sigma_index]; \
715 t0 = _mm_cvtsi32_si128(*(const Int32 *)GET_SIGMA_PTR(data, ii)); \
716 t1 = _mm_cvtsi32_si128(*(const Int32 *)GET_SIGMA_PTR(data, Z7_BLAKE2S_BLOCK_SIZE + ii)); \
717 } \
718 AXR2_W_PRE_INSERT(sigma_index, 1) \
719 AXR2_W_PRE_INSERT(sigma_index, 2) \
720 AXR2_W_PRE_INSERT(sigma_index, 3) \
721 a0 = _mm_add_epi32(a0, t0); \
722 a1 = _mm_add_epi32(a1, t1); \
723 AXR(a0, b0, d0, shift1) \
724 AXR(a1, b1, d1, shift1) \
725 AXR(c0, d0, b0, shift2) \
726 AXR(c1, d1, b1, shift2) \
727 }
728#endif
729
730
731#define AXR4_W(sigma_index) \
732 AXR2_W(sigma_index, 16, 12) \
733 AXR2_W(sigma_index + 1, 8, 7) \
734
735#define WW(r) \
736 { const Byte * const sigma = k_Blake2s_Sigma_4[r]; \
737 AXR4_W(0) \
738 ROTATE_WORDS_TO_RIGHT(b0, 1) \
739 ROTATE_WORDS_TO_RIGHT(b1, 1) \
740 ROTATE_WORDS_TO_RIGHT(c0, 2) \
741 ROTATE_WORDS_TO_RIGHT(c1, 2) \
742 ROTATE_WORDS_TO_RIGHT(d0, 3) \
743 ROTATE_WORDS_TO_RIGHT(d1, 3) \
744 AXR4_W(8) \
745 ROTATE_WORDS_TO_RIGHT(b0, 3) \
746 ROTATE_WORDS_TO_RIGHT(b1, 3) \
747 ROTATE_WORDS_TO_RIGHT(c0, 2) \
748 ROTATE_WORDS_TO_RIGHT(c1, 2) \
749 ROTATE_WORDS_TO_RIGHT(d0, 1) \
750 ROTATE_WORDS_TO_RIGHT(d1, 1) \
751 }
752
753
754static
755Z7_NO_INLINE
756#ifdef BLAKE2S_ATTRIB_128BIT
757 BLAKE2S_ATTRIB_128BIT
758#endif
759void
760Z7_FASTCALL
761Blake2sp_Compress2_V128_Way2(UInt32 *s_items, const Byte *data, const Byte *end)
762{
763 size_t pos = 0;
764 end -= Z7_BLAKE2S_BLOCK_SIZE;
765
766 if (data != end)
767 {
768 LOAD_ROTATE_CONSTS
769 do
770 {
771 UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);
772 __m128i a0, b0, c0, d0;
773 __m128i a1, b1, c1, d1;
774 {
775 const __m128i inc = k_inc;
776 const __m128i temp = k_iv4_128;
777 d0 = LOAD_128_FROM_STRUCT (STATE_T(s));
778 d1 = LOAD_128_FROM_STRUCT (STATE_T(s + NSW));
779 D_ADD_EPI64_128(d0, inc);
780 D_ADD_EPI64_128(d1, inc);
781 STORE_128_TO_STRUCT (STATE_T(s ), d0);
782 STORE_128_TO_STRUCT (STATE_T(s + NSW), d1);
783 D_XOR_128(d0, temp);
784 D_XOR_128(d1, temp);
785 }
786 c1 = c0 = k_iv0_128;
787 a0 = LOAD_128_FROM_STRUCT(s);
788 b0 = LOAD_128_FROM_STRUCT(s + 4);
789 a1 = LOAD_128_FROM_STRUCT(s + NSW);
790 b1 = LOAD_128_FROM_STRUCT(s + NSW + 4);
791
792 ROUNDS_LOOP (WW)
793
794#undef WW
795
796 D_XOR_128(a0, c0);
797 D_XOR_128(b0, d0);
798 D_XOR_128(a1, c1);
799 D_XOR_128(b1, d1);
800
801 D_XOR_128(a0, LOAD_128_FROM_STRUCT(s));
802 D_XOR_128(b0, LOAD_128_FROM_STRUCT(s + 4));
803 D_XOR_128(a1, LOAD_128_FROM_STRUCT(s + NSW));
804 D_XOR_128(b1, LOAD_128_FROM_STRUCT(s + NSW + 4));
805
806 STORE_128_TO_STRUCT(s, a0);
807 STORE_128_TO_STRUCT(s + 4, b0);
808 STORE_128_TO_STRUCT(s + NSW, a1);
809 STORE_128_TO_STRUCT(s + NSW + 4, b1);
810
811 data += Z7_BLAKE2S_BLOCK_SIZE * 2;
812 pos += Z7_BLAKE2S_BLOCK_SIZE * 2;
813 pos &= SUPER_BLOCK_MASK;
814 }
815 while (data < end);
816 if (data != end)
817 return;
818 }
819 {
820 UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);
821 Z7_BLAKE2S_CompressSingleBlock(s, data);
822 }
823}
824#endif // Z7_BLAKE2S_USE_V128_WAY2
825
826
827#ifdef Z7_BLAKE2S_USE_V128_WAY2
828 #define Z7_BLAKE2S_Compress2_V128 Blake2sp_Compress2_V128_Way2
829#else
830 #define Z7_BLAKE2S_Compress2_V128 Blake2sp_Compress2_V128_Way1
831#endif
832
833
834
835#ifdef Z7_BLAKE2S_MM_ROR_EPI32_IS_SUPPORTED
836 #define ROT_128_8(x) MM_ROR_EPI32(x, 8)
837 #define ROT_128_16(x) MM_ROR_EPI32(x, 16)
838 #define ROT_128_7(x) MM_ROR_EPI32(x, 7)
839 #define ROT_128_12(x) MM_ROR_EPI32(x, 12)
840#else
841#if defined(Z7_BLAKE2S_USE_SSSE3) || defined(Z7_BLAKE2S_USE_SSE41)
842 #define ROT_128_8(x) _mm_shuffle_epi8(x, r8) // k_r8
843 #define ROT_128_16(x) _mm_shuffle_epi8(x, r16) // k_r16
844#else
845 #define ROT_128_8(x) MM_ROR_EPI32_VIA_SHIFT(x, 8)
846 #define ROT_128_16(x) MM_ROR_EPI32_VIA_SHIFT(x, 16)
847#endif
848 #define ROT_128_7(x) MM_ROR_EPI32_VIA_SHIFT(x, 7)
849 #define ROT_128_12(x) MM_ROR_EPI32_VIA_SHIFT(x, 12)
850#endif
851
852
853#if 1
854// this branch can provide similar speed on x86* in most cases,
855// because [base + index*4] provides same speed as [base + index].
856// but some compilers can generate different code with this branch, that can be faster sometimes.
857// this branch uses additional table of 10*16=160 bytes.
858#define SIGMA_TABLE_MULT_16( a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) \
859 SIGMA_TABLE_MULT(16, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
860MY_ALIGN(16)
861static const Byte k_Blake2s_Sigma_16[BLAKE2S_NUM_ROUNDS][16] =
862 { SIGMA_TABLE(SIGMA_TABLE_MULT_16) };
863#define GET_SIGMA_PTR_128(r) const Byte * const sigma = k_Blake2s_Sigma_16[r];
864#define GET_SIGMA_VAL_128(n) (sigma[n])
865#else
866#define GET_SIGMA_PTR_128(r) const Byte * const sigma = k_Blake2s_Sigma_4[r];
867#define GET_SIGMA_VAL_128(n) (4 * (size_t)sigma[n])
868#endif
869
870
871#ifdef Z7_BLAKE2S_USE_AVX2_FAST
872#if 1
873#define SIGMA_TABLE_MULT_32( a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) \
874 SIGMA_TABLE_MULT(32, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
875MY_ALIGN(64)
876static const UInt16 k_Blake2s_Sigma_32[BLAKE2S_NUM_ROUNDS][16] =
877 { SIGMA_TABLE(SIGMA_TABLE_MULT_32) };
878#define GET_SIGMA_PTR_256(r) const UInt16 * const sigma = k_Blake2s_Sigma_32[r];
879#define GET_SIGMA_VAL_256(n) (sigma[n])
880#else
881#define GET_SIGMA_PTR_256(r) const Byte * const sigma = k_Blake2s_Sigma_4[r];
882#define GET_SIGMA_VAL_256(n) (8 * (size_t)sigma[n])
883#endif
884#endif // Z7_BLAKE2S_USE_AVX2_FAST
885
886
887#define D_ROT_128_7(dest) dest = ROT_128_7(dest)
888#define D_ROT_128_8(dest) dest = ROT_128_8(dest)
889#define D_ROT_128_12(dest) dest = ROT_128_12(dest)
890#define D_ROT_128_16(dest) dest = ROT_128_16(dest)
891
892#define OP_L(a, i) D_ADD_128 (V(a, 0), \
893 LOAD_128((const Byte *)(w) + GET_SIGMA_VAL_128(2*(a)+(i))));
894
895#define OP_0(a) OP_L(a, 0)
896#define OP_7(a) OP_L(a, 1)
897
898#define OP_1(a) D_ADD_128 (V(a, 0), V(a, 1));
899#define OP_2(a) D_XOR_128 (V(a, 3), V(a, 0));
900#define OP_4(a) D_ADD_128 (V(a, 2), V(a, 3));
901#define OP_5(a) D_XOR_128 (V(a, 1), V(a, 2));
902
903#define OP_3(a) D_ROT_128_16 (V(a, 3));
904#define OP_6(a) D_ROT_128_12 (V(a, 1));
905#define OP_8(a) D_ROT_128_8 (V(a, 3));
906#define OP_9(a) D_ROT_128_7 (V(a, 1));
907
908
909// for 32-bit x86 : interleave mode works slower, because of register pressure.
910
911#if 0 || 1 && (defined(MY_CPU_X86) \
912 || defined(__GNUC__) && !defined(__clang__))
913// non-inteleaved version:
914// is fast for x86 32-bit.
915// is fast for GCC x86-64.
916
917#define V4G(a) \
918 OP_0 (a) \
919 OP_1 (a) \
920 OP_2 (a) \
921 OP_3 (a) \
922 OP_4 (a) \
923 OP_5 (a) \
924 OP_6 (a) \
925 OP_7 (a) \
926 OP_1 (a) \
927 OP_2 (a) \
928 OP_8 (a) \
929 OP_4 (a) \
930 OP_5 (a) \
931 OP_9 (a) \
932
933#define V4R \
934{ \
935 V4G (0) \
936 V4G (1) \
937 V4G (2) \
938 V4G (3) \
939 V4G (4) \
940 V4G (5) \
941 V4G (6) \
942 V4G (7) \
943}
944
945#elif 0 || 1 && defined(MY_CPU_X86)
946
947#define OP_INTER_2(op, a,b) \
948 op (a) \
949 op (b) \
950
951#define V4G(a,b) \
952 OP_INTER_2 (OP_0, a,b) \
953 OP_INTER_2 (OP_1, a,b) \
954 OP_INTER_2 (OP_2, a,b) \
955 OP_INTER_2 (OP_3, a,b) \
956 OP_INTER_2 (OP_4, a,b) \
957 OP_INTER_2 (OP_5, a,b) \
958 OP_INTER_2 (OP_6, a,b) \
959 OP_INTER_2 (OP_7, a,b) \
960 OP_INTER_2 (OP_1, a,b) \
961 OP_INTER_2 (OP_2, a,b) \
962 OP_INTER_2 (OP_8, a,b) \
963 OP_INTER_2 (OP_4, a,b) \
964 OP_INTER_2 (OP_5, a,b) \
965 OP_INTER_2 (OP_9, a,b) \
966
967#define V4R \
968{ \
969 V4G (0, 1) \
970 V4G (2, 3) \
971 V4G (4, 5) \
972 V4G (6, 7) \
973}
974
975#else
976// iterleave-4 version is fast for x64 (MSVC/CLANG)
977
978#define OP_INTER_4(op, a,b,c,d) \
979 op (a) \
980 op (b) \
981 op (c) \
982 op (d) \
983
984#define V4G(a,b,c,d) \
985 OP_INTER_4 (OP_0, a,b,c,d) \
986 OP_INTER_4 (OP_1, a,b,c,d) \
987 OP_INTER_4 (OP_2, a,b,c,d) \
988 OP_INTER_4 (OP_3, a,b,c,d) \
989 OP_INTER_4 (OP_4, a,b,c,d) \
990 OP_INTER_4 (OP_5, a,b,c,d) \
991 OP_INTER_4 (OP_6, a,b,c,d) \
992 OP_INTER_4 (OP_7, a,b,c,d) \
993 OP_INTER_4 (OP_1, a,b,c,d) \
994 OP_INTER_4 (OP_2, a,b,c,d) \
995 OP_INTER_4 (OP_8, a,b,c,d) \
996 OP_INTER_4 (OP_4, a,b,c,d) \
997 OP_INTER_4 (OP_5, a,b,c,d) \
998 OP_INTER_4 (OP_9, a,b,c,d) \
999
1000#define V4R \
1001{ \
1002 V4G (0, 1, 2, 3) \
1003 V4G (4, 5, 6, 7) \
1004}
1005
1006#endif
1007
1008#define V4_ROUND(r) { GET_SIGMA_PTR_128(r); V4R }
1009
1010
1011#define V4_LOAD_MSG_1(w, m, i) \
1012{ \
1013 __m128i m0, m1, m2, m3; \
1014 __m128i t0, t1, t2, t3; \
1015 m0 = LOADU_128((m) + ((i) + 0 * 4) * 16); \
1016 m1 = LOADU_128((m) + ((i) + 1 * 4) * 16); \
1017 m2 = LOADU_128((m) + ((i) + 2 * 4) * 16); \
1018 m3 = LOADU_128((m) + ((i) + 3 * 4) * 16); \
1019 t0 = _mm_unpacklo_epi32(m0, m1); \
1020 t1 = _mm_unpackhi_epi32(m0, m1); \
1021 t2 = _mm_unpacklo_epi32(m2, m3); \
1022 t3 = _mm_unpackhi_epi32(m2, m3); \
1023 w[(i) * 4 + 0] = _mm_unpacklo_epi64(t0, t2); \
1024 w[(i) * 4 + 1] = _mm_unpackhi_epi64(t0, t2); \
1025 w[(i) * 4 + 2] = _mm_unpacklo_epi64(t1, t3); \
1026 w[(i) * 4 + 3] = _mm_unpackhi_epi64(t1, t3); \
1027}
1028
1029#define V4_LOAD_MSG(w, m) \
1030{ \
1031 V4_LOAD_MSG_1 (w, m, 0) \
1032 V4_LOAD_MSG_1 (w, m, 1) \
1033 V4_LOAD_MSG_1 (w, m, 2) \
1034 V4_LOAD_MSG_1 (w, m, 3) \
1035}
1036
1037#define V4_LOAD_UNPACK_PAIR_128(src32, i, d0, d1) \
1038{ \
1039 const __m128i v0 = LOAD_128_FROM_STRUCT((src32) + (i ) * 4); \
1040 const __m128i v1 = LOAD_128_FROM_STRUCT((src32) + (i + 1) * 4); \
1041 d0 = _mm_unpacklo_epi32(v0, v1); \
1042 d1 = _mm_unpackhi_epi32(v0, v1); \
1043}
1044
1045#define V4_UNPACK_PAIR_128(dest32, i, s0, s1) \
1046{ \
1047 STORE_128_TO_STRUCT((dest32) + i * 4 , _mm_unpacklo_epi64(s0, s1)); \
1048 STORE_128_TO_STRUCT((dest32) + i * 4 + 16, _mm_unpackhi_epi64(s0, s1)); \
1049}
1050
1051#define V4_UNPACK_STATE(dest32, src32) \
1052{ \
1053 __m128i t0, t1, t2, t3, t4, t5, t6, t7; \
1054 V4_LOAD_UNPACK_PAIR_128(src32, 0, t0, t1) \
1055 V4_LOAD_UNPACK_PAIR_128(src32, 2, t2, t3) \
1056 V4_LOAD_UNPACK_PAIR_128(src32, 4, t4, t5) \
1057 V4_LOAD_UNPACK_PAIR_128(src32, 6, t6, t7) \
1058 V4_UNPACK_PAIR_128(dest32, 0, t0, t2) \
1059 V4_UNPACK_PAIR_128(dest32, 8, t1, t3) \
1060 V4_UNPACK_PAIR_128(dest32, 1, t4, t6) \
1061 V4_UNPACK_PAIR_128(dest32, 9, t5, t7) \
1062}
1063
1064
1065static
1066Z7_NO_INLINE
1067#ifdef BLAKE2S_ATTRIB_128BIT
1068 BLAKE2S_ATTRIB_128BIT
1069#endif
1070void
1071Z7_FASTCALL
1072Blake2sp_Compress2_V128_Fast(UInt32 *s_items, const Byte *data, const Byte *end)
1073{
1074 // PrintStates2(s_items, 8, 16);
1075 size_t pos = 0;
1076 pos /= 2;
1077 do
1078 {
1079#if defined(Z7_BLAKE2S_USE_SSSE3) && \
1080 !defined(Z7_BLAKE2S_MM_ROR_EPI32_IS_SUPPORTED)
1081 const __m128i r8 = k_r8;
1082 const __m128i r16 = k_r16;
1083#endif
1084 __m128i w[16];
1085 __m128i v[16];
1086 UInt32 *s;
1087 V4_LOAD_MSG(w, data)
1088 s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);
1089 {
1090 __m128i ctr = LOAD_128_FROM_STRUCT(s + 64);
1091 D_ADD_EPI64_128 (ctr, k_inc);
1092 STORE_128_TO_STRUCT(s + 64, ctr);
1093 v[12] = XOR_128 (GET_128_IV_WAY4(4), _mm_shuffle_epi32(ctr, _MM_SHUFFLE(0, 0, 0, 0)));
1094 v[13] = XOR_128 (GET_128_IV_WAY4(5), _mm_shuffle_epi32(ctr, _MM_SHUFFLE(1, 1, 1, 1)));
1095 }
1096 v[ 8] = GET_128_IV_WAY4(0);
1097 v[ 9] = GET_128_IV_WAY4(1);
1098 v[10] = GET_128_IV_WAY4(2);
1099 v[11] = GET_128_IV_WAY4(3);
1100 v[14] = GET_128_IV_WAY4(6);
1101 v[15] = GET_128_IV_WAY4(7);
60 1102
61 for (i = 0; i < 16; i++) 1103#define LOAD_STATE_128_FROM_STRUCT(i) \
62 m[i] = GetUi32(p->buf + i * sizeof(m[i])); 1104 v[i] = LOAD_128_FROM_STRUCT(s + (i) * 4);
1105
1106#define UPDATE_STATE_128_IN_STRUCT(i) \
1107 STORE_128_TO_STRUCT(s + (i) * 4, XOR_128( \
1108 XOR_128(v[i], v[(i) + 8]), \
1109 LOAD_128_FROM_STRUCT(s + (i) * 4)));
63 1110
64 for (i = 0; i < 8; i++) 1111 REP8_MACRO (LOAD_STATE_128_FROM_STRUCT)
65 v[i] = p->h[i]; 1112 ROUNDS_LOOP (V4_ROUND)
1113 REP8_MACRO (UPDATE_STATE_128_IN_STRUCT)
1114
1115 data += Z7_BLAKE2S_BLOCK_SIZE * 4;
1116 pos += Z7_BLAKE2S_BLOCK_SIZE * 4 / 2;
1117 pos &= SUPER_BLOCK_SIZE / 2 - 1;
66 } 1118 }
1119 while (data != end);
1120}
67 1121
68 v[ 8] = k_Blake2s_IV[0];
69 v[ 9] = k_Blake2s_IV[1];
70 v[10] = k_Blake2s_IV[2];
71 v[11] = k_Blake2s_IV[3];
72
73 v[12] = p->t[0] ^ k_Blake2s_IV[4];
74 v[13] = p->t[1] ^ k_Blake2s_IV[5];
75 v[14] = p->f[0] ^ k_Blake2s_IV[6];
76 v[15] = p->f[1] ^ k_Blake2s_IV[7];
77 1122
78 #define G(r,i,a,b,c,d) \ 1123static
79 a += b + m[sigma[2*i+0]]; d ^= a; d = rotr32(d, 16); c += d; b ^= c; b = rotr32(b, 12); \ 1124Z7_NO_INLINE
80 a += b + m[sigma[2*i+1]]; d ^= a; d = rotr32(d, 8); c += d; b ^= c; b = rotr32(b, 7); \ 1125#ifdef BLAKE2S_ATTRIB_128BIT
1126 BLAKE2S_ATTRIB_128BIT
1127#endif
1128void
1129Z7_FASTCALL
1130Blake2sp_Final_V128_Fast(UInt32 *states)
1131{
1132 const __m128i ctr = LOAD_128_FROM_STRUCT(states + 64);
1133 // printf("\nBlake2sp_Compress2_V128_Fast_Final4\n");
1134 // PrintStates2(states, 8, 16);
1135 {
1136 ptrdiff_t pos = 8 * 4;
1137 do
1138 {
1139 UInt32 *src32 = states + (size_t)(pos * 1);
1140 UInt32 *dest32 = states + (size_t)(pos * 2);
1141 V4_UNPACK_STATE(dest32, src32)
1142 pos -= 8 * 4;
1143 }
1144 while (pos >= 0);
1145 }
1146 {
1147 unsigned k;
1148 for (k = 0; k < 8; k++)
1149 {
1150 UInt32 *s = states + (size_t)k * 16;
1151 STORE_128_TO_STRUCT (STATE_T(s), ctr);
1152 }
1153 }
1154 // PrintStates2(states, 8, 16);
1155}
1156
1157
1158
1159#ifdef Z7_BLAKE2S_USE_AVX2
1160
1161#define ADD_256(a, b) _mm256_add_epi32(a, b)
1162#define XOR_256(a, b) _mm256_xor_si256(a, b)
1163
1164#if 1 && defined(Z7_BLAKE2S_USE_AVX512_ALWAYS)
1165 #define MM256_ROR_EPI32 _mm256_ror_epi32
1166 #define Z7_MM256_ROR_EPI32_IS_SUPPORTED
1167 #define LOAD_ROTATE_CONSTS_256
1168#else
1169#ifdef Z7_BLAKE2S_USE_AVX2_WAY_SLOW
1170#ifdef Z7_BLAKE2S_USE_AVX2_WAY2
1171 #define LOAD_ROTATE_CONSTS_256 \
1172 const __m256i r8 = k_r8_256; \
1173 const __m256i r16 = k_r16_256;
1174#endif // AVX2_WAY2
1175
1176 #define MM256_ROR_EPI32(r, c) ( \
1177 ( 8==(c)) ? _mm256_shuffle_epi8(r,r8) \
1178 : (16==(c)) ? _mm256_shuffle_epi8(r,r16) \
1179 : _mm256_or_si256( \
1180 _mm256_srli_epi32((r), (c)), \
1181 _mm256_slli_epi32((r), 32-(c))))
1182#endif // WAY_SLOW
1183#endif
1184
1185
1186#define D_ADD_256(dest, src) dest = ADD_256(dest, src)
1187#define D_XOR_256(dest, src) dest = XOR_256(dest, src)
1188
1189#define LOADU_256(p) _mm256_loadu_si256((const __m256i *)(const void *)(p))
1190
1191#ifdef Z7_BLAKE2S_USE_AVX2_FAST
1192
1193#ifdef Z7_MM256_ROR_EPI32_IS_SUPPORTED
1194#define ROT_256_16(x) MM256_ROR_EPI32((x), 16)
1195#define ROT_256_12(x) MM256_ROR_EPI32((x), 12)
1196#define ROT_256_8(x) MM256_ROR_EPI32((x), 8)
1197#define ROT_256_7(x) MM256_ROR_EPI32((x), 7)
1198#else
1199#define ROTATE8 _mm256_set_epi8(12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1, \
1200 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1)
1201#define ROTATE16 _mm256_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2, \
1202 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2)
1203#define ROT_256_16(x) _mm256_shuffle_epi8((x), ROTATE16)
1204#define ROT_256_12(x) _mm256_or_si256(_mm256_srli_epi32((x), 12), _mm256_slli_epi32((x), 20))
1205#define ROT_256_8(x) _mm256_shuffle_epi8((x), ROTATE8)
1206#define ROT_256_7(x) _mm256_or_si256(_mm256_srli_epi32((x), 7), _mm256_slli_epi32((x), 25))
1207#endif
1208
1209#define D_ROT_256_7(dest) dest = ROT_256_7(dest)
1210#define D_ROT_256_8(dest) dest = ROT_256_8(dest)
1211#define D_ROT_256_12(dest) dest = ROT_256_12(dest)
1212#define D_ROT_256_16(dest) dest = ROT_256_16(dest)
1213
1214#define LOAD_256(p) _mm256_load_si256((const __m256i *)(const void *)(p))
1215#ifdef Z7_BLAKE2SP_STRUCT_IS_NOT_ALIGNED
1216 #define STOREU_256(p, r) _mm256_storeu_si256((__m256i *)(void *)(p), r)
1217 #define LOAD_256_FROM_STRUCT(p) LOADU_256(p)
1218 #define STORE_256_TO_STRUCT(p, r) STOREU_256(p, r)
1219#else
1220 // if struct is aligned for 32-bytes
1221 #define STORE_256(p, r) _mm256_store_si256((__m256i *)(void *)(p), r)
1222 #define LOAD_256_FROM_STRUCT(p) LOAD_256(p)
1223 #define STORE_256_TO_STRUCT(p, r) STORE_256(p, r)
1224#endif
1225
1226#endif // Z7_BLAKE2S_USE_AVX2_FAST
1227
1228
1229
1230#ifdef Z7_BLAKE2S_USE_AVX2_WAY_SLOW
1231
1232#if 0
1233 #define DIAG_PERM2(s) \
1234 { \
1235 const __m256i a = LOAD_256_FROM_STRUCT((s) ); \
1236 const __m256i b = LOAD_256_FROM_STRUCT((s) + NSW); \
1237 STORE_256_TO_STRUCT((s ), _mm256_permute2x128_si256(a, b, 0x20)); \
1238 STORE_256_TO_STRUCT((s + NSW), _mm256_permute2x128_si256(a, b, 0x31)); \
1239 }
1240#else
1241 #define DIAG_PERM2(s) \
1242 { \
1243 const __m128i a = LOAD_128_FROM_STRUCT((s) + 4); \
1244 const __m128i b = LOAD_128_FROM_STRUCT((s) + NSW); \
1245 STORE_128_TO_STRUCT((s) + NSW, a); \
1246 STORE_128_TO_STRUCT((s) + 4 , b); \
1247 }
1248#endif
1249 #define DIAG_PERM8(s_items) \
1250 { \
1251 DIAG_PERM2(s_items) \
1252 DIAG_PERM2(s_items + NSW * 2) \
1253 DIAG_PERM2(s_items + NSW * 4) \
1254 DIAG_PERM2(s_items + NSW * 6) \
1255 }
1256
1257
1258#define AXR256(a, b, d, shift) \
1259 D_ADD_256(a, b); \
1260 D_XOR_256(d, a); \
1261 d = MM256_ROR_EPI32(d, shift); \
1262
1263
1264
1265#ifdef Z7_BLAKE2S_USE_GATHER
1266
1267 #define TABLE_GATHER_256_4(a0,a1,a2,a3) \
1268 a0,a1,a2,a3, a0+16,a1+16,a2+16,a3+16
1269 #define TABLE_GATHER_256( \
1270 a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) \
1271 { TABLE_GATHER_256_4(a0,a2,a4,a6), \
1272 TABLE_GATHER_256_4(a1,a3,a5,a7), \
1273 TABLE_GATHER_256_4(a8,a10,a12,a14), \
1274 TABLE_GATHER_256_4(a9,a11,a13,a15) }
1275MY_ALIGN(64)
1276static const UInt32 k_Blake2s_Sigma_gather256[BLAKE2S_NUM_ROUNDS][16 * 2] =
1277 { SIGMA_TABLE(TABLE_GATHER_256) };
1278 #define GET_SIGMA(r) \
1279 const UInt32 * const sigma = k_Blake2s_Sigma_gather256[r];
1280 #define AXR2_LOAD_INDEXES_AVX(sigma_index) \
1281 const __m256i i01234567 = LOAD_256(sigma + (sigma_index));
1282 #define SET_ROW_FROM_SIGMA_AVX(in) \
1283 _mm256_i32gather_epi32((const void *)(in), i01234567, 4)
1284 #define SIGMA_INTERLEAVE 8
1285 #define SIGMA_HALF_ROW_SIZE 16
1286
1287#else // !Z7_BLAKE2S_USE_GATHER
1288
1289 #define GET_SIGMA(r) \
1290 const Byte * const sigma = k_Blake2s_Sigma_4[r];
1291 #define AXR2_LOAD_INDEXES_AVX(sigma_index) \
1292 AXR2_LOAD_INDEXES(sigma_index)
1293 #define SET_ROW_FROM_SIGMA_AVX(in) \
1294 MY_mm256_set_m128i( \
1295 SET_ROW_FROM_SIGMA_W((in) + Z7_BLAKE2S_BLOCK_SIZE), \
1296 SET_ROW_FROM_SIGMA_W(in))
1297 #define SIGMA_INTERLEAVE 1
1298 #define SIGMA_HALF_ROW_SIZE 8
1299#endif // !Z7_BLAKE2S_USE_GATHER
1300
81 1301
82 #define R(r) \ 1302#define ROTATE_WORDS_TO_RIGHT_256(a, n) \
83 G(r,0,v[ 0],v[ 4],v[ 8],v[12]) \ 1303 a = _mm256_shuffle_epi32(a, _MM_SHUFFLE((3+n)&3, (2+n)&3, (1+n)&3, (0+n)&3));
84 G(r,1,v[ 1],v[ 5],v[ 9],v[13]) \
85 G(r,2,v[ 2],v[ 6],v[10],v[14]) \
86 G(r,3,v[ 3],v[ 7],v[11],v[15]) \
87 G(r,4,v[ 0],v[ 5],v[10],v[15]) \
88 G(r,5,v[ 1],v[ 6],v[11],v[12]) \
89 G(r,6,v[ 2],v[ 7],v[ 8],v[13]) \
90 G(r,7,v[ 3],v[ 4],v[ 9],v[14]) \
91 1304
1305
1306
1307#ifdef Z7_BLAKE2S_USE_AVX2_WAY2
1308
1309#define AXR2_A(sigma_index, shift1, shift2) \
1310 AXR2_LOAD_INDEXES_AVX(sigma_index) \
1311 D_ADD_256( a0, SET_ROW_FROM_SIGMA_AVX(data)); \
1312 AXR256(a0, b0, d0, shift1) \
1313 AXR256(c0, d0, b0, shift2) \
1314
1315#define AXR4_A(sigma_index) \
1316 { AXR2_A(sigma_index, 16, 12) } \
1317 { AXR2_A(sigma_index + SIGMA_INTERLEAVE, 8, 7) }
1318
1319#define EE1(r) \
1320 { GET_SIGMA(r) \
1321 AXR4_A(0) \
1322 ROTATE_WORDS_TO_RIGHT_256(b0, 1) \
1323 ROTATE_WORDS_TO_RIGHT_256(c0, 2) \
1324 ROTATE_WORDS_TO_RIGHT_256(d0, 3) \
1325 AXR4_A(SIGMA_HALF_ROW_SIZE) \
1326 ROTATE_WORDS_TO_RIGHT_256(b0, 3) \
1327 ROTATE_WORDS_TO_RIGHT_256(c0, 2) \
1328 ROTATE_WORDS_TO_RIGHT_256(d0, 1) \
1329 }
1330
1331static
1332Z7_NO_INLINE
1333#ifdef BLAKE2S_ATTRIB_AVX2
1334 BLAKE2S_ATTRIB_AVX2
1335#endif
1336void
1337Z7_FASTCALL
1338Blake2sp_Compress2_AVX2_Way2(UInt32 *s_items, const Byte *data, const Byte *end)
1339{
1340 size_t pos = 0;
1341 end -= Z7_BLAKE2S_BLOCK_SIZE;
1342
1343 if (data != end)
92 { 1344 {
93 unsigned r; 1345 LOAD_ROTATE_CONSTS_256
94 for (r = 0; r < BLAKE2S_NUM_ROUNDS; r++) 1346 DIAG_PERM8(s_items)
1347 do
95 { 1348 {
96 const Byte *sigma = k_Blake2s_Sigma[r]; 1349 UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);
97 R(r) 1350 __m256i a0, b0, c0, d0;
1351 {
1352 const __m128i inc = k_inc;
1353 __m128i d0_128 = LOAD_128_FROM_STRUCT (STATE_T(s));
1354 __m128i d1_128 = LOAD_128_FROM_STRUCT (STATE_T(s + NSW));
1355 D_ADD_EPI64_128(d0_128, inc);
1356 D_ADD_EPI64_128(d1_128, inc);
1357 STORE_128_TO_STRUCT (STATE_T(s ), d0_128);
1358 STORE_128_TO_STRUCT (STATE_T(s + NSW), d1_128);
1359 d0 = MY_mm256_set_m128i(d1_128, d0_128);
1360 D_XOR_256(d0, k_iv4_256);
1361 }
1362 c0 = SET_FROM_128(k_iv0_128);
1363 a0 = LOAD_256_FROM_STRUCT(s + NSW * 0);
1364 b0 = LOAD_256_FROM_STRUCT(s + NSW * 1);
1365
1366 ROUNDS_LOOP (EE1)
1367
1368 D_XOR_256(a0, c0);
1369 D_XOR_256(b0, d0);
1370
1371 D_XOR_256(a0, LOAD_256_FROM_STRUCT(s + NSW * 0));
1372 D_XOR_256(b0, LOAD_256_FROM_STRUCT(s + NSW * 1));
1373
1374 STORE_256_TO_STRUCT(s + NSW * 0, a0);
1375 STORE_256_TO_STRUCT(s + NSW * 1, b0);
1376
1377 data += Z7_BLAKE2S_BLOCK_SIZE * 2;
1378 pos += Z7_BLAKE2S_BLOCK_SIZE * 2;
1379 pos &= SUPER_BLOCK_MASK;
98 } 1380 }
99 /* R(0); R(1); R(2); R(3); R(4); R(5); R(6); R(7); R(8); R(9); */ 1381 while (data < end);
1382 DIAG_PERM8(s_items)
1383 if (data != end)
1384 return;
1385 }
1386 {
1387 UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);
1388 Z7_BLAKE2S_CompressSingleBlock(s, data);
100 } 1389 }
1390}
1391
1392#endif // Z7_BLAKE2S_USE_AVX2_WAY2
101 1393
102 #undef G
103 #undef R
104 1394
1395
1396#ifdef Z7_BLAKE2S_USE_AVX2_WAY4
1397
1398#define AXR2_X(sigma_index, shift1, shift2) \
1399 AXR2_LOAD_INDEXES_AVX(sigma_index) \
1400 D_ADD_256( a0, SET_ROW_FROM_SIGMA_AVX(data)); \
1401 D_ADD_256( a1, SET_ROW_FROM_SIGMA_AVX((data) + Z7_BLAKE2S_BLOCK_SIZE * 2)); \
1402 AXR256(a0, b0, d0, shift1) \
1403 AXR256(a1, b1, d1, shift1) \
1404 AXR256(c0, d0, b0, shift2) \
1405 AXR256(c1, d1, b1, shift2) \
1406
1407#define AXR4_X(sigma_index) \
1408 { AXR2_X(sigma_index, 16, 12) } \
1409 { AXR2_X(sigma_index + SIGMA_INTERLEAVE, 8, 7) }
1410
1411#define EE2(r) \
1412 { GET_SIGMA(r) \
1413 AXR4_X(0) \
1414 ROTATE_WORDS_TO_RIGHT_256(b0, 1) \
1415 ROTATE_WORDS_TO_RIGHT_256(b1, 1) \
1416 ROTATE_WORDS_TO_RIGHT_256(c0, 2) \
1417 ROTATE_WORDS_TO_RIGHT_256(c1, 2) \
1418 ROTATE_WORDS_TO_RIGHT_256(d0, 3) \
1419 ROTATE_WORDS_TO_RIGHT_256(d1, 3) \
1420 AXR4_X(SIGMA_HALF_ROW_SIZE) \
1421 ROTATE_WORDS_TO_RIGHT_256(b0, 3) \
1422 ROTATE_WORDS_TO_RIGHT_256(b1, 3) \
1423 ROTATE_WORDS_TO_RIGHT_256(c0, 2) \
1424 ROTATE_WORDS_TO_RIGHT_256(c1, 2) \
1425 ROTATE_WORDS_TO_RIGHT_256(d0, 1) \
1426 ROTATE_WORDS_TO_RIGHT_256(d1, 1) \
1427 }
1428
1429static
1430Z7_NO_INLINE
1431#ifdef BLAKE2S_ATTRIB_AVX2
1432 BLAKE2S_ATTRIB_AVX2
1433#endif
1434void
1435Z7_FASTCALL
1436Blake2sp_Compress2_AVX2_Way4(UInt32 *s_items, const Byte *data, const Byte *end)
1437{
1438 size_t pos = 0;
1439
1440 if ((size_t)(end - data) >= Z7_BLAKE2S_BLOCK_SIZE * 4)
105 { 1441 {
106 unsigned i; 1442#ifndef Z7_MM256_ROR_EPI32_IS_SUPPORTED
107 for (i = 0; i < 8; i++) 1443 const __m256i r8 = k_r8_256;
108 p->h[i] ^= v[i] ^ v[i + 8]; 1444 const __m256i r16 = k_r16_256;
1445#endif
1446 end -= Z7_BLAKE2S_BLOCK_SIZE * 3;
1447 DIAG_PERM8(s_items)
1448 do
1449 {
1450 UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);
1451 __m256i a0, b0, c0, d0;
1452 __m256i a1, b1, c1, d1;
1453 {
1454 const __m128i inc = k_inc;
1455 __m128i d0_128 = LOAD_128_FROM_STRUCT (STATE_T(s));
1456 __m128i d1_128 = LOAD_128_FROM_STRUCT (STATE_T(s + NSW));
1457 __m128i d2_128 = LOAD_128_FROM_STRUCT (STATE_T(s + NSW * 2));
1458 __m128i d3_128 = LOAD_128_FROM_STRUCT (STATE_T(s + NSW * 3));
1459 D_ADD_EPI64_128(d0_128, inc);
1460 D_ADD_EPI64_128(d1_128, inc);
1461 D_ADD_EPI64_128(d2_128, inc);
1462 D_ADD_EPI64_128(d3_128, inc);
1463 STORE_128_TO_STRUCT (STATE_T(s ), d0_128);
1464 STORE_128_TO_STRUCT (STATE_T(s + NSW * 1), d1_128);
1465 STORE_128_TO_STRUCT (STATE_T(s + NSW * 2), d2_128);
1466 STORE_128_TO_STRUCT (STATE_T(s + NSW * 3), d3_128);
1467 d0 = MY_mm256_set_m128i(d1_128, d0_128);
1468 d1 = MY_mm256_set_m128i(d3_128, d2_128);
1469 D_XOR_256(d0, k_iv4_256);
1470 D_XOR_256(d1, k_iv4_256);
1471 }
1472 c1 = c0 = SET_FROM_128(k_iv0_128);
1473 a0 = LOAD_256_FROM_STRUCT(s + NSW * 0);
1474 b0 = LOAD_256_FROM_STRUCT(s + NSW * 1);
1475 a1 = LOAD_256_FROM_STRUCT(s + NSW * 2);
1476 b1 = LOAD_256_FROM_STRUCT(s + NSW * 3);
1477
1478 ROUNDS_LOOP (EE2)
1479
1480 D_XOR_256(a0, c0);
1481 D_XOR_256(b0, d0);
1482 D_XOR_256(a1, c1);
1483 D_XOR_256(b1, d1);
1484
1485 D_XOR_256(a0, LOAD_256_FROM_STRUCT(s + NSW * 0));
1486 D_XOR_256(b0, LOAD_256_FROM_STRUCT(s + NSW * 1));
1487 D_XOR_256(a1, LOAD_256_FROM_STRUCT(s + NSW * 2));
1488 D_XOR_256(b1, LOAD_256_FROM_STRUCT(s + NSW * 3));
1489
1490 STORE_256_TO_STRUCT(s + NSW * 0, a0);
1491 STORE_256_TO_STRUCT(s + NSW * 1, b0);
1492 STORE_256_TO_STRUCT(s + NSW * 2, a1);
1493 STORE_256_TO_STRUCT(s + NSW * 3, b1);
1494
1495 data += Z7_BLAKE2S_BLOCK_SIZE * 4;
1496 pos += Z7_BLAKE2S_BLOCK_SIZE * 4;
1497 pos &= SUPER_BLOCK_MASK;
1498 }
1499 while (data < end);
1500 DIAG_PERM8(s_items)
1501 end += Z7_BLAKE2S_BLOCK_SIZE * 3;
109 } 1502 }
1503 if (data == end)
1504 return;
1505 // Z7_BLAKE2S_Compress2_V128(s_items, data, end, pos);
1506 do
1507 {
1508 UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);
1509 Z7_BLAKE2S_CompressSingleBlock(s, data);
1510 data += Z7_BLAKE2S_BLOCK_SIZE;
1511 pos += Z7_BLAKE2S_BLOCK_SIZE;
1512 pos &= SUPER_BLOCK_MASK;
1513 }
1514 while (data != end);
1515}
1516
1517#endif // Z7_BLAKE2S_USE_AVX2_WAY4
1518#endif // Z7_BLAKE2S_USE_AVX2_WAY_SLOW
1519
1520
1521// ---------------------------------------------------------
1522
1523#ifdef Z7_BLAKE2S_USE_AVX2_FAST
1524
1525#define OP256_L(a, i) D_ADD_256 (V(a, 0), \
1526 LOAD_256((const Byte *)(w) + GET_SIGMA_VAL_256(2*(a)+(i))));
1527
1528#define OP256_0(a) OP256_L(a, 0)
1529#define OP256_7(a) OP256_L(a, 1)
1530
1531#define OP256_1(a) D_ADD_256 (V(a, 0), V(a, 1));
1532#define OP256_2(a) D_XOR_256 (V(a, 3), V(a, 0));
1533#define OP256_4(a) D_ADD_256 (V(a, 2), V(a, 3));
1534#define OP256_5(a) D_XOR_256 (V(a, 1), V(a, 2));
1535
1536#define OP256_3(a) D_ROT_256_16 (V(a, 3));
1537#define OP256_6(a) D_ROT_256_12 (V(a, 1));
1538#define OP256_8(a) D_ROT_256_8 (V(a, 3));
1539#define OP256_9(a) D_ROT_256_7 (V(a, 1));
1540
1541
1542#if 0 || 1 && defined(MY_CPU_X86)
1543
1544#define V8_G(a) \
1545 OP256_0 (a) \
1546 OP256_1 (a) \
1547 OP256_2 (a) \
1548 OP256_3 (a) \
1549 OP256_4 (a) \
1550 OP256_5 (a) \
1551 OP256_6 (a) \
1552 OP256_7 (a) \
1553 OP256_1 (a) \
1554 OP256_2 (a) \
1555 OP256_8 (a) \
1556 OP256_4 (a) \
1557 OP256_5 (a) \
1558 OP256_9 (a) \
1559
1560#define V8R { \
1561 V8_G (0); \
1562 V8_G (1); \
1563 V8_G (2); \
1564 V8_G (3); \
1565 V8_G (4); \
1566 V8_G (5); \
1567 V8_G (6); \
1568 V8_G (7); \
1569}
1570
1571#else
1572
1573#define OP256_INTER_4(op, a,b,c,d) \
1574 op (a) \
1575 op (b) \
1576 op (c) \
1577 op (d) \
1578
1579#define V8_G(a,b,c,d) \
1580 OP256_INTER_4 (OP256_0, a,b,c,d) \
1581 OP256_INTER_4 (OP256_1, a,b,c,d) \
1582 OP256_INTER_4 (OP256_2, a,b,c,d) \
1583 OP256_INTER_4 (OP256_3, a,b,c,d) \
1584 OP256_INTER_4 (OP256_4, a,b,c,d) \
1585 OP256_INTER_4 (OP256_5, a,b,c,d) \
1586 OP256_INTER_4 (OP256_6, a,b,c,d) \
1587 OP256_INTER_4 (OP256_7, a,b,c,d) \
1588 OP256_INTER_4 (OP256_1, a,b,c,d) \
1589 OP256_INTER_4 (OP256_2, a,b,c,d) \
1590 OP256_INTER_4 (OP256_8, a,b,c,d) \
1591 OP256_INTER_4 (OP256_4, a,b,c,d) \
1592 OP256_INTER_4 (OP256_5, a,b,c,d) \
1593 OP256_INTER_4 (OP256_9, a,b,c,d) \
1594
1595#define V8R { \
1596 V8_G (0, 1, 2, 3) \
1597 V8_G (4, 5, 6, 7) \
1598}
1599#endif
1600
1601#define V8_ROUND(r) { GET_SIGMA_PTR_256(r); V8R }
1602
1603
1604// for debug:
1605// #define Z7_BLAKE2S_PERMUTE_WITH_GATHER
1606#if defined(Z7_BLAKE2S_PERMUTE_WITH_GATHER)
1607// gather instruction is slow.
1608#define V8_LOAD_MSG(w, m) \
1609{ \
1610 unsigned i; \
1611 for (i = 0; i < 16; ++i) { \
1612 w[i] = _mm256_i32gather_epi32( \
1613 (const void *)((m) + i * sizeof(UInt32)),\
1614 _mm256_set_epi32(0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00), \
1615 sizeof(UInt32)); \
1616 } \
1617}
1618#else // !Z7_BLAKE2S_PERMUTE_WITH_GATHER
1619
1620#define V8_LOAD_MSG_2(w, a0, a1) \
1621{ \
1622 (w)[0] = _mm256_permute2x128_si256(a0, a1, 0x20); \
1623 (w)[4] = _mm256_permute2x128_si256(a0, a1, 0x31); \
1624}
1625
1626#define V8_LOAD_MSG_4(w, z0, z1, z2, z3) \
1627{ \
1628 __m256i s0, s1, s2, s3; \
1629 s0 = _mm256_unpacklo_epi64(z0, z1); \
1630 s1 = _mm256_unpackhi_epi64(z0, z1); \
1631 s2 = _mm256_unpacklo_epi64(z2, z3); \
1632 s3 = _mm256_unpackhi_epi64(z2, z3); \
1633 V8_LOAD_MSG_2((w) + 0, s0, s2) \
1634 V8_LOAD_MSG_2((w) + 1, s1, s3) \
1635}
1636
1637#define V8_LOAD_MSG_0(t0, t1, m) \
1638{ \
1639 __m256i m0, m1; \
1640 m0 = LOADU_256(m); \
1641 m1 = LOADU_256((m) + 2 * 32); \
1642 t0 = _mm256_unpacklo_epi32(m0, m1); \
1643 t1 = _mm256_unpackhi_epi32(m0, m1); \
1644}
1645
1646#define V8_LOAD_MSG_8(w, m) \
1647{ \
1648 __m256i t0, t1, t2, t3, t4, t5, t6, t7; \
1649 V8_LOAD_MSG_0(t0, t4, (m) + 0 * 4 * 32) \
1650 V8_LOAD_MSG_0(t1, t5, (m) + 1 * 4 * 32) \
1651 V8_LOAD_MSG_0(t2, t6, (m) + 2 * 4 * 32) \
1652 V8_LOAD_MSG_0(t3, t7, (m) + 3 * 4 * 32) \
1653 V8_LOAD_MSG_4((w) , t0, t1, t2, t3) \
1654 V8_LOAD_MSG_4((w) + 2, t4, t5, t6, t7) \
1655}
1656
1657#define V8_LOAD_MSG(w, m) \
1658{ \
1659 V8_LOAD_MSG_8(w, m) \
1660 V8_LOAD_MSG_8((w) + 8, (m) + 32) \
1661}
1662
1663#endif // !Z7_BLAKE2S_PERMUTE_WITH_GATHER
1664
1665
1666#define V8_PERM_PAIR_STORE(u, a0, a2) \
1667{ \
1668 STORE_256_TO_STRUCT((u), _mm256_permute2x128_si256(a0, a2, 0x20)); \
1669 STORE_256_TO_STRUCT((u) + 8, _mm256_permute2x128_si256(a0, a2, 0x31)); \
1670}
1671
1672#define V8_UNPACK_STORE_4(u, z0, z1, z2, z3) \
1673{ \
1674 __m256i s0, s1, s2, s3; \
1675 s0 = _mm256_unpacklo_epi64(z0, z1); \
1676 s1 = _mm256_unpackhi_epi64(z0, z1); \
1677 s2 = _mm256_unpacklo_epi64(z2, z3); \
1678 s3 = _mm256_unpackhi_epi64(z2, z3); \
1679 V8_PERM_PAIR_STORE(u + 0, s0, s2) \
1680 V8_PERM_PAIR_STORE(u + 2, s1, s3) \
1681}
1682
1683#define V8_UNPACK_STORE_0(src32, d0, d1) \
1684{ \
1685 const __m256i v0 = LOAD_256_FROM_STRUCT ((src32) ); \
1686 const __m256i v1 = LOAD_256_FROM_STRUCT ((src32) + 8); \
1687 d0 = _mm256_unpacklo_epi32(v0, v1); \
1688 d1 = _mm256_unpackhi_epi32(v0, v1); \
1689}
1690
1691#define V8_UNPACK_STATE(dest32, src32) \
1692{ \
1693 __m256i t0, t1, t2, t3, t4, t5, t6, t7; \
1694 V8_UNPACK_STORE_0 ((src32) + 16 * 0, t0, t4) \
1695 V8_UNPACK_STORE_0 ((src32) + 16 * 1, t1, t5) \
1696 V8_UNPACK_STORE_0 ((src32) + 16 * 2, t2, t6) \
1697 V8_UNPACK_STORE_0 ((src32) + 16 * 3, t3, t7) \
1698 V8_UNPACK_STORE_4 ((__m256i *)(void *)(dest32) , t0, t1, t2, t3) \
1699 V8_UNPACK_STORE_4 ((__m256i *)(void *)(dest32) + 4, t4, t5, t6, t7) \
110} 1700}
111 1701
112 1702
113#define Blake2s_Increment_Counter(S, inc) \
114 { p->t[0] += (inc); p->t[1] += (p->t[0] < (inc)); }
115 1703
116#define Blake2s_Set_LastBlock(p) \ 1704#define V8_LOAD_STATE_256_FROM_STRUCT(i) \
117 { p->f[0] = BLAKE2S_FINAL_FLAG; p->f[1] = p->lastNode_f1; } 1705 v[i] = LOAD_256_FROM_STRUCT(s_items + (i) * 8);
1706
1707#if 0 || 0 && defined(MY_CPU_X86)
1708#define Z7_BLAKE2S_AVX2_FAST_USE_STRUCT
1709#endif
1710
1711#ifdef Z7_BLAKE2S_AVX2_FAST_USE_STRUCT
1712// this branch doesn't use (iv) array
1713// so register pressure can be lower.
1714// it can be faster sometimes
1715#define V8_LOAD_STATE_256(i) V8_LOAD_STATE_256_FROM_STRUCT(i)
1716#define V8_UPDATE_STATE_256(i) \
1717{ \
1718 STORE_256_TO_STRUCT(s_items + (i) * 8, XOR_256( \
1719 XOR_256(v[i], v[(i) + 8]), \
1720 LOAD_256_FROM_STRUCT(s_items + (i) * 8))); \
1721}
1722#else
1723// it uses more variables (iv) registers
1724// it's better for gcc
1725// maybe that branch is better, if register pressure will be lower (avx512)
1726#define V8_LOAD_STATE_256(i) { iv[i] = v[i]; }
1727#define V8_UPDATE_STATE_256(i) { v[i] = XOR_256(XOR_256(v[i], v[i + 8]), iv[i]); }
1728#define V8_STORE_STATE_256(i) { STORE_256_TO_STRUCT(s_items + (i) * 8, v[i]); }
1729#endif
118 1730
119 1731
120static void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size) 1732#if 0
1733 // use loading constants from memory
1734 #define KK8(n) KIV(n), KIV(n), KIV(n), KIV(n), KIV(n), KIV(n), KIV(n), KIV(n)
1735MY_ALIGN(64)
1736static const UInt32 k_Blake2s_IV_WAY8[]=
121{ 1737{
122 while (size != 0) 1738 KK8(0), KK8(1), KK8(2), KK8(3), KK8(4), KK8(5), KK8(6), KK8(7)
123 { 1739};
124 unsigned pos = (unsigned)p->bufPos; 1740 #define GET_256_IV_WAY8(i) LOAD_256(k_Blake2s_IV_WAY8 + 8 * (i))
125 unsigned rem = BLAKE2S_BLOCK_SIZE - pos; 1741#else
1742 // use constant generation:
1743 #define GET_256_IV_WAY8(i) _mm256_set1_epi32((Int32)KIV(i))
1744#endif
126 1745
127 if (size <= rem) 1746
1747static
1748Z7_NO_INLINE
1749#ifdef BLAKE2S_ATTRIB_AVX2
1750 BLAKE2S_ATTRIB_AVX2
1751#endif
1752void
1753Z7_FASTCALL
1754Blake2sp_Compress2_AVX2_Fast(UInt32 *s_items, const Byte *data, const Byte *end)
1755{
1756#ifndef Z7_BLAKE2S_AVX2_FAST_USE_STRUCT
1757 __m256i v[16];
1758#endif
1759
1760 // PrintStates2(s_items, 8, 16);
1761
1762#ifndef Z7_BLAKE2S_AVX2_FAST_USE_STRUCT
1763 REP8_MACRO (V8_LOAD_STATE_256_FROM_STRUCT)
1764#endif
1765
1766 do
1767 {
1768 __m256i w[16];
1769#ifdef Z7_BLAKE2S_AVX2_FAST_USE_STRUCT
1770 __m256i v[16];
1771#else
1772 __m256i iv[8];
1773#endif
1774 V8_LOAD_MSG(w, data)
128 { 1775 {
129 memcpy(p->buf + pos, data, size); 1776 // we use load/store ctr inside loop to reduce register pressure:
130 p->bufPos += (UInt32)size; 1777#if 1 || 1 && defined(MY_CPU_X86)
131 return; 1778 const __m256i ctr = _mm256_add_epi64(
1779 LOAD_256_FROM_STRUCT(s_items + 64),
1780 _mm256_set_epi32(
1781 0, 0, 0, Z7_BLAKE2S_BLOCK_SIZE,
1782 0, 0, 0, Z7_BLAKE2S_BLOCK_SIZE));
1783 STORE_256_TO_STRUCT(s_items + 64, ctr);
1784#else
1785 const UInt64 ctr64 = *(const UInt64 *)(const void *)(s_items + 64)
1786 + Z7_BLAKE2S_BLOCK_SIZE;
1787 const __m256i ctr = _mm256_set_epi64x(0, (Int64)ctr64, 0, (Int64)ctr64);
1788 *(UInt64 *)(void *)(s_items + 64) = ctr64;
1789#endif
1790 v[12] = XOR_256 (GET_256_IV_WAY8(4), _mm256_shuffle_epi32(ctr, _MM_SHUFFLE(0, 0, 0, 0)));
1791 v[13] = XOR_256 (GET_256_IV_WAY8(5), _mm256_shuffle_epi32(ctr, _MM_SHUFFLE(1, 1, 1, 1)));
132 } 1792 }
1793 v[ 8] = GET_256_IV_WAY8(0);
1794 v[ 9] = GET_256_IV_WAY8(1);
1795 v[10] = GET_256_IV_WAY8(2);
1796 v[11] = GET_256_IV_WAY8(3);
1797 v[14] = GET_256_IV_WAY8(6);
1798 v[15] = GET_256_IV_WAY8(7);
133 1799
134 memcpy(p->buf + pos, data, rem); 1800 REP8_MACRO (V8_LOAD_STATE_256)
135 Blake2s_Increment_Counter(S, BLAKE2S_BLOCK_SIZE) 1801 ROUNDS_LOOP (V8_ROUND)
136 Blake2s_Compress(p); 1802 REP8_MACRO (V8_UPDATE_STATE_256)
137 p->bufPos = 0; 1803 data += SUPER_BLOCK_SIZE;
138 data += rem;
139 size -= rem;
140 } 1804 }
1805 while (data != end);
1806
1807#ifndef Z7_BLAKE2S_AVX2_FAST_USE_STRUCT
1808 REP8_MACRO (V8_STORE_STATE_256)
1809#endif
141} 1810}
142 1811
143 1812
144static void Blake2s_Final(CBlake2s *p, Byte *digest) 1813static
1814Z7_NO_INLINE
1815#ifdef BLAKE2S_ATTRIB_AVX2
1816 BLAKE2S_ATTRIB_AVX2
1817#endif
1818void
1819Z7_FASTCALL
1820Blake2sp_Final_AVX2_Fast(UInt32 *states)
145{ 1821{
146 unsigned i; 1822 const __m128i ctr = LOAD_128_FROM_STRUCT(states + 64);
1823 // PrintStates2(states, 8, 16);
1824 V8_UNPACK_STATE(states, states)
1825 // PrintStates2(states, 8, 16);
1826 {
1827 unsigned k;
1828 for (k = 0; k < 8; k++)
1829 {
1830 UInt32 *s = states + (size_t)k * 16;
1831 STORE_128_TO_STRUCT (STATE_T(s), ctr);
1832 }
1833 }
1834 // PrintStates2(states, 8, 16);
1835 // printf("\nafter V8_UNPACK_STATE \n");
1836}
1837
1838#endif // Z7_BLAKE2S_USE_AVX2_FAST
1839#endif // avx2
1840#endif // vector
1841
1842
1843/*
1844#define Blake2s_Increment_Counter(s, inc) \
1845 { STATE_T(s)[0] += (inc); STATE_T(s)[1] += (STATE_T(s)[0] < (inc)); }
1846#define Blake2s_Increment_Counter_Small(s, inc) \
1847 { STATE_T(s)[0] += (inc); }
1848*/
1849
1850#define Blake2s_Set_LastBlock(s) \
1851 { STATE_F(s)[0] = BLAKE2S_FINAL_FLAG; /* STATE_F(s)[1] = p->u.header.lastNode_f1; */ }
1852
1853
1854#if 0 || 1 && defined(Z7_MSC_VER_ORIGINAL) && Z7_MSC_VER_ORIGINAL >= 1600
1855 // good for vs2022
1856 #define LOOP_8(mac) { unsigned kkk; for (kkk = 0; kkk < 8; kkk++) mac(kkk) }
1857#else
1858 // good for Z7_BLAKE2S_UNROLL for GCC9 (arm*/x86*) and MSC_VER_1400-x64.
1859 #define LOOP_8(mac) { REP8_MACRO(mac) }
1860#endif
1861
1862
1863static
1864Z7_FORCE_INLINE
1865// Z7_NO_INLINE
1866void
1867Z7_FASTCALL
1868Blake2s_Compress(UInt32 *s, const Byte *input)
1869{
1870 UInt32 m[16];
1871 UInt32 v[16];
1872 {
1873 unsigned i;
1874 for (i = 0; i < 16; i++)
1875 m[i] = GetUi32(input + i * 4);
1876 }
1877
1878#define INIT_v_FROM_s(i) v[i] = s[i];
1879
1880 LOOP_8(INIT_v_FROM_s)
1881
1882 // Blake2s_Increment_Counter(s, Z7_BLAKE2S_BLOCK_SIZE)
1883 {
1884 const UInt32 t0 = STATE_T(s)[0] + Z7_BLAKE2S_BLOCK_SIZE;
1885 const UInt32 t1 = STATE_T(s)[1] + (t0 < Z7_BLAKE2S_BLOCK_SIZE);
1886 STATE_T(s)[0] = t0;
1887 STATE_T(s)[1] = t1;
1888 v[12] = t0 ^ KIV(4);
1889 v[13] = t1 ^ KIV(5);
1890 }
1891 // v[12] = STATE_T(s)[0] ^ KIV(4);
1892 // v[13] = STATE_T(s)[1] ^ KIV(5);
1893 v[14] = STATE_F(s)[0] ^ KIV(6);
1894 v[15] = STATE_F(s)[1] ^ KIV(7);
1895
1896 v[ 8] = KIV(0);
1897 v[ 9] = KIV(1);
1898 v[10] = KIV(2);
1899 v[11] = KIV(3);
1900 // PrintStates2((const UInt32 *)v, 1, 16);
1901
1902 #define ADD_SIGMA(a, index) V(a, 0) += *(const UInt32 *)GET_SIGMA_PTR(m, sigma[index]);
1903 #define ADD32M(dest, src, a) V(a, dest) += V(a, src);
1904 #define XOR32M(dest, src, a) V(a, dest) ^= V(a, src);
1905 #define RTR32M(dest, shift, a) V(a, dest) = rotrFixed(V(a, dest), shift);
1906
1907// big interleaving can provides big performance gain, if scheduler queues are small.
1908#if 0 || 1 && defined(MY_CPU_X86)
1909 // interleave-1: for small register number (x86-32bit)
1910 #define G2(index, a, x, y) \
1911 ADD_SIGMA (a, (index) + 2 * 0) \
1912 ADD32M (0, 1, a) \
1913 XOR32M (3, 0, a) \
1914 RTR32M (3, x, a) \
1915 ADD32M (2, 3, a) \
1916 XOR32M (1, 2, a) \
1917 RTR32M (1, y, a) \
1918
1919 #define G(a) \
1920 G2(a * 2 , a, 16, 12) \
1921 G2(a * 2 + 1, a, 8, 7) \
1922
1923 #define R2 \
1924 G(0) \
1925 G(1) \
1926 G(2) \
1927 G(3) \
1928 G(4) \
1929 G(5) \
1930 G(6) \
1931 G(7) \
1932
1933#elif 0 || 1 && defined(MY_CPU_X86_OR_AMD64)
1934 // interleave-2: is good if the number of registers is not big (x86-64).
1935
1936 #define REP2(mac, dest, src, a, b) \
1937 mac(dest, src, a) \
1938 mac(dest, src, b)
1939
1940 #define G2(index, a, b, x, y) \
1941 ADD_SIGMA (a, (index) + 2 * 0) \
1942 ADD_SIGMA (b, (index) + 2 * 1) \
1943 REP2 (ADD32M, 0, 1, a, b) \
1944 REP2 (XOR32M, 3, 0, a, b) \
1945 REP2 (RTR32M, 3, x, a, b) \
1946 REP2 (ADD32M, 2, 3, a, b) \
1947 REP2 (XOR32M, 1, 2, a, b) \
1948 REP2 (RTR32M, 1, y, a, b) \
1949
1950 #define G(a, b) \
1951 G2(a * 2 , a, b, 16, 12) \
1952 G2(a * 2 + 1, a, b, 8, 7) \
1953
1954 #define R2 \
1955 G(0, 1) \
1956 G(2, 3) \
1957 G(4, 5) \
1958 G(6, 7) \
147 1959
148 Blake2s_Increment_Counter(S, (UInt32)p->bufPos) 1960#else
149 Blake2s_Set_LastBlock(p) 1961 // interleave-4:
150 memset(p->buf + p->bufPos, 0, BLAKE2S_BLOCK_SIZE - p->bufPos); 1962 // it has big register pressure for x86/x64.
151 Blake2s_Compress(p); 1963 // and MSVC compilers for x86/x64 are slow for this branch.
1964 // but if we have big number of registers, this branch can be faster.
152 1965
153 for (i = 0; i < 8; i++) 1966 #define REP4(mac, dest, src, a, b, c, d) \
1967 mac(dest, src, a) \
1968 mac(dest, src, b) \
1969 mac(dest, src, c) \
1970 mac(dest, src, d)
1971
1972 #define G2(index, a, b, c, d, x, y) \
1973 ADD_SIGMA (a, (index) + 2 * 0) \
1974 ADD_SIGMA (b, (index) + 2 * 1) \
1975 ADD_SIGMA (c, (index) + 2 * 2) \
1976 ADD_SIGMA (d, (index) + 2 * 3) \
1977 REP4 (ADD32M, 0, 1, a, b, c, d) \
1978 REP4 (XOR32M, 3, 0, a, b, c, d) \
1979 REP4 (RTR32M, 3, x, a, b, c, d) \
1980 REP4 (ADD32M, 2, 3, a, b, c, d) \
1981 REP4 (XOR32M, 1, 2, a, b, c, d) \
1982 REP4 (RTR32M, 1, y, a, b, c, d) \
1983
1984 #define G(a, b, c, d) \
1985 G2(a * 2 , a, b, c, d, 16, 12) \
1986 G2(a * 2 + 1, a, b, c, d, 8, 7) \
1987
1988 #define R2 \
1989 G(0, 1, 2, 3) \
1990 G(4, 5, 6, 7) \
1991
1992#endif
1993
1994 #define R(r) { const Byte *sigma = k_Blake2s_Sigma_4[r]; R2 }
1995
1996 // Z7_BLAKE2S_UNROLL gives 5-6 KB larger code, but faster:
1997 // 20-40% faster for (x86/x64) VC2010+/GCC/CLANG.
1998 // 30-60% faster for (arm64-arm32) GCC.
1999 // 5-11% faster for (arm64) CLANG-MAC.
2000 // so Z7_BLAKE2S_UNROLL is good optimization, if there is no vector branch.
2001 // But if there is vectors branch (for x86*), this scalar code will be unused mostly.
2002 // So we want smaller code (without unrolling) in that case (x86*).
2003#if 0 || 1 && !defined(Z7_BLAKE2S_USE_VECTORS)
2004 #define Z7_BLAKE2S_UNROLL
2005#endif
2006
2007#ifdef Z7_BLAKE2S_UNROLL
2008 ROUNDS_LOOP_UNROLLED (R)
2009#else
2010 ROUNDS_LOOP (R)
2011#endif
2012
2013 #undef G
2014 #undef G2
2015 #undef R
2016 #undef R2
2017
2018 // printf("\n v after: \n");
2019 // PrintStates2((const UInt32 *)v, 1, 16);
2020#define XOR_s_PAIR_v(i) s[i] ^= v[i] ^ v[i + 8];
2021
2022 LOOP_8(XOR_s_PAIR_v)
2023 // printf("\n s after:\n");
2024 // PrintStates2((const UInt32 *)s, 1, 16);
2025}
2026
2027
2028static
2029Z7_NO_INLINE
2030void
2031Z7_FASTCALL
2032Blake2sp_Compress2(UInt32 *s_items, const Byte *data, const Byte *end)
2033{
2034 size_t pos = 0;
2035 // PrintStates2(s_items, 8, 16);
2036 do
154 { 2037 {
155 SetUi32(digest + sizeof(p->h[i]) * i, p->h[i]) 2038 UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);
2039 Blake2s_Compress(s, data);
2040 data += Z7_BLAKE2S_BLOCK_SIZE;
2041 pos += Z7_BLAKE2S_BLOCK_SIZE;
2042 pos &= SUPER_BLOCK_MASK;
156 } 2043 }
2044 while (data != end);
157} 2045}
158 2046
159 2047
160/* ---------- BLAKE2s ---------- */ 2048#ifdef Z7_BLAKE2S_USE_VECTORS
2049
2050static Z7_BLAKE2SP_FUNC_COMPRESS g_Z7_BLAKE2SP_FUNC_COMPRESS_Fast = Blake2sp_Compress2;
2051static Z7_BLAKE2SP_FUNC_COMPRESS g_Z7_BLAKE2SP_FUNC_COMPRESS_Single = Blake2sp_Compress2;
2052static Z7_BLAKE2SP_FUNC_INIT g_Z7_BLAKE2SP_FUNC_INIT_Init;
2053static Z7_BLAKE2SP_FUNC_INIT g_Z7_BLAKE2SP_FUNC_INIT_Final;
2054static unsigned g_z7_Blake2sp_SupportedFlags;
2055
2056 #define Z7_BLAKE2SP_Compress_Fast(p) (p)->u.header.func_Compress_Fast
2057 #define Z7_BLAKE2SP_Compress_Single(p) (p)->u.header.func_Compress_Single
2058#else
2059 #define Z7_BLAKE2SP_Compress_Fast(p) Blake2sp_Compress2
2060 #define Z7_BLAKE2SP_Compress_Single(p) Blake2sp_Compress2
2061#endif // Z7_BLAKE2S_USE_VECTORS
2062
161 2063
162/* we need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */ 2064#if 1 && defined(MY_CPU_LE)
2065 #define GET_DIGEST(_s, _digest) \
2066 { memcpy(_digest, _s, Z7_BLAKE2S_DIGEST_SIZE); }
2067#else
2068 #define GET_DIGEST(_s, _digest) \
2069 { unsigned _i; for (_i = 0; _i < 8; _i++) \
2070 { SetUi32((_digest) + 4 * _i, (_s)[_i]) } \
2071 }
2072#endif
2073
2074
2075/* ---------- BLAKE2s ---------- */
163/* 2076/*
2077// we need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0()
164typedef struct 2078typedef struct
165{ 2079{
166 Byte digest_length; 2080 Byte digest_length;
167 Byte key_length; 2081 Byte key_length;
168 Byte fanout; 2082 Byte fanout; // = 1 : in sequential mode
169 Byte depth; 2083 Byte depth; // = 1 : in sequential mode
170 UInt32 leaf_length; 2084 UInt32 leaf_length;
171 Byte node_offset[6]; 2085 Byte node_offset[6]; // 0 for the first, leftmost, leaf, or in sequential mode
172 Byte node_depth; 2086 Byte node_depth; // 0 for the leaves, or in sequential mode
173 Byte inner_length; 2087 Byte inner_length; // [0, 32], 0 in sequential mode
174 Byte salt[BLAKE2S_SALTBYTES]; 2088 Byte salt[BLAKE2S_SALTBYTES];
175 Byte personal[BLAKE2S_PERSONALBYTES]; 2089 Byte personal[BLAKE2S_PERSONALBYTES];
176} CBlake2sParam; 2090} CBlake2sParam;
177*/ 2091*/
178 2092
2093#define k_Blake2sp_IV_0 \
2094 (KIV(0) ^ (Z7_BLAKE2S_DIGEST_SIZE | ((UInt32)Z7_BLAKE2SP_PARALLEL_DEGREE << 16) | ((UInt32)2 << 24)))
2095#define k_Blake2sp_IV_3_FROM_NODE_DEPTH(node_depth) \
2096 (KIV(3) ^ ((UInt32)(node_depth) << 16) ^ ((UInt32)Z7_BLAKE2S_DIGEST_SIZE << 24))
179 2097
180static void Blake2sp_Init_Spec(CBlake2s *p, unsigned node_offset, unsigned node_depth) 2098Z7_FORCE_INLINE
2099static void Blake2sp_Init_Spec(UInt32 *s, unsigned node_offset, unsigned node_depth)
181{ 2100{
182 Blake2s_Init0(p); 2101 s[0] = k_Blake2sp_IV_0;
183 2102 s[1] = KIV(1);
184 p->h[0] ^= (BLAKE2S_DIGEST_SIZE | ((UInt32)BLAKE2SP_PARALLEL_DEGREE << 16) | ((UInt32)2 << 24)); 2103 s[2] = KIV(2) ^ (UInt32)node_offset;
185 p->h[2] ^= ((UInt32)node_offset); 2104 s[3] = k_Blake2sp_IV_3_FROM_NODE_DEPTH(node_depth);
186 p->h[3] ^= ((UInt32)node_depth << 16) | ((UInt32)BLAKE2S_DIGEST_SIZE << 24); 2105 s[4] = KIV(4);
187 /* 2106 s[5] = KIV(5);
188 P->digest_length = BLAKE2S_DIGEST_SIZE; 2107 s[6] = KIV(6);
189 P->key_length = 0; 2108 s[7] = KIV(7);
190 P->fanout = BLAKE2SP_PARALLEL_DEGREE; 2109
191 P->depth = 2; 2110 STATE_T(s)[0] = 0;
192 P->leaf_length = 0; 2111 STATE_T(s)[1] = 0;
193 store48(P->node_offset, node_offset); 2112 STATE_F(s)[0] = 0;
194 P->node_depth = node_depth; 2113 STATE_F(s)[1] = 0;
195 P->inner_length = BLAKE2S_DIGEST_SIZE;
196 */
197} 2114}
198 2115
199 2116
2117#ifdef Z7_BLAKE2S_USE_V128_FAST
2118
2119static
2120Z7_NO_INLINE
2121#ifdef BLAKE2S_ATTRIB_128BIT
2122 BLAKE2S_ATTRIB_128BIT
2123#endif
2124void
2125Z7_FASTCALL
2126Blake2sp_InitState_V128_Fast(UInt32 *states)
2127{
2128#define STORE_128_PAIR_INIT_STATES_2(i, t0, t1) \
2129 { STORE_128_TO_STRUCT(states + 0 + 4 * (i), (t0)); \
2130 STORE_128_TO_STRUCT(states + 32 + 4 * (i), (t1)); \
2131 }
2132#define STORE_128_PAIR_INIT_STATES_1(i, mac) \
2133 { const __m128i t = mac; \
2134 STORE_128_PAIR_INIT_STATES_2(i, t, t) \
2135 }
2136#define STORE_128_PAIR_INIT_STATES_IV(i) \
2137 STORE_128_PAIR_INIT_STATES_1(i, GET_128_IV_WAY4(i))
2138
2139 STORE_128_PAIR_INIT_STATES_1 (0, _mm_set1_epi32((Int32)k_Blake2sp_IV_0))
2140 STORE_128_PAIR_INIT_STATES_IV (1)
2141 {
2142 const __m128i t = GET_128_IV_WAY4(2);
2143 STORE_128_PAIR_INIT_STATES_2 (2,
2144 XOR_128(t, _mm_set_epi32(3, 2, 1, 0)),
2145 XOR_128(t, _mm_set_epi32(7, 6, 5, 4)))
2146 }
2147 STORE_128_PAIR_INIT_STATES_1 (3, _mm_set1_epi32((Int32)k_Blake2sp_IV_3_FROM_NODE_DEPTH(0)))
2148 STORE_128_PAIR_INIT_STATES_IV (4)
2149 STORE_128_PAIR_INIT_STATES_IV (5)
2150 STORE_128_PAIR_INIT_STATES_IV (6)
2151 STORE_128_PAIR_INIT_STATES_IV (7)
2152 STORE_128_PAIR_INIT_STATES_1 (16, _mm_set_epi32(0, 0, 0, 0))
2153 // printf("\n== exit Blake2sp_InitState_V128_Fast ctr=%d\n", states[64]);
2154}
2155
2156#endif // Z7_BLAKE2S_USE_V128_FAST
2157
2158
2159#ifdef Z7_BLAKE2S_USE_AVX2_FAST
2160
2161static
2162Z7_NO_INLINE
2163#ifdef BLAKE2S_ATTRIB_AVX2
2164 BLAKE2S_ATTRIB_AVX2
2165#endif
2166void
2167Z7_FASTCALL
2168Blake2sp_InitState_AVX2_Fast(UInt32 *states)
2169{
2170#define STORE_256_INIT_STATES(i, t) \
2171 STORE_256_TO_STRUCT(states + 8 * (i), t);
2172#define STORE_256_INIT_STATES_IV(i) \
2173 STORE_256_INIT_STATES(i, GET_256_IV_WAY8(i))
2174
2175 STORE_256_INIT_STATES (0, _mm256_set1_epi32((Int32)k_Blake2sp_IV_0))
2176 STORE_256_INIT_STATES_IV (1)
2177 STORE_256_INIT_STATES (2, XOR_256( GET_256_IV_WAY8(2),
2178 _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)))
2179 STORE_256_INIT_STATES (3, _mm256_set1_epi32((Int32)k_Blake2sp_IV_3_FROM_NODE_DEPTH(0)))
2180 STORE_256_INIT_STATES_IV (4)
2181 STORE_256_INIT_STATES_IV (5)
2182 STORE_256_INIT_STATES_IV (6)
2183 STORE_256_INIT_STATES_IV (7)
2184 STORE_256_INIT_STATES (8, _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, 0))
2185 // printf("\n== exit Blake2sp_InitState_AVX2_Fast\n");
2186}
2187
2188#endif // Z7_BLAKE2S_USE_AVX2_FAST
2189
2190
2191
2192Z7_NO_INLINE
2193void Blake2sp_InitState(CBlake2sp *p)
2194{
2195 size_t i;
2196 // memset(p->states, 0, sizeof(p->states)); // for debug
2197 p->u.header.cycPos = 0;
2198#ifdef Z7_BLAKE2SP_USE_FUNCTIONS
2199 if (p->u.header.func_Init)
2200 {
2201 p->u.header.func_Init(p->states);
2202 return;
2203 }
2204#endif
2205 for (i = 0; i < Z7_BLAKE2SP_PARALLEL_DEGREE; i++)
2206 Blake2sp_Init_Spec(p->states + i * NSW, (unsigned)i, 0);
2207}
2208
200void Blake2sp_Init(CBlake2sp *p) 2209void Blake2sp_Init(CBlake2sp *p)
201{ 2210{
202 unsigned i; 2211#ifdef Z7_BLAKE2SP_USE_FUNCTIONS
203 2212 p->u.header.func_Compress_Fast =
204 p->bufPos = 0; 2213#ifdef Z7_BLAKE2S_USE_VECTORS
2214 g_Z7_BLAKE2SP_FUNC_COMPRESS_Fast;
2215#else
2216 NULL;
2217#endif
2218
2219 p->u.header.func_Compress_Single =
2220#ifdef Z7_BLAKE2S_USE_VECTORS
2221 g_Z7_BLAKE2SP_FUNC_COMPRESS_Single;
2222#else
2223 NULL;
2224#endif
2225
2226 p->u.header.func_Init =
2227#ifdef Z7_BLAKE2S_USE_VECTORS
2228 g_Z7_BLAKE2SP_FUNC_INIT_Init;
2229#else
2230 NULL;
2231#endif
205 2232
206 for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++) 2233 p->u.header.func_Final =
207 Blake2sp_Init_Spec(&p->S[i], i, 0); 2234#ifdef Z7_BLAKE2S_USE_VECTORS
2235 g_Z7_BLAKE2SP_FUNC_INIT_Final;
2236#else
2237 NULL;
2238#endif
2239#endif
208 2240
209 p->S[BLAKE2SP_PARALLEL_DEGREE - 1].lastNode_f1 = BLAKE2S_FINAL_FLAG; 2241 Blake2sp_InitState(p);
210} 2242}
211 2243
212 2244
213void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size) 2245void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size)
214{ 2246{
215 unsigned pos = p->bufPos; 2247 size_t pos;
216 while (size != 0) 2248 // printf("\nsize = 0x%6x, cycPos = %5u data = %p\n", (unsigned)size, (unsigned)p->u.header.cycPos, data);
2249 if (size == 0)
2250 return;
2251 pos = p->u.header.cycPos;
2252 // pos < SUPER_BLOCK_SIZE * 2 : is expected
2253 // pos == SUPER_BLOCK_SIZE * 2 : is not expected, but is supported also
2254 {
2255 const size_t pos2 = pos & SUPER_BLOCK_MASK;
2256 if (pos2)
2257 {
2258 const size_t rem = SUPER_BLOCK_SIZE - pos2;
2259 if (rem > size)
2260 {
2261 p->u.header.cycPos = (unsigned)(pos + size);
2262 // cycPos < SUPER_BLOCK_SIZE * 2
2263 memcpy((Byte *)(void *)p->buf32 + pos, data, size);
2264 /* to simpilify the code here we don't try to process first superblock,
2265 if (cycPos > SUPER_BLOCK_SIZE * 2 - Z7_BLAKE2S_BLOCK_SIZE) */
2266 return;
2267 }
2268 // (rem <= size)
2269 memcpy((Byte *)(void *)p->buf32 + pos, data, rem);
2270 pos += rem;
2271 data += rem;
2272 size -= rem;
2273 }
2274 }
2275
2276 // pos <= SUPER_BLOCK_SIZE * 2
2277 // pos % SUPER_BLOCK_SIZE == 0
2278 if (pos)
2279 {
2280 /* pos == SUPER_BLOCK_SIZE ||
2281 pos == SUPER_BLOCK_SIZE * 2 */
2282 size_t end = pos;
2283 if (size > SUPER_BLOCK_SIZE - Z7_BLAKE2S_BLOCK_SIZE
2284 || (end -= SUPER_BLOCK_SIZE))
2285 {
2286 Z7_BLAKE2SP_Compress_Fast(p)(p->states,
2287 (const Byte *)(const void *)p->buf32,
2288 (const Byte *)(const void *)p->buf32 + end);
2289 if (pos -= end)
2290 memcpy(p->buf32, (const Byte *)(const void *)p->buf32
2291 + SUPER_BLOCK_SIZE, SUPER_BLOCK_SIZE);
2292 }
2293 }
2294
2295 // pos == 0 || (pos == SUPER_BLOCK_SIZE && size <= SUPER_BLOCK_SIZE - Z7_BLAKE2S_BLOCK_SIZE)
2296 if (size > SUPER_BLOCK_SIZE * 2 - Z7_BLAKE2S_BLOCK_SIZE)
2297 {
2298 // pos == 0
2299 const Byte *end;
2300 const size_t size2 = (size - (SUPER_BLOCK_SIZE - Z7_BLAKE2S_BLOCK_SIZE + 1))
2301 & ~(size_t)SUPER_BLOCK_MASK;
2302 size -= size2;
2303 // size < SUPER_BLOCK_SIZE * 2
2304 end = data + size2;
2305 Z7_BLAKE2SP_Compress_Fast(p)(p->states, data, end);
2306 data = end;
2307 }
2308
2309 if (size != 0)
217 { 2310 {
218 unsigned index = pos / BLAKE2S_BLOCK_SIZE; 2311 memcpy((Byte *)(void *)p->buf32 + pos, data, size);
219 unsigned rem = BLAKE2S_BLOCK_SIZE - (pos & (BLAKE2S_BLOCK_SIZE - 1)); 2312 pos += size;
220 if (rem > size)
221 rem = (unsigned)size;
222 Blake2s_Update(&p->S[index], data, rem);
223 size -= rem;
224 data += rem;
225 pos += rem;
226 pos &= (BLAKE2S_BLOCK_SIZE * BLAKE2SP_PARALLEL_DEGREE - 1);
227 } 2313 }
228 p->bufPos = pos; 2314 p->u.header.cycPos = (unsigned)pos;
2315 // cycPos < SUPER_BLOCK_SIZE * 2
229} 2316}
230 2317
231 2318
232void Blake2sp_Final(CBlake2sp *p, Byte *digest) 2319void Blake2sp_Final(CBlake2sp *p, Byte *digest)
233{ 2320{
234 CBlake2s R; 2321 // UInt32 * const R_states = p->states;
235 unsigned i; 2322 // printf("\nBlake2sp_Final \n");
2323#ifdef Z7_BLAKE2SP_USE_FUNCTIONS
2324 if (p->u.header.func_Final)
2325 p->u.header.func_Final(p->states);
2326#endif
2327 // printf("\n=====\nBlake2sp_Final \n");
2328 // PrintStates(p->states, 32);
2329
2330 // (p->u.header.cycPos == SUPER_BLOCK_SIZE) can be processed in any branch:
2331 if (p->u.header.cycPos <= SUPER_BLOCK_SIZE)
2332 {
2333 unsigned pos;
2334 memset((Byte *)(void *)p->buf32 + p->u.header.cycPos,
2335 0, SUPER_BLOCK_SIZE - p->u.header.cycPos);
2336 STATE_F(&p->states[(Z7_BLAKE2SP_PARALLEL_DEGREE - 1) * NSW])[1] = BLAKE2S_FINAL_FLAG;
2337 for (pos = 0; pos < SUPER_BLOCK_SIZE; pos += Z7_BLAKE2S_BLOCK_SIZE)
2338 {
2339 UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(p->states, pos);
2340 Blake2s_Set_LastBlock(s)
2341 if (pos + Z7_BLAKE2S_BLOCK_SIZE > p->u.header.cycPos)
2342 {
2343 UInt32 delta = Z7_BLAKE2S_BLOCK_SIZE;
2344 if (pos < p->u.header.cycPos)
2345 delta -= p->u.header.cycPos & (Z7_BLAKE2S_BLOCK_SIZE - 1);
2346 // 0 < delta <= Z7_BLAKE2S_BLOCK_SIZE
2347 {
2348 const UInt32 v = STATE_T(s)[0];
2349 STATE_T(s)[1] -= v < delta; // (v < delta) is same condition here as (v == 0)
2350 STATE_T(s)[0] = v - delta;
2351 }
2352 }
2353 }
2354 // PrintStates(p->states, 16);
2355 Z7_BLAKE2SP_Compress_Single(p)(p->states,
2356 (Byte *)(void *)p->buf32,
2357 (Byte *)(void *)p->buf32 + SUPER_BLOCK_SIZE);
2358 // PrintStates(p->states, 16);
2359 }
2360 else
2361 {
2362 // (p->u.header.cycPos > SUPER_BLOCK_SIZE)
2363 unsigned pos;
2364 for (pos = 0; pos < SUPER_BLOCK_SIZE; pos += Z7_BLAKE2S_BLOCK_SIZE)
2365 {
2366 UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(p->states, pos);
2367 if (pos + SUPER_BLOCK_SIZE >= p->u.header.cycPos)
2368 Blake2s_Set_LastBlock(s)
2369 }
2370 if (p->u.header.cycPos <= SUPER_BLOCK_SIZE * 2 - Z7_BLAKE2S_BLOCK_SIZE)
2371 STATE_F(&p->states[(Z7_BLAKE2SP_PARALLEL_DEGREE - 1) * NSW])[1] = BLAKE2S_FINAL_FLAG;
2372
2373 Z7_BLAKE2SP_Compress_Single(p)(p->states,
2374 (Byte *)(void *)p->buf32,
2375 (Byte *)(void *)p->buf32 + SUPER_BLOCK_SIZE);
236 2376
237 Blake2sp_Init_Spec(&R, 0, 1); 2377 // if (p->u.header.cycPos > SUPER_BLOCK_SIZE * 2 - Z7_BLAKE2S_BLOCK_SIZE;
238 R.lastNode_f1 = BLAKE2S_FINAL_FLAG; 2378 STATE_F(&p->states[(Z7_BLAKE2SP_PARALLEL_DEGREE - 1) * NSW])[1] = BLAKE2S_FINAL_FLAG;
2379
2380 // if (p->u.header.cycPos != SUPER_BLOCK_SIZE)
2381 {
2382 pos = SUPER_BLOCK_SIZE;
2383 for (;;)
2384 {
2385 UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(p->states, pos & SUPER_BLOCK_MASK);
2386 Blake2s_Set_LastBlock(s)
2387 pos += Z7_BLAKE2S_BLOCK_SIZE;
2388 if (pos >= p->u.header.cycPos)
2389 {
2390 if (pos != p->u.header.cycPos)
2391 {
2392 const UInt32 delta = pos - p->u.header.cycPos;
2393 const UInt32 v = STATE_T(s)[0];
2394 STATE_T(s)[1] -= v < delta;
2395 STATE_T(s)[0] = v - delta;
2396 memset((Byte *)(void *)p->buf32 + p->u.header.cycPos, 0, delta);
2397 }
2398 break;
2399 }
2400 }
2401 Z7_BLAKE2SP_Compress_Single(p)(p->states,
2402 (Byte *)(void *)p->buf32 + SUPER_BLOCK_SIZE,
2403 (Byte *)(void *)p->buf32 + pos);
2404 }
2405 }
239 2406
240 for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++)
241 { 2407 {
242 Byte hash[BLAKE2S_DIGEST_SIZE]; 2408 size_t pos;
243 Blake2s_Final(&p->S[i], hash); 2409 for (pos = 0; pos < SUPER_BLOCK_SIZE / 2; pos += Z7_BLAKE2S_BLOCK_SIZE / 2)
244 Blake2s_Update(&R, hash, BLAKE2S_DIGEST_SIZE); 2410 {
2411 const UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(p->states, (pos * 2));
2412 Byte *dest = (Byte *)(void *)p->buf32 + pos;
2413 GET_DIGEST(s, dest)
2414 }
245 } 2415 }
2416 Blake2sp_Init_Spec(p->states, 0, 1);
2417 {
2418 size_t pos;
2419 for (pos = 0; pos < (Z7_BLAKE2SP_PARALLEL_DEGREE * Z7_BLAKE2S_DIGEST_SIZE)
2420 - Z7_BLAKE2S_BLOCK_SIZE; pos += Z7_BLAKE2S_BLOCK_SIZE)
2421 {
2422 Z7_BLAKE2SP_Compress_Single(p)(p->states,
2423 (const Byte *)(const void *)p->buf32 + pos,
2424 (const Byte *)(const void *)p->buf32 + pos + Z7_BLAKE2S_BLOCK_SIZE);
2425 }
2426 }
2427 // Blake2s_Final(p->states, 0, digest, p, (Byte *)(void *)p->buf32 + i);
2428 Blake2s_Set_LastBlock(p->states)
2429 STATE_F(p->states)[1] = BLAKE2S_FINAL_FLAG;
2430 {
2431 Z7_BLAKE2SP_Compress_Single(p)(p->states,
2432 (const Byte *)(const void *)p->buf32 + Z7_BLAKE2SP_PARALLEL_DEGREE / 2 * Z7_BLAKE2S_BLOCK_SIZE - Z7_BLAKE2S_BLOCK_SIZE,
2433 (const Byte *)(const void *)p->buf32 + Z7_BLAKE2SP_PARALLEL_DEGREE / 2 * Z7_BLAKE2S_BLOCK_SIZE);
2434 }
2435 GET_DIGEST(p->states, digest)
2436 // printf("\n Blake2sp_Final 555 numDataInBufs = %5u\n", (unsigned)p->u.header.numDataInBufs);
2437}
2438
246 2439
247 Blake2s_Final(&R, digest); 2440BoolInt Blake2sp_SetFunction(CBlake2sp *p, unsigned algo)
2441{
2442 // printf("\n========== setfunction = %d ======== \n", algo);
2443#ifdef Z7_BLAKE2SP_USE_FUNCTIONS
2444 Z7_BLAKE2SP_FUNC_COMPRESS func = NULL;
2445 Z7_BLAKE2SP_FUNC_COMPRESS func_Single = NULL;
2446 Z7_BLAKE2SP_FUNC_INIT func_Final = NULL;
2447 Z7_BLAKE2SP_FUNC_INIT func_Init = NULL;
2448#else
2449 UNUSED_VAR(p)
2450#endif
2451
2452#ifdef Z7_BLAKE2S_USE_VECTORS
2453
2454 func = func_Single = Blake2sp_Compress2;
2455
2456 if (algo != Z7_BLAKE2SP_ALGO_SCALAR)
2457 {
2458 // printf("\n========== setfunction NON-SCALER ======== \n");
2459 if (algo == Z7_BLAKE2SP_ALGO_DEFAULT)
2460 {
2461 func = g_Z7_BLAKE2SP_FUNC_COMPRESS_Fast;
2462 func_Single = g_Z7_BLAKE2SP_FUNC_COMPRESS_Single;
2463 func_Init = g_Z7_BLAKE2SP_FUNC_INIT_Init;
2464 func_Final = g_Z7_BLAKE2SP_FUNC_INIT_Final;
2465 }
2466 else
2467 {
2468 if ((g_z7_Blake2sp_SupportedFlags & (1u << algo)) == 0)
2469 return False;
2470
2471#ifdef Z7_BLAKE2S_USE_AVX2
2472
2473 func_Single =
2474#if defined(Z7_BLAKE2S_USE_AVX2_WAY2)
2475 Blake2sp_Compress2_AVX2_Way2;
2476#else
2477 Z7_BLAKE2S_Compress2_V128;
2478#endif
2479
2480#ifdef Z7_BLAKE2S_USE_AVX2_FAST
2481 if (algo == Z7_BLAKE2SP_ALGO_V256_FAST)
2482 {
2483 func = Blake2sp_Compress2_AVX2_Fast;
2484 func_Final = Blake2sp_Final_AVX2_Fast;
2485 func_Init = Blake2sp_InitState_AVX2_Fast;
2486 }
2487 else
2488#endif
2489#ifdef Z7_BLAKE2S_USE_AVX2_WAY2
2490 if (algo == Z7_BLAKE2SP_ALGO_V256_WAY2)
2491 func = Blake2sp_Compress2_AVX2_Way2;
2492 else
2493#endif
2494#ifdef Z7_BLAKE2S_USE_AVX2_WAY4
2495 if (algo == Z7_BLAKE2SP_ALGO_V256_WAY4)
2496 {
2497 func_Single = func = Blake2sp_Compress2_AVX2_Way4;
2498 }
2499 else
2500#endif
2501#endif // avx2
2502 {
2503 if (algo == Z7_BLAKE2SP_ALGO_V128_FAST)
2504 {
2505 func = Blake2sp_Compress2_V128_Fast;
2506 func_Final = Blake2sp_Final_V128_Fast;
2507 func_Init = Blake2sp_InitState_V128_Fast;
2508 func_Single = Z7_BLAKE2S_Compress2_V128;
2509 }
2510 else
2511#ifdef Z7_BLAKE2S_USE_V128_WAY2
2512 if (algo == Z7_BLAKE2SP_ALGO_V128_WAY2)
2513 func = func_Single = Blake2sp_Compress2_V128_Way2;
2514 else
2515#endif
2516 {
2517 if (algo != Z7_BLAKE2SP_ALGO_V128_WAY1)
2518 return False;
2519 func = func_Single = Blake2sp_Compress2_V128_Way1;
2520 }
2521 }
2522 }
2523 }
2524#else // !VECTORS
2525 if (algo > 1) // Z7_BLAKE2SP_ALGO_SCALAR
2526 return False;
2527#endif // !VECTORS
2528
2529#ifdef Z7_BLAKE2SP_USE_FUNCTIONS
2530 p->u.header.func_Compress_Fast = func;
2531 p->u.header.func_Compress_Single = func_Single;
2532 p->u.header.func_Final = func_Final;
2533 p->u.header.func_Init = func_Init;
2534#endif
2535 // printf("\n p->u.header.func_Compress = %p", p->u.header.func_Compress);
2536 return True;
2537}
2538
2539
2540void z7_Black2sp_Prepare(void)
2541{
2542#ifdef Z7_BLAKE2S_USE_VECTORS
2543 unsigned flags = 0; // (1u << Z7_BLAKE2SP_ALGO_V128_SCALAR);
2544
2545 Z7_BLAKE2SP_FUNC_COMPRESS func_Fast = Blake2sp_Compress2;
2546 Z7_BLAKE2SP_FUNC_COMPRESS func_Single = Blake2sp_Compress2;
2547 Z7_BLAKE2SP_FUNC_INIT func_Init = NULL;
2548 Z7_BLAKE2SP_FUNC_INIT func_Final = NULL;
2549
2550#if defined(MY_CPU_X86_OR_AMD64)
2551 #if defined(Z7_BLAKE2S_USE_AVX512_ALWAYS)
2552 if (CPU_IsSupported_AVX512F_AVX512VL())
2553 #endif
2554 #if defined(Z7_BLAKE2S_USE_SSE41)
2555 if (CPU_IsSupported_SSE41())
2556 #elif defined(Z7_BLAKE2S_USE_SSSE3)
2557 if (CPU_IsSupported_SSSE3())
2558 #elif !defined(MY_CPU_AMD64)
2559 if (CPU_IsSupported_SSE2())
2560 #endif
2561#endif
2562 {
2563 #if defined(Z7_BLAKE2S_USE_SSE41)
2564 // printf("\n========== Blake2s SSE41 128-bit\n");
2565 #elif defined(Z7_BLAKE2S_USE_SSSE3)
2566 // printf("\n========== Blake2s SSSE3 128-bit\n");
2567 #else
2568 // printf("\n========== Blake2s SSE2 128-bit\n");
2569 #endif
2570 // func_Fast = f_vector = Blake2sp_Compress2_V128_Way2;
2571 // printf("\n========== Blake2sp_Compress2_V128_Way2\n");
2572 func_Fast =
2573 func_Single = Z7_BLAKE2S_Compress2_V128;
2574 flags |= (1u << Z7_BLAKE2SP_ALGO_V128_WAY1);
2575#ifdef Z7_BLAKE2S_USE_V128_WAY2
2576 flags |= (1u << Z7_BLAKE2SP_ALGO_V128_WAY2);
2577#endif
2578#ifdef Z7_BLAKE2S_USE_V128_FAST
2579 flags |= (1u << Z7_BLAKE2SP_ALGO_V128_FAST);
2580 func_Fast = Blake2sp_Compress2_V128_Fast;
2581 func_Init = Blake2sp_InitState_V128_Fast;
2582 func_Final = Blake2sp_Final_V128_Fast;
2583#endif
2584
2585#ifdef Z7_BLAKE2S_USE_AVX2
2586#if defined(MY_CPU_X86_OR_AMD64)
2587 if (
2588 #if 0 && defined(Z7_BLAKE2S_USE_AVX512_ALWAYS)
2589 CPU_IsSupported_AVX512F_AVX512VL() &&
2590 #endif
2591 CPU_IsSupported_AVX2()
2592 )
2593#endif
2594 {
2595 // #pragma message ("=== Blake2s AVX2")
2596 // printf("\n========== Blake2s AVX2\n");
2597
2598#ifdef Z7_BLAKE2S_USE_AVX2_WAY2
2599 func_Single = Blake2sp_Compress2_AVX2_Way2;
2600 flags |= (1u << Z7_BLAKE2SP_ALGO_V256_WAY2);
2601#endif
2602#ifdef Z7_BLAKE2S_USE_AVX2_WAY4
2603 flags |= (1u << Z7_BLAKE2SP_ALGO_V256_WAY4);
2604#endif
2605
2606#ifdef Z7_BLAKE2S_USE_AVX2_FAST
2607 flags |= (1u << Z7_BLAKE2SP_ALGO_V256_FAST);
2608 func_Fast = Blake2sp_Compress2_AVX2_Fast;
2609 func_Init = Blake2sp_InitState_AVX2_Fast;
2610 func_Final = Blake2sp_Final_AVX2_Fast;
2611#elif defined(Z7_BLAKE2S_USE_AVX2_WAY4)
2612 func_Fast = Blake2sp_Compress2_AVX2_Way4;
2613#elif defined(Z7_BLAKE2S_USE_AVX2_WAY2)
2614 func_Fast = Blake2sp_Compress2_AVX2_Way2;
2615#endif
2616 } // avx2
2617#endif // avx2
2618 } // sse*
2619 g_Z7_BLAKE2SP_FUNC_COMPRESS_Fast = func_Fast;
2620 g_Z7_BLAKE2SP_FUNC_COMPRESS_Single = func_Single;
2621 g_Z7_BLAKE2SP_FUNC_INIT_Init = func_Init;
2622 g_Z7_BLAKE2SP_FUNC_INIT_Final = func_Final;
2623 g_z7_Blake2sp_SupportedFlags = flags;
2624 // printf("\nflags=%x\n", flags);
2625#endif // vectors
248} 2626}
249 2627
250#undef rotr32 2628/*
2629#ifdef Z7_BLAKE2S_USE_VECTORS
2630void align_test2(CBlake2sp *sp);
2631void align_test2(CBlake2sp *sp)
2632{
2633 __m128i a = LOAD_128(sp->states);
2634 D_XOR_128(a, LOAD_128(sp->states + 4));
2635 STORE_128(sp->states, a);
2636}
2637void align_test2(void);
2638void align_test2(void)
2639{
2640 CBlake2sp sp;
2641 Blake2sp_Init(&sp);
2642 Blake2sp_Update(&sp, NULL, 0);
2643}
2644#endif
2645*/
diff --git a/C/Bra.c b/C/Bra.c
index 22e0e47..e61edf8 100644
--- a/C/Bra.c
+++ b/C/Bra.c
@@ -1,11 +1,11 @@
1/* Bra.c -- Branch converters for RISC code 1/* Bra.c -- Branch converters for RISC code
22023-04-02 : Igor Pavlov : Public domain */ 22024-01-20 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
6#include "Bra.h" 6#include "Bra.h"
7#include "CpuArch.h"
8#include "RotateDefs.h" 7#include "RotateDefs.h"
8#include "CpuArch.h"
9 9
10#if defined(MY_CPU_SIZEOF_POINTER) \ 10#if defined(MY_CPU_SIZEOF_POINTER) \
11 && ( MY_CPU_SIZEOF_POINTER == 4 \ 11 && ( MY_CPU_SIZEOF_POINTER == 4 \
@@ -26,7 +26,7 @@
26#define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c; 26#define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c;
27// #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c; 27// #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c;
28 28
29#define Z7_BRANCH_CONV(name) z7_BranchConv_ ## name 29#define Z7_BRANCH_CONV(name) z7_ ## name
30 30
31#define Z7_BRANCH_FUNC_MAIN(name) \ 31#define Z7_BRANCH_FUNC_MAIN(name) \
32static \ 32static \
@@ -42,11 +42,11 @@ Byte *m(name)(Byte *data, SizeT size, UInt32 pc) \
42 42
43#ifdef Z7_EXTRACT_ONLY 43#ifdef Z7_EXTRACT_ONLY
44#define Z7_BRANCH_FUNCS_IMP(name) \ 44#define Z7_BRANCH_FUNCS_IMP(name) \
45 Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC, 0) 45 Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0)
46#else 46#else
47#define Z7_BRANCH_FUNCS_IMP(name) \ 47#define Z7_BRANCH_FUNCS_IMP(name) \
48 Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC, 0) \ 48 Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0) \
49 Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC, 1) 49 Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC_2, 1)
50#endif 50#endif
51 51
52#if defined(__clang__) 52#if defined(__clang__)
@@ -72,7 +72,7 @@ Byte *m(name)(Byte *data, SizeT size, UInt32 pc) \
72#endif 72#endif
73 73
74 74
75Z7_BRANCH_FUNC_MAIN(ARM64) 75Z7_BRANCH_FUNC_MAIN(BranchConv_ARM64)
76{ 76{
77 // Byte *p = data; 77 // Byte *p = data;
78 const Byte *lim; 78 const Byte *lim;
@@ -121,10 +121,10 @@ Z7_BRANCH_FUNC_MAIN(ARM64)
121 } 121 }
122 } 122 }
123} 123}
124Z7_BRANCH_FUNCS_IMP(ARM64) 124Z7_BRANCH_FUNCS_IMP(BranchConv_ARM64)
125 125
126 126
127Z7_BRANCH_FUNC_MAIN(ARM) 127Z7_BRANCH_FUNC_MAIN(BranchConv_ARM)
128{ 128{
129 // Byte *p = data; 129 // Byte *p = data;
130 const Byte *lim; 130 const Byte *lim;
@@ -152,10 +152,10 @@ Z7_BRANCH_FUNC_MAIN(ARM)
152 } 152 }
153 } 153 }
154} 154}
155Z7_BRANCH_FUNCS_IMP(ARM) 155Z7_BRANCH_FUNCS_IMP(BranchConv_ARM)
156 156
157 157
158Z7_BRANCH_FUNC_MAIN(PPC) 158Z7_BRANCH_FUNC_MAIN(BranchConv_PPC)
159{ 159{
160 // Byte *p = data; 160 // Byte *p = data;
161 const Byte *lim; 161 const Byte *lim;
@@ -192,14 +192,14 @@ Z7_BRANCH_FUNC_MAIN(PPC)
192 } 192 }
193 } 193 }
194} 194}
195Z7_BRANCH_FUNCS_IMP(PPC) 195Z7_BRANCH_FUNCS_IMP(BranchConv_PPC)
196 196
197 197
198#ifdef Z7_CPU_FAST_ROTATE_SUPPORTED 198#ifdef Z7_CPU_FAST_ROTATE_SUPPORTED
199#define BR_SPARC_USE_ROTATE 199#define BR_SPARC_USE_ROTATE
200#endif 200#endif
201 201
202Z7_BRANCH_FUNC_MAIN(SPARC) 202Z7_BRANCH_FUNC_MAIN(BranchConv_SPARC)
203{ 203{
204 // Byte *p = data; 204 // Byte *p = data;
205 const Byte *lim; 205 const Byte *lim;
@@ -254,10 +254,10 @@ Z7_BRANCH_FUNC_MAIN(SPARC)
254 } 254 }
255 } 255 }
256} 256}
257Z7_BRANCH_FUNCS_IMP(SPARC) 257Z7_BRANCH_FUNCS_IMP(BranchConv_SPARC)
258 258
259 259
260Z7_BRANCH_FUNC_MAIN(ARMT) 260Z7_BRANCH_FUNC_MAIN(BranchConv_ARMT)
261{ 261{
262 // Byte *p = data; 262 // Byte *p = data;
263 Byte *lim; 263 Byte *lim;
@@ -335,12 +335,12 @@ Z7_BRANCH_FUNC_MAIN(ARMT)
335 // return (Byte *)(lim + (((lim[1] ^ ~0xfu) & ~7u) == 0 ? 0 : 2)); 335 // return (Byte *)(lim + (((lim[1] ^ ~0xfu) & ~7u) == 0 ? 0 : 2));
336 // return (Byte *)(lim + 2 - (((((unsigned)lim[1] ^ 8) + 8) >> 7) & 2)); 336 // return (Byte *)(lim + 2 - (((((unsigned)lim[1] ^ 8) + 8) >> 7) & 2));
337} 337}
338Z7_BRANCH_FUNCS_IMP(ARMT) 338Z7_BRANCH_FUNCS_IMP(BranchConv_ARMT)
339 339
340 340
341// #define BR_IA64_NO_INLINE 341// #define BR_IA64_NO_INLINE
342 342
343Z7_BRANCH_FUNC_MAIN(IA64) 343Z7_BRANCH_FUNC_MAIN(BranchConv_IA64)
344{ 344{
345 // Byte *p = data; 345 // Byte *p = data;
346 const Byte *lim; 346 const Byte *lim;
@@ -417,4 +417,293 @@ Z7_BRANCH_FUNC_MAIN(IA64)
417 } 417 }
418 } 418 }
419} 419}
420Z7_BRANCH_FUNCS_IMP(IA64) 420Z7_BRANCH_FUNCS_IMP(BranchConv_IA64)
421
422
423#define BR_CONVERT_VAL_ENC(v) v += BR_PC_GET;
424#define BR_CONVERT_VAL_DEC(v) v -= BR_PC_GET;
425
426#if 1 && defined(MY_CPU_LE_UNALIGN)
427 #define RISCV_USE_UNALIGNED_LOAD
428#endif
429
430#ifdef RISCV_USE_UNALIGNED_LOAD
431 #define RISCV_GET_UI32(p) GetUi32(p)
432 #define RISCV_SET_UI32(p, v) { SetUi32(p, v) }
433#else
434 #define RISCV_GET_UI32(p) \
435 ((UInt32)GetUi16a(p) + \
436 ((UInt32)GetUi16a((p) + 2) << 16))
437 #define RISCV_SET_UI32(p, v) { \
438 SetUi16a(p, (UInt16)(v)) \
439 SetUi16a((p) + 2, (UInt16)(v >> 16)) }
440#endif
441
442#if 1 && defined(MY_CPU_LE)
443 #define RISCV_USE_16BIT_LOAD
444#endif
445
446#ifdef RISCV_USE_16BIT_LOAD
447 #define RISCV_LOAD_VAL(p) GetUi16a(p)
448#else
449 #define RISCV_LOAD_VAL(p) (*(p))
450#endif
451
452#define RISCV_INSTR_SIZE 2
453#define RISCV_STEP_1 (4 + RISCV_INSTR_SIZE)
454#define RISCV_STEP_2 4
455#define RISCV_REG_VAL (2 << 7)
456#define RISCV_CMD_VAL 3
457#if 1
458 // for code size optimization:
459 #define RISCV_DELTA_7F 0x7f
460#else
461 #define RISCV_DELTA_7F 0
462#endif
463
464#define RISCV_CHECK_1(v, b) \
465 (((((b) - RISCV_CMD_VAL) ^ ((v) << 8)) & (0xf8000 + RISCV_CMD_VAL)) == 0)
466
467#if 1
468 #define RISCV_CHECK_2(v, r) \
469 ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL | 8)) \
470 << 18) \
471 < ((r) & 0x1d))
472#else
473 // this branch gives larger code, because
474 // compilers generate larger code for big constants.
475 #define RISCV_CHECK_2(v, r) \
476 ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \
477 & ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \
478 < ((r) & 0x1d))
479#endif
480
481
482#define RISCV_SCAN_LOOP \
483 Byte *lim; \
484 size &= ~(SizeT)(RISCV_INSTR_SIZE - 1); \
485 if (size <= 6) return p; \
486 size -= 6; \
487 lim = p + size; \
488 BR_PC_INIT \
489 for (;;) \
490 { \
491 UInt32 a, v; \
492 /* Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE */ \
493 for (;;) \
494 { \
495 if Z7_UNLIKELY(p >= lim) { return p; } \
496 a = (RISCV_LOAD_VAL(p) ^ 0x10u) + 1; \
497 if ((a & 0x77) == 0) break; \
498 a = (RISCV_LOAD_VAL(p + RISCV_INSTR_SIZE) ^ 0x10u) + 1; \
499 p += RISCV_INSTR_SIZE * 2; \
500 if ((a & 0x77) == 0) \
501 { \
502 p -= RISCV_INSTR_SIZE; \
503 if Z7_UNLIKELY(p >= lim) { return p; } \
504 break; \
505 } \
506 }
507// (xx6f ^ 10) + 1 = xx7f + 1 = xx80 : JAL
508// (xxef ^ 10) + 1 = xxff + 1 = xx00 + 100 : JAL
509// (xx17 ^ 10) + 1 = xx07 + 1 = xx08 : AUIPC
510// (xx97 ^ 10) + 1 = xx87 + 1 = xx88 : AUIPC
511
512Byte * Z7_BRANCH_CONV_ENC(RISCV)(Byte *p, SizeT size, UInt32 pc)
513{
514 RISCV_SCAN_LOOP
515 v = a;
516 a = RISCV_GET_UI32(p);
517#ifndef RISCV_USE_16BIT_LOAD
518 v += (UInt32)p[1] << 8;
519#endif
520
521 if ((v & 8) == 0) // JAL
522 {
523 if ((v - (0x100 /* - RISCV_DELTA_7F */)) & 0xd80)
524 {
525 p += RISCV_INSTR_SIZE;
526 continue;
527 }
528 {
529 v = ((a & 1u << 31) >> 11)
530 | ((a & 0x3ff << 21) >> 20)
531 | ((a & 1 << 20) >> 9)
532 | (a & 0xff << 12);
533 BR_CONVERT_VAL_ENC(v)
534 // ((v & 1) == 0)
535 // v: bits [1 : 20] contain offset bits
536#if 0 && defined(RISCV_USE_UNALIGNED_LOAD)
537 a &= 0xfff;
538 a |= ((UInt32)(v << 23))
539 | ((UInt32)(v << 7) & ((UInt32)0xff << 16))
540 | ((UInt32)(v >> 5) & ((UInt32)0xf0 << 8));
541 RISCV_SET_UI32(p, a)
542#else // aligned
543#if 0
544 SetUi16a(p, (UInt16)(((v >> 5) & 0xf000) | (a & 0xfff)))
545#else
546 p[1] = (Byte)(((v >> 13) & 0xf0) | ((a >> 8) & 0xf));
547#endif
548
549#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
550 v <<= 15;
551 v = Z7_BSWAP32(v);
552 SetUi16a(p + 2, (UInt16)v)
553#else
554 p[2] = (Byte)(v >> 9);
555 p[3] = (Byte)(v >> 1);
556#endif
557#endif // aligned
558 }
559 p += 4;
560 continue;
561 } // JAL
562
563 {
564 // AUIPC
565 if (v & 0xe80) // (not x0) and (not x2)
566 {
567 const UInt32 b = RISCV_GET_UI32(p + 4);
568 if (RISCV_CHECK_1(v, b))
569 {
570 {
571 const UInt32 temp = (b << 12) | (0x17 + RISCV_REG_VAL);
572 RISCV_SET_UI32(p, temp)
573 }
574 a &= 0xfffff000;
575 {
576#if 1
577 const int t = -1 >> 1;
578 if (t != -1)
579 a += (b >> 20) - ((b >> 19) & 0x1000); // arithmetic right shift emulation
580 else
581#endif
582 a += (UInt32)((Int32)b >> 20); // arithmetic right shift (sign-extension).
583 }
584 BR_CONVERT_VAL_ENC(a)
585#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
586 a = Z7_BSWAP32(a);
587 RISCV_SET_UI32(p + 4, a)
588#else
589 SetBe32(p + 4, a)
590#endif
591 p += 8;
592 }
593 else
594 p += RISCV_STEP_1;
595 }
596 else
597 {
598 UInt32 r = a >> 27;
599 if (RISCV_CHECK_2(v, r))
600 {
601 v = RISCV_GET_UI32(p + 4);
602 r = (r << 7) + 0x17 + (v & 0xfffff000);
603 a = (a >> 12) | (v << 20);
604 RISCV_SET_UI32(p, r)
605 RISCV_SET_UI32(p + 4, a)
606 p += 8;
607 }
608 else
609 p += RISCV_STEP_2;
610 }
611 }
612 } // for
613}
614
615
616Byte * Z7_BRANCH_CONV_DEC(RISCV)(Byte *p, SizeT size, UInt32 pc)
617{
618 RISCV_SCAN_LOOP
619#ifdef RISCV_USE_16BIT_LOAD
620 if ((a & 8) == 0)
621 {
622#else
623 v = a;
624 a += (UInt32)p[1] << 8;
625 if ((v & 8) == 0)
626 {
627#endif
628 // JAL
629 a -= 0x100 - RISCV_DELTA_7F;
630 if (a & 0xd80)
631 {
632 p += RISCV_INSTR_SIZE;
633 continue;
634 }
635 {
636 const UInt32 a_old = (a + (0xef - RISCV_DELTA_7F)) & 0xfff;
637#if 0 // unaligned
638 a = GetUi32(p);
639 v = (UInt32)(a >> 23) & ((UInt32)0xff << 1)
640 | (UInt32)(a >> 7) & ((UInt32)0xff << 9)
641#elif 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
642 v = GetUi16a(p + 2);
643 v = Z7_BSWAP32(v) >> 15
644#else
645 v = (UInt32)p[3] << 1
646 | (UInt32)p[2] << 9
647#endif
648 | (UInt32)((a & 0xf000) << 5);
649 BR_CONVERT_VAL_DEC(v)
650 a = a_old
651 | (v << 11 & 1u << 31)
652 | (v << 20 & 0x3ff << 21)
653 | (v << 9 & 1 << 20)
654 | (v & 0xff << 12);
655 RISCV_SET_UI32(p, a)
656 }
657 p += 4;
658 continue;
659 } // JAL
660
661 {
662 // AUIPC
663 v = a;
664#if 1 && defined(RISCV_USE_UNALIGNED_LOAD)
665 a = GetUi32(p);
666#else
667 a |= (UInt32)GetUi16a(p + 2) << 16;
668#endif
669 if ((v & 0xe80) == 0) // x0/x2
670 {
671 const UInt32 r = a >> 27;
672 if (RISCV_CHECK_2(v, r))
673 {
674 UInt32 b;
675#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
676 b = RISCV_GET_UI32(p + 4);
677 b = Z7_BSWAP32(b);
678#else
679 b = GetBe32(p + 4);
680#endif
681 v = a >> 12;
682 BR_CONVERT_VAL_DEC(b)
683 a = (r << 7) + 0x17;
684 a += (b + 0x800) & 0xfffff000;
685 v |= b << 20;
686 RISCV_SET_UI32(p, a)
687 RISCV_SET_UI32(p + 4, v)
688 p += 8;
689 }
690 else
691 p += RISCV_STEP_2;
692 }
693 else
694 {
695 const UInt32 b = RISCV_GET_UI32(p + 4);
696 if (!RISCV_CHECK_1(v, b))
697 p += RISCV_STEP_1;
698 else
699 {
700 v = (a & 0xfffff000) | (b >> 20);
701 a = (b << 12) | (0x17 + RISCV_REG_VAL);
702 RISCV_SET_UI32(p, a)
703 RISCV_SET_UI32(p + 4, v)
704 p += 8;
705 }
706 }
707 }
708 } // for
709}
diff --git a/C/Bra.h b/C/Bra.h
index a4ee568..b47112c 100644
--- a/C/Bra.h
+++ b/C/Bra.h
@@ -1,5 +1,5 @@
1/* Bra.h -- Branch converters for executables 1/* Bra.h -- Branch converters for executables
22023-04-02 : Igor Pavlov : Public domain */ 22024-01-20 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_BRA_H 4#ifndef ZIP7_INC_BRA_H
5#define ZIP7_INC_BRA_H 5#define ZIP7_INC_BRA_H
@@ -8,8 +8,12 @@
8 8
9EXTERN_C_BEGIN 9EXTERN_C_BEGIN
10 10
11#define Z7_BRANCH_CONV_DEC(name) z7_BranchConv_ ## name ## _Dec 11/* #define PPC BAD_PPC_11 // for debug */
12#define Z7_BRANCH_CONV_ENC(name) z7_BranchConv_ ## name ## _Enc 12
13#define Z7_BRANCH_CONV_DEC_2(name) z7_ ## name ## _Dec
14#define Z7_BRANCH_CONV_ENC_2(name) z7_ ## name ## _Enc
15#define Z7_BRANCH_CONV_DEC(name) Z7_BRANCH_CONV_DEC_2(BranchConv_ ## name)
16#define Z7_BRANCH_CONV_ENC(name) Z7_BRANCH_CONV_ENC_2(BranchConv_ ## name)
13#define Z7_BRANCH_CONV_ST_DEC(name) z7_BranchConvSt_ ## name ## _Dec 17#define Z7_BRANCH_CONV_ST_DEC(name) z7_BranchConvSt_ ## name ## _Dec
14#define Z7_BRANCH_CONV_ST_ENC(name) z7_BranchConvSt_ ## name ## _Enc 18#define Z7_BRANCH_CONV_ST_ENC(name) z7_BranchConvSt_ ## name ## _Enc
15 19
@@ -20,19 +24,20 @@ typedef Z7_BRANCH_CONV_DECL( (*z7_Func_BranchConv));
20typedef Z7_BRANCH_CONV_ST_DECL((*z7_Func_BranchConvSt)); 24typedef Z7_BRANCH_CONV_ST_DECL((*z7_Func_BranchConvSt));
21 25
22#define Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL 0 26#define Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL 0
23Z7_BRANCH_CONV_ST_DECL(Z7_BRANCH_CONV_ST_DEC(X86)); 27Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_DEC(X86));
24Z7_BRANCH_CONV_ST_DECL(Z7_BRANCH_CONV_ST_ENC(X86)); 28Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_ENC(X86));
25 29
26#define Z7_BRANCH_FUNCS_DECL(name) \ 30#define Z7_BRANCH_FUNCS_DECL(name) \
27Z7_BRANCH_CONV_DECL(Z7_BRANCH_CONV_DEC(name)); \ 31Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_DEC_2(name)); \
28Z7_BRANCH_CONV_DECL(Z7_BRANCH_CONV_ENC(name)); 32Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_ENC_2(name));
29 33
30Z7_BRANCH_FUNCS_DECL(ARM64) 34Z7_BRANCH_FUNCS_DECL (BranchConv_ARM64)
31Z7_BRANCH_FUNCS_DECL(ARM) 35Z7_BRANCH_FUNCS_DECL (BranchConv_ARM)
32Z7_BRANCH_FUNCS_DECL(ARMT) 36Z7_BRANCH_FUNCS_DECL (BranchConv_ARMT)
33Z7_BRANCH_FUNCS_DECL(PPC) 37Z7_BRANCH_FUNCS_DECL (BranchConv_PPC)
34Z7_BRANCH_FUNCS_DECL(SPARC) 38Z7_BRANCH_FUNCS_DECL (BranchConv_SPARC)
35Z7_BRANCH_FUNCS_DECL(IA64) 39Z7_BRANCH_FUNCS_DECL (BranchConv_IA64)
40Z7_BRANCH_FUNCS_DECL (BranchConv_RISCV)
36 41
37/* 42/*
38These functions convert data that contain CPU instructions. 43These functions convert data that contain CPU instructions.
@@ -49,14 +54,14 @@ and one for decoding (_Enc/_Dec postfixes in function name).
49In params: 54In params:
50 data : data buffer 55 data : data buffer
51 size : size of data 56 size : size of data
52 pc : current virtual Program Counter (Instruction Pinter) value 57 pc : current virtual Program Counter (Instruction Pointer) value
53In/Out param: 58In/Out param:
54 state : pointer to state variable (for X86 converter only) 59 state : pointer to state variable (for X86 converter only)
55 60
56Return: 61Return:
57 The pointer to position in (data) buffer after last byte that was processed. 62 The pointer to position in (data) buffer after last byte that was processed.
58 If the caller calls converter again, it must call it starting with that position. 63 If the caller calls converter again, it must call it starting with that position.
59 But the caller is allowed to move data in buffer. so pointer to 64 But the caller is allowed to move data in buffer. So pointer to
60 current processed position also will be changed for next call. 65 current processed position also will be changed for next call.
61 Also the caller must increase internal (pc) value for next call. 66 Also the caller must increase internal (pc) value for next call.
62 67
@@ -65,6 +70,7 @@ Each converter has some characteristics: Endian, Alignment, LookAhead.
65 70
66 X86 little 1 4 71 X86 little 1 4
67 ARMT little 2 2 72 ARMT little 2 2
73 RISCV little 2 6
68 ARM little 4 0 74 ARM little 4 0
69 ARM64 little 4 0 75 ARM64 little 4 0
70 PPC big 4 0 76 PPC big 4 0
diff --git a/C/Compiler.h b/C/Compiler.h
index 185a52d..2a9c2b7 100644
--- a/C/Compiler.h
+++ b/C/Compiler.h
@@ -1,5 +1,5 @@
1/* Compiler.h : Compiler specific defines and pragmas 1/* Compiler.h : Compiler specific defines and pragmas
22023-04-02 : Igor Pavlov : Public domain */ 22024-01-22 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_COMPILER_H 4#ifndef ZIP7_INC_COMPILER_H
5#define ZIP7_INC_COMPILER_H 5#define ZIP7_INC_COMPILER_H
@@ -25,11 +25,79 @@
25#define Z7_MINGW 25#define Z7_MINGW
26#endif 26#endif
27 27
28#if defined(__LCC__) && (defined(__MCST__) || defined(__e2k__))
29#define Z7_MCST_LCC
30#define Z7_MCST_LCC_VERSION (__LCC__ * 100 + __LCC_MINOR__)
31#endif
32
33/*
34#if defined(__AVX2__) \
35 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
36 || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \
37 || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \
38 || defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \
39 || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)
40 #define Z7_COMPILER_AVX2_SUPPORTED
41 #endif
42#endif
43*/
44
28// #pragma GCC diagnostic ignored "-Wunknown-pragmas" 45// #pragma GCC diagnostic ignored "-Wunknown-pragmas"
29 46
30#ifdef __clang__ 47#ifdef __clang__
31// padding size of '' with 4 bytes to alignment boundary 48// padding size of '' with 4 bytes to alignment boundary
32#pragma GCC diagnostic ignored "-Wpadded" 49#pragma GCC diagnostic ignored "-Wpadded"
50
51#if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13) \
52 && defined(__FreeBSD__)
53// freebsd:
54#pragma GCC diagnostic ignored "-Wexcess-padding"
55#endif
56
57#if __clang_major__ >= 16
58#pragma GCC diagnostic ignored "-Wunsafe-buffer-usage"
59#endif
60
61#if __clang_major__ == 13
62#if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)
63// cheri
64#pragma GCC diagnostic ignored "-Wcapability-to-integer-cast"
65#endif
66#endif
67
68#if __clang_major__ == 13
69 // for <arm_neon.h>
70 #pragma GCC diagnostic ignored "-Wreserved-identifier"
71#endif
72
73#endif // __clang__
74
75#if defined(_WIN32) && defined(__clang__) && __clang_major__ >= 16
76// #pragma GCC diagnostic ignored "-Wcast-function-type-strict"
77#define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION \
78 _Pragma("GCC diagnostic ignored \"-Wcast-function-type-strict\"")
79#else
80#define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
81#endif
82
83typedef void (*Z7_void_Function)(void);
84#if defined(__clang__) || defined(__GNUC__)
85#define Z7_CAST_FUNC_C (Z7_void_Function)
86#elif defined(_MSC_VER) && _MSC_VER > 1920
87#define Z7_CAST_FUNC_C (void *)
88// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()'
89#else
90#define Z7_CAST_FUNC_C
91#endif
92/*
93#if (defined(__GNUC__) && (__GNUC__ >= 8)) || defined(__clang__)
94 // #pragma GCC diagnostic ignored "-Wcast-function-type"
95#endif
96*/
97#ifdef __GNUC__
98#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40000) && (Z7_GCC_VERSION < 70000)
99#pragma GCC diagnostic ignored "-Wstrict-aliasing"
100#endif
33#endif 101#endif
34 102
35 103
@@ -101,7 +169,8 @@
101 _Pragma("clang loop unroll(disable)") \ 169 _Pragma("clang loop unroll(disable)") \
102 _Pragma("clang loop vectorize(disable)") 170 _Pragma("clang loop vectorize(disable)")
103 #define Z7_ATTRIB_NO_VECTORIZE 171 #define Z7_ATTRIB_NO_VECTORIZE
104#elif defined(__GNUC__) && (__GNUC__ >= 5) 172#elif defined(__GNUC__) && (__GNUC__ >= 5) \
173 && (!defined(Z7_MCST_LCC_VERSION) || (Z7_MCST_LCC_VERSION >= 12610))
105 #define Z7_ATTRIB_NO_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) 174 #define Z7_ATTRIB_NO_VECTORIZE __attribute__((optimize("no-tree-vectorize")))
106 // __attribute__((optimize("no-unroll-loops"))); 175 // __attribute__((optimize("no-unroll-loops")));
107 #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE 176 #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
@@ -142,15 +211,23 @@
142#endif 211#endif
143 212
144 213
145#if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 36000)) 214#if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30600))
146#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \ 215
216#if (Z7_CLANG_VERSION < 130000)
217#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \
218 _Pragma("GCC diagnostic push") \
219 _Pragma("GCC diagnostic ignored \"-Wreserved-id-macro\"")
220#else
221#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \
147 _Pragma("GCC diagnostic push") \ 222 _Pragma("GCC diagnostic push") \
148 _Pragma("GCC diagnostic ignored \"-Wreserved-macro-identifier\"") 223 _Pragma("GCC diagnostic ignored \"-Wreserved-macro-identifier\"")
149#define Z7_DIAGNOSCTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER \ 224#endif
225
226#define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER \
150 _Pragma("GCC diagnostic pop") 227 _Pragma("GCC diagnostic pop")
151#else 228#else
152#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER 229#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
153#define Z7_DIAGNOSCTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER 230#define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
154#endif 231#endif
155 232
156#define UNUSED_VAR(x) (void)x; 233#define UNUSED_VAR(x) (void)x;
diff --git a/C/CpuArch.c b/C/CpuArch.c
index 33f8a3a..d51b38a 100644
--- a/C/CpuArch.c
+++ b/C/CpuArch.c
@@ -1,5 +1,5 @@
1/* CpuArch.c -- CPU specific code 1/* CpuArch.c -- CPU specific code
22023-05-18 : Igor Pavlov : Public domain */ 22024-03-02 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -226,7 +226,7 @@ void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
226DON'T remove Z7_NO_INLINE and Z7_FASTCALL for MY_cpuidex_HACK(): !!! 226DON'T remove Z7_NO_INLINE and Z7_FASTCALL for MY_cpuidex_HACK(): !!!
227*/ 227*/
228static 228static
229Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(UInt32 subFunction, UInt32 func, int *CPUInfo) 229Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(Int32 subFunction, Int32 func, Int32 *CPUInfo)
230{ 230{
231 UNUSED_VAR(subFunction) 231 UNUSED_VAR(subFunction)
232 __cpuid(CPUInfo, func); 232 __cpuid(CPUInfo, func);
@@ -242,13 +242,13 @@ Z7_NO_INLINE
242#endif 242#endif
243void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) 243void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
244{ 244{
245 MY_cpuidex((int *)p, (int)func, 0); 245 MY_cpuidex((Int32 *)p, (Int32)func, 0);
246} 246}
247 247
248Z7_NO_INLINE 248Z7_NO_INLINE
249UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) 249UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
250{ 250{
251 int a[4]; 251 Int32 a[4];
252 MY_cpuidex(a, 0, 0); 252 MY_cpuidex(a, 0, 0);
253 return a[0]; 253 return a[0];
254} 254}
@@ -384,7 +384,7 @@ BoolInt CPU_IsSupported_CMOV(void)
384 UInt32 a[4]; 384 UInt32 a[4];
385 if (!x86cpuid_Func_1(&a[0])) 385 if (!x86cpuid_Func_1(&a[0]))
386 return 0; 386 return 0;
387 return (a[3] >> 15) & 1; 387 return (BoolInt)(a[3] >> 15) & 1;
388} 388}
389 389
390BoolInt CPU_IsSupported_SSE(void) 390BoolInt CPU_IsSupported_SSE(void)
@@ -393,7 +393,7 @@ BoolInt CPU_IsSupported_SSE(void)
393 CHECK_SYS_SSE_SUPPORT 393 CHECK_SYS_SSE_SUPPORT
394 if (!x86cpuid_Func_1(&a[0])) 394 if (!x86cpuid_Func_1(&a[0]))
395 return 0; 395 return 0;
396 return (a[3] >> 25) & 1; 396 return (BoolInt)(a[3] >> 25) & 1;
397} 397}
398 398
399BoolInt CPU_IsSupported_SSE2(void) 399BoolInt CPU_IsSupported_SSE2(void)
@@ -402,7 +402,7 @@ BoolInt CPU_IsSupported_SSE2(void)
402 CHECK_SYS_SSE_SUPPORT 402 CHECK_SYS_SSE_SUPPORT
403 if (!x86cpuid_Func_1(&a[0])) 403 if (!x86cpuid_Func_1(&a[0]))
404 return 0; 404 return 0;
405 return (a[3] >> 26) & 1; 405 return (BoolInt)(a[3] >> 26) & 1;
406} 406}
407 407
408#endif 408#endif
@@ -419,17 +419,17 @@ static UInt32 x86cpuid_Func_1_ECX(void)
419 419
420BoolInt CPU_IsSupported_AES(void) 420BoolInt CPU_IsSupported_AES(void)
421{ 421{
422 return (x86cpuid_Func_1_ECX() >> 25) & 1; 422 return (BoolInt)(x86cpuid_Func_1_ECX() >> 25) & 1;
423} 423}
424 424
425BoolInt CPU_IsSupported_SSSE3(void) 425BoolInt CPU_IsSupported_SSSE3(void)
426{ 426{
427 return (x86cpuid_Func_1_ECX() >> 9) & 1; 427 return (BoolInt)(x86cpuid_Func_1_ECX() >> 9) & 1;
428} 428}
429 429
430BoolInt CPU_IsSupported_SSE41(void) 430BoolInt CPU_IsSupported_SSE41(void)
431{ 431{
432 return (x86cpuid_Func_1_ECX() >> 19) & 1; 432 return (BoolInt)(x86cpuid_Func_1_ECX() >> 19) & 1;
433} 433}
434 434
435BoolInt CPU_IsSupported_SHA(void) 435BoolInt CPU_IsSupported_SHA(void)
@@ -441,7 +441,7 @@ BoolInt CPU_IsSupported_SHA(void)
441 { 441 {
442 UInt32 d[4]; 442 UInt32 d[4];
443 z7_x86_cpuid(d, 7); 443 z7_x86_cpuid(d, 7);
444 return (d[1] >> 29) & 1; 444 return (BoolInt)(d[1] >> 29) & 1;
445 } 445 }
446} 446}
447 447
@@ -640,8 +640,8 @@ BoolInt CPU_IsSupported_AVX(void)
640 const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK); 640 const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK);
641 // printf("\n=== XGetBV=%d\n", bm); 641 // printf("\n=== XGetBV=%d\n", bm);
642 return 1 642 return 1
643 & (bm >> 1) // SSE state is supported (set by OS) for storing/restoring 643 & (BoolInt)(bm >> 1) // SSE state is supported (set by OS) for storing/restoring
644 & (bm >> 2); // AVX state is supported (set by OS) for storing/restoring 644 & (BoolInt)(bm >> 2); // AVX state is supported (set by OS) for storing/restoring
645 } 645 }
646 // since Win7SP1: we can use GetEnabledXStateFeatures(); 646 // since Win7SP1: we can use GetEnabledXStateFeatures();
647} 647}
@@ -658,10 +658,29 @@ BoolInt CPU_IsSupported_AVX2(void)
658 z7_x86_cpuid(d, 7); 658 z7_x86_cpuid(d, 7);
659 // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); 659 // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
660 return 1 660 return 1
661 & (d[1] >> 5); // avx2 661 & (BoolInt)(d[1] >> 5); // avx2
662 } 662 }
663} 663}
664 664
665/*
666// fix it:
667BoolInt CPU_IsSupported_AVX512F_AVX512VL(void)
668{
669 if (!CPU_IsSupported_AVX())
670 return False;
671 if (z7_x86_cpuid_GetMaxFunc() < 7)
672 return False;
673 {
674 UInt32 d[4];
675 z7_x86_cpuid(d, 7);
676 // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
677 return 1
678 & (BoolInt)(d[1] >> 16) // avx512-f
679 & (BoolInt)(d[1] >> 31); // avx512-Vl
680 }
681}
682*/
683
665BoolInt CPU_IsSupported_VAES_AVX2(void) 684BoolInt CPU_IsSupported_VAES_AVX2(void)
666{ 685{
667 if (!CPU_IsSupported_AVX()) 686 if (!CPU_IsSupported_AVX())
@@ -673,9 +692,9 @@ BoolInt CPU_IsSupported_VAES_AVX2(void)
673 z7_x86_cpuid(d, 7); 692 z7_x86_cpuid(d, 7);
674 // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); 693 // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
675 return 1 694 return 1
676 & (d[1] >> 5) // avx2 695 & (BoolInt)(d[1] >> 5) // avx2
677 // & (d[1] >> 31) // avx512vl 696 // & (d[1] >> 31) // avx512vl
678 & (d[2] >> 9); // vaes // VEX-256/EVEX 697 & (BoolInt)(d[2] >> 9); // vaes // VEX-256/EVEX
679 } 698 }
680} 699}
681 700
@@ -688,7 +707,7 @@ BoolInt CPU_IsSupported_PageGB(void)
688 if (d[0] < 0x80000001) 707 if (d[0] < 0x80000001)
689 return False; 708 return False;
690 z7_x86_cpuid(d, 0x80000001); 709 z7_x86_cpuid(d, 0x80000001);
691 return (d[3] >> 26) & 1; 710 return (BoolInt)(d[3] >> 26) & 1;
692 } 711 }
693} 712}
694 713
@@ -760,32 +779,65 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
760 779
761#else // __APPLE__ 780#else // __APPLE__
762 781
763#include <sys/auxv.h> 782#if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)
783 #define Z7_GETAUXV_AVAILABLE
784#else
785// #pragma message("=== is not NEW GLIBC === ")
786 #if defined __has_include
787 #if __has_include (<sys/auxv.h>)
788// #pragma message("=== sys/auxv.h is avail=== ")
789 #define Z7_GETAUXV_AVAILABLE
790 #endif
791 #endif
792#endif
764 793
794#ifdef Z7_GETAUXV_AVAILABLE
795// #pragma message("=== Z7_GETAUXV_AVAILABLE === ")
796#include <sys/auxv.h>
765#define USE_HWCAP 797#define USE_HWCAP
798#endif
766 799
767#ifdef USE_HWCAP 800#ifdef USE_HWCAP
768 801
802#if defined(__FreeBSD__)
803static unsigned long MY_getauxval(int aux)
804{
805 unsigned long val;
806 if (elf_aux_info(aux, &val, sizeof(val)))
807 return 0;
808 return val;
809}
810#else
811#define MY_getauxval getauxval
812 #if defined __has_include
813 #if __has_include (<asm/hwcap.h>)
769#include <asm/hwcap.h> 814#include <asm/hwcap.h>
815 #endif
816 #endif
817#endif
770 818
771 #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \ 819 #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \
772 BoolInt CPU_IsSupported_ ## name1() { return (getauxval(AT_HWCAP) & (HWCAP_ ## name2)) ? 1 : 0; } 820 BoolInt CPU_IsSupported_ ## name1(void) { return (MY_getauxval(AT_HWCAP) & (HWCAP_ ## name2)); }
773 821
774#ifdef MY_CPU_ARM64 822#ifdef MY_CPU_ARM64
775 #define MY_HWCAP_CHECK_FUNC(name) \ 823 #define MY_HWCAP_CHECK_FUNC(name) \
776 MY_HWCAP_CHECK_FUNC_2(name, name) 824 MY_HWCAP_CHECK_FUNC_2(name, name)
825#if 1 || defined(__ARM_NEON)
826 BoolInt CPU_IsSupported_NEON(void) { return True; }
827#else
777 MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD) 828 MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD)
829#endif
778// MY_HWCAP_CHECK_FUNC (ASIMD) 830// MY_HWCAP_CHECK_FUNC (ASIMD)
779#elif defined(MY_CPU_ARM) 831#elif defined(MY_CPU_ARM)
780 #define MY_HWCAP_CHECK_FUNC(name) \ 832 #define MY_HWCAP_CHECK_FUNC(name) \
781 BoolInt CPU_IsSupported_ ## name() { return (getauxval(AT_HWCAP2) & (HWCAP2_ ## name)) ? 1 : 0; } 833 BoolInt CPU_IsSupported_ ## name(void) { return (MY_getauxval(AT_HWCAP2) & (HWCAP2_ ## name)); }
782 MY_HWCAP_CHECK_FUNC_2(NEON, NEON) 834 MY_HWCAP_CHECK_FUNC_2(NEON, NEON)
783#endif 835#endif
784 836
785#else // USE_HWCAP 837#else // USE_HWCAP
786 838
787 #define MY_HWCAP_CHECK_FUNC(name) \ 839 #define MY_HWCAP_CHECK_FUNC(name) \
788 BoolInt CPU_IsSupported_ ## name() { return 0; } 840 BoolInt CPU_IsSupported_ ## name(void) { return 0; }
789 MY_HWCAP_CHECK_FUNC(NEON) 841 MY_HWCAP_CHECK_FUNC(NEON)
790 842
791#endif // USE_HWCAP 843#endif // USE_HWCAP
diff --git a/C/CpuArch.h b/C/CpuArch.h
index 8e5d8a5..dfc68f1 100644
--- a/C/CpuArch.h
+++ b/C/CpuArch.h
@@ -1,5 +1,5 @@
1/* CpuArch.h -- CPU specific code 1/* CpuArch.h -- CPU specific code
22023-04-02 : Igor Pavlov : Public domain */ 22024-05-13 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_CPU_ARCH_H 4#ifndef ZIP7_INC_CPU_ARCH_H
5#define ZIP7_INC_CPU_ARCH_H 5#define ZIP7_INC_CPU_ARCH_H
@@ -20,6 +20,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
20 MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8) 20 MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8)
21*/ 21*/
22 22
23#if !defined(_M_ARM64EC)
23#if defined(_M_X64) \ 24#if defined(_M_X64) \
24 || defined(_M_AMD64) \ 25 || defined(_M_AMD64) \
25 || defined(__x86_64__) \ 26 || defined(__x86_64__) \
@@ -35,6 +36,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
35 #endif 36 #endif
36 #define MY_CPU_64BIT 37 #define MY_CPU_64BIT
37#endif 38#endif
39#endif
38 40
39 41
40#if defined(_M_IX86) \ 42#if defined(_M_IX86) \
@@ -47,17 +49,26 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
47 49
48 50
49#if defined(_M_ARM64) \ 51#if defined(_M_ARM64) \
52 || defined(_M_ARM64EC) \
50 || defined(__AARCH64EL__) \ 53 || defined(__AARCH64EL__) \
51 || defined(__AARCH64EB__) \ 54 || defined(__AARCH64EB__) \
52 || defined(__aarch64__) 55 || defined(__aarch64__)
53 #define MY_CPU_ARM64 56 #define MY_CPU_ARM64
54 #ifdef __ILP32__ 57#if defined(__ILP32__) \
58 || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)
55 #define MY_CPU_NAME "arm64-32" 59 #define MY_CPU_NAME "arm64-32"
56 #define MY_CPU_SIZEOF_POINTER 4 60 #define MY_CPU_SIZEOF_POINTER 4
57 #else 61#elif defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)
62 #define MY_CPU_NAME "arm64-128"
63 #define MY_CPU_SIZEOF_POINTER 16
64#else
65#if defined(_M_ARM64EC)
66 #define MY_CPU_NAME "arm64ec"
67#else
58 #define MY_CPU_NAME "arm64" 68 #define MY_CPU_NAME "arm64"
69#endif
59 #define MY_CPU_SIZEOF_POINTER 8 70 #define MY_CPU_SIZEOF_POINTER 8
60 #endif 71#endif
61 #define MY_CPU_64BIT 72 #define MY_CPU_64BIT
62#endif 73#endif
63 74
@@ -133,8 +144,36 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
133#endif 144#endif
134 145
135 146
147#if defined(__sparc__) \
148 || defined(__sparc)
149 #define MY_CPU_SPARC
150 #if defined(__LP64__) \
151 || defined(_LP64) \
152 || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8)
153 #define MY_CPU_NAME "sparcv9"
154 #define MY_CPU_SIZEOF_POINTER 8
155 #define MY_CPU_64BIT
156 #elif defined(__sparc_v9__) \
157 || defined(__sparcv9)
158 #define MY_CPU_64BIT
159 #if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)
160 #define MY_CPU_NAME "sparcv9-32"
161 #else
162 #define MY_CPU_NAME "sparcv9m"
163 #endif
164 #elif defined(__sparc_v8__) \
165 || defined(__sparcv8)
166 #define MY_CPU_NAME "sparcv8"
167 #define MY_CPU_SIZEOF_POINTER 4
168 #else
169 #define MY_CPU_NAME "sparc"
170 #endif
171#endif
172
173
136#if defined(__riscv) \ 174#if defined(__riscv) \
137 || defined(__riscv__) 175 || defined(__riscv__)
176 #define MY_CPU_RISCV
138 #if __riscv_xlen == 32 177 #if __riscv_xlen == 32
139 #define MY_CPU_NAME "riscv32" 178 #define MY_CPU_NAME "riscv32"
140 #elif __riscv_xlen == 64 179 #elif __riscv_xlen == 64
@@ -145,6 +184,39 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
145#endif 184#endif
146 185
147 186
187#if defined(__loongarch__)
188 #define MY_CPU_LOONGARCH
189 #if defined(__loongarch64) || defined(__loongarch_grlen) && (__loongarch_grlen == 64)
190 #define MY_CPU_64BIT
191 #endif
192 #if defined(__loongarch64)
193 #define MY_CPU_NAME "loongarch64"
194 #define MY_CPU_LOONGARCH64
195 #else
196 #define MY_CPU_NAME "loongarch"
197 #endif
198#endif
199
200
201// #undef MY_CPU_NAME
202// #undef MY_CPU_SIZEOF_POINTER
203// #define __e2k__
204// #define __SIZEOF_POINTER__ 4
205#if defined(__e2k__)
206 #define MY_CPU_E2K
207 #if defined(__ILP32__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)
208 #define MY_CPU_NAME "e2k-32"
209 #define MY_CPU_SIZEOF_POINTER 4
210 #else
211 #define MY_CPU_NAME "e2k"
212 #if defined(__LP64__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8)
213 #define MY_CPU_SIZEOF_POINTER 8
214 #endif
215 #endif
216 #define MY_CPU_64BIT
217#endif
218
219
148#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) 220#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
149#define MY_CPU_X86_OR_AMD64 221#define MY_CPU_X86_OR_AMD64
150#endif 222#endif
@@ -175,6 +247,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
175 || defined(MY_CPU_ARM_LE) \ 247 || defined(MY_CPU_ARM_LE) \
176 || defined(MY_CPU_ARM64_LE) \ 248 || defined(MY_CPU_ARM64_LE) \
177 || defined(MY_CPU_IA64_LE) \ 249 || defined(MY_CPU_IA64_LE) \
250 || defined(_LITTLE_ENDIAN) \
178 || defined(__LITTLE_ENDIAN__) \ 251 || defined(__LITTLE_ENDIAN__) \
179 || defined(__ARMEL__) \ 252 || defined(__ARMEL__) \
180 || defined(__THUMBEL__) \ 253 || defined(__THUMBEL__) \
@@ -251,6 +324,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
251 324
252 325
253#ifndef MY_CPU_NAME 326#ifndef MY_CPU_NAME
327 // #define MY_CPU_IS_UNKNOWN
254 #ifdef MY_CPU_LE 328 #ifdef MY_CPU_LE
255 #define MY_CPU_NAME "LE" 329 #define MY_CPU_NAME "LE"
256 #elif defined(MY_CPU_BE) 330 #elif defined(MY_CPU_BE)
@@ -295,9 +369,19 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
295#define Z7_BSWAP64(v) _byteswap_uint64(v) 369#define Z7_BSWAP64(v) _byteswap_uint64(v)
296#define Z7_CPU_FAST_BSWAP_SUPPORTED 370#define Z7_CPU_FAST_BSWAP_SUPPORTED
297 371
298#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ 372/* GCC can generate slow code that calls function for __builtin_bswap32() for:
299 || (defined(__clang__) && Z7_has_builtin(__builtin_bswap16)) 373 - GCC for RISCV, if Zbb extension is not used.
300 374 - GCC for SPARC.
375 The code from CLANG for SPARC also is not fastest.
376 So we don't define Z7_CPU_FAST_BSWAP_SUPPORTED in some cases.
377*/
378#elif (!defined(MY_CPU_RISCV) || defined (__riscv_zbb)) \
379 && !defined(MY_CPU_SPARC) \
380 && ( \
381 (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \
382 || (defined(__clang__) && Z7_has_builtin(__builtin_bswap16)) \
383 )
384
301#define Z7_BSWAP16(v) __builtin_bswap16(v) 385#define Z7_BSWAP16(v) __builtin_bswap16(v)
302#define Z7_BSWAP32(v) __builtin_bswap32(v) 386#define Z7_BSWAP32(v) __builtin_bswap32(v)
303#define Z7_BSWAP64(v) __builtin_bswap64(v) 387#define Z7_BSWAP64(v) __builtin_bswap64(v)
@@ -329,13 +413,48 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
329 413
330#ifdef MY_CPU_LE 414#ifdef MY_CPU_LE
331 #if defined(MY_CPU_X86_OR_AMD64) \ 415 #if defined(MY_CPU_X86_OR_AMD64) \
332 || defined(MY_CPU_ARM64) 416 || defined(MY_CPU_ARM64) \
417 || defined(MY_CPU_RISCV) && defined(__riscv_misaligned_fast) \
418 || defined(MY_CPU_E2K) && defined(__iset__) && (__iset__ >= 6)
333 #define MY_CPU_LE_UNALIGN 419 #define MY_CPU_LE_UNALIGN
334 #define MY_CPU_LE_UNALIGN_64 420 #define MY_CPU_LE_UNALIGN_64
335 #elif defined(__ARM_FEATURE_UNALIGNED) 421 #elif defined(__ARM_FEATURE_UNALIGNED)
336 /* gcc9 for 32-bit arm can use LDRD instruction that requires 32-bit alignment. 422/* === ALIGNMENT on 32-bit arm and LDRD/STRD/LDM/STM instructions.
337 So we can't use unaligned 64-bit operations. */ 423 Description of problems:
338 #define MY_CPU_LE_UNALIGN 424problem-1 : 32-bit ARM architecture:
425 multi-access (pair of 32-bit accesses) instructions (LDRD/STRD/LDM/STM)
426 require 32-bit (WORD) alignment (by 32-bit ARM architecture).
427 So there is "Alignment fault exception", if data is not aligned for 32-bit.
428
429problem-2 : 32-bit kernels and arm64 kernels:
430 32-bit linux kernels provide fixup for these "paired" instruction "Alignment fault exception".
431 So unaligned paired-access instructions work via exception handler in kernel in 32-bit linux.
432
433 But some arm64 kernels do not handle these faults in 32-bit programs.
434 So we have unhandled exception for such instructions.
435 Probably some new arm64 kernels have fixed it, and unaligned
436 paired-access instructions work in new kernels?
437
438problem-3 : compiler for 32-bit arm:
439 Compilers use LDRD/STRD/LDM/STM for UInt64 accesses
440 and for another cases where two 32-bit accesses are fused
441 to one multi-access instruction.
442 So UInt64 variables must be aligned for 32-bit, and each
443 32-bit access must be aligned for 32-bit, if we want to
444 avoid "Alignment fault" exception (handled or unhandled).
445
446problem-4 : performace:
447 Even if unaligned access is handled by kernel, it will be slow.
448 So if we allow unaligned access, we can get fast unaligned
449 single-access, and slow unaligned paired-access.
450
451 We don't allow unaligned access on 32-bit arm, because compiler
452 genarates paired-access instructions that require 32-bit alignment,
453 and some arm64 kernels have no handler for these instructions.
454 Also unaligned paired-access instructions will be slow, if kernel handles them.
455*/
456 // it must be disabled:
457 // #define MY_CPU_LE_UNALIGN
339 #endif 458 #endif
340#endif 459#endif
341 460
@@ -439,6 +558,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
439 558
440#if defined(MY_CPU_BE) 559#if defined(MY_CPU_BE)
441 560
561#define GetBe64a(p) (*(const UInt64 *)(const void *)(p))
442#define GetBe32a(p) (*(const UInt32 *)(const void *)(p)) 562#define GetBe32a(p) (*(const UInt32 *)(const void *)(p))
443#define GetBe16a(p) (*(const UInt16 *)(const void *)(p)) 563#define GetBe16a(p) (*(const UInt16 *)(const void *)(p))
444#define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); } 564#define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); }
@@ -456,6 +576,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
456#define SetUi32a(p, v) { *(UInt32 *)(void *)(p) = (v); } 576#define SetUi32a(p, v) { *(UInt32 *)(void *)(p) = (v); }
457#define SetUi16a(p, v) { *(UInt16 *)(void *)(p) = (v); } 577#define SetUi16a(p, v) { *(UInt16 *)(void *)(p) = (v); }
458 578
579#define GetBe64a(p) GetBe64(p)
459#define GetBe32a(p) GetBe32(p) 580#define GetBe32a(p) GetBe32(p)
460#define GetBe16a(p) GetBe16(p) 581#define GetBe16a(p) GetBe16(p)
461#define SetBe32a(p, v) SetBe32(p, v) 582#define SetBe32a(p, v) SetBe32(p, v)
@@ -486,6 +607,7 @@ UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void);
486BoolInt CPU_IsSupported_AES(void); 607BoolInt CPU_IsSupported_AES(void);
487BoolInt CPU_IsSupported_AVX(void); 608BoolInt CPU_IsSupported_AVX(void);
488BoolInt CPU_IsSupported_AVX2(void); 609BoolInt CPU_IsSupported_AVX2(void);
610// BoolInt CPU_IsSupported_AVX512F_AVX512VL(void);
489BoolInt CPU_IsSupported_VAES_AVX2(void); 611BoolInt CPU_IsSupported_VAES_AVX2(void);
490BoolInt CPU_IsSupported_CMOV(void); 612BoolInt CPU_IsSupported_CMOV(void);
491BoolInt CPU_IsSupported_SSE(void); 613BoolInt CPU_IsSupported_SSE(void);
diff --git a/C/DllSecur.c b/C/DllSecur.c
index 02a0f97..bbbfc0a 100644
--- a/C/DllSecur.c
+++ b/C/DllSecur.c
@@ -1,5 +1,5 @@
1/* DllSecur.c -- DLL loading security 1/* DllSecur.c -- DLL loading security
22023-04-02 : Igor Pavlov : Public domain */ 22023-12-03 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -11,19 +11,7 @@
11 11
12#ifndef UNDER_CE 12#ifndef UNDER_CE
13 13
14#if (defined(__GNUC__) && (__GNUC__ >= 8)) || defined(__clang__) 14Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
15 // #pragma GCC diagnostic ignored "-Wcast-function-type"
16#endif
17
18#if defined(__clang__) || defined(__GNUC__)
19typedef void (*Z7_voidFunction)(void);
20#define MY_CAST_FUNC (Z7_voidFunction)
21#elif defined(_MSC_VER) && _MSC_VER > 1920
22#define MY_CAST_FUNC (void *)
23// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()'
24#else
25#define MY_CAST_FUNC
26#endif
27 15
28typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags); 16typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags);
29 17
@@ -61,7 +49,7 @@ static const char * const g_Dlls =
61 if ((UInt16)GetVersion() != 6) { \ 49 if ((UInt16)GetVersion() != 6) { \
62 const \ 50 const \
63 Func_SetDefaultDllDirectories setDllDirs = \ 51 Func_SetDefaultDllDirectories setDllDirs = \
64 (Func_SetDefaultDllDirectories) MY_CAST_FUNC GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), \ 52 (Func_SetDefaultDllDirectories) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), \
65 "SetDefaultDllDirectories"); \ 53 "SetDefaultDllDirectories"); \
66 if (setDllDirs) if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) return; } 54 if (setDllDirs) if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) return; }
67 55
diff --git a/C/HuffEnc.c b/C/HuffEnc.c
index 3dc1e39..996da30 100644
--- a/C/HuffEnc.c
+++ b/C/HuffEnc.c
@@ -1,5 +1,5 @@
1/* HuffEnc.c -- functions for Huffman encoding 1/* HuffEnc.c -- functions for Huffman encoding
22023-03-04 : Igor Pavlov : Public domain */ 22023-09-07 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -8,7 +8,7 @@
8 8
9#define kMaxLen 16 9#define kMaxLen 16
10#define NUM_BITS 10 10#define NUM_BITS 10
11#define MASK (((unsigned)1 << NUM_BITS) - 1) 11#define MASK ((1u << NUM_BITS) - 1)
12 12
13#define NUM_COUNTERS 64 13#define NUM_COUNTERS 64
14 14
diff --git a/C/LzFind.c b/C/LzFind.c
index 0fbd5aa..1ce4046 100644
--- a/C/LzFind.c
+++ b/C/LzFind.c
@@ -1,5 +1,5 @@
1/* LzFind.c -- Match finder for LZ algorithms 1/* LzFind.c -- Match finder for LZ algorithms
22023-03-14 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -108,9 +108,15 @@ static int LzInWindow_Create2(CMatchFinder *p, UInt32 blockSize, ISzAllocPtr all
108 return (p->bufBase != NULL); 108 return (p->bufBase != NULL);
109} 109}
110 110
111static const Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } 111static const Byte *MatchFinder_GetPointerToCurrentPos(void *p)
112{
113 return ((CMatchFinder *)p)->buffer;
114}
112 115
113static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return GET_AVAIL_BYTES(p); } 116static UInt32 MatchFinder_GetNumAvailableBytes(void *p)
117{
118 return GET_AVAIL_BYTES((CMatchFinder *)p);
119}
114 120
115 121
116Z7_NO_INLINE 122Z7_NO_INLINE
@@ -571,8 +577,9 @@ void MatchFinder_Init_4(CMatchFinder *p)
571#define CYC_TO_POS_OFFSET 0 577#define CYC_TO_POS_OFFSET 0
572// #define CYC_TO_POS_OFFSET 1 // for debug 578// #define CYC_TO_POS_OFFSET 1 // for debug
573 579
574void MatchFinder_Init(CMatchFinder *p) 580void MatchFinder_Init(void *_p)
575{ 581{
582 CMatchFinder *p = (CMatchFinder *)_p;
576 MatchFinder_Init_HighHash(p); 583 MatchFinder_Init_HighHash(p);
577 MatchFinder_Init_LowHash(p); 584 MatchFinder_Init_LowHash(p);
578 MatchFinder_Init_4(p); 585 MatchFinder_Init_4(p);
@@ -607,16 +614,16 @@ void MatchFinder_Init(CMatchFinder *p)
607 #endif 614 #endif
608 #endif 615 #endif
609 616
610// #elif defined(MY_CPU_ARM_OR_ARM64) 617#elif defined(MY_CPU_ARM64) \
611#elif defined(MY_CPU_ARM64) 618 /* || (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) */
612 619
613 #if defined(__clang__) && (__clang_major__ >= 8) \ 620 #if defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
614 || defined(__GNUC__) && (__GNUC__ >= 8) 621 || defined(__GNUC__) && (__GNUC__ >= 6)
615 #define USE_LZFIND_SATUR_SUB_128 622 #define USE_LZFIND_SATUR_SUB_128
616 #ifdef MY_CPU_ARM64 623 #ifdef MY_CPU_ARM64
617 // #define LZFIND_ATTRIB_SSE41 __attribute__((__target__(""))) 624 // #define LZFIND_ATTRIB_SSE41 __attribute__((__target__("")))
618 #else 625 #else
619 // #define LZFIND_ATTRIB_SSE41 __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) 626 #define LZFIND_ATTRIB_SSE41 __attribute__((__target__("fpu=neon")))
620 #endif 627 #endif
621 628
622 #elif defined(_MSC_VER) 629 #elif defined(_MSC_VER)
@@ -625,7 +632,7 @@ void MatchFinder_Init(CMatchFinder *p)
625 #endif 632 #endif
626 #endif 633 #endif
627 634
628 #if defined(_MSC_VER) && defined(MY_CPU_ARM64) 635 #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
629 #include <arm64_neon.h> 636 #include <arm64_neon.h>
630 #else 637 #else
631 #include <arm_neon.h> 638 #include <arm_neon.h>
@@ -1082,9 +1089,11 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
1082 1089
1083 1090
1084#define MOVE_POS \ 1091#define MOVE_POS \
1085 ++p->cyclicBufferPos; \ 1092 p->cyclicBufferPos++; \
1086 p->buffer++; \ 1093 p->buffer++; \
1087 { const UInt32 pos1 = p->pos + 1; p->pos = pos1; if (pos1 == p->posLimit) MatchFinder_CheckLimits(p); } 1094 { const UInt32 pos1 = p->pos + 1; \
1095 p->pos = pos1; \
1096 if (pos1 == p->posLimit) MatchFinder_CheckLimits(p); }
1088 1097
1089#define MOVE_POS_RET MOVE_POS return distances; 1098#define MOVE_POS_RET MOVE_POS return distances;
1090 1099
@@ -1103,20 +1112,26 @@ static void MatchFinder_MovePos(CMatchFinder *p)
1103} 1112}
1104 1113
1105#define GET_MATCHES_HEADER2(minLen, ret_op) \ 1114#define GET_MATCHES_HEADER2(minLen, ret_op) \
1106 unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \ 1115 UInt32 hv; const Byte *cur; UInt32 curMatch; \
1107 lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ 1116 UInt32 lenLimit = p->lenLimit; \
1117 if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; } \
1108 cur = p->buffer; 1118 cur = p->buffer;
1109 1119
1110#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return distances) 1120#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return distances)
1111#define SKIP_HEADER(minLen) do { GET_MATCHES_HEADER2(minLen, continue) 1121#define SKIP_HEADER(minLen) \
1122 do { GET_MATCHES_HEADER2(minLen, continue)
1112 1123
1113#define MF_PARAMS(p) lenLimit, curMatch, p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue 1124#define MF_PARAMS(p) lenLimit, curMatch, p->pos, p->buffer, p->son, \
1125 p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
1114 1126
1115#define SKIP_FOOTER SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS } while (--num); 1127#define SKIP_FOOTER \
1128 SkipMatchesSpec(MF_PARAMS(p)); \
1129 MOVE_POS \
1130 } while (--num);
1116 1131
1117#define GET_MATCHES_FOOTER_BASE(_maxLen_, func) \ 1132#define GET_MATCHES_FOOTER_BASE(_maxLen_, func) \
1118 distances = func(MF_PARAMS(p), \ 1133 distances = func(MF_PARAMS(p), distances, (UInt32)_maxLen_); \
1119 distances, (UInt32)_maxLen_); MOVE_POS_RET 1134 MOVE_POS_RET
1120 1135
1121#define GET_MATCHES_FOOTER_BT(_maxLen_) \ 1136#define GET_MATCHES_FOOTER_BT(_maxLen_) \
1122 GET_MATCHES_FOOTER_BASE(_maxLen_, GetMatchesSpec1) 1137 GET_MATCHES_FOOTER_BASE(_maxLen_, GetMatchesSpec1)
@@ -1133,8 +1148,9 @@ static void MatchFinder_MovePos(CMatchFinder *p)
1133 for (; c != lim; c++) if (*(c + diff) != *c) break; \ 1148 for (; c != lim; c++) if (*(c + diff) != *c) break; \
1134 maxLen = (unsigned)(c - cur); } 1149 maxLen = (unsigned)(c - cur); }
1135 1150
1136static UInt32* Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 1151static UInt32* Bt2_MatchFinder_GetMatches(void *_p, UInt32 *distances)
1137{ 1152{
1153 CMatchFinder *p = (CMatchFinder *)_p;
1138 GET_MATCHES_HEADER(2) 1154 GET_MATCHES_HEADER(2)
1139 HASH2_CALC 1155 HASH2_CALC
1140 curMatch = p->hash[hv]; 1156 curMatch = p->hash[hv];
@@ -1158,8 +1174,9 @@ UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1158 mmm = pos; 1174 mmm = pos;
1159 1175
1160 1176
1161static UInt32* Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 1177static UInt32* Bt3_MatchFinder_GetMatches(void *_p, UInt32 *distances)
1162{ 1178{
1179 CMatchFinder *p = (CMatchFinder *)_p;
1163 UInt32 mmm; 1180 UInt32 mmm;
1164 UInt32 h2, d2, pos; 1181 UInt32 h2, d2, pos;
1165 unsigned maxLen; 1182 unsigned maxLen;
@@ -1199,8 +1216,9 @@ static UInt32* Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1199} 1216}
1200 1217
1201 1218
1202static UInt32* Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 1219static UInt32* Bt4_MatchFinder_GetMatches(void *_p, UInt32 *distances)
1203{ 1220{
1221 CMatchFinder *p = (CMatchFinder *)_p;
1204 UInt32 mmm; 1222 UInt32 mmm;
1205 UInt32 h2, h3, d2, d3, pos; 1223 UInt32 h2, h3, d2, d3, pos;
1206 unsigned maxLen; 1224 unsigned maxLen;
@@ -1267,10 +1285,12 @@ static UInt32* Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1267} 1285}
1268 1286
1269 1287
1270static UInt32* Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 1288static UInt32* Bt5_MatchFinder_GetMatches(void *_p, UInt32 *distances)
1271{ 1289{
1290 CMatchFinder *p = (CMatchFinder *)_p;
1272 UInt32 mmm; 1291 UInt32 mmm;
1273 UInt32 h2, h3, d2, d3, maxLen, pos; 1292 UInt32 h2, h3, d2, d3, pos;
1293 unsigned maxLen;
1274 UInt32 *hash; 1294 UInt32 *hash;
1275 GET_MATCHES_HEADER(5) 1295 GET_MATCHES_HEADER(5)
1276 1296
@@ -1339,8 +1359,9 @@ static UInt32* Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1339} 1359}
1340 1360
1341 1361
1342static UInt32* Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 1362static UInt32* Hc4_MatchFinder_GetMatches(void *_p, UInt32 *distances)
1343{ 1363{
1364 CMatchFinder *p = (CMatchFinder *)_p;
1344 UInt32 mmm; 1365 UInt32 mmm;
1345 UInt32 h2, h3, d2, d3, pos; 1366 UInt32 h2, h3, d2, d3, pos;
1346 unsigned maxLen; 1367 unsigned maxLen;
@@ -1407,10 +1428,12 @@ static UInt32* Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1407} 1428}
1408 1429
1409 1430
1410static UInt32 * Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 1431static UInt32 * Hc5_MatchFinder_GetMatches(void *_p, UInt32 *distances)
1411{ 1432{
1433 CMatchFinder *p = (CMatchFinder *)_p;
1412 UInt32 mmm; 1434 UInt32 mmm;
1413 UInt32 h2, h3, d2, d3, maxLen, pos; 1435 UInt32 h2, h3, d2, d3, pos;
1436 unsigned maxLen;
1414 UInt32 *hash; 1437 UInt32 *hash;
1415 GET_MATCHES_HEADER(5) 1438 GET_MATCHES_HEADER(5)
1416 1439
@@ -1466,7 +1489,7 @@ static UInt32 * Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1466 if (*(cur - d2 + 3) != cur[3]) 1489 if (*(cur - d2 + 3) != cur[3])
1467 break; 1490 break;
1468 UPDATE_maxLen 1491 UPDATE_maxLen
1469 distances[-2] = maxLen; 1492 distances[-2] = (UInt32)maxLen;
1470 if (maxLen == lenLimit) 1493 if (maxLen == lenLimit)
1471 { 1494 {
1472 p->son[p->cyclicBufferPos] = curMatch; 1495 p->son[p->cyclicBufferPos] = curMatch;
@@ -1489,8 +1512,9 @@ UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1489} 1512}
1490 1513
1491 1514
1492static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 1515static void Bt2_MatchFinder_Skip(void *_p, UInt32 num)
1493{ 1516{
1517 CMatchFinder *p = (CMatchFinder *)_p;
1494 SKIP_HEADER(2) 1518 SKIP_HEADER(2)
1495 { 1519 {
1496 HASH2_CALC 1520 HASH2_CALC
@@ -1511,8 +1535,9 @@ void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1511 SKIP_FOOTER 1535 SKIP_FOOTER
1512} 1536}
1513 1537
1514static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 1538static void Bt3_MatchFinder_Skip(void *_p, UInt32 num)
1515{ 1539{
1540 CMatchFinder *p = (CMatchFinder *)_p;
1516 SKIP_HEADER(3) 1541 SKIP_HEADER(3)
1517 { 1542 {
1518 UInt32 h2; 1543 UInt32 h2;
@@ -1526,8 +1551,9 @@ static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1526 SKIP_FOOTER 1551 SKIP_FOOTER
1527} 1552}
1528 1553
1529static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 1554static void Bt4_MatchFinder_Skip(void *_p, UInt32 num)
1530{ 1555{
1556 CMatchFinder *p = (CMatchFinder *)_p;
1531 SKIP_HEADER(4) 1557 SKIP_HEADER(4)
1532 { 1558 {
1533 UInt32 h2, h3; 1559 UInt32 h2, h3;
@@ -1542,8 +1568,9 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1542 SKIP_FOOTER 1568 SKIP_FOOTER
1543} 1569}
1544 1570
1545static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 1571static void Bt5_MatchFinder_Skip(void *_p, UInt32 num)
1546{ 1572{
1573 CMatchFinder *p = (CMatchFinder *)_p;
1547 SKIP_HEADER(5) 1574 SKIP_HEADER(5)
1548 { 1575 {
1549 UInt32 h2, h3; 1576 UInt32 h2, h3;
@@ -1589,8 +1616,9 @@ static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1589 }} while(num); \ 1616 }} while(num); \
1590 1617
1591 1618
1592static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 1619static void Hc4_MatchFinder_Skip(void *_p, UInt32 num)
1593{ 1620{
1621 CMatchFinder *p = (CMatchFinder *)_p;
1594 HC_SKIP_HEADER(4) 1622 HC_SKIP_HEADER(4)
1595 1623
1596 UInt32 h2, h3; 1624 UInt32 h2, h3;
@@ -1604,8 +1632,9 @@ static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1604} 1632}
1605 1633
1606 1634
1607static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 1635static void Hc5_MatchFinder_Skip(void *_p, UInt32 num)
1608{ 1636{
1637 CMatchFinder *p = (CMatchFinder *)_p;
1609 HC_SKIP_HEADER(5) 1638 HC_SKIP_HEADER(5)
1610 1639
1611 UInt32 h2, h3; 1640 UInt32 h2, h3;
@@ -1634,41 +1663,41 @@ void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1634 1663
1635void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable) 1664void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable)
1636{ 1665{
1637 vTable->Init = (Mf_Init_Func)MatchFinder_Init; 1666 vTable->Init = MatchFinder_Init;
1638 vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; 1667 vTable->GetNumAvailableBytes = MatchFinder_GetNumAvailableBytes;
1639 vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; 1668 vTable->GetPointerToCurrentPos = MatchFinder_GetPointerToCurrentPos;
1640 if (!p->btMode) 1669 if (!p->btMode)
1641 { 1670 {
1642 if (p->numHashBytes <= 4) 1671 if (p->numHashBytes <= 4)
1643 { 1672 {
1644 vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; 1673 vTable->GetMatches = Hc4_MatchFinder_GetMatches;
1645 vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; 1674 vTable->Skip = Hc4_MatchFinder_Skip;
1646 } 1675 }
1647 else 1676 else
1648 { 1677 {
1649 vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches; 1678 vTable->GetMatches = Hc5_MatchFinder_GetMatches;
1650 vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip; 1679 vTable->Skip = Hc5_MatchFinder_Skip;
1651 } 1680 }
1652 } 1681 }
1653 else if (p->numHashBytes == 2) 1682 else if (p->numHashBytes == 2)
1654 { 1683 {
1655 vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; 1684 vTable->GetMatches = Bt2_MatchFinder_GetMatches;
1656 vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; 1685 vTable->Skip = Bt2_MatchFinder_Skip;
1657 } 1686 }
1658 else if (p->numHashBytes == 3) 1687 else if (p->numHashBytes == 3)
1659 { 1688 {
1660 vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; 1689 vTable->GetMatches = Bt3_MatchFinder_GetMatches;
1661 vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; 1690 vTable->Skip = Bt3_MatchFinder_Skip;
1662 } 1691 }
1663 else if (p->numHashBytes == 4) 1692 else if (p->numHashBytes == 4)
1664 { 1693 {
1665 vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; 1694 vTable->GetMatches = Bt4_MatchFinder_GetMatches;
1666 vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; 1695 vTable->Skip = Bt4_MatchFinder_Skip;
1667 } 1696 }
1668 else 1697 else
1669 { 1698 {
1670 vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches; 1699 vTable->GetMatches = Bt5_MatchFinder_GetMatches;
1671 vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip; 1700 vTable->Skip = Bt5_MatchFinder_Skip;
1672 } 1701 }
1673} 1702}
1674 1703
diff --git a/C/LzFind.h b/C/LzFind.h
index a3f72c9..67e8a6e 100644
--- a/C/LzFind.h
+++ b/C/LzFind.h
@@ -1,5 +1,5 @@
1/* LzFind.h -- Match finder for LZ algorithms 1/* LzFind.h -- Match finder for LZ algorithms
22023-03-04 : Igor Pavlov : Public domain */ 22024-01-22 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_LZ_FIND_H 4#ifndef ZIP7_INC_LZ_FIND_H
5#define ZIP7_INC_LZ_FIND_H 5#define ZIP7_INC_LZ_FIND_H
@@ -144,7 +144,8 @@ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable);
144void MatchFinder_Init_LowHash(CMatchFinder *p); 144void MatchFinder_Init_LowHash(CMatchFinder *p);
145void MatchFinder_Init_HighHash(CMatchFinder *p); 145void MatchFinder_Init_HighHash(CMatchFinder *p);
146void MatchFinder_Init_4(CMatchFinder *p); 146void MatchFinder_Init_4(CMatchFinder *p);
147void MatchFinder_Init(CMatchFinder *p); 147// void MatchFinder_Init(CMatchFinder *p);
148void MatchFinder_Init(void *p);
148 149
149UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); 150UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
150UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); 151UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
diff --git a/C/LzFindMt.c b/C/LzFindMt.c
index 5253e6e..ac9d59d 100644
--- a/C/LzFindMt.c
+++ b/C/LzFindMt.c
@@ -1,5 +1,5 @@
1/* LzFindMt.c -- multithreaded Match finder for LZ algorithms 1/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
22023-04-02 : Igor Pavlov : Public domain */ 22024-01-22 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -94,7 +94,7 @@ static void MtSync_Construct(CMtSync *p)
94} 94}
95 95
96 96
97#define DEBUG_BUFFER_LOCK // define it to debug lock state 97// #define DEBUG_BUFFER_LOCK // define it to debug lock state
98 98
99#ifdef DEBUG_BUFFER_LOCK 99#ifdef DEBUG_BUFFER_LOCK
100#include <stdlib.h> 100#include <stdlib.h>
@@ -877,8 +877,9 @@ SRes MatchFinderMt_InitMt(CMatchFinderMt *p)
877} 877}
878 878
879 879
880static void MatchFinderMt_Init(CMatchFinderMt *p) 880static void MatchFinderMt_Init(void *_p)
881{ 881{
882 CMatchFinderMt *p = (CMatchFinderMt *)_p;
882 CMatchFinder *mf = MF(p); 883 CMatchFinder *mf = MF(p);
883 884
884 p->btBufPos = 885 p->btBufPos =
@@ -981,8 +982,9 @@ static UInt32 MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
981 982
982 983
983 984
984static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) 985static const Byte * MatchFinderMt_GetPointerToCurrentPos(void *_p)
985{ 986{
987 CMatchFinderMt *p = (CMatchFinderMt *)_p;
986 return p->pointerToCurPos; 988 return p->pointerToCurPos;
987} 989}
988 990
@@ -990,8 +992,9 @@ static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
990#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); 992#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
991 993
992 994
993static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) 995static UInt32 MatchFinderMt_GetNumAvailableBytes(void *_p)
994{ 996{
997 CMatchFinderMt *p = (CMatchFinderMt *)_p;
995 if (p->btBufPos != p->btBufPosLimit) 998 if (p->btBufPos != p->btBufPosLimit)
996 return p->btNumAvailBytes; 999 return p->btNumAvailBytes;
997 return MatchFinderMt_GetNextBlock_Bt(p); 1000 return MatchFinderMt_GetNextBlock_Bt(p);
@@ -1243,8 +1246,9 @@ static UInt32 * MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d)
1243} 1246}
1244 1247
1245 1248
1246static UInt32 * MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *d) 1249static UInt32 * MatchFinderMt2_GetMatches(void *_p, UInt32 *d)
1247{ 1250{
1251 CMatchFinderMt *p = (CMatchFinderMt *)_p;
1248 const UInt32 *bt = p->btBufPos; 1252 const UInt32 *bt = p->btBufPos;
1249 const UInt32 len = *bt++; 1253 const UInt32 len = *bt++;
1250 const UInt32 *btLim = bt + len; 1254 const UInt32 *btLim = bt + len;
@@ -1267,8 +1271,9 @@ static UInt32 * MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *d)
1267 1271
1268 1272
1269 1273
1270static UInt32 * MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *d) 1274static UInt32 * MatchFinderMt_GetMatches(void *_p, UInt32 *d)
1271{ 1275{
1276 CMatchFinderMt *p = (CMatchFinderMt *)_p;
1272 const UInt32 *bt = p->btBufPos; 1277 const UInt32 *bt = p->btBufPos;
1273 UInt32 len = *bt++; 1278 UInt32 len = *bt++;
1274 const UInt32 avail = p->btNumAvailBytes - 1; 1279 const UInt32 avail = p->btNumAvailBytes - 1;
@@ -1315,14 +1320,16 @@ static UInt32 * MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *d)
1315#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; 1320#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
1316#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += (size_t)*p->btBufPos + 1; } while (--num != 0); 1321#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += (size_t)*p->btBufPos + 1; } while (--num != 0);
1317 1322
1318static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) 1323static void MatchFinderMt0_Skip(void *_p, UInt32 num)
1319{ 1324{
1325 CMatchFinderMt *p = (CMatchFinderMt *)_p;
1320 SKIP_HEADER2_MT { p->btNumAvailBytes--; 1326 SKIP_HEADER2_MT { p->btNumAvailBytes--;
1321 SKIP_FOOTER_MT 1327 SKIP_FOOTER_MT
1322} 1328}
1323 1329
1324static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) 1330static void MatchFinderMt2_Skip(void *_p, UInt32 num)
1325{ 1331{
1332 CMatchFinderMt *p = (CMatchFinderMt *)_p;
1326 SKIP_HEADER_MT(2) 1333 SKIP_HEADER_MT(2)
1327 UInt32 h2; 1334 UInt32 h2;
1328 MT_HASH2_CALC 1335 MT_HASH2_CALC
@@ -1330,8 +1337,9 @@ static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
1330 SKIP_FOOTER_MT 1337 SKIP_FOOTER_MT
1331} 1338}
1332 1339
1333static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) 1340static void MatchFinderMt3_Skip(void *_p, UInt32 num)
1334{ 1341{
1342 CMatchFinderMt *p = (CMatchFinderMt *)_p;
1335 SKIP_HEADER_MT(3) 1343 SKIP_HEADER_MT(3)
1336 UInt32 h2, h3; 1344 UInt32 h2, h3;
1337 MT_HASH3_CALC 1345 MT_HASH3_CALC
@@ -1361,39 +1369,39 @@ static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
1361 1369
1362void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable) 1370void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable)
1363{ 1371{
1364 vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; 1372 vTable->Init = MatchFinderMt_Init;
1365 vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; 1373 vTable->GetNumAvailableBytes = MatchFinderMt_GetNumAvailableBytes;
1366 vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; 1374 vTable->GetPointerToCurrentPos = MatchFinderMt_GetPointerToCurrentPos;
1367 vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; 1375 vTable->GetMatches = MatchFinderMt_GetMatches;
1368 1376
1369 switch (MF(p)->numHashBytes) 1377 switch (MF(p)->numHashBytes)
1370 { 1378 {
1371 case 2: 1379 case 2:
1372 p->GetHeadsFunc = GetHeads2; 1380 p->GetHeadsFunc = GetHeads2;
1373 p->MixMatchesFunc = (Mf_Mix_Matches)NULL; 1381 p->MixMatchesFunc = NULL;
1374 vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; 1382 vTable->Skip = MatchFinderMt0_Skip;
1375 vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; 1383 vTable->GetMatches = MatchFinderMt2_GetMatches;
1376 break; 1384 break;
1377 case 3: 1385 case 3:
1378 p->GetHeadsFunc = MF(p)->bigHash ? GetHeads3b : GetHeads3; 1386 p->GetHeadsFunc = MF(p)->bigHash ? GetHeads3b : GetHeads3;
1379 p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; 1387 p->MixMatchesFunc = MixMatches2;
1380 vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; 1388 vTable->Skip = MatchFinderMt2_Skip;
1381 break; 1389 break;
1382 case 4: 1390 case 4:
1383 p->GetHeadsFunc = MF(p)->bigHash ? GetHeads4b : GetHeads4; 1391 p->GetHeadsFunc = MF(p)->bigHash ? GetHeads4b : GetHeads4;
1384 1392
1385 // it's fast inline version of GetMatches() 1393 // it's fast inline version of GetMatches()
1386 // vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches_Bt4; 1394 // vTable->GetMatches = MatchFinderMt_GetMatches_Bt4;
1387 1395
1388 p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; 1396 p->MixMatchesFunc = MixMatches3;
1389 vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; 1397 vTable->Skip = MatchFinderMt3_Skip;
1390 break; 1398 break;
1391 default: 1399 default:
1392 p->GetHeadsFunc = MF(p)->bigHash ? GetHeads5b : GetHeads5; 1400 p->GetHeadsFunc = MF(p)->bigHash ? GetHeads5b : GetHeads5;
1393 p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; 1401 p->MixMatchesFunc = MixMatches4;
1394 vTable->Skip = 1402 vTable->Skip =
1395 (Mf_Skip_Func)MatchFinderMt3_Skip; 1403 MatchFinderMt3_Skip;
1396 // (Mf_Skip_Func)MatchFinderMt4_Skip; 1404 // MatchFinderMt4_Skip;
1397 break; 1405 break;
1398 } 1406 }
1399} 1407}
diff --git a/C/LzFindMt.h b/C/LzFindMt.h
index db5923e..fcb479d 100644
--- a/C/LzFindMt.h
+++ b/C/LzFindMt.h
@@ -1,5 +1,5 @@
1/* LzFindMt.h -- multithreaded Match finder for LZ algorithms 1/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
22023-03-05 : Igor Pavlov : Public domain */ 22024-01-22 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_LZ_FIND_MT_H 4#ifndef ZIP7_INC_LZ_FIND_MT_H
5#define ZIP7_INC_LZ_FIND_MT_H 5#define ZIP7_INC_LZ_FIND_MT_H
@@ -31,7 +31,10 @@ typedef struct
31 // UInt32 numBlocks_Sent; 31 // UInt32 numBlocks_Sent;
32} CMtSync; 32} CMtSync;
33 33
34typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); 34
35struct CMatchFinderMt_;
36
37typedef UInt32 * (*Mf_Mix_Matches)(struct CMatchFinderMt_ *p, UInt32 matchMinPos, UInt32 *distances);
35 38
36/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ 39/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
37#define kMtCacheLineDummy 128 40#define kMtCacheLineDummy 128
@@ -39,7 +42,7 @@ typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distance
39typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, 42typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
40 UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); 43 UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);
41 44
42typedef struct 45typedef struct CMatchFinderMt_
43{ 46{
44 /* LZ */ 47 /* LZ */
45 const Byte *pointerToCurPos; 48 const Byte *pointerToCurPos;
diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c
index 388cbc7..8bf54e4 100644
--- a/C/Lzma2Dec.c
+++ b/C/Lzma2Dec.c
@@ -1,5 +1,5 @@
1/* Lzma2Dec.c -- LZMA2 Decoder 1/* Lzma2Dec.c -- LZMA2 Decoder
22023-03-03 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4/* #define SHOW_DEBUG_INFO */ 4/* #define SHOW_DEBUG_INFO */
5 5
@@ -157,8 +157,10 @@ static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
157 p->decoder.prop.lp = (Byte)lp; 157 p->decoder.prop.lp = (Byte)lp;
158 return LZMA2_STATE_DATA; 158 return LZMA2_STATE_DATA;
159 } 159 }
160
161 default:
162 return LZMA2_STATE_ERROR;
160 } 163 }
161 return LZMA2_STATE_ERROR;
162} 164}
163 165
164static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) 166static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c
index 6d13cac..37b2787 100644
--- a/C/LzmaEnc.c
+++ b/C/LzmaEnc.c
@@ -1,5 +1,5 @@
1/* LzmaEnc.c -- LZMA Encoder 1/* LzmaEnc.c -- LZMA Encoder
22023-04-13: Igor Pavlov : Public domain */ 22024-01-24: Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -195,11 +195,11 @@ unsigned GetPosSlot1(UInt32 pos);
195unsigned GetPosSlot1(UInt32 pos) 195unsigned GetPosSlot1(UInt32 pos)
196{ 196{
197 unsigned res; 197 unsigned res;
198 BSR2_RET(pos, res); 198 BSR2_RET(pos, res)
199 return res; 199 return res;
200} 200}
201#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } 201#define GetPosSlot2(pos, res) { BSR2_RET(pos, res) }
202#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } 202#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res) }
203 203
204 204
205#else // ! LZMA_LOG_BSR 205#else // ! LZMA_LOG_BSR
@@ -512,7 +512,7 @@ struct CLzmaEnc
512 COPY_ARR(d, s, posEncoders) \ 512 COPY_ARR(d, s, posEncoders) \
513 (d)->lenProbs = (s)->lenProbs; \ 513 (d)->lenProbs = (s)->lenProbs; \
514 (d)->repLenProbs = (s)->repLenProbs; \ 514 (d)->repLenProbs = (s)->repLenProbs; \
515 memcpy((d)->litProbs, (s)->litProbs, ((UInt32)0x300 << (p)->lclp) * sizeof(CLzmaProb)); 515 memcpy((d)->litProbs, (s)->litProbs, ((size_t)0x300 * sizeof(CLzmaProb)) << (p)->lclp);
516 516
517void LzmaEnc_SaveState(CLzmaEncHandle p) 517void LzmaEnc_SaveState(CLzmaEncHandle p)
518{ 518{
@@ -1040,14 +1040,14 @@ Z7_NO_INLINE static void Z7_FASTCALL LenPriceEnc_UpdateTables(
1040 UInt32 price = b; 1040 UInt32 price = b;
1041 do 1041 do
1042 { 1042 {
1043 unsigned bit = sym & 1; 1043 const unsigned bit = sym & 1;
1044 sym >>= 1; 1044 sym >>= 1;
1045 price += GET_PRICEa(probs[sym], bit); 1045 price += GET_PRICEa(probs[sym], bit);
1046 } 1046 }
1047 while (sym >= 2); 1047 while (sym >= 2);
1048 1048
1049 { 1049 {
1050 unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))]; 1050 const unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))];
1051 prices[(size_t)i * 2 ] = price + GET_PRICEa_0(prob); 1051 prices[(size_t)i * 2 ] = price + GET_PRICEa_0(prob);
1052 prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob); 1052 prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob);
1053 } 1053 }
@@ -1056,7 +1056,7 @@ Z7_NO_INLINE static void Z7_FASTCALL LenPriceEnc_UpdateTables(
1056 1056
1057 { 1057 {
1058 unsigned posState; 1058 unsigned posState;
1059 size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]); 1059 const size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]);
1060 for (posState = 1; posState < numPosStates; posState++) 1060 for (posState = 1; posState < numPosStates; posState++)
1061 memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num); 1061 memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num);
1062 } 1062 }
@@ -2696,12 +2696,12 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc,
2696 #endif 2696 #endif
2697 2697
2698 { 2698 {
2699 unsigned lclp = p->lc + p->lp; 2699 const unsigned lclp = p->lc + p->lp;
2700 if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp) 2700 if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
2701 { 2701 {
2702 LzmaEnc_FreeLits(p, alloc); 2702 LzmaEnc_FreeLits(p, alloc);
2703 p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); 2703 p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((size_t)0x300 * sizeof(CLzmaProb)) << lclp);
2704 p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); 2704 p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((size_t)0x300 * sizeof(CLzmaProb)) << lclp);
2705 if (!p->litProbs || !p->saveState.litProbs) 2705 if (!p->litProbs || !p->saveState.litProbs)
2706 { 2706 {
2707 LzmaEnc_FreeLits(p, alloc); 2707 LzmaEnc_FreeLits(p, alloc);
@@ -2802,8 +2802,8 @@ static void LzmaEnc_Init(CLzmaEnc *p)
2802 } 2802 }
2803 2803
2804 { 2804 {
2805 UInt32 num = (UInt32)0x300 << (p->lp + p->lc); 2805 const size_t num = (size_t)0x300 << (p->lp + p->lc);
2806 UInt32 k; 2806 size_t k;
2807 CLzmaProb *probs = p->litProbs; 2807 CLzmaProb *probs = p->litProbs;
2808 for (k = 0; k < num; k++) 2808 for (k = 0; k < num; k++)
2809 probs[k] = kProbInitValue; 2809 probs[k] = kProbInitValue;
diff --git a/C/MtCoder.c b/C/MtCoder.c
index 6f58abb..03959b6 100644
--- a/C/MtCoder.c
+++ b/C/MtCoder.c
@@ -1,5 +1,5 @@
1/* MtCoder.c -- Multi-thread Coder 1/* MtCoder.c -- Multi-thread Coder
22023-04-13 : Igor Pavlov : Public domain */ 22023-09-07 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -430,7 +430,7 @@ SRes MtCoder_Code(CMtCoder *p)
430 SRes res = SZ_OK; 430 SRes res = SZ_OK;
431 431
432 if (numThreads > MTCODER_THREADS_MAX) 432 if (numThreads > MTCODER_THREADS_MAX)
433 numThreads = MTCODER_THREADS_MAX; 433 numThreads = MTCODER_THREADS_MAX;
434 numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads); 434 numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads);
435 435
436 if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++; 436 if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++;
@@ -438,7 +438,7 @@ SRes MtCoder_Code(CMtCoder *p)
438 if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++; 438 if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++;
439 439
440 if (numBlocksMax > MTCODER_BLOCKS_MAX) 440 if (numBlocksMax > MTCODER_BLOCKS_MAX)
441 numBlocksMax = MTCODER_BLOCKS_MAX; 441 numBlocksMax = MTCODER_BLOCKS_MAX;
442 442
443 if (p->blockSize != p->allocatedBufsSize) 443 if (p->blockSize != p->allocatedBufsSize)
444 { 444 {
@@ -469,7 +469,7 @@ SRes MtCoder_Code(CMtCoder *p)
469 469
470 { 470 {
471 RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->readEvent)) 471 RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->readEvent))
472 RINOK_THREAD(Semaphore_OptCreateInit(&p->blocksSemaphore, numBlocksMax, numBlocksMax)) 472 RINOK_THREAD(Semaphore_OptCreateInit(&p->blocksSemaphore, (UInt32)numBlocksMax, (UInt32)numBlocksMax))
473 } 473 }
474 474
475 for (i = 0; i < MTCODER_BLOCKS_MAX - 1; i++) 475 for (i = 0; i < MTCODER_BLOCKS_MAX - 1; i++)
diff --git a/C/MtDec.c b/C/MtDec.c
index 7820699..96274b6 100644
--- a/C/MtDec.c
+++ b/C/MtDec.c
@@ -1,5 +1,5 @@
1/* MtDec.c -- Multi-thread Decoder 1/* MtDec.c -- Multi-thread Decoder
22023-04-02 : Igor Pavlov : Public domain */ 22024-02-20 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -809,6 +809,16 @@ static WRes MtDec_ThreadFunc2(CMtDecThread *t)
809#endif 809#endif
810 810
811 811
812typedef
813 #ifdef _WIN32
814 UINT_PTR
815 #elif 1
816 uintptr_t
817 #else
818 ptrdiff_t
819 #endif
820 MY_uintptr_t;
821
812static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp) 822static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp)
813{ 823{
814 WRes res; 824 WRes res;
@@ -821,7 +831,7 @@ static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp)
821 res = MtDec_ThreadFunc2(t); 831 res = MtDec_ThreadFunc2(t);
822 p = t->mtDec; 832 p = t->mtDec;
823 if (res == 0) 833 if (res == 0)
824 return (THREAD_FUNC_RET_TYPE)(UINT_PTR)p->exitThreadWRes; 834 return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)p->exitThreadWRes;
825 { 835 {
826 // it's unexpected situation for some threading function error 836 // it's unexpected situation for some threading function error
827 if (p->exitThreadWRes == 0) 837 if (p->exitThreadWRes == 0)
@@ -832,7 +842,7 @@ static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp)
832 Event_Set(&p->threads[0].canWrite); 842 Event_Set(&p->threads[0].canWrite);
833 MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res)); 843 MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res));
834 } 844 }
835 return (THREAD_FUNC_RET_TYPE)(UINT_PTR)res; 845 return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)res;
836} 846}
837 847
838static Z7_NO_INLINE THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp) 848static Z7_NO_INLINE THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp)
@@ -1072,7 +1082,7 @@ SRes MtDec_Code(CMtDec *p)
1072 if (wres == 0) { wres = Event_Set(&nextThread->canWrite); 1082 if (wres == 0) { wres = Event_Set(&nextThread->canWrite);
1073 if (wres == 0) { wres = Event_Set(&nextThread->canRead); 1083 if (wres == 0) { wres = Event_Set(&nextThread->canRead);
1074 if (wres == 0) { THREAD_FUNC_RET_TYPE res = MtDec_ThreadFunc(nextThread); 1084 if (wres == 0) { THREAD_FUNC_RET_TYPE res = MtDec_ThreadFunc(nextThread);
1075 wres = (WRes)(UINT_PTR)res; 1085 wres = (WRes)(MY_uintptr_t)res;
1076 if (wres != 0) 1086 if (wres != 0)
1077 { 1087 {
1078 p->needContinue = False; 1088 p->needContinue = False;
diff --git a/C/Ppmd7.c b/C/Ppmd7.c
index 6e1307e..efcc5d8 100644
--- a/C/Ppmd7.c
+++ b/C/Ppmd7.c
@@ -1,5 +1,5 @@
1/* Ppmd7.c -- PPMdH codec 1/* Ppmd7.c -- PPMdH codec
22023-04-02 : Igor Pavlov : Public domain 22023-09-07 : Igor Pavlov : Public domain
3This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ 3This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
4 4
5#include "Precomp.h" 5#include "Precomp.h"
@@ -302,8 +302,17 @@ static void *Ppmd7_AllocUnits(CPpmd7 *p, unsigned indx)
302 302
303 303
304#define MEM_12_CPY(dest, src, num) \ 304#define MEM_12_CPY(dest, src, num) \
305 { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \ 305 { UInt32 *d = (UInt32 *)(dest); \
306 do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); } 306 const UInt32 *z = (const UInt32 *)(src); \
307 unsigned n = (num); \
308 do { \
309 d[0] = z[0]; \
310 d[1] = z[1]; \
311 d[2] = z[2]; \
312 z += 3; \
313 d += 3; \
314 } while (--n); \
315 }
307 316
308 317
309/* 318/*
@@ -711,8 +720,8 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
711 if ((ns1 & 1) == 0) 720 if ((ns1 & 1) == 0)
712 { 721 {
713 /* Expand for one UNIT */ 722 /* Expand for one UNIT */
714 unsigned oldNU = ns1 >> 1; 723 const unsigned oldNU = ns1 >> 1;
715 unsigned i = U2I(oldNU); 724 const unsigned i = U2I(oldNU);
716 if (i != U2I((size_t)oldNU + 1)) 725 if (i != U2I((size_t)oldNU + 1))
717 { 726 {
718 void *ptr = Ppmd7_AllocUnits(p, i + 1); 727 void *ptr = Ppmd7_AllocUnits(p, i + 1);
@@ -731,7 +740,7 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
731 sum = c->Union2.SummFreq; 740 sum = c->Union2.SummFreq;
732 /* max increase of Escape_Freq is 3 here. 741 /* max increase of Escape_Freq is 3 here.
733 total increase of Union2.SummFreq for all symbols is less than 256 here */ 742 total increase of Union2.SummFreq for all symbols is less than 256 here */
734 sum += (UInt32)(2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1)); 743 sum += (UInt32)(unsigned)((2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1)));
735 /* original PPMdH uses 16-bit variable for (sum) here. 744 /* original PPMdH uses 16-bit variable for (sum) here.
736 But (sum < 0x9000). So we don't truncate (sum) to 16-bit */ 745 But (sum < 0x9000). So we don't truncate (sum) to 16-bit */
737 // sum = (UInt16)sum; 746 // sum = (UInt16)sum;
@@ -761,7 +770,7 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
761 // (max(s->freq) == 120), when we convert from 1-symbol into 2-symbol context 770 // (max(s->freq) == 120), when we convert from 1-symbol into 2-symbol context
762 s->Freq = (Byte)freq; 771 s->Freq = (Byte)freq;
763 // max(InitEsc = PPMD7_kExpEscape[*]) is 25. So the max(escapeFreq) is 26 here 772 // max(InitEsc = PPMD7_kExpEscape[*]) is 25. So the max(escapeFreq) is 26 here
764 sum = freq + p->InitEsc + (ns > 3); 773 sum = (UInt32)(freq + p->InitEsc + (ns > 3));
765 } 774 }
766 } 775 }
767 776
@@ -933,10 +942,10 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
933 p->HiBitsFlag; 942 p->HiBitsFlag;
934 { 943 {
935 // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ 944 // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ
936 unsigned summ = (UInt16)see->Summ; // & 0xFFFF 945 const unsigned summ = (UInt16)see->Summ; // & 0xFFFF
937 unsigned r = (summ >> see->Shift); 946 const unsigned r = (summ >> see->Shift);
938 see->Summ = (UInt16)(summ - r); 947 see->Summ = (UInt16)(summ - r);
939 *escFreq = r + (r == 0); 948 *escFreq = (UInt32)(r + (r == 0));
940 } 949 }
941 } 950 }
942 else 951 else
@@ -981,9 +990,9 @@ void Ppmd7_Update1_0(CPpmd7 *p)
981 CPpmd_State *s = p->FoundState; 990 CPpmd_State *s = p->FoundState;
982 CPpmd7_Context *mc = p->MinContext; 991 CPpmd7_Context *mc = p->MinContext;
983 unsigned freq = s->Freq; 992 unsigned freq = s->Freq;
984 unsigned summFreq = mc->Union2.SummFreq; 993 const unsigned summFreq = mc->Union2.SummFreq;
985 p->PrevSuccess = (2 * freq > summFreq); 994 p->PrevSuccess = (2 * freq > summFreq);
986 p->RunLength += (int)p->PrevSuccess; 995 p->RunLength += (Int32)p->PrevSuccess;
987 mc->Union2.SummFreq = (UInt16)(summFreq + 4); 996 mc->Union2.SummFreq = (UInt16)(summFreq + 4);
988 freq += 4; 997 freq += 4;
989 s->Freq = (Byte)freq; 998 s->Freq = (Byte)freq;
diff --git a/C/Ppmd7Dec.c b/C/Ppmd7Dec.c
index 8323828..081ab89 100644
--- a/C/Ppmd7Dec.c
+++ b/C/Ppmd7Dec.c
@@ -1,5 +1,5 @@
1/* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder 1/* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder
22023-04-02 : Igor Pavlov : Public domain 22023-09-07 : Igor Pavlov : Public domain
3This code is based on: 3This code is based on:
4 PPMd var.H (2001): Dmitry Shkarin : Public domain */ 4 PPMd var.H (2001): Dmitry Shkarin : Public domain */
5 5
@@ -58,7 +58,7 @@ static void Ppmd7z_RD_Decode(CPpmd7 *p, UInt32 start, UInt32 size)
58#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) 58#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
59void Ppmd7_UpdateModel(CPpmd7 *p); 59void Ppmd7_UpdateModel(CPpmd7 *p);
60 60
61#define MASK(sym) ((unsigned char *)charMask)[sym] 61#define MASK(sym) ((Byte *)charMask)[sym]
62// Z7_FORCE_INLINE 62// Z7_FORCE_INLINE
63// static 63// static
64int Ppmd7z_DecodeSymbol(CPpmd7 *p) 64int Ppmd7z_DecodeSymbol(CPpmd7 *p)
@@ -120,8 +120,8 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p)
120 MASK(s->Symbol) = 0; 120 MASK(s->Symbol) = 0;
121 do 121 do
122 { 122 {
123 unsigned sym0 = s2[0].Symbol; 123 const unsigned sym0 = s2[0].Symbol;
124 unsigned sym1 = s2[1].Symbol; 124 const unsigned sym1 = s2[1].Symbol;
125 s2 += 2; 125 s2 += 2;
126 MASK(sym0) = 0; 126 MASK(sym0) = 0;
127 MASK(sym1) = 0; 127 MASK(sym1) = 0;
@@ -209,17 +209,17 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p)
209 unsigned num2 = num / 2; 209 unsigned num2 = num / 2;
210 210
211 num &= 1; 211 num &= 1;
212 hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num); 212 hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);
213 s += num; 213 s += num;
214 p->MinContext = mc; 214 p->MinContext = mc;
215 215
216 do 216 do
217 { 217 {
218 unsigned sym0 = s[0].Symbol; 218 const unsigned sym0 = s[0].Symbol;
219 unsigned sym1 = s[1].Symbol; 219 const unsigned sym1 = s[1].Symbol;
220 s += 2; 220 s += 2;
221 hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0))); 221 hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));
222 hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1))); 222 hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));
223 } 223 }
224 while (--num2); 224 while (--num2);
225 } 225 }
@@ -238,13 +238,13 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p)
238 238
239 s = Ppmd7_GetStats(p, p->MinContext); 239 s = Ppmd7_GetStats(p, p->MinContext);
240 hiCnt = count; 240 hiCnt = count;
241 // count -= s->Freq & (unsigned)(MASK(s->Symbol)); 241 // count -= s->Freq & (UInt32)(MASK(s->Symbol));
242 // if ((Int32)count >= 0) 242 // if ((Int32)count >= 0)
243 { 243 {
244 for (;;) 244 for (;;)
245 { 245 {
246 count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; 246 count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
247 // count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; 247 // count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
248 } 248 }
249 } 249 }
250 s--; 250 s--;
diff --git a/C/Ppmd7Enc.c b/C/Ppmd7Enc.c
index 41106ba..49cbbe6 100644
--- a/C/Ppmd7Enc.c
+++ b/C/Ppmd7Enc.c
@@ -1,5 +1,5 @@
1/* Ppmd7Enc.c -- Ppmd7z (PPMdH with 7z Range Coder) Encoder 1/* Ppmd7Enc.c -- Ppmd7z (PPMdH with 7z Range Coder) Encoder
22023-04-02 : Igor Pavlov : Public domain 22023-09-07 : Igor Pavlov : Public domain
3This code is based on: 3This code is based on:
4 PPMd var.H (2001): Dmitry Shkarin : Public domain */ 4 PPMd var.H (2001): Dmitry Shkarin : Public domain */
5 5
@@ -82,7 +82,7 @@ void Ppmd7z_Flush_RangeEnc(CPpmd7 *p)
82 82
83void Ppmd7_UpdateModel(CPpmd7 *p); 83void Ppmd7_UpdateModel(CPpmd7 *p);
84 84
85#define MASK(sym) ((unsigned char *)charMask)[sym] 85#define MASK(sym) ((Byte *)charMask)[sym]
86 86
87Z7_FORCE_INLINE 87Z7_FORCE_INLINE
88static 88static
@@ -139,8 +139,8 @@ void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol)
139 MASK(s->Symbol) = 0; 139 MASK(s->Symbol) = 0;
140 do 140 do
141 { 141 {
142 unsigned sym0 = s2[0].Symbol; 142 const unsigned sym0 = s2[0].Symbol;
143 unsigned sym1 = s2[1].Symbol; 143 const unsigned sym1 = s2[1].Symbol;
144 s2 += 2; 144 s2 += 2;
145 MASK(sym0) = 0; 145 MASK(sym0) = 0;
146 MASK(sym1) = 0; 146 MASK(sym1) = 0;
@@ -265,16 +265,15 @@ void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol)
265 if (num2 != 0) 265 if (num2 != 0)
266 { 266 {
267 s += i; 267 s += i;
268 for (;;) 268 do
269 { 269 {
270 unsigned sym0 = s[0].Symbol; 270 const unsigned sym0 = s[0].Symbol;
271 unsigned sym1 = s[1].Symbol; 271 const unsigned sym1 = s[1].Symbol;
272 s += 2; 272 s += 2;
273 sum += (s[-2].Freq & (unsigned)(MASK(sym0))); 273 sum += (s[-2].Freq & (unsigned)(MASK(sym0)));
274 sum += (s[-1].Freq & (unsigned)(MASK(sym1))); 274 sum += (s[-1].Freq & (unsigned)(MASK(sym1)));
275 if (--num2 == 0)
276 break;
277 } 275 }
276 while (--num2);
278 } 277 }
279 278
280 279
diff --git a/C/Ppmd7aDec.c b/C/Ppmd7aDec.c
index 55e164e..ef86dde 100644
--- a/C/Ppmd7aDec.c
+++ b/C/Ppmd7aDec.c
@@ -1,5 +1,5 @@
1/* Ppmd7aDec.c -- PPMd7a (PPMdH) Decoder 1/* Ppmd7aDec.c -- PPMd7a (PPMdH) Decoder
22023-04-02 : Igor Pavlov : Public domain 22023-09-07 : Igor Pavlov : Public domain
3This code is based on: 3This code is based on:
4 PPMd var.H (2001): Dmitry Shkarin : Public domain 4 PPMd var.H (2001): Dmitry Shkarin : Public domain
5 Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ 5 Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
@@ -58,7 +58,7 @@ typedef CPpmd7_Context * CTX_PTR;
58#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) 58#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
59void Ppmd7_UpdateModel(CPpmd7 *p); 59void Ppmd7_UpdateModel(CPpmd7 *p);
60 60
61#define MASK(sym) ((unsigned char *)charMask)[sym] 61#define MASK(sym) ((Byte *)charMask)[sym]
62 62
63 63
64int Ppmd7a_DecodeSymbol(CPpmd7 *p) 64int Ppmd7a_DecodeSymbol(CPpmd7 *p)
@@ -120,8 +120,8 @@ int Ppmd7a_DecodeSymbol(CPpmd7 *p)
120 MASK(s->Symbol) = 0; 120 MASK(s->Symbol) = 0;
121 do 121 do
122 { 122 {
123 unsigned sym0 = s2[0].Symbol; 123 const unsigned sym0 = s2[0].Symbol;
124 unsigned sym1 = s2[1].Symbol; 124 const unsigned sym1 = s2[1].Symbol;
125 s2 += 2; 125 s2 += 2;
126 MASK(sym0) = 0; 126 MASK(sym0) = 0;
127 MASK(sym1) = 0; 127 MASK(sym1) = 0;
@@ -209,17 +209,17 @@ int Ppmd7a_DecodeSymbol(CPpmd7 *p)
209 unsigned num2 = num / 2; 209 unsigned num2 = num / 2;
210 210
211 num &= 1; 211 num &= 1;
212 hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num); 212 hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);
213 s += num; 213 s += num;
214 p->MinContext = mc; 214 p->MinContext = mc;
215 215
216 do 216 do
217 { 217 {
218 unsigned sym0 = s[0].Symbol; 218 const unsigned sym0 = s[0].Symbol;
219 unsigned sym1 = s[1].Symbol; 219 const unsigned sym1 = s[1].Symbol;
220 s += 2; 220 s += 2;
221 hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0))); 221 hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));
222 hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1))); 222 hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));
223 } 223 }
224 while (--num2); 224 while (--num2);
225 } 225 }
@@ -238,13 +238,13 @@ int Ppmd7a_DecodeSymbol(CPpmd7 *p)
238 238
239 s = Ppmd7_GetStats(p, p->MinContext); 239 s = Ppmd7_GetStats(p, p->MinContext);
240 hiCnt = count; 240 hiCnt = count;
241 // count -= s->Freq & (unsigned)(MASK(s->Symbol)); 241 // count -= s->Freq & (UInt32)(MASK(s->Symbol));
242 // if ((Int32)count >= 0) 242 // if ((Int32)count >= 0)
243 { 243 {
244 for (;;) 244 for (;;)
245 { 245 {
246 count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; 246 count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
247 // count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; 247 // count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
248 } 248 }
249 } 249 }
250 s--; 250 s--;
diff --git a/C/Ppmd8.c b/C/Ppmd8.c
index 28abf27..c6bdd86 100644
--- a/C/Ppmd8.c
+++ b/C/Ppmd8.c
@@ -1,5 +1,5 @@
1/* Ppmd8.c -- PPMdI codec 1/* Ppmd8.c -- PPMdI codec
22023-04-02 : Igor Pavlov : Public domain 22023-09-07 : Igor Pavlov : Public domain
3This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */ 3This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
4 4
5#include "Precomp.h" 5#include "Precomp.h"
@@ -302,8 +302,17 @@ static void *Ppmd8_AllocUnits(CPpmd8 *p, unsigned indx)
302 302
303 303
304#define MEM_12_CPY(dest, src, num) \ 304#define MEM_12_CPY(dest, src, num) \
305 { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \ 305 { UInt32 *d = (UInt32 *)(dest); \
306 do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); } 306 const UInt32 *z = (const UInt32 *)(src); \
307 unsigned n = (num); \
308 do { \
309 d[0] = z[0]; \
310 d[1] = z[1]; \
311 d[2] = z[2]; \
312 z += 3; \
313 d += 3; \
314 } while (--n); \
315 }
307 316
308 317
309 318
@@ -1215,8 +1224,8 @@ void Ppmd8_UpdateModel(CPpmd8 *p)
1215 if ((ns1 & 1) != 0) 1224 if ((ns1 & 1) != 0)
1216 { 1225 {
1217 /* Expand for one UNIT */ 1226 /* Expand for one UNIT */
1218 unsigned oldNU = (ns1 + 1) >> 1; 1227 const unsigned oldNU = (ns1 + 1) >> 1;
1219 unsigned i = U2I(oldNU); 1228 const unsigned i = U2I(oldNU);
1220 if (i != U2I((size_t)oldNU + 1)) 1229 if (i != U2I((size_t)oldNU + 1))
1221 { 1230 {
1222 void *ptr = Ppmd8_AllocUnits(p, i + 1); 1231 void *ptr = Ppmd8_AllocUnits(p, i + 1);
@@ -1235,7 +1244,7 @@ void Ppmd8_UpdateModel(CPpmd8 *p)
1235 sum = c->Union2.SummFreq; 1244 sum = c->Union2.SummFreq;
1236 /* max increase of Escape_Freq is 1 here. 1245 /* max increase of Escape_Freq is 1 here.
1237 an average increase is 1/3 per symbol */ 1246 an average increase is 1/3 per symbol */
1238 sum += (3 * ns1 + 1 < ns); 1247 sum += (UInt32)(unsigned)(3 * ns1 + 1 < ns);
1239 /* original PPMdH uses 16-bit variable for (sum) here. 1248 /* original PPMdH uses 16-bit variable for (sum) here.
1240 But (sum < ???). Do we need to truncate (sum) to 16-bit */ 1249 But (sum < ???). Do we need to truncate (sum) to 16-bit */
1241 // sum = (UInt16)sum; 1250 // sum = (UInt16)sum;
@@ -1265,7 +1274,7 @@ void Ppmd8_UpdateModel(CPpmd8 *p)
1265 1274
1266 s->Freq = (Byte)freq; 1275 s->Freq = (Byte)freq;
1267 1276
1268 sum = freq + p->InitEsc + (ns > 2); // Ppmd8 (> 2) 1277 sum = (UInt32)(freq + p->InitEsc + (ns > 2)); // Ppmd8 (> 2)
1269 } 1278 }
1270 } 1279 }
1271 1280
@@ -1437,10 +1446,10 @@ CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq)
1437 1446
1438 { 1447 {
1439 // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ 1448 // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ
1440 unsigned summ = (UInt16)see->Summ; // & 0xFFFF 1449 const unsigned summ = (UInt16)see->Summ; // & 0xFFFF
1441 unsigned r = (summ >> see->Shift); 1450 const unsigned r = (summ >> see->Shift);
1442 see->Summ = (UInt16)(summ - r); 1451 see->Summ = (UInt16)(summ - r);
1443 *escFreq = r + (r == 0); 1452 *escFreq = (UInt32)(r + (r == 0));
1444 } 1453 }
1445 } 1454 }
1446 else 1455 else
@@ -1485,9 +1494,9 @@ void Ppmd8_Update1_0(CPpmd8 *p)
1485 CPpmd_State *s = p->FoundState; 1494 CPpmd_State *s = p->FoundState;
1486 CPpmd8_Context *mc = p->MinContext; 1495 CPpmd8_Context *mc = p->MinContext;
1487 unsigned freq = s->Freq; 1496 unsigned freq = s->Freq;
1488 unsigned summFreq = mc->Union2.SummFreq; 1497 const unsigned summFreq = mc->Union2.SummFreq;
1489 p->PrevSuccess = (2 * freq >= summFreq); // Ppmd8 (>=) 1498 p->PrevSuccess = (2 * freq >= summFreq); // Ppmd8 (>=)
1490 p->RunLength += (int)p->PrevSuccess; 1499 p->RunLength += (Int32)p->PrevSuccess;
1491 mc->Union2.SummFreq = (UInt16)(summFreq + 4); 1500 mc->Union2.SummFreq = (UInt16)(summFreq + 4);
1492 freq += 4; 1501 freq += 4;
1493 s->Freq = (Byte)freq; 1502 s->Freq = (Byte)freq;
diff --git a/C/Ppmd8Dec.c b/C/Ppmd8Dec.c
index 72d3626..ff91167 100644
--- a/C/Ppmd8Dec.c
+++ b/C/Ppmd8Dec.c
@@ -1,5 +1,5 @@
1/* Ppmd8Dec.c -- Ppmd8 (PPMdI) Decoder 1/* Ppmd8Dec.c -- Ppmd8 (PPMdI) Decoder
22023-04-02 : Igor Pavlov : Public domain 22023-09-07 : Igor Pavlov : Public domain
3This code is based on: 3This code is based on:
4 PPMd var.I (2002): Dmitry Shkarin : Public domain 4 PPMd var.I (2002): Dmitry Shkarin : Public domain
5 Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ 5 Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
@@ -58,7 +58,7 @@ static void Ppmd8_RD_Decode(CPpmd8 *p, UInt32 start, UInt32 size)
58#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) 58#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
59void Ppmd8_UpdateModel(CPpmd8 *p); 59void Ppmd8_UpdateModel(CPpmd8 *p);
60 60
61#define MASK(sym) ((unsigned char *)charMask)[sym] 61#define MASK(sym) ((Byte *)charMask)[sym]
62 62
63 63
64int Ppmd8_DecodeSymbol(CPpmd8 *p) 64int Ppmd8_DecodeSymbol(CPpmd8 *p)
@@ -120,8 +120,8 @@ int Ppmd8_DecodeSymbol(CPpmd8 *p)
120 MASK(s->Symbol) = 0; 120 MASK(s->Symbol) = 0;
121 do 121 do
122 { 122 {
123 unsigned sym0 = s2[0].Symbol; 123 const unsigned sym0 = s2[0].Symbol;
124 unsigned sym1 = s2[1].Symbol; 124 const unsigned sym1 = s2[1].Symbol;
125 s2 += 2; 125 s2 += 2;
126 MASK(sym0) = 0; 126 MASK(sym0) = 0;
127 MASK(sym1) = 0; 127 MASK(sym1) = 0;
@@ -209,17 +209,17 @@ int Ppmd8_DecodeSymbol(CPpmd8 *p)
209 unsigned num2 = num / 2; 209 unsigned num2 = num / 2;
210 210
211 num &= 1; 211 num &= 1;
212 hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num); 212 hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);
213 s += num; 213 s += num;
214 p->MinContext = mc; 214 p->MinContext = mc;
215 215
216 do 216 do
217 { 217 {
218 unsigned sym0 = s[0].Symbol; 218 const unsigned sym0 = s[0].Symbol;
219 unsigned sym1 = s[1].Symbol; 219 const unsigned sym1 = s[1].Symbol;
220 s += 2; 220 s += 2;
221 hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0))); 221 hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));
222 hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1))); 222 hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));
223 } 223 }
224 while (--num2); 224 while (--num2);
225 } 225 }
@@ -243,8 +243,8 @@ int Ppmd8_DecodeSymbol(CPpmd8 *p)
243 { 243 {
244 for (;;) 244 for (;;)
245 { 245 {
246 count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; 246 count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
247 // count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; 247 // count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
248 } 248 }
249 } 249 }
250 s--; 250 s--;
diff --git a/C/Ppmd8Enc.c b/C/Ppmd8Enc.c
index 9e29ef7..b0e34c4 100644
--- a/C/Ppmd8Enc.c
+++ b/C/Ppmd8Enc.c
@@ -1,5 +1,5 @@
1/* Ppmd8Enc.c -- Ppmd8 (PPMdI) Encoder 1/* Ppmd8Enc.c -- Ppmd8 (PPMdI) Encoder
22023-04-02 : Igor Pavlov : Public domain 22023-09-07 : Igor Pavlov : Public domain
3This code is based on: 3This code is based on:
4 PPMd var.I (2002): Dmitry Shkarin : Public domain 4 PPMd var.I (2002): Dmitry Shkarin : Public domain
5 Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ 5 Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
@@ -82,7 +82,7 @@ static void Ppmd8_RangeEnc_Encode(CPpmd8 *p, UInt32 start, UInt32 size, UInt32 t
82 82
83void Ppmd8_UpdateModel(CPpmd8 *p); 83void Ppmd8_UpdateModel(CPpmd8 *p);
84 84
85#define MASK(sym) ((unsigned char *)charMask)[sym] 85#define MASK(sym) ((Byte *)charMask)[sym]
86 86
87// Z7_FORCE_INLINE 87// Z7_FORCE_INLINE
88// static 88// static
@@ -139,8 +139,8 @@ void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol)
139 MASK(s->Symbol) = 0; 139 MASK(s->Symbol) = 0;
140 do 140 do
141 { 141 {
142 unsigned sym0 = s2[0].Symbol; 142 const unsigned sym0 = s2[0].Symbol;
143 unsigned sym1 = s2[1].Symbol; 143 const unsigned sym1 = s2[1].Symbol;
144 s2 += 2; 144 s2 += 2;
145 MASK(sym0) = 0; 145 MASK(sym0) = 0;
146 MASK(sym1) = 0; 146 MASK(sym1) = 0;
@@ -265,16 +265,15 @@ void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol)
265 if (num2 != 0) 265 if (num2 != 0)
266 { 266 {
267 s += i; 267 s += i;
268 for (;;) 268 do
269 { 269 {
270 unsigned sym0 = s[0].Symbol; 270 const unsigned sym0 = s[0].Symbol;
271 unsigned sym1 = s[1].Symbol; 271 const unsigned sym1 = s[1].Symbol;
272 s += 2; 272 s += 2;
273 sum += (s[-2].Freq & (unsigned)(MASK(sym0))); 273 sum += (s[-2].Freq & (unsigned)(MASK(sym0)));
274 sum += (s[-1].Freq & (unsigned)(MASK(sym1))); 274 sum += (s[-1].Freq & (unsigned)(MASK(sym1)));
275 if (--num2 == 0)
276 break;
277 } 275 }
276 while (--num2);
278 } 277 }
279 278
280 PPMD8_CORRECT_SUM_RANGE(p, sum) 279 PPMD8_CORRECT_SUM_RANGE(p, sum)
diff --git a/C/Precomp.h b/C/Precomp.h
index 69afb2f..7747fdd 100644
--- a/C/Precomp.h
+++ b/C/Precomp.h
@@ -1,10 +1,127 @@
1/* Precomp.h -- StdAfx 1/* Precomp.h -- precompilation file
22023-04-02 : Igor Pavlov : Public domain */ 22024-01-25 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_PRECOMP_H 4#ifndef ZIP7_INC_PRECOMP_H
5#define ZIP7_INC_PRECOMP_H 5#define ZIP7_INC_PRECOMP_H
6 6
7/*
8 this file must be included before another *.h files and before <windows.h>.
9 this file is included from the following files:
10 C\*.c
11 C\Util\*\Precomp.h <- C\Util\*\*.c
12 CPP\Common\Common.h <- *\StdAfx.h <- *\*.cpp
13
14 this file can set the following macros:
15 Z7_LARGE_PAGES 1
16 Z7_LONG_PATH 1
17 Z7_WIN32_WINNT_MIN 0x0500 (or higher) : we require at least win2000+ for 7-Zip
18 _WIN32_WINNT 0x0500 (or higher)
19 WINVER _WIN32_WINNT
20 UNICODE 1
21 _UNICODE 1
22*/
23
7#include "Compiler.h" 24#include "Compiler.h"
8/* #include "7zTypes.h" */ 25
26#ifdef _MSC_VER
27// #pragma warning(disable : 4206) // nonstandard extension used : translation unit is empty
28#if _MSC_VER >= 1912
29// #pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to 'extern "C"' function under - EHc.Undefined behavior may occur if this function throws an exception.
30#endif
31#endif
32
33/*
34// for debug:
35#define UNICODE 1
36#define _UNICODE 1
37#define _WIN32_WINNT 0x0500 // win2000
38#ifndef WINVER
39 #define WINVER _WIN32_WINNT
40#endif
41*/
42
43#ifdef _WIN32
44/*
45 this "Precomp.h" file must be included before <windows.h>,
46 if we want to define _WIN32_WINNT before <windows.h>.
47*/
48
49#ifndef Z7_LARGE_PAGES
50#ifndef Z7_NO_LARGE_PAGES
51#define Z7_LARGE_PAGES 1
52#endif
53#endif
54
55#ifndef Z7_LONG_PATH
56#ifndef Z7_NO_LONG_PATH
57#define Z7_LONG_PATH 1
58#endif
59#endif
60
61#ifndef Z7_DEVICE_FILE
62#ifndef Z7_NO_DEVICE_FILE
63// #define Z7_DEVICE_FILE 1
64#endif
65#endif
66
67// we don't change macros if included after <windows.h>
68#ifndef _WINDOWS_
69
70#ifndef Z7_WIN32_WINNT_MIN
71 #if defined(_M_ARM64) || defined(__aarch64__)
72 // #define Z7_WIN32_WINNT_MIN 0x0a00 // win10
73 #define Z7_WIN32_WINNT_MIN 0x0600 // vista
74 #elif defined(_M_ARM) && defined(_M_ARMT) && defined(_M_ARM_NT)
75 // #define Z7_WIN32_WINNT_MIN 0x0602 // win8
76 #define Z7_WIN32_WINNT_MIN 0x0600 // vista
77 #elif defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) || defined(_M_IA64)
78 #define Z7_WIN32_WINNT_MIN 0x0503 // win2003
79 // #elif defined(_M_IX86) || defined(__i386__)
80 // #define Z7_WIN32_WINNT_MIN 0x0500 // win2000
81 #else // x86 and another(old) systems
82 #define Z7_WIN32_WINNT_MIN 0x0500 // win2000
83 // #define Z7_WIN32_WINNT_MIN 0x0502 // win2003 // for debug
84 #endif
85#endif // Z7_WIN32_WINNT_MIN
86
87
88#ifndef Z7_DO_NOT_DEFINE_WIN32_WINNT
89#ifdef _WIN32_WINNT
90 // #error Stop_Compiling_Bad_WIN32_WINNT
91#else
92 #ifndef Z7_NO_DEFINE_WIN32_WINNT
93Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
94 #define _WIN32_WINNT Z7_WIN32_WINNT_MIN
95Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
96 #endif
97#endif // _WIN32_WINNT
98
99#ifndef WINVER
100 #define WINVER _WIN32_WINNT
101#endif
102#endif // Z7_DO_NOT_DEFINE_WIN32_WINNT
103
104
105#ifndef _MBCS
106#ifndef Z7_NO_UNICODE
107// UNICODE and _UNICODE are used by <windows.h> and by 7-zip code.
108
109#ifndef UNICODE
110#define UNICODE 1
111#endif
112
113#ifndef _UNICODE
114Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
115#define _UNICODE 1
116Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
117#endif
118
119#endif // Z7_NO_UNICODE
120#endif // _MBCS
121#endif // _WINDOWS_
122
123// #include "7zWindows.h"
124
125#endif // _WIN32
9 126
10#endif 127#endif
diff --git a/C/Sha1.c b/C/Sha1.c
index fd6c018..4c92892 100644
--- a/C/Sha1.c
+++ b/C/Sha1.c
@@ -1,5 +1,5 @@
1/* Sha1.c -- SHA-1 Hash 1/* Sha1.c -- SHA-1 Hash
22023-04-02 : Igor Pavlov : Public domain 22024-03-01 : Igor Pavlov : Public domain
3This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */ 3This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */
4 4
5#include "Precomp.h" 5#include "Precomp.h"
@@ -15,35 +15,35 @@ This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ l
15#endif 15#endif
16 16
17#ifdef MY_CPU_X86_OR_AMD64 17#ifdef MY_CPU_X86_OR_AMD64
18 #ifdef _MSC_VER 18 #if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \
19 #if _MSC_VER >= 1200 19 || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \
20 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
21 || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) \
22 || defined(_MSC_VER) && (_MSC_VER >= 1200)
20 #define Z7_COMPILER_SHA1_SUPPORTED 23 #define Z7_COMPILER_SHA1_SUPPORTED
21 #endif
22 #elif defined(__clang__)
23 #if (__clang_major__ >= 8) // fix that check
24 #define Z7_COMPILER_SHA1_SUPPORTED
25 #endif
26 #elif defined(__GNUC__)
27 #if (__GNUC__ >= 8) // fix that check
28 #define Z7_COMPILER_SHA1_SUPPORTED
29 #endif
30 #elif defined(__INTEL_COMPILER)
31 #if (__INTEL_COMPILER >= 1800) // fix that check
32 #define Z7_COMPILER_SHA1_SUPPORTED
33 #endif
34 #endif 24 #endif
35#elif defined(MY_CPU_ARM_OR_ARM64) 25#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) \
36 #ifdef _MSC_VER 26 && (!defined(Z7_MSC_VER_ORIGINAL) || (_MSC_VER >= 1929) && (_MSC_FULL_VER >= 192930037))
37 #if _MSC_VER >= 1910 && _MSC_VER >= 1929 && _MSC_FULL_VER >= 192930037 27 #if defined(__ARM_FEATURE_SHA2) \
28 || defined(__ARM_FEATURE_CRYPTO)
29 #define Z7_COMPILER_SHA1_SUPPORTED
30 #else
31 #if defined(MY_CPU_ARM64) \
32 || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
33 || defined(Z7_MSC_VER_ORIGINAL)
34 #if defined(__ARM_FP) && \
35 ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
36 || defined(__GNUC__) && (__GNUC__ >= 6) \
37 ) \
38 || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
39 #if defined(MY_CPU_ARM64) \
40 || !defined(Z7_CLANG_VERSION) \
41 || defined(__ARM_NEON) && \
42 (Z7_CLANG_VERSION < 170000 || \
43 Z7_CLANG_VERSION > 170001)
38 #define Z7_COMPILER_SHA1_SUPPORTED 44 #define Z7_COMPILER_SHA1_SUPPORTED
39 #endif 45 #endif
40 #elif defined(__clang__)
41 #if (__clang_major__ >= 8) // fix that check
42 #define Z7_COMPILER_SHA1_SUPPORTED
43 #endif 46 #endif
44 #elif defined(__GNUC__)
45 #if (__GNUC__ >= 6) // fix that check
46 #define Z7_COMPILER_SHA1_SUPPORTED
47 #endif 47 #endif
48 #endif 48 #endif
49#endif 49#endif
@@ -436,7 +436,7 @@ void Sha1Prepare(void)
436 #endif 436 #endif
437 { 437 {
438 // printf("\n========== HW SHA1 ======== \n"); 438 // printf("\n========== HW SHA1 ======== \n");
439 #if defined(MY_CPU_ARM_OR_ARM64) && defined(_MSC_VER) 439 #if 0 && defined(MY_CPU_ARM_OR_ARM64) && defined(_MSC_VER)
440 /* there was bug in MSVC compiler for ARM64 -O2 before version VS2019 16.10 (19.29.30037). 440 /* there was bug in MSVC compiler for ARM64 -O2 before version VS2019 16.10 (19.29.30037).
441 It generated incorrect SHA-1 code. 441 It generated incorrect SHA-1 code.
442 21.03 : we test sha1-hardware code at runtime initialization */ 442 21.03 : we test sha1-hardware code at runtime initialization */
diff --git a/C/Sha1Opt.c b/C/Sha1Opt.c
index 27796aa..4e835f1 100644
--- a/C/Sha1Opt.c
+++ b/C/Sha1Opt.c
@@ -1,5 +1,5 @@
1/* Sha1Opt.c -- SHA-1 optimized code for SHA-1 hardware instructions 1/* Sha1Opt.c -- SHA-1 optimized code for SHA-1 hardware instructions
22023-04-02 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5#include "Compiler.h" 5#include "Compiler.h"
@@ -11,6 +11,8 @@
11#endif 11#endif
12#endif 12#endif
13 13
14// #define Z7_USE_HW_SHA_STUB // for debug
15
14#ifdef MY_CPU_X86_OR_AMD64 16#ifdef MY_CPU_X86_OR_AMD64
15 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check 17 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check
16 #define USE_HW_SHA 18 #define USE_HW_SHA
@@ -32,9 +34,14 @@
32 #endif 34 #endif
33 #if (_MSC_VER >= USE_VER_MIN) 35 #if (_MSC_VER >= USE_VER_MIN)
34 #define USE_HW_SHA 36 #define USE_HW_SHA
37 #else
38 #define Z7_USE_HW_SHA_STUB
35 #endif 39 #endif
36 #endif 40 #endif
37// #endif // MY_CPU_X86_OR_AMD64 41// #endif // MY_CPU_X86_OR_AMD64
42#ifndef USE_HW_SHA
43 // #define Z7_USE_HW_SHA_STUB // for debug
44#endif
38 45
39#ifdef USE_HW_SHA 46#ifdef USE_HW_SHA
40 47
@@ -202,46 +209,124 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t
202 209
203#endif // USE_HW_SHA 210#endif // USE_HW_SHA
204 211
205#elif defined(MY_CPU_ARM_OR_ARM64) 212#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) \
206 213 && (!defined(Z7_MSC_VER_ORIGINAL) || (_MSC_VER >= 1929) && (_MSC_FULL_VER >= 192930037))
207 #if defined(__clang__) 214 #if defined(__ARM_FEATURE_SHA2) \
208 #if (__clang_major__ >= 8) // fix that check 215 || defined(__ARM_FEATURE_CRYPTO)
216 #define USE_HW_SHA
217 #else
218 #if defined(MY_CPU_ARM64) \
219 || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
220 || defined(Z7_MSC_VER_ORIGINAL)
221 #if defined(__ARM_FP) && \
222 ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
223 || defined(__GNUC__) && (__GNUC__ >= 6) \
224 ) \
225 || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
226 #if defined(MY_CPU_ARM64) \
227 || !defined(Z7_CLANG_VERSION) \
228 || defined(__ARM_NEON) && \
229 (Z7_CLANG_VERSION < 170000 || \
230 Z7_CLANG_VERSION > 170001)
209 #define USE_HW_SHA 231 #define USE_HW_SHA
210 #endif 232 #endif
211 #elif defined(__GNUC__)
212 #if (__GNUC__ >= 6) // fix that check
213 #define USE_HW_SHA
214 #endif 233 #endif
215 #elif defined(_MSC_VER)
216 #if _MSC_VER >= 1910
217 #define USE_HW_SHA
218 #endif 234 #endif
219 #endif 235 #endif
220 236
221#ifdef USE_HW_SHA 237#ifdef USE_HW_SHA
222 238
223// #pragma message("=== Sha1 HW === ") 239// #pragma message("=== Sha1 HW === ")
240// __ARM_FEATURE_CRYPTO macro is deprecated in favor of the finer grained feature macro __ARM_FEATURE_SHA2
224 241
225#if defined(__clang__) || defined(__GNUC__) 242#if defined(__clang__) || defined(__GNUC__)
243#if !defined(__ARM_FEATURE_SHA2) && \
244 !defined(__ARM_FEATURE_CRYPTO)
226 #ifdef MY_CPU_ARM64 245 #ifdef MY_CPU_ARM64
246#if defined(__clang__)
247 #define ATTRIB_SHA __attribute__((__target__("crypto")))
248#else
227 #define ATTRIB_SHA __attribute__((__target__("+crypto"))) 249 #define ATTRIB_SHA __attribute__((__target__("+crypto")))
250#endif
228 #else 251 #else
252#if defined(__clang__) && (__clang_major__ >= 1)
253 #define ATTRIB_SHA __attribute__((__target__("armv8-a,sha2")))
254#else
229 #define ATTRIB_SHA __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) 255 #define ATTRIB_SHA __attribute__((__target__("fpu=crypto-neon-fp-armv8")))
256#endif
230 #endif 257 #endif
258#endif
231#else 259#else
232 // _MSC_VER 260 // _MSC_VER
233 // for arm32 261 // for arm32
234 #define _ARM_USE_NEW_NEON_INTRINSICS 262 #define _ARM_USE_NEW_NEON_INTRINSICS
235#endif 263#endif
236 264
237#if defined(_MSC_VER) && defined(MY_CPU_ARM64) 265
266
267
268
269#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
238#include <arm64_neon.h> 270#include <arm64_neon.h>
239#else 271#else
272
273
274
275
276
277
278
279
280
281#if defined(__clang__) && __clang_major__ < 16
282#if !defined(__ARM_FEATURE_SHA2) && \
283 !defined(__ARM_FEATURE_CRYPTO)
284// #pragma message("=== we set __ARM_FEATURE_CRYPTO 1 === ")
285 Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
286 #define Z7_ARM_FEATURE_CRYPTO_WAS_SET 1
287// #if defined(__clang__) && __clang_major__ < 13
288 #define __ARM_FEATURE_CRYPTO 1
289// #else
290 #define __ARM_FEATURE_SHA2 1
291// #endif
292 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
293#endif
294#endif // clang
295
296#if defined(__clang__)
297
298#if defined(__ARM_ARCH) && __ARM_ARCH < 8
299 Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
300// #pragma message("#define __ARM_ARCH 8")
301 #undef __ARM_ARCH
302 #define __ARM_ARCH 8
303 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
304#endif
305
306#endif // clang
307
240#include <arm_neon.h> 308#include <arm_neon.h>
309
310#if defined(Z7_ARM_FEATURE_CRYPTO_WAS_SET) && \
311 defined(__ARM_FEATURE_CRYPTO) && \
312 defined(__ARM_FEATURE_SHA2)
313Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
314 #undef __ARM_FEATURE_CRYPTO
315 #undef __ARM_FEATURE_SHA2
316 #undef Z7_ARM_FEATURE_CRYPTO_WAS_SET
317Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
318// #pragma message("=== we undefine __ARM_FEATURE_CRYPTO === ")
241#endif 319#endif
242 320
321#endif // Z7_MSC_VER_ORIGINAL
322
243typedef uint32x4_t v128; 323typedef uint32x4_t v128;
244// typedef __n128 v128; // MSVC 324// typedef __n128 v128; // MSVC
325// the bug in clang 3.8.1:
326// __builtin_neon_vgetq_lane_i32((int8x16_t)__s0, __p1);
327#if defined(__clang__) && (__clang_major__ <= 9)
328#pragma GCC diagnostic ignored "-Wvector-conversion"
329#endif
245 330
246#ifdef MY_CPU_BE 331#ifdef MY_CPU_BE
247 #define MY_rev32_for_LE(x) 332 #define MY_rev32_for_LE(x)
@@ -256,11 +341,11 @@ typedef uint32x4_t v128;
256 m = LOAD_128((data + (k) * 16)); \ 341 m = LOAD_128((data + (k) * 16)); \
257 MY_rev32_for_LE(m); \ 342 MY_rev32_for_LE(m); \
258 343
259#define SU0(dest, src2, src3) dest = vsha1su0q_u32(dest, src2, src3); 344#define SU0(dest, src2, src3) dest = vsha1su0q_u32(dest, src2, src3)
260#define SU1(dest, src) dest = vsha1su1q_u32(dest, src); 345#define SU1(dest, src) dest = vsha1su1q_u32(dest, src)
261#define C(e) abcd = vsha1cq_u32(abcd, e, t); 346#define C(e) abcd = vsha1cq_u32(abcd, e, t)
262#define P(e) abcd = vsha1pq_u32(abcd, e, t); 347#define P(e) abcd = vsha1pq_u32(abcd, e, t)
263#define M(e) abcd = vsha1mq_u32(abcd, e, t); 348#define M(e) abcd = vsha1mq_u32(abcd, e, t)
264#define H(e) e = vsha1h_u32(vgetq_lane_u32(abcd, 0)) 349#define H(e) e = vsha1h_u32(vgetq_lane_u32(abcd, 0))
265#define T(m, c) t = vaddq_u32(m, c) 350#define T(m, c) t = vaddq_u32(m, c)
266 351
@@ -337,16 +422,17 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t
337#endif // MY_CPU_ARM_OR_ARM64 422#endif // MY_CPU_ARM_OR_ARM64
338 423
339 424
340#ifndef USE_HW_SHA 425#if !defined(USE_HW_SHA) && defined(Z7_USE_HW_SHA_STUB)
341
342// #error Stop_Compiling_UNSUPPORTED_SHA 426// #error Stop_Compiling_UNSUPPORTED_SHA
343// #include <stdlib.h> 427// #include <stdlib.h>
344 428
345// #include "Sha1.h"
346void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t numBlocks);
347 429
348#pragma message("Sha1 HW-SW stub was used")
349 430
431// #include "Sha1.h"
432// #if defined(_MSC_VER)
433#pragma message("Sha1 HW-SW stub was used")
434// #endif
435void Z7_FASTCALL Sha1_UpdateBlocks (UInt32 state[5], const Byte *data, size_t numBlocks);
350void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t numBlocks); 436void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t numBlocks);
351void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t numBlocks) 437void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t numBlocks)
352{ 438{
@@ -359,7 +445,6 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t
359 return; 445 return;
360 */ 446 */
361} 447}
362
363#endif 448#endif
364 449
365#undef SU0 450#undef SU0
@@ -384,3 +469,4 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t
384#undef USE_HW_SHA 469#undef USE_HW_SHA
385#undef ATTRIB_SHA 470#undef ATTRIB_SHA
386#undef USE_VER_MIN 471#undef USE_VER_MIN
472#undef Z7_USE_HW_SHA_STUB
diff --git a/C/Sha256.c b/C/Sha256.c
index 018cf6f..14d3be9 100644
--- a/C/Sha256.c
+++ b/C/Sha256.c
@@ -1,5 +1,5 @@
1/* Sha256.c -- SHA-256 Hash 1/* Sha256.c -- SHA-256 Hash
22023-04-02 : Igor Pavlov : Public domain 22024-03-01 : Igor Pavlov : Public domain
3This code is based on public domain code from Wei Dai's Crypto++ library. */ 3This code is based on public domain code from Wei Dai's Crypto++ library. */
4 4
5#include "Precomp.h" 5#include "Precomp.h"
@@ -15,35 +15,35 @@ This code is based on public domain code from Wei Dai's Crypto++ library. */
15#endif 15#endif
16 16
17#ifdef MY_CPU_X86_OR_AMD64 17#ifdef MY_CPU_X86_OR_AMD64
18 #ifdef _MSC_VER 18 #if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \
19 #if _MSC_VER >= 1200 19 || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \
20 || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
21 || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) \
22 || defined(_MSC_VER) && (_MSC_VER >= 1200)
20 #define Z7_COMPILER_SHA256_SUPPORTED 23 #define Z7_COMPILER_SHA256_SUPPORTED
21 #endif
22 #elif defined(__clang__)
23 #if (__clang_major__ >= 8) // fix that check
24 #define Z7_COMPILER_SHA256_SUPPORTED
25 #endif
26 #elif defined(__GNUC__)
27 #if (__GNUC__ >= 8) // fix that check
28 #define Z7_COMPILER_SHA256_SUPPORTED
29 #endif
30 #elif defined(__INTEL_COMPILER)
31 #if (__INTEL_COMPILER >= 1800) // fix that check
32 #define Z7_COMPILER_SHA256_SUPPORTED
33 #endif
34 #endif 24 #endif
35#elif defined(MY_CPU_ARM_OR_ARM64) 25#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)
36 #ifdef _MSC_VER 26
37 #if _MSC_VER >= 1910 27 #if defined(__ARM_FEATURE_SHA2) \
28 || defined(__ARM_FEATURE_CRYPTO)
29 #define Z7_COMPILER_SHA256_SUPPORTED
30 #else
31 #if defined(MY_CPU_ARM64) \
32 || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
33 || defined(Z7_MSC_VER_ORIGINAL)
34 #if defined(__ARM_FP) && \
35 ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
36 || defined(__GNUC__) && (__GNUC__ >= 6) \
37 ) \
38 || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
39 #if defined(MY_CPU_ARM64) \
40 || !defined(Z7_CLANG_VERSION) \
41 || defined(__ARM_NEON) && \
42 (Z7_CLANG_VERSION < 170000 || \
43 Z7_CLANG_VERSION > 170001)
38 #define Z7_COMPILER_SHA256_SUPPORTED 44 #define Z7_COMPILER_SHA256_SUPPORTED
39 #endif 45 #endif
40 #elif defined(__clang__)
41 #if (__clang_major__ >= 8) // fix that check
42 #define Z7_COMPILER_SHA256_SUPPORTED
43 #endif 46 #endif
44 #elif defined(__GNUC__)
45 #if (__GNUC__ >= 6) // fix that check
46 #define Z7_COMPILER_SHA256_SUPPORTED
47 #endif 47 #endif
48 #endif 48 #endif
49#endif 49#endif
@@ -224,8 +224,6 @@ void Sha256_Init(CSha256 *p)
224 224
225#endif 225#endif
226 226
227void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks);
228
229// static 227// static
230extern MY_ALIGN(64) 228extern MY_ALIGN(64)
231const UInt32 SHA256_K_ARRAY[64]; 229const UInt32 SHA256_K_ARRAY[64];
diff --git a/C/Sha256Opt.c b/C/Sha256Opt.c
index e4465e3..eb38166 100644
--- a/C/Sha256Opt.c
+++ b/C/Sha256Opt.c
@@ -1,5 +1,5 @@
1/* Sha256Opt.c -- SHA-256 optimized code for SHA-256 hardware instructions 1/* Sha256Opt.c -- SHA-256 optimized code for SHA-256 hardware instructions
22023-04-02 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5#include "Compiler.h" 5#include "Compiler.h"
@@ -11,6 +11,8 @@
11#endif 11#endif
12#endif 12#endif
13 13
14// #define Z7_USE_HW_SHA_STUB // for debug
15
14#ifdef MY_CPU_X86_OR_AMD64 16#ifdef MY_CPU_X86_OR_AMD64
15 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check 17 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check
16 #define USE_HW_SHA 18 #define USE_HW_SHA
@@ -32,9 +34,14 @@
32 #endif 34 #endif
33 #if (_MSC_VER >= USE_VER_MIN) 35 #if (_MSC_VER >= USE_VER_MIN)
34 #define USE_HW_SHA 36 #define USE_HW_SHA
37 #else
38 #define Z7_USE_HW_SHA_STUB
35 #endif 39 #endif
36 #endif 40 #endif
37// #endif // MY_CPU_X86_OR_AMD64 41// #endif // MY_CPU_X86_OR_AMD64
42#ifndef USE_HW_SHA
43 // #define Z7_USE_HW_SHA_STUB // for debug
44#endif
38 45
39#ifdef USE_HW_SHA 46#ifdef USE_HW_SHA
40 47
@@ -202,19 +209,28 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
202 209
203#endif // USE_HW_SHA 210#endif // USE_HW_SHA
204 211
205#elif defined(MY_CPU_ARM_OR_ARM64) 212#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)
206 213
207 #if defined(__clang__) 214 #if defined(__ARM_FEATURE_SHA2) \
208 #if (__clang_major__ >= 8) // fix that check 215 || defined(__ARM_FEATURE_CRYPTO)
216 #define USE_HW_SHA
217 #else
218 #if defined(MY_CPU_ARM64) \
219 || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
220 || defined(Z7_MSC_VER_ORIGINAL)
221 #if defined(__ARM_FP) && \
222 ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
223 || defined(__GNUC__) && (__GNUC__ >= 6) \
224 ) \
225 || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
226 #if defined(MY_CPU_ARM64) \
227 || !defined(Z7_CLANG_VERSION) \
228 || defined(__ARM_NEON) && \
229 (Z7_CLANG_VERSION < 170000 || \
230 Z7_CLANG_VERSION > 170001)
209 #define USE_HW_SHA 231 #define USE_HW_SHA
210 #endif 232 #endif
211 #elif defined(__GNUC__)
212 #if (__GNUC__ >= 6) // fix that check
213 #define USE_HW_SHA
214 #endif 233 #endif
215 #elif defined(_MSC_VER)
216 #if _MSC_VER >= 1910
217 #define USE_HW_SHA
218 #endif 234 #endif
219 #endif 235 #endif
220 236
@@ -222,24 +238,88 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
222 238
223// #pragma message("=== Sha256 HW === ") 239// #pragma message("=== Sha256 HW === ")
224 240
241
225#if defined(__clang__) || defined(__GNUC__) 242#if defined(__clang__) || defined(__GNUC__)
243#if !defined(__ARM_FEATURE_SHA2) && \
244 !defined(__ARM_FEATURE_CRYPTO)
226 #ifdef MY_CPU_ARM64 245 #ifdef MY_CPU_ARM64
246#if defined(__clang__)
247 #define ATTRIB_SHA __attribute__((__target__("crypto")))
248#else
227 #define ATTRIB_SHA __attribute__((__target__("+crypto"))) 249 #define ATTRIB_SHA __attribute__((__target__("+crypto")))
250#endif
228 #else 251 #else
252#if defined(__clang__) && (__clang_major__ >= 1)
253 #define ATTRIB_SHA __attribute__((__target__("armv8-a,sha2")))
254#else
229 #define ATTRIB_SHA __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) 255 #define ATTRIB_SHA __attribute__((__target__("fpu=crypto-neon-fp-armv8")))
256#endif
230 #endif 257 #endif
258#endif
231#else 259#else
232 // _MSC_VER 260 // _MSC_VER
233 // for arm32 261 // for arm32
234 #define _ARM_USE_NEW_NEON_INTRINSICS 262 #define _ARM_USE_NEW_NEON_INTRINSICS
235#endif 263#endif
236 264
237#if defined(_MSC_VER) && defined(MY_CPU_ARM64) 265
266
267
268
269#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
238#include <arm64_neon.h> 270#include <arm64_neon.h>
239#else 271#else
272
273
274
275
276
277
278
279
280
281#if defined(__clang__) && __clang_major__ < 16
282#if !defined(__ARM_FEATURE_SHA2) && \
283 !defined(__ARM_FEATURE_CRYPTO)
284// #pragma message("=== we set __ARM_FEATURE_CRYPTO 1 === ")
285 Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
286 #define Z7_ARM_FEATURE_CRYPTO_WAS_SET 1
287// #if defined(__clang__) && __clang_major__ < 13
288 #define __ARM_FEATURE_CRYPTO 1
289// #else
290 #define __ARM_FEATURE_SHA2 1
291// #endif
292 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
293#endif
294#endif // clang
295
296#if defined(__clang__)
297
298#if defined(__ARM_ARCH) && __ARM_ARCH < 8
299 Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
300// #pragma message("#define __ARM_ARCH 8")
301 #undef __ARM_ARCH
302 #define __ARM_ARCH 8
303 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
304#endif
305
306#endif // clang
307
240#include <arm_neon.h> 308#include <arm_neon.h>
309
310#if defined(Z7_ARM_FEATURE_CRYPTO_WAS_SET) && \
311 defined(__ARM_FEATURE_CRYPTO) && \
312 defined(__ARM_FEATURE_SHA2)
313Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
314 #undef __ARM_FEATURE_CRYPTO
315 #undef __ARM_FEATURE_SHA2
316 #undef Z7_ARM_FEATURE_CRYPTO_WAS_SET
317Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
318// #pragma message("=== we undefine __ARM_FEATURE_CRYPTO === ")
241#endif 319#endif
242 320
321#endif // Z7_MSC_VER_ORIGINAL
322
243typedef uint32x4_t v128; 323typedef uint32x4_t v128;
244// typedef __n128 v128; // MSVC 324// typedef __n128 v128; // MSVC
245 325
@@ -316,10 +396,10 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
316 LOAD_SHUFFLE (m2, 2) 396 LOAD_SHUFFLE (m2, 2)
317 LOAD_SHUFFLE (m3, 3) 397 LOAD_SHUFFLE (m3, 3)
318 398
319 R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 ); 399 R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 )
320 R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ); 400 R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 )
321 R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ); 401 R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 )
322 R16 ( 3, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN ); 402 R16 ( 3, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN )
323 403
324 state0 = vaddq_u32(state0, state0_save); 404 state0 = vaddq_u32(state0, state0_save);
325 state1 = vaddq_u32(state1, state1_save); 405 state1 = vaddq_u32(state1, state1_save);
@@ -337,16 +417,17 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
337#endif // MY_CPU_ARM_OR_ARM64 417#endif // MY_CPU_ARM_OR_ARM64
338 418
339 419
340#ifndef USE_HW_SHA 420#if !defined(USE_HW_SHA) && defined(Z7_USE_HW_SHA_STUB)
341
342// #error Stop_Compiling_UNSUPPORTED_SHA 421// #error Stop_Compiling_UNSUPPORTED_SHA
343// #include <stdlib.h> 422// #include <stdlib.h>
344 423// We can compile this file with another C compiler,
424// or we can compile asm version.
425// So we can generate real code instead of this stub function.
345// #include "Sha256.h" 426// #include "Sha256.h"
346void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks); 427// #if defined(_MSC_VER)
347
348#pragma message("Sha256 HW-SW stub was used") 428#pragma message("Sha256 HW-SW stub was used")
349 429// #endif
430void Z7_FASTCALL Sha256_UpdateBlocks (UInt32 state[8], const Byte *data, size_t numBlocks);
350void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); 431void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks);
351void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) 432void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks)
352{ 433{
@@ -359,7 +440,6 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
359 return; 440 return;
360 */ 441 */
361} 442}
362
363#endif 443#endif
364 444
365 445
@@ -384,3 +464,4 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
384#undef USE_HW_SHA 464#undef USE_HW_SHA
385#undef ATTRIB_SHA 465#undef ATTRIB_SHA
386#undef USE_VER_MIN 466#undef USE_VER_MIN
467#undef Z7_USE_HW_SHA_STUB
diff --git a/C/SwapBytes.c b/C/SwapBytes.c
index 7901bba..9290592 100644
--- a/C/SwapBytes.c
+++ b/C/SwapBytes.c
@@ -1,5 +1,5 @@
1/* SwapBytes.c -- Byte Swap conversion filter 1/* SwapBytes.c -- Byte Swap conversion filter
22023-04-07 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -305,11 +305,12 @@ ShufBytes_256(void *items8, const void *lim8, const void *mask128_ptr)
305 msvc 19.30+ (VS2022): replaces _mm256_set_m128i(m,m) to vbroadcastf128(m) as we want 305 msvc 19.30+ (VS2022): replaces _mm256_set_m128i(m,m) to vbroadcastf128(m) as we want
306 */ 306 */
307 // _mm256_broadcastsi128_si256(*mask128_ptr); 307 // _mm256_broadcastsi128_si256(*mask128_ptr);
308 /* 308#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION < 80000)
309 #define MY_mm256_set_m128i(hi, lo) _mm256_insertf128_si256(_mm256_castsi128_si256(lo), (hi), 1) 309 #define MY_mm256_set_m128i(hi, lo) _mm256_insertf128_si256(_mm256_castsi128_si256(lo), (hi), 1)
310 MY_mm256_set_m128i 310#else
311 */ 311 #define MY_mm256_set_m128i _mm256_set_m128i
312 _mm256_set_m128i( 312#endif
313 MY_mm256_set_m128i(
313 *(const __m128i *)mask128_ptr, 314 *(const __m128i *)mask128_ptr,
314 *(const __m128i *)mask128_ptr); 315 *(const __m128i *)mask128_ptr);
315 #endif 316 #endif
@@ -330,32 +331,59 @@ ShufBytes_256(void *items8, const void *lim8, const void *mask128_ptr)
330 331
331 332
332// compile message "NEON intrinsics not available with the soft-float ABI" 333// compile message "NEON intrinsics not available with the soft-float ABI"
333#elif defined(MY_CPU_ARM_OR_ARM64) || \ 334#elif defined(MY_CPU_ARM_OR_ARM64) \
334 (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) 335 && defined(MY_CPU_LE) \
335// #elif defined(MY_CPU_ARM64) 336 && !defined(Z7_DISABLE_ARM_NEON)
336 337
337 #if defined(__clang__) && (__clang_major__ >= 8) \ 338 #if defined(__clang__) && (__clang_major__ >= 8) \
338 || defined(__GNUC__) && (__GNUC__ >= 8) 339 || defined(__GNUC__) && (__GNUC__ >= 6)
339 #if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) \ 340 #if defined(__ARM_FP)
341 #if (defined(__ARM_ARCH) && (__ARM_ARCH >= 4)) \
340 || defined(MY_CPU_ARM64) 342 || defined(MY_CPU_ARM64)
343 #if defined(MY_CPU_ARM64) \
344 || !defined(Z7_CLANG_VERSION) \
345 || defined(__ARM_NEON)
341 #define USE_SWAP_128 346 #define USE_SWAP_128
342 #endif
343 #ifdef MY_CPU_ARM64 347 #ifdef MY_CPU_ARM64
344 // #define SWAP_ATTRIB_NEON __attribute__((__target__(""))) 348 // #define SWAP_ATTRIB_NEON __attribute__((__target__("")))
345 #else 349 #else
346 // #define SWAP_ATTRIB_NEON __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) 350#if defined(Z7_CLANG_VERSION)
347 #endif 351 // #define SWAP_ATTRIB_NEON __attribute__((__target__("neon")))
352#else
353 // #pragma message("SWAP_ATTRIB_NEON __attribute__((__target__(fpu=neon))")
354 #define SWAP_ATTRIB_NEON __attribute__((__target__("fpu=neon")))
355#endif
356 #endif // MY_CPU_ARM64
357 #endif // __ARM_NEON
358 #endif // __ARM_ARCH
359 #endif // __ARM_FP
360
348 #elif defined(_MSC_VER) 361 #elif defined(_MSC_VER)
349 #if (_MSC_VER >= 1910) 362 #if (_MSC_VER >= 1910)
350 #define USE_SWAP_128 363 #define USE_SWAP_128
351 #endif 364 #endif
352 #endif 365 #endif
353 366
354 #if defined(_MSC_VER) && defined(MY_CPU_ARM64) 367 #ifdef USE_SWAP_128
368 #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
355 #include <arm64_neon.h> 369 #include <arm64_neon.h>
356 #else 370 #else
371
372/*
373#if !defined(__ARM_NEON)
374#if defined(Z7_GCC_VERSION) && (__GNUC__ < 5) \
375 || defined(Z7_GCC_VERSION) && (__GNUC__ == 5) && (Z7_GCC_VERSION < 90201) \
376 || defined(Z7_GCC_VERSION) && (__GNUC__ == 5) && (Z7_GCC_VERSION < 100100)
377Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
378#pragma message("#define __ARM_NEON 1")
379// #define __ARM_NEON 1
380Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
381#endif
382#endif
383*/
357 #include <arm_neon.h> 384 #include <arm_neon.h>
358 #endif 385 #endif
386 #endif
359 387
360#ifndef USE_SWAP_128 388#ifndef USE_SWAP_128
361 #define FORCE_SWAP_MODE 389 #define FORCE_SWAP_MODE
@@ -464,6 +492,13 @@ Z7_ATTRIB_NO_VECTOR \
464void Z7_FASTCALL 492void Z7_FASTCALL
465 493
466 494
495#if defined(MY_CPU_ARM_OR_ARM64)
496#if defined(__clang__)
497#pragma GCC diagnostic ignored "-Wlanguage-extension-token"
498#endif
499#endif
500
501
467#ifdef MY_CPU_64BIT 502#ifdef MY_CPU_64BIT
468 503
469#if defined(MY_CPU_ARM64) \ 504#if defined(MY_CPU_ARM64) \
diff --git a/C/Threads.c b/C/Threads.c
index cf52bd3..464efec 100644
--- a/C/Threads.c
+++ b/C/Threads.c
@@ -1,5 +1,5 @@
1/* Threads.c -- multithreading library 1/* Threads.c -- multithreading library
22023-03-04 : Igor Pavlov : Public domain */ 22024-03-28 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -195,20 +195,19 @@ WRes CriticalSection_Init(CCriticalSection *p)
195 195
196// ---------- POSIX ---------- 196// ---------- POSIX ----------
197 197
198#ifndef __APPLE__ 198#if defined(__linux__) && !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)
199#ifndef Z7_AFFINITY_DISABLE 199#ifndef Z7_AFFINITY_DISABLE
200// _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET 200// _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET
201// clang < 3.6 : unknown warning group '-Wreserved-id-macro' 201// clang < 3.6 : unknown warning group '-Wreserved-id-macro'
202// clang 3.6 - 12.01 : gives warning "macro name is a reserved identifier" 202// clang 3.6 - 12.01 : gives warning "macro name is a reserved identifier"
203// clang >= 13 : do not give warning 203// clang >= 13 : do not give warning
204#if !defined(_GNU_SOURCE) 204#if !defined(_GNU_SOURCE)
205 #if defined(__clang__) && (__clang_major__ >= 4) && (__clang_major__ <= 12) 205Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
206 #pragma GCC diagnostic ignored "-Wreserved-id-macro" 206// #define _GNU_SOURCE
207 #endif 207Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
208#define _GNU_SOURCE
209#endif // !defined(_GNU_SOURCE) 208#endif // !defined(_GNU_SOURCE)
210#endif // Z7_AFFINITY_DISABLE 209#endif // Z7_AFFINITY_DISABLE
211#endif // __APPLE__ 210#endif // __linux__
212 211
213#include "Threads.h" 212#include "Threads.h"
214 213
@@ -244,8 +243,9 @@ WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param,
244 { 243 {
245 if (cpuSet) 244 if (cpuSet)
246 { 245 {
247 #ifdef Z7_AFFINITY_SUPPORTED 246 // pthread_attr_setaffinity_np() is not supported for MUSL compile.
248 247 // so we check for __GLIBC__ here
248#if defined(Z7_AFFINITY_SUPPORTED) && defined( __GLIBC__)
249 /* 249 /*
250 printf("\n affinity :"); 250 printf("\n affinity :");
251 unsigned i; 251 unsigned i;
@@ -267,7 +267,7 @@ WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param,
267 // ret2 = 267 // ret2 =
268 pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet); 268 pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet);
269 // if (ret2) ret = ret2; 269 // if (ret2) ret = ret2;
270 #endif 270#endif
271 } 271 }
272 272
273 ret = pthread_create(&p->_tid, &attr, func, param); 273 ret = pthread_create(&p->_tid, &attr, func, param);
@@ -369,13 +369,20 @@ WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p)
369 { return AutoResetEvent_Create(p, 0); } 369 { return AutoResetEvent_Create(p, 0); }
370 370
371 371
372#if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13)
373// freebsd:
374#pragma GCC diagnostic ignored "-Wthread-safety-analysis"
375#endif
376
372WRes Event_Set(CEvent *p) 377WRes Event_Set(CEvent *p)
373{ 378{
374 RINOK(pthread_mutex_lock(&p->_mutex)) 379 RINOK(pthread_mutex_lock(&p->_mutex))
375 p->_state = True; 380 p->_state = True;
376 int res1 = pthread_cond_broadcast(&p->_cond); 381 {
377 int res2 = pthread_mutex_unlock(&p->_mutex); 382 const int res1 = pthread_cond_broadcast(&p->_cond);
378 return (res2 ? res2 : res1); 383 const int res2 = pthread_mutex_unlock(&p->_mutex);
384 return (res2 ? res2 : res1);
385 }
379} 386}
380 387
381WRes Event_Reset(CEvent *p) 388WRes Event_Reset(CEvent *p)
@@ -408,8 +415,8 @@ WRes Event_Close(CEvent *p)
408 return 0; 415 return 0;
409 p->_created = 0; 416 p->_created = 0;
410 { 417 {
411 int res1 = pthread_mutex_destroy(&p->_mutex); 418 const int res1 = pthread_mutex_destroy(&p->_mutex);
412 int res2 = pthread_cond_destroy(&p->_cond); 419 const int res2 = pthread_cond_destroy(&p->_cond);
413 return (res1 ? res1 : res2); 420 return (res1 ? res1 : res2);
414 } 421 }
415} 422}
@@ -487,8 +494,8 @@ WRes Semaphore_Close(CSemaphore *p)
487 return 0; 494 return 0;
488 p->_created = 0; 495 p->_created = 0;
489 { 496 {
490 int res1 = pthread_mutex_destroy(&p->_mutex); 497 const int res1 = pthread_mutex_destroy(&p->_mutex);
491 int res2 = pthread_cond_destroy(&p->_cond); 498 const int res2 = pthread_cond_destroy(&p->_cond);
492 return (res1 ? res1 : res2); 499 return (res1 ? res1 : res2);
493 } 500 }
494} 501}
@@ -549,6 +556,18 @@ LONG InterlockedIncrement(LONG volatile *addend)
549 #endif 556 #endif
550} 557}
551 558
559LONG InterlockedDecrement(LONG volatile *addend)
560{
561 // Print("InterlockedDecrement")
562 #ifdef USE_HACK_UNSAFE_ATOMIC
563 LONG val = *addend - 1;
564 *addend = val;
565 return val;
566 #else
567 return __sync_sub_and_fetch(addend, 1);
568 #endif
569}
570
552#endif // _WIN32 571#endif // _WIN32
553 572
554WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p) 573WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p)
diff --git a/C/Threads.h b/C/Threads.h
index 4028464..c1484a2 100644
--- a/C/Threads.h
+++ b/C/Threads.h
@@ -1,5 +1,5 @@
1/* Threads.h -- multithreading library 1/* Threads.h -- multithreading library
22023-04-02 : Igor Pavlov : Public domain */ 22024-03-28 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_THREADS_H 4#ifndef ZIP7_INC_THREADS_H
5#define ZIP7_INC_THREADS_H 5#define ZIP7_INC_THREADS_H
@@ -9,12 +9,21 @@
9 9
10#else 10#else
11 11
12#include "Compiler.h"
13
14// #define Z7_AFFINITY_DISABLE
12#if defined(__linux__) 15#if defined(__linux__)
13#if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__) 16#if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)
14#ifndef Z7_AFFINITY_DISABLE 17#ifndef Z7_AFFINITY_DISABLE
15#define Z7_AFFINITY_SUPPORTED 18#define Z7_AFFINITY_SUPPORTED
16// #pragma message(" ==== Z7_AFFINITY_SUPPORTED") 19// #pragma message(" ==== Z7_AFFINITY_SUPPORTED")
17// #define _GNU_SOURCE 20#if !defined(_GNU_SOURCE)
21// #pragma message(" ==== _GNU_SOURCE set")
22// we need _GNU_SOURCE for cpu_set_t, if we compile for MUSL
23Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
24#define _GNU_SOURCE
25Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
26#endif
18#endif 27#endif
19#endif 28#endif
20#endif 29#endif
@@ -173,7 +182,7 @@ WRes CriticalSection_Init(CCriticalSection *p);
173 182
174#else // _WIN32 183#else // _WIN32
175 184
176typedef struct _CEvent 185typedef struct
177{ 186{
178 int _created; 187 int _created;
179 int _manual_reset; 188 int _manual_reset;
@@ -199,7 +208,7 @@ WRes Event_Wait(CEvent *p);
199WRes Event_Close(CEvent *p); 208WRes Event_Close(CEvent *p);
200 209
201 210
202typedef struct _CSemaphore 211typedef struct
203{ 212{
204 int _created; 213 int _created;
205 UInt32 _count; 214 UInt32 _count;
@@ -219,7 +228,7 @@ WRes Semaphore_Wait(CSemaphore *p);
219WRes Semaphore_Close(CSemaphore *p); 228WRes Semaphore_Close(CSemaphore *p);
220 229
221 230
222typedef struct _CCriticalSection 231typedef struct
223{ 232{
224 pthread_mutex_t _mutex; 233 pthread_mutex_t _mutex;
225} CCriticalSection; 234} CCriticalSection;
@@ -230,6 +239,7 @@ void CriticalSection_Enter(CCriticalSection *cs);
230void CriticalSection_Leave(CCriticalSection *cs); 239void CriticalSection_Leave(CCriticalSection *cs);
231 240
232LONG InterlockedIncrement(LONG volatile *addend); 241LONG InterlockedIncrement(LONG volatile *addend);
242LONG InterlockedDecrement(LONG volatile *addend);
233 243
234#endif // _WIN32 244#endif // _WIN32
235 245
diff --git a/C/Util/7z/7z.dsp b/C/Util/7z/7z.dsp
index 11e1b03..474c660 100644
--- a/C/Util/7z/7z.dsp
+++ b/C/Util/7z/7z.dsp
@@ -42,7 +42,7 @@ RSC=rc.exe
42# PROP Ignore_Export_Lib 0 42# PROP Ignore_Export_Lib 0
43# PROP Target_Dir "" 43# PROP Target_Dir ""
44# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 44# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
45# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "Z7_PPMD_SUPPORT" /FAcs /Yu"Precomp.h" /FD /c 45# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "Z7_PPMD_SUPPORT" /D "Z7_EXTRACT_ONLY" /FAcs /Yu"Precomp.h" /FD /c
46# ADD BASE RSC /l 0x419 /d "NDEBUG" 46# ADD BASE RSC /l 0x419 /d "NDEBUG"
47# ADD RSC /l 0x419 /d "NDEBUG" 47# ADD RSC /l 0x419 /d "NDEBUG"
48BSC32=bscmake.exe 48BSC32=bscmake.exe
@@ -67,7 +67,7 @@ LINK32=link.exe
67# PROP Ignore_Export_Lib 0 67# PROP Ignore_Export_Lib 0
68# PROP Target_Dir "" 68# PROP Target_Dir ""
69# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 69# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
70# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "Z7_PPMD_SUPPORT" /Yu"Precomp.h" /FD /GZ /c 70# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "Z7_PPMD_SUPPORT" /D "Z7_EXTRACT_ONLY" /Yu"Precomp.h" /FD /GZ /c
71# ADD BASE RSC /l 0x419 /d "_DEBUG" 71# ADD BASE RSC /l 0x419 /d "_DEBUG"
72# ADD RSC /l 0x419 /d "_DEBUG" 72# ADD RSC /l 0x419 /d "_DEBUG"
73BSC32=bscmake.exe 73BSC32=bscmake.exe
@@ -234,6 +234,10 @@ SOURCE=.\Precomp.c
234# End Source File 234# End Source File
235# Begin Source File 235# Begin Source File
236 236
237SOURCE=..\..\Precomp.h
238# End Source File
239# Begin Source File
240
237SOURCE=.\Precomp.h 241SOURCE=.\Precomp.h
238# End Source File 242# End Source File
239# End Group 243# End Group
diff --git a/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c
index 547920a..6baf979 100644
--- a/C/Util/7z/7zMain.c
+++ b/C/Util/7z/7zMain.c
@@ -1,20 +1,11 @@
1/* 7zMain.c - Test application for 7z Decoder 1/* 7zMain.c - Test application for 7z Decoder
22023-04-04 : Igor Pavlov : Public domain */ 22024-02-28 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
6#include <stdio.h> 6#include <stdio.h>
7#include <string.h> 7#include <string.h>
8 8
9#include "../../CpuArch.h"
10
11#include "../../7z.h"
12#include "../../7zAlloc.h"
13#include "../../7zBuf.h"
14#include "../../7zCrc.h"
15#include "../../7zFile.h"
16#include "../../7zVersion.h"
17
18#ifndef USE_WINDOWS_FILE 9#ifndef USE_WINDOWS_FILE
19/* for mkdir */ 10/* for mkdir */
20#ifdef _WIN32 11#ifdef _WIN32
@@ -32,6 +23,15 @@
32#endif 23#endif
33#endif 24#endif
34 25
26#include "../../7zFile.h"
27#include "../../7z.h"
28#include "../../7zAlloc.h"
29#include "../../7zBuf.h"
30#include "../../7zCrc.h"
31#include "../../7zVersion.h"
32
33#include "../../CpuArch.h"
34
35#define kInputBufSize ((size_t)1 << 18) 35#define kInputBufSize ((size_t)1 << 18)
36 36
37static const ISzAlloc g_Alloc = { SzAlloc, SzFree }; 37static const ISzAlloc g_Alloc = { SzAlloc, SzFree };
@@ -168,12 +168,12 @@ static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s
168 #endif 168 #endif
169 ) 169 )
170{ 170{
171 unsigned len = 0; 171 size_t len = 0;
172 for (len = 0; s[len] != 0; len++) {} 172 for (len = 0; s[len] != 0; len++) {}
173 173
174 #ifndef MY_USE_UTF8 174 #ifndef MY_USE_UTF8
175 { 175 {
176 const unsigned size = len * 3 + 100; 176 const size_t size = len * 3 + 100;
177 if (!Buf_EnsureSize(buf, size)) 177 if (!Buf_EnsureSize(buf, size))
178 return SZ_ERROR_MEM; 178 return SZ_ERROR_MEM;
179 { 179 {
@@ -320,21 +320,20 @@ static void UIntToStr_2(char *s, unsigned value)
320// typedef long BOOL; 320// typedef long BOOL;
321typedef int BOOL; 321typedef int BOOL;
322 322
323typedef struct _FILETIME 323typedef struct
324{ 324{
325 DWORD dwLowDateTime; 325 DWORD dwLowDateTime;
326 DWORD dwHighDateTime; 326 DWORD dwHighDateTime;
327} FILETIME; 327} FILETIME;
328 328
329static LONG TIME_GetBias() 329static LONG TIME_GetBias(void)
330{ 330{
331 const time_t utc = time(NULL); 331 const time_t utc = time(NULL);
332 struct tm *ptm = localtime(&utc); 332 struct tm *ptm = localtime(&utc);
333 const int localdaylight = ptm->tm_isdst; /* daylight for local timezone */ 333 const int localdaylight = ptm->tm_isdst; /* daylight for local timezone */
334 ptm = gmtime(&utc); 334 ptm = gmtime(&utc);
335 ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */ 335 ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */
336 const LONG bias = (int)(mktime(ptm) - utc); 336 return (int)(mktime(ptm) - utc);
337 return bias;
338} 337}
339 338
340#define TICKS_PER_SEC 10000000 339#define TICKS_PER_SEC 10000000
@@ -359,11 +358,11 @@ static BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *l
359static const UInt32 kNumTimeQuantumsInSecond = 10000000; 358static const UInt32 kNumTimeQuantumsInSecond = 10000000;
360static const UInt32 kFileTimeStartYear = 1601; 359static const UInt32 kFileTimeStartYear = 1601;
361static const UInt32 kUnixTimeStartYear = 1970; 360static const UInt32 kUnixTimeStartYear = 1970;
362static const UInt64 kUnixTimeOffset =
363 (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));
364 361
365static Int64 Time_FileTimeToUnixTime64(const FILETIME *ft) 362static Int64 Time_FileTimeToUnixTime64(const FILETIME *ft)
366{ 363{
364 const UInt64 kUnixTimeOffset =
365 (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));
367 const UInt64 winTime = GET_TIME_64(ft); 366 const UInt64 winTime = GET_TIME_64(ft);
368 return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; 367 return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset;
369} 368}
@@ -384,8 +383,10 @@ static void FILETIME_To_timespec(const FILETIME *ft, struct MY_ST_TIMESPEC *ts)
384 if (sec2 == sec) 383 if (sec2 == sec)
385 { 384 {
386 ts->tv_sec = sec2; 385 ts->tv_sec = sec2;
387 const UInt64 winTime = GET_TIME_64(ft); 386 {
388 ts->tv_nsec = (long)((winTime % 10000000) * 100); 387 const UInt64 winTime = GET_TIME_64(ft);
388 ts->tv_nsec = (long)((winTime % 10000000) * 100);
389 }
389 return; 390 return;
390 } 391 }
391 } 392 }
@@ -429,7 +430,7 @@ static void ConvertFileTimeToString(const CNtfsFileTime *nTime, char *s)
429{ 430{
430 unsigned year, mon, hour, min, sec; 431 unsigned year, mon, hour, min, sec;
431 Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 432 Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
432 unsigned t; 433 UInt32 t;
433 UInt32 v; 434 UInt32 v;
434 // UInt64 v64 = nt->Low | ((UInt64)nt->High << 32); 435 // UInt64 v64 = nt->Low | ((UInt64)nt->High << 32);
435 UInt64 v64; 436 UInt64 v64;
@@ -461,7 +462,7 @@ static void ConvertFileTimeToString(const CNtfsFileTime *nTime, char *s)
461 ms[1] = 29; 462 ms[1] = 29;
462 for (mon = 0;; mon++) 463 for (mon = 0;; mon++)
463 { 464 {
464 const unsigned d = ms[mon]; 465 const UInt32 d = ms[mon];
465 if (v < d) 466 if (v < d)
466 break; 467 break;
467 v -= d; 468 v -= d;
diff --git a/C/Util/7z/Precomp.h b/C/Util/7z/Precomp.h
index bc8fa21..13a41ef 100644
--- a/C/Util/7z/Precomp.h
+++ b/C/Util/7z/Precomp.h
@@ -1,14 +1,13 @@
1/* Precomp.h -- StdAfx 1/* Precomp.h -- Precomp
22023-03-04 : Igor Pavlov : Public domain */ 22024-01-23 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_PRECOMP_H 4// #ifndef ZIP7_INC_PRECOMP_LOC_H
5#define ZIP7_INC_PRECOMP_H 5// #define ZIP7_INC_PRECOMP_LOC_H
6 6
7#if defined(_MSC_VER) && _MSC_VER >= 1800 7#if defined(_MSC_VER) && _MSC_VER >= 1800
8#pragma warning(disable : 4464) // relative include path contains '..' 8#pragma warning(disable : 4464) // relative include path contains '..'
9#endif 9#endif
10 10
11#include "../../Compiler.h" 11#include "../../Precomp.h"
12#include "../../7zTypes.h"
13 12
14#endif 13// #endif
diff --git a/C/Util/7z/makefile b/C/Util/7z/makefile
index dfc560e..987f065 100644
--- a/C/Util/7z/makefile
+++ b/C/Util/7z/makefile
@@ -5,8 +5,6 @@ PROG = 7zDec.exe
5C_OBJS = \ 5C_OBJS = \
6 $O\7zAlloc.obj \ 6 $O\7zAlloc.obj \
7 $O\7zBuf.obj \ 7 $O\7zBuf.obj \
8 $O\7zCrc.obj \
9 $O\7zCrcOpt.obj \
10 $O\7zFile.obj \ 8 $O\7zFile.obj \
11 $O\7zDec.obj \ 9 $O\7zDec.obj \
12 $O\7zArcIn.obj \ 10 $O\7zArcIn.obj \
@@ -25,10 +23,14 @@ C_OBJS = \
257Z_OBJS = \ 237Z_OBJS = \
26 $O\7zMain.obj \ 24 $O\7zMain.obj \
27 25
26!include "../../../CPP/7zip/Crc.mak"
27!include "../../../CPP/7zip/LzmaDec.mak"
28
28OBJS = \ 29OBJS = \
29 $O\Precomp.obj \ 30 $O\Precomp.obj \
30 $(7Z_OBJS) \ 31 $(7Z_OBJS) \
31 $(C_OBJS) \ 32 $(C_OBJS) \
33 $(ASM_OBJS) \
32 34
33!include "../../../CPP/Build.mak" 35!include "../../../CPP/Build.mak"
34 36
@@ -38,3 +40,5 @@ $(C_OBJS): ../../$(*B).c
38 $(CCOMPL_USE) 40 $(CCOMPL_USE)
39$O\Precomp.obj: Precomp.c 41$O\Precomp.obj: Precomp.c
40 $(CCOMPL_PCH) 42 $(CCOMPL_PCH)
43
44!include "../../Asm_c.mak"
diff --git a/C/Util/7zipInstall/7zipInstall.c b/C/Util/7zipInstall/7zipInstall.c
index 7f5fd19..7d8e8c4 100644
--- a/C/Util/7zipInstall/7zipInstall.c
+++ b/C/Util/7zipInstall/7zipInstall.c
@@ -1,5 +1,5 @@
1/* 7zipInstall.c - 7-Zip Installer 1/* 7zipInstall.c - 7-Zip Installer
22023-04-04 : Igor Pavlov : Public domain */ 22024-04-05 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -11,6 +11,8 @@
11#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union 11#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
12#endif 12#endif
13 13
14Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
15
14#ifdef Z7_OLD_WIN_SDK 16#ifdef Z7_OLD_WIN_SDK
15struct IShellView; 17struct IShellView;
16#define SHFOLDERAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE 18#define SHFOLDERAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
@@ -41,16 +43,6 @@ typedef enum {
41 // #pragma GCC diagnostic ignored "-Wcast-function-type" 43 // #pragma GCC diagnostic ignored "-Wcast-function-type"
42#endif 44#endif
43 45
44#if defined(__clang__) || defined(__GNUC__)
45typedef void (*Z7_voidFunction)(void);
46#define MY_CAST_FUNC (Z7_voidFunction)
47#elif defined(_MSC_VER) && _MSC_VER > 1920
48#define MY_CAST_FUNC (void *)
49// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()'
50#else
51#define MY_CAST_FUNC
52#endif
53
54#define LLL_(quote) L##quote 46#define LLL_(quote) L##quote
55#define LLL(quote) LLL_(quote) 47#define LLL(quote) LLL_(quote)
56 48
@@ -118,11 +110,13 @@ static LPCWSTR const k_Reg_Path32 = L"Path"
118 #define k_Reg_WOW_Flag 0 110 #define k_Reg_WOW_Flag 0
119#endif 111#endif
120 112
113#ifdef USE_7ZIP_32_DLL
121#ifdef _WIN64 114#ifdef _WIN64
122 #define k_Reg_WOW_Flag_32 KEY_WOW64_32KEY 115 #define k_Reg_WOW_Flag_32 KEY_WOW64_32KEY
123#else 116#else
124 #define k_Reg_WOW_Flag_32 0 117 #define k_Reg_WOW_Flag_32 0
125#endif 118#endif
119#endif
126 120
127#define k_7zip_CLSID L"{23170F69-40C1-278A-1000-000100020000}" 121#define k_7zip_CLSID L"{23170F69-40C1-278A-1000-000100020000}"
128 122
@@ -219,11 +213,11 @@ static DWORD GetFileVersion(LPCWSTR s)
219 return 0; 213 return 0;
220 } 214 }
221 215
222 my_GetFileVersionInfoSizeW = (Func_GetFileVersionInfoSizeW) MY_CAST_FUNC GetProcAddress(g_version_dll_hModule, 216 my_GetFileVersionInfoSizeW = (Func_GetFileVersionInfoSizeW) Z7_CAST_FUNC_C GetProcAddress(g_version_dll_hModule,
223 "GetFileVersionInfoSizeW"); 217 "GetFileVersionInfoSizeW");
224 my_GetFileVersionInfoW = (Func_GetFileVersionInfoW) MY_CAST_FUNC GetProcAddress(g_version_dll_hModule, 218 my_GetFileVersionInfoW = (Func_GetFileVersionInfoW) Z7_CAST_FUNC_C GetProcAddress(g_version_dll_hModule,
225 "GetFileVersionInfoW"); 219 "GetFileVersionInfoW");
226 my_VerQueryValueW = (Func_VerQueryValueW) MY_CAST_FUNC GetProcAddress(g_version_dll_hModule, 220 my_VerQueryValueW = (Func_VerQueryValueW) Z7_CAST_FUNC_C GetProcAddress(g_version_dll_hModule,
227 "VerQueryValueW"); 221 "VerQueryValueW");
228 222
229 if (!my_GetFileVersionInfoSizeW 223 if (!my_GetFileVersionInfoSizeW
@@ -1102,7 +1096,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
1102 { 1096 {
1103 BOOL isWow64 = FALSE; 1097 BOOL isWow64 = FALSE;
1104 const Func_IsWow64Process func_IsWow64Process = (Func_IsWow64Process) 1098 const Func_IsWow64Process func_IsWow64Process = (Func_IsWow64Process)
1105 MY_CAST_FUNC GetProcAddress(GetModuleHandleW(L"kernel32.dll"), 1099 Z7_CAST_FUNC_C GetProcAddress(GetModuleHandleW(L"kernel32.dll"),
1106 "IsWow64Process"); 1100 "IsWow64Process");
1107 1101
1108 if (func_IsWow64Process) 1102 if (func_IsWow64Process)
@@ -1111,7 +1105,13 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
1111 if (!isWow64) 1105 if (!isWow64)
1112 { 1106 {
1113 if (!g_SilentMode) 1107 if (!g_SilentMode)
1114 PrintErrorMessage("This installation requires Windows " MY_CPU_NAME, NULL); 1108 PrintErrorMessage("This installation requires Windows "
1109 #ifdef MY_CPU_X86_OR_AMD64
1110 "x64"
1111 #else
1112 "64-bit"
1113 #endif
1114 , NULL);
1115 return 1; 1115 return 1;
1116 } 1116 }
1117 } 1117 }
diff --git a/C/Util/7zipInstall/Precomp.h b/C/Util/7zipInstall/Precomp.h
index bc8fa21..13a41ef 100644
--- a/C/Util/7zipInstall/Precomp.h
+++ b/C/Util/7zipInstall/Precomp.h
@@ -1,14 +1,13 @@
1/* Precomp.h -- StdAfx 1/* Precomp.h -- Precomp
22023-03-04 : Igor Pavlov : Public domain */ 22024-01-23 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_PRECOMP_H 4// #ifndef ZIP7_INC_PRECOMP_LOC_H
5#define ZIP7_INC_PRECOMP_H 5// #define ZIP7_INC_PRECOMP_LOC_H
6 6
7#if defined(_MSC_VER) && _MSC_VER >= 1800 7#if defined(_MSC_VER) && _MSC_VER >= 1800
8#pragma warning(disable : 4464) // relative include path contains '..' 8#pragma warning(disable : 4464) // relative include path contains '..'
9#endif 9#endif
10 10
11#include "../../Compiler.h" 11#include "../../Precomp.h"
12#include "../../7zTypes.h"
13 12
14#endif 13// #endif
diff --git a/C/Util/7zipInstall/makefile b/C/Util/7zipInstall/makefile
index 18e2783..424bd6c 100644
--- a/C/Util/7zipInstall/makefile
+++ b/C/Util/7zipInstall/makefile
@@ -19,9 +19,6 @@ C_OBJS = \
19 $O\7zAlloc.obj \ 19 $O\7zAlloc.obj \
20 $O\7zArcIn.obj \ 20 $O\7zArcIn.obj \
21 $O\7zBuf.obj \ 21 $O\7zBuf.obj \
22 $O\7zBuf2.obj \
23 $O\7zCrc.obj \
24 $O\7zCrcOpt.obj \
25 $O\7zFile.obj \ 22 $O\7zFile.obj \
26 $O\7zDec.obj \ 23 $O\7zDec.obj \
27 $O\7zStream.obj \ 24 $O\7zStream.obj \
@@ -34,11 +31,17 @@ C_OBJS = \
34OBJS = \ 31OBJS = \
35 $(MAIN_OBJS) \ 32 $(MAIN_OBJS) \
36 $(C_OBJS) \ 33 $(C_OBJS) \
34 $(ASM_OBJS) \
37 $O\resource.res 35 $O\resource.res
38 36
37!include "../../../CPP/7zip/Crc.mak"
38# !include "../../../CPP/7zip/LzmaDec.mak"
39
39!include "../../../CPP/Build.mak" 40!include "../../../CPP/Build.mak"
40 41
41$(MAIN_OBJS): $(*B).c 42$(MAIN_OBJS): $(*B).c
42 $(COMPL_O1) 43 $(COMPL_O1)
43$(C_OBJS): ../../$(*B).c 44$(C_OBJS): ../../$(*B).c
44 $(COMPL_O1) 45 $(COMPL_O1)
46
47!include "../../Asm_c.mak"
diff --git a/C/Util/7zipInstall/resource.rc b/C/Util/7zipInstall/resource.rc
index df6474e..40ed580 100644
--- a/C/Util/7zipInstall/resource.rc
+++ b/C/Util/7zipInstall/resource.rc
@@ -1,5 +1,6 @@
1#include <winnt.h> 1#include <windows.h>
2#include <WinUser.h> 2// #include <winnt.h>
3// #include <WinUser.h>
3#include <CommCtrl.h> 4#include <CommCtrl.h>
4 5
5#define USE_COPYRIGHT_CR 6#define USE_COPYRIGHT_CR
diff --git a/C/Util/7zipUninstall/7zipUninstall.c b/C/Util/7zipUninstall/7zipUninstall.c
index 8bc18b3..e7051e2 100644
--- a/C/Util/7zipUninstall/7zipUninstall.c
+++ b/C/Util/7zipUninstall/7zipUninstall.c
@@ -1,10 +1,11 @@
1/* 7zipUninstall.c - 7-Zip Uninstaller 1/* 7zipUninstall.c - 7-Zip Uninstaller
22022-07-15 : Igor Pavlov : Public domain */ 22024-03-21 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
6// #define SZ_ERROR_ABORT 100 6// #define SZ_ERROR_ABORT 100
7 7
8#include "../../7zTypes.h"
8#include "../../7zWindows.h" 9#include "../../7zWindows.h"
9 10
10#if defined(_MSC_VER) && _MSC_VER < 1600 11#if defined(_MSC_VER) && _MSC_VER < 1600
@@ -31,16 +32,7 @@ typedef enum {
31 32
32#include "resource.h" 33#include "resource.h"
33 34
34#if (defined(__GNUC__) && (__GNUC__ >= 8)) || defined(__clang__)
35 // #pragma GCC diagnostic ignored "-Wcast-function-type"
36#endif
37 35
38#if defined(_MSC_VER) && _MSC_VER > 1920
39#define MY_CAST_FUNC (void *)
40// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()'
41#else
42#define MY_CAST_FUNC
43#endif
44 36
45 37
46#define LLL_(quote) L##quote 38#define LLL_(quote) L##quote
@@ -101,11 +93,13 @@ static LPCWSTR const k_Reg_Path32 = L"Path"
101 #define k_Reg_WOW_Flag 0 93 #define k_Reg_WOW_Flag 0
102#endif 94#endif
103 95
96#ifdef USE_7ZIP_32_DLL
104#ifdef _WIN64 97#ifdef _WIN64
105 #define k_Reg_WOW_Flag_32 KEY_WOW64_32KEY 98 #define k_Reg_WOW_Flag_32 KEY_WOW64_32KEY
106#else 99#else
107 #define k_Reg_WOW_Flag_32 0 100 #define k_Reg_WOW_Flag_32 0
108#endif 101#endif
102#endif
109 103
110#define k_7zip_CLSID L"{23170F69-40C1-278A-1000-000100020000}" 104#define k_7zip_CLSID L"{23170F69-40C1-278A-1000-000100020000}"
111 105
@@ -124,9 +118,19 @@ static HWND g_Path_HWND;
124static HWND g_InfoLine_HWND; 118static HWND g_InfoLine_HWND;
125static HWND g_Progress_HWND; 119static HWND g_Progress_HWND;
126 120
127// WINADVAPI 121// RegDeleteKeyExW is supported starting from win2003sp1/xp-pro-x64
122// Z7_WIN32_WINNT_MIN < 0x0600 // Vista
123#if !defined(Z7_WIN32_WINNT_MIN) \
124 || Z7_WIN32_WINNT_MIN < 0x0502 /* < win2003 */ \
125 || Z7_WIN32_WINNT_MIN == 0x0502 && !defined(_M_AMD64)
126#define Z7_USE_DYN_RegDeleteKeyExW
127#endif
128
129#ifdef Z7_USE_DYN_RegDeleteKeyExW
130Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
128typedef LONG (APIENTRY *Func_RegDeleteKeyExW)(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved); 131typedef LONG (APIENTRY *Func_RegDeleteKeyExW)(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved);
129static Func_RegDeleteKeyExW func_RegDeleteKeyExW; 132static Func_RegDeleteKeyExW func_RegDeleteKeyExW;
133#endif
130 134
131static WCHAR cmd[MAX_PATH + 4]; 135static WCHAR cmd[MAX_PATH + 4];
132static WCHAR cmdError[MAX_PATH + 4]; 136static WCHAR cmdError[MAX_PATH + 4];
@@ -247,13 +251,18 @@ static LONG MyRegistry_OpenKey_ReadWrite(HKEY parentKey, LPCWSTR name, HKEY *des
247 251
248static LONG MyRegistry_DeleteKey(HKEY parentKey, LPCWSTR name) 252static LONG MyRegistry_DeleteKey(HKEY parentKey, LPCWSTR name)
249{ 253{
250 #if k_Reg_WOW_Flag != 0 254#if k_Reg_WOW_Flag != 0
251 if (func_RegDeleteKeyExW) 255#ifdef Z7_USE_DYN_RegDeleteKeyExW
252 return func_RegDeleteKeyExW(parentKey, name, k_Reg_WOW_Flag, 0); 256 if (!func_RegDeleteKeyExW)
253 return E_FAIL; 257 return E_FAIL;
254 #else 258 return func_RegDeleteKeyExW
259#else
260 return RegDeleteKeyExW
261#endif
262 (parentKey, name, k_Reg_WOW_Flag, 0);
263#else
255 return RegDeleteKeyW(parentKey, name); 264 return RegDeleteKeyW(parentKey, name);
256 #endif 265#endif
257} 266}
258 267
259#ifdef USE_7ZIP_32_DLL 268#ifdef USE_7ZIP_32_DLL
@@ -278,13 +287,18 @@ static LONG MyRegistry_OpenKey_ReadWrite_32(HKEY parentKey, LPCWSTR name, HKEY *
278 287
279static LONG MyRegistry_DeleteKey_32(HKEY parentKey, LPCWSTR name) 288static LONG MyRegistry_DeleteKey_32(HKEY parentKey, LPCWSTR name)
280{ 289{
281 #if k_Reg_WOW_Flag_32 != 0 290#if k_Reg_WOW_Flag_32 != 0
282 if (func_RegDeleteKeyExW) 291#ifdef Z7_USE_DYN_RegDeleteKeyExW
283 return func_RegDeleteKeyExW(parentKey, name, k_Reg_WOW_Flag_32, 0); 292 if (!func_RegDeleteKeyExW)
284 return E_FAIL; 293 return E_FAIL;
285 #else 294 return func_RegDeleteKeyExW
295#else
296 return RegDeleteKeyExW
297#endif
298 (parentKey, name, k_Reg_WOW_Flag_32, 0);
299#else
286 return RegDeleteKeyW(parentKey, name); 300 return RegDeleteKeyW(parentKey, name);
287 #endif 301#endif
288} 302}
289 303
290#endif 304#endif
@@ -930,14 +944,17 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
930 UNUSED_VAR(lpCmdLine) 944 UNUSED_VAR(lpCmdLine)
931 UNUSED_VAR(nCmdShow) 945 UNUSED_VAR(nCmdShow)
932 946
933 #ifndef UNDER_CE 947#ifndef UNDER_CE
934 CoInitialize(NULL); 948 CoInitialize(NULL);
935 #endif 949#endif
936 950
937 #ifndef UNDER_CE 951#ifndef UNDER_CE
938 func_RegDeleteKeyExW = (Func_RegDeleteKeyExW) MY_CAST_FUNC 952#ifdef Z7_USE_DYN_RegDeleteKeyExW
939 GetProcAddress(GetModuleHandleW(L"advapi32.dll"), "RegDeleteKeyExW"); 953 func_RegDeleteKeyExW =
940 #endif 954 (Func_RegDeleteKeyExW) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandleW(L"advapi32.dll"),
955 "RegDeleteKeyExW");
956#endif
957#endif
941 958
942 { 959 {
943 const wchar_t *s = GetCommandLineW(); 960 const wchar_t *s = GetCommandLineW();
diff --git a/C/Util/7zipUninstall/Precomp.h b/C/Util/7zipUninstall/Precomp.h
index bc8fa21..13a41ef 100644
--- a/C/Util/7zipUninstall/Precomp.h
+++ b/C/Util/7zipUninstall/Precomp.h
@@ -1,14 +1,13 @@
1/* Precomp.h -- StdAfx 1/* Precomp.h -- Precomp
22023-03-04 : Igor Pavlov : Public domain */ 22024-01-23 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_PRECOMP_H 4// #ifndef ZIP7_INC_PRECOMP_LOC_H
5#define ZIP7_INC_PRECOMP_H 5// #define ZIP7_INC_PRECOMP_LOC_H
6 6
7#if defined(_MSC_VER) && _MSC_VER >= 1800 7#if defined(_MSC_VER) && _MSC_VER >= 1800
8#pragma warning(disable : 4464) // relative include path contains '..' 8#pragma warning(disable : 4464) // relative include path contains '..'
9#endif 9#endif
10 10
11#include "../../Compiler.h" 11#include "../../Precomp.h"
12#include "../../7zTypes.h"
13 12
14#endif 13// #endif
diff --git a/C/Util/7zipUninstall/resource.rc b/C/Util/7zipUninstall/resource.rc
index 00bdcc0..79400c6 100644
--- a/C/Util/7zipUninstall/resource.rc
+++ b/C/Util/7zipUninstall/resource.rc
@@ -1,5 +1,6 @@
1#include <winnt.h> 1#include <windows.h>
2#include <WinUser.h> 2// #include <winnt.h>
3// #include <WinUser.h>
3#include <CommCtrl.h> 4#include <CommCtrl.h>
4 5
5#define USE_COPYRIGHT_CR 6#define USE_COPYRIGHT_CR
diff --git a/C/Util/Lzma/Precomp.h b/C/Util/Lzma/Precomp.h
index bc8fa21..13a41ef 100644
--- a/C/Util/Lzma/Precomp.h
+++ b/C/Util/Lzma/Precomp.h
@@ -1,14 +1,13 @@
1/* Precomp.h -- StdAfx 1/* Precomp.h -- Precomp
22023-03-04 : Igor Pavlov : Public domain */ 22024-01-23 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_PRECOMP_H 4// #ifndef ZIP7_INC_PRECOMP_LOC_H
5#define ZIP7_INC_PRECOMP_H 5// #define ZIP7_INC_PRECOMP_LOC_H
6 6
7#if defined(_MSC_VER) && _MSC_VER >= 1800 7#if defined(_MSC_VER) && _MSC_VER >= 1800
8#pragma warning(disable : 4464) // relative include path contains '..' 8#pragma warning(disable : 4464) // relative include path contains '..'
9#endif 9#endif
10 10
11#include "../../Compiler.h" 11#include "../../Precomp.h"
12#include "../../7zTypes.h"
13 12
14#endif 13// #endif
diff --git a/C/Util/LzmaLib/Precomp.h b/C/Util/LzmaLib/Precomp.h
index bc8fa21..13a41ef 100644
--- a/C/Util/LzmaLib/Precomp.h
+++ b/C/Util/LzmaLib/Precomp.h
@@ -1,14 +1,13 @@
1/* Precomp.h -- StdAfx 1/* Precomp.h -- Precomp
22023-03-04 : Igor Pavlov : Public domain */ 22024-01-23 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_PRECOMP_H 4// #ifndef ZIP7_INC_PRECOMP_LOC_H
5#define ZIP7_INC_PRECOMP_H 5// #define ZIP7_INC_PRECOMP_LOC_H
6 6
7#if defined(_MSC_VER) && _MSC_VER >= 1800 7#if defined(_MSC_VER) && _MSC_VER >= 1800
8#pragma warning(disable : 4464) // relative include path contains '..' 8#pragma warning(disable : 4464) // relative include path contains '..'
9#endif 9#endif
10 10
11#include "../../Compiler.h" 11#include "../../Precomp.h"
12#include "../../7zTypes.h"
13 12
14#endif 13// #endif
diff --git a/C/Util/LzmaLib/makefile b/C/Util/LzmaLib/makefile
index b8e054e..9ed0aa4 100644
--- a/C/Util/LzmaLib/makefile
+++ b/C/Util/LzmaLib/makefile
@@ -14,16 +14,19 @@ C_OBJS = \
14 $O\CpuArch.obj \ 14 $O\CpuArch.obj \
15 $O\LzFind.obj \ 15 $O\LzFind.obj \
16 $O\LzFindMt.obj \ 16 $O\LzFindMt.obj \
17 $O\LzFindOpt.obj \
18 $O\LzmaDec.obj \ 17 $O\LzmaDec.obj \
19 $O\LzmaEnc.obj \ 18 $O\LzmaEnc.obj \
20 $O\LzmaLib.obj \ 19 $O\LzmaLib.obj \
21 $O\Threads.obj \ 20 $O\Threads.obj \
22 21
22!include "../../../CPP/7zip/LzFindOpt.mak"
23!include "../../../CPP/7zip/LzmaDec.mak"
24
23OBJS = \ 25OBJS = \
24 $O\Precomp.obj \ 26 $O\Precomp.obj \
25 $(LIB_OBJS) \ 27 $(LIB_OBJS) \
26 $(C_OBJS) \ 28 $(C_OBJS) \
29 $(ASM_OBJS) \
27 $O\resource.res 30 $O\resource.res
28 31
29!include "../../../CPP/Build.mak" 32!include "../../../CPP/Build.mak"
@@ -52,3 +55,5 @@ $(C_OBJS): ../../$(*B).c
52 $(CCOMPLB_USE) 55 $(CCOMPLB_USE)
53 56
54!ENDIF 57!ENDIF
58
59!include "../../Asm_c.mak"
diff --git a/C/Util/SfxSetup/Precomp.h b/C/Util/SfxSetup/Precomp.h
index bc8fa21..13a41ef 100644
--- a/C/Util/SfxSetup/Precomp.h
+++ b/C/Util/SfxSetup/Precomp.h
@@ -1,14 +1,13 @@
1/* Precomp.h -- StdAfx 1/* Precomp.h -- Precomp
22023-03-04 : Igor Pavlov : Public domain */ 22024-01-23 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_PRECOMP_H 4// #ifndef ZIP7_INC_PRECOMP_LOC_H
5#define ZIP7_INC_PRECOMP_H 5// #define ZIP7_INC_PRECOMP_LOC_H
6 6
7#if defined(_MSC_VER) && _MSC_VER >= 1800 7#if defined(_MSC_VER) && _MSC_VER >= 1800
8#pragma warning(disable : 4464) // relative include path contains '..' 8#pragma warning(disable : 4464) // relative include path contains '..'
9#endif 9#endif
10 10
11#include "../../Compiler.h" 11#include "../../Precomp.h"
12#include "../../7zTypes.h"
13 12
14#endif 13// #endif
diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c
index 7304a0b..9b5c1f9 100644
--- a/C/Util/SfxSetup/SfxSetup.c
+++ b/C/Util/SfxSetup/SfxSetup.c
@@ -1,5 +1,5 @@
1/* SfxSetup.c - 7z SFX Setup 1/* SfxSetup.c - 7z SFX Setup
22019-02-02 : Igor Pavlov : Public domain */ 22024-01-24 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -278,10 +278,10 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
278 #ifdef _CONSOLE 278 #ifdef _CONSOLE
279 SetConsoleCtrlHandler(HandlerRoutine, TRUE); 279 SetConsoleCtrlHandler(HandlerRoutine, TRUE);
280 #else 280 #else
281 UNUSED_VAR(hInstance); 281 UNUSED_VAR(hInstance)
282 UNUSED_VAR(hPrevInstance); 282 UNUSED_VAR(hPrevInstance)
283 UNUSED_VAR(lpCmdLine); 283 UNUSED_VAR(lpCmdLine)
284 UNUSED_VAR(nCmdShow); 284 UNUSED_VAR(nCmdShow)
285 #endif 285 #endif
286 286
287 CrcGenerateTable(); 287 CrcGenerateTable();
@@ -516,12 +516,13 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
516 #endif 516 #endif
517 517
518 { 518 {
519 const SRes res2 = File_Close(&outFile); 519 const WRes res2 = File_Close(&outFile);
520 if (res != SZ_OK) 520 if (res != SZ_OK)
521 break; 521 break;
522 if (res2 != SZ_OK) 522 if (res2 != 0)
523 { 523 {
524 res = res2; 524 errorMessage = "Can't close output file";
525 res = SZ_ERROR_FAIL;
525 break; 526 break;
526 } 527 }
527 } 528 }
diff --git a/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile
index bc0cf8b..b3f25a2 100644
--- a/C/Util/SfxSetup/makefile
+++ b/C/Util/SfxSetup/makefile
@@ -9,8 +9,6 @@ C_OBJS = \
9 $O\7zArcIn.obj \ 9 $O\7zArcIn.obj \
10 $O\7zBuf.obj \ 10 $O\7zBuf.obj \
11 $O\7zBuf2.obj \ 11 $O\7zBuf2.obj \
12 $O\7zCrc.obj \
13 $O\7zCrcOpt.obj \
14 $O\7zFile.obj \ 12 $O\7zFile.obj \
15 $O\7zDec.obj \ 13 $O\7zDec.obj \
16 $O\7zStream.obj \ 14 $O\7zStream.obj \
@@ -27,9 +25,13 @@ C_OBJS = \
277Z_OBJS = \ 257Z_OBJS = \
28 $O\SfxSetup.obj \ 26 $O\SfxSetup.obj \
29 27
28!include "../../../CPP/7zip/Crc.mak"
29# !include "../../../CPP/7zip/LzmaDec.mak"
30
30OBJS = \ 31OBJS = \
31 $(7Z_OBJS) \ 32 $(7Z_OBJS) \
32 $(C_OBJS) \ 33 $(C_OBJS) \
34 $(ASM_OBJS) \
33 $O\resource.res 35 $O\resource.res
34 36
35!include "../../../CPP/Build.mak" 37!include "../../../CPP/Build.mak"
@@ -38,3 +40,5 @@ $(7Z_OBJS): $(*B).c
38 $(COMPL_O1) 40 $(COMPL_O1)
39$(C_OBJS): ../../$(*B).c 41$(C_OBJS): ../../$(*B).c
40 $(COMPL_O1) 42 $(COMPL_O1)
43
44!include "../../Asm_c.mak"
diff --git a/C/Xxh64.c b/C/Xxh64.c
new file mode 100644
index 0000000..dc02a02
--- /dev/null
+++ b/C/Xxh64.c
@@ -0,0 +1,327 @@
1/* Xxh64.c -- XXH64 hash calculation
2original code: Copyright (c) Yann Collet.
32023-08-18 : modified by Igor Pavlov.
4This source code is licensed under BSD 2-Clause License.
5*/
6
7#include "Precomp.h"
8
9#include "CpuArch.h"
10#include "RotateDefs.h"
11#include "Xxh64.h"
12
13#define Z7_XXH_PRIME64_1 UINT64_CONST(0x9E3779B185EBCA87)
14#define Z7_XXH_PRIME64_2 UINT64_CONST(0xC2B2AE3D27D4EB4F)
15#define Z7_XXH_PRIME64_3 UINT64_CONST(0x165667B19E3779F9)
16#define Z7_XXH_PRIME64_4 UINT64_CONST(0x85EBCA77C2B2AE63)
17#define Z7_XXH_PRIME64_5 UINT64_CONST(0x27D4EB2F165667C5)
18
19void Xxh64State_Init(CXxh64State *p)
20{
21 const UInt64 seed = 0;
22 p->v[0] = seed + Z7_XXH_PRIME64_1 + Z7_XXH_PRIME64_2;
23 p->v[1] = seed + Z7_XXH_PRIME64_2;
24 p->v[2] = seed;
25 p->v[3] = seed - Z7_XXH_PRIME64_1;
26}
27
28#if !defined(MY_CPU_64BIT) && defined(MY_CPU_X86) && defined(_MSC_VER)
29 #define Z7_XXH64_USE_ASM
30#endif
31
32#if !defined(MY_CPU_64BIT) && defined(MY_CPU_X86) \
33 && defined(Z7_MSC_VER_ORIGINAL) && Z7_MSC_VER_ORIGINAL > 1200
34/* we try to avoid __allmul calls in MSVC for 64-bit multiply.
35 But MSVC6 still uses __allmul for our code.
36 So for MSVC6 we use default 64-bit multiply without our optimization.
37*/
38#define LOW32(b) ((UInt32)(b & 0xffffffff))
39/* MSVC compiler (MSVC > 1200) can use "mul" instruction
40 without __allmul for our MY_emulu MACRO.
41 MY_emulu is similar to __emulu(a, b) MACRO */
42#define MY_emulu(a, b) ((UInt64)(a) * (b))
43#define MY_SET_HIGH32(a) ((UInt64)(a) << 32)
44#define MY_MUL32_SET_HIGH32(a, b) MY_SET_HIGH32((UInt32)(a) * (UInt32)(b))
45// /*
46#define MY_MUL64(a, b) \
47 ( MY_emulu((UInt32)(a), LOW32(b)) + \
48 MY_SET_HIGH32( \
49 (UInt32)((a) >> 32) * LOW32(b) + \
50 (UInt32)(a) * (UInt32)((b) >> 32) \
51 ))
52// */
53/*
54#define MY_MUL64(a, b) \
55 ( MY_emulu((UInt32)(a), LOW32(b)) \
56 + MY_MUL32_SET_HIGH32((a) >> 32, LOW32(b)) + \
57 + MY_MUL32_SET_HIGH32(a, (b) >> 32) \
58 )
59*/
60
61#define MY_MUL_32_64(a32, b) \
62 ( MY_emulu((UInt32)(a32), LOW32(b)) \
63 + MY_MUL32_SET_HIGH32(a32, (b) >> 32) \
64 )
65
66#else
67#define MY_MUL64(a, b) ((a) * (b))
68#define MY_MUL_32_64(a32, b) ((a32) * (UInt64)(b))
69#endif
70
71
72static
73Z7_FORCE_INLINE
74UInt64 Xxh64_Round(UInt64 acc, UInt64 input)
75{
76 acc += MY_MUL64(input, Z7_XXH_PRIME64_2);
77 acc = Z7_ROTL64(acc, 31);
78 return MY_MUL64(acc, Z7_XXH_PRIME64_1);
79}
80
81static UInt64 Xxh64_Merge(UInt64 acc, UInt64 val)
82{
83 acc ^= Xxh64_Round(0, val);
84 return MY_MUL64(acc, Z7_XXH_PRIME64_1) + Z7_XXH_PRIME64_4;
85}
86
87
88#ifdef Z7_XXH64_USE_ASM
89
90#define Z7_XXH_PRIME64_1_HIGH 0x9E3779B1
91#define Z7_XXH_PRIME64_1_LOW 0x85EBCA87
92#define Z7_XXH_PRIME64_2_HIGH 0xC2B2AE3D
93#define Z7_XXH_PRIME64_2_LOW 0x27D4EB4F
94
95void
96Z7_NO_INLINE
97__declspec(naked)
98Z7_FASTCALL
99Xxh64State_UpdateBlocks(CXxh64State *p, const void *data, const void *end)
100{
101 #if !defined(__clang__)
102 UNUSED_VAR(p)
103 UNUSED_VAR(data)
104 UNUSED_VAR(end)
105 #endif
106 __asm push ebx
107 __asm push ebp
108 __asm push esi
109 __asm push edi
110
111 #define STACK_OFFSET 4 * 8
112 __asm sub esp, STACK_OFFSET
113
114#define COPY_1(n) \
115 __asm mov eax, [ecx + n * 4] \
116 __asm mov [esp + n * 4], eax \
117
118#define COPY_2(n) \
119 __asm mov eax, [esp + n * 4] \
120 __asm mov [ecx + n * 4], eax \
121
122 COPY_1(0)
123 __asm mov edi, [ecx + 1 * 4] \
124 COPY_1(2)
125 COPY_1(3)
126 COPY_1(4)
127 COPY_1(5)
128 COPY_1(6)
129 COPY_1(7)
130
131 __asm mov esi, edx \
132 __asm mov [esp + 0 * 8 + 4], ecx
133 __asm mov ecx, Z7_XXH_PRIME64_2_LOW \
134 __asm mov ebp, Z7_XXH_PRIME64_1_LOW \
135
136#define R(n, state1, state1_reg) \
137 __asm mov eax, [esi + n * 8] \
138 __asm imul ebx, eax, Z7_XXH_PRIME64_2_HIGH \
139 __asm add ebx, state1 \
140 __asm mul ecx \
141 __asm add edx, ebx \
142 __asm mov ebx, [esi + n * 8 + 4] \
143 __asm imul ebx, ecx \
144 __asm add eax, [esp + n * 8] \
145 __asm adc edx, ebx \
146 __asm mov ebx, eax \
147 __asm shld eax, edx, 31 \
148 __asm shld edx, ebx, 31 \
149 __asm imul state1_reg, eax, Z7_XXH_PRIME64_1_HIGH \
150 __asm imul edx, ebp \
151 __asm add state1_reg, edx \
152 __asm mul ebp \
153 __asm add state1_reg, edx \
154 __asm mov [esp + n * 8], eax \
155
156#define R2(n) \
157 R(n, [esp + n * 8 + 4], ebx) \
158 __asm mov [esp + n * 8 + 4], ebx \
159
160 __asm align 16
161 __asm main_loop:
162 R(0, edi, edi)
163 R2(1)
164 R2(2)
165 R2(3)
166 __asm add esi, 32
167 __asm cmp esi, [esp + STACK_OFFSET + 4 * 4 + 4]
168 __asm jne main_loop
169
170 __asm mov ecx, [esp + 0 * 8 + 4]
171
172 COPY_2(0)
173 __asm mov [ecx + 1 * 4], edi
174 COPY_2(2)
175 COPY_2(3)
176 COPY_2(4)
177 COPY_2(5)
178 COPY_2(6)
179 COPY_2(7)
180
181 __asm add esp, STACK_OFFSET
182 __asm pop edi
183 __asm pop esi
184 __asm pop ebp
185 __asm pop ebx
186 __asm ret 4
187}
188
189#else
190
191void
192Z7_NO_INLINE
193Z7_FASTCALL
194Xxh64State_UpdateBlocks(CXxh64State *p, const void *_data, const void *end)
195{
196 const Byte *data = (const Byte *)_data;
197 UInt64 v[4];
198 v[0] = p->v[0];
199 v[1] = p->v[1];
200 v[2] = p->v[2];
201 v[3] = p->v[3];
202 do
203 {
204 v[0] = Xxh64_Round(v[0], GetUi64(data)); data += 8;
205 v[1] = Xxh64_Round(v[1], GetUi64(data)); data += 8;
206 v[2] = Xxh64_Round(v[2], GetUi64(data)); data += 8;
207 v[3] = Xxh64_Round(v[3], GetUi64(data)); data += 8;
208 }
209 while (data != end);
210 p->v[0] = v[0];
211 p->v[1] = v[1];
212 p->v[2] = v[2];
213 p->v[3] = v[3];
214}
215
216#endif
217
218UInt64 Xxh64State_Digest(const CXxh64State *p, const void *_data, UInt64 count)
219{
220 UInt64 h = p->v[2];
221
222 if (count >= 32)
223 {
224 h = Z7_ROTL64(p->v[0], 1) +
225 Z7_ROTL64(p->v[1], 7) +
226 Z7_ROTL64(h, 12) +
227 Z7_ROTL64(p->v[3], 18);
228 h = Xxh64_Merge(h, p->v[0]);
229 h = Xxh64_Merge(h, p->v[1]);
230 h = Xxh64_Merge(h, p->v[2]);
231 h = Xxh64_Merge(h, p->v[3]);
232 }
233 else
234 h += Z7_XXH_PRIME64_5;
235
236 h += count;
237
238 // XXH64_finalize():
239 {
240 unsigned cnt = (unsigned)count & 31;
241 const Byte *data = (const Byte *)_data;
242 while (cnt >= 8)
243 {
244 h ^= Xxh64_Round(0, GetUi64(data));
245 data += 8;
246 h = Z7_ROTL64(h, 27);
247 h = MY_MUL64(h, Z7_XXH_PRIME64_1) + Z7_XXH_PRIME64_4;
248 cnt -= 8;
249 }
250 if (cnt >= 4)
251 {
252 const UInt32 v = GetUi32(data);
253 data += 4;
254 h ^= MY_MUL_32_64(v, Z7_XXH_PRIME64_1);
255 h = Z7_ROTL64(h, 23);
256 h = MY_MUL64(h, Z7_XXH_PRIME64_2) + Z7_XXH_PRIME64_3;
257 cnt -= 4;
258 }
259 while (cnt)
260 {
261 const UInt32 v = *data++;
262 h ^= MY_MUL_32_64(v, Z7_XXH_PRIME64_5);
263 h = Z7_ROTL64(h, 11);
264 h = MY_MUL64(h, Z7_XXH_PRIME64_1);
265 cnt--;
266 }
267 // XXH64_avalanche(h):
268 h ^= h >> 33; h = MY_MUL64(h, Z7_XXH_PRIME64_2);
269 h ^= h >> 29; h = MY_MUL64(h, Z7_XXH_PRIME64_3);
270 h ^= h >> 32;
271 return h;
272 }
273}
274
275
276void Xxh64_Init(CXxh64 *p)
277{
278 Xxh64State_Init(&p->state);
279 p->count = 0;
280 p->buf64[0] = 0;
281 p->buf64[1] = 0;
282 p->buf64[2] = 0;
283 p->buf64[3] = 0;
284}
285
286void Xxh64_Update(CXxh64 *p, const void *_data, size_t size)
287{
288 const Byte *data = (const Byte *)_data;
289 unsigned cnt;
290 if (size == 0)
291 return;
292 cnt = (unsigned)p->count;
293 p->count += size;
294
295 if (cnt &= 31)
296 {
297 unsigned rem = 32 - cnt;
298 Byte *dest = (Byte *)p->buf64 + cnt;
299 if (rem > size)
300 rem = (unsigned)size;
301 size -= rem;
302 cnt += rem;
303 // memcpy((Byte *)p->buf64 + cnt, data, rem);
304 do
305 *dest++ = *data++;
306 while (--rem);
307 if (cnt != 32)
308 return;
309 Xxh64State_UpdateBlocks(&p->state, p->buf64, &p->buf64[4]);
310 }
311
312 if (size &= ~(size_t)31)
313 {
314 Xxh64State_UpdateBlocks(&p->state, data, data + size);
315 data += size;
316 }
317
318 cnt = (unsigned)p->count & 31;
319 if (cnt)
320 {
321 // memcpy(p->buf64, data, cnt);
322 Byte *dest = (Byte *)p->buf64;
323 do
324 *dest++ = *data++;
325 while (--cnt);
326 }
327}
diff --git a/C/Xxh64.h b/C/Xxh64.h
new file mode 100644
index 0000000..efef65e
--- /dev/null
+++ b/C/Xxh64.h
@@ -0,0 +1,50 @@
1/* Xxh64.h -- XXH64 hash calculation interfaces
22023-08-18 : Igor Pavlov : Public domain */
3
4#ifndef ZIP7_INC_XXH64_H
5#define ZIP7_INC_XXH64_H
6
7#include "7zTypes.h"
8
9EXTERN_C_BEGIN
10
11#define Z7_XXH64_BLOCK_SIZE (4 * 8)
12
13typedef struct
14{
15 UInt64 v[4];
16} CXxh64State;
17
18void Xxh64State_Init(CXxh64State *p);
19
20// end != data && end == data + Z7_XXH64_BLOCK_SIZE * numBlocks
21void Z7_FASTCALL Xxh64State_UpdateBlocks(CXxh64State *p, const void *data, const void *end);
22
23/*
24Xxh64State_Digest():
25data:
26 the function processes only
27 (totalCount & (Z7_XXH64_BLOCK_SIZE - 1)) bytes in (data): (smaller than 32 bytes).
28totalCount: total size of hashed stream:
29 it includes total size of data processed by previous Xxh64State_UpdateBlocks() calls,
30 and it also includes current processed size in (data).
31*/
32UInt64 Xxh64State_Digest(const CXxh64State *p, const void *data, UInt64 totalCount);
33
34
35typedef struct
36{
37 CXxh64State state;
38 UInt64 count;
39 UInt64 buf64[4];
40} CXxh64;
41
42void Xxh64_Init(CXxh64 *p);
43void Xxh64_Update(CXxh64 *p, const void *data, size_t size);
44
45#define Xxh64_Digest(p) \
46 Xxh64State_Digest(&(p)->state, (p)->buf64, (p)->count)
47
48EXTERN_C_END
49
50#endif
diff --git a/C/Xz.c b/C/Xz.c
index 4ad0710..d07550d 100644
--- a/C/Xz.c
+++ b/C/Xz.c
@@ -1,5 +1,5 @@
1/* Xz.c - Xz 1/* Xz.c - Xz
22023-04-02 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -52,6 +52,7 @@ void XzCheck_Init(CXzCheck *p, unsigned mode)
52 case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break; 52 case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break;
53 case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break; 53 case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break;
54 case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break; 54 case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break;
55 default: break;
55 } 56 }
56} 57}
57 58
@@ -62,6 +63,7 @@ void XzCheck_Update(CXzCheck *p, const void *data, size_t size)
62 case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break; 63 case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break;
63 case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break; 64 case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break;
64 case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break; 65 case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break;
66 default: break;
65 } 67 }
66} 68}
67 69
diff --git a/C/Xz.h b/C/Xz.h
index d5001f6..42bc685 100644
--- a/C/Xz.h
+++ b/C/Xz.h
@@ -1,5 +1,5 @@
1/* Xz.h - Xz interface 1/* Xz.h - Xz interface
22023-04-13 : Igor Pavlov : Public domain */ 22024-01-26 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_XZ_H 4#ifndef ZIP7_INC_XZ_H
5#define ZIP7_INC_XZ_H 5#define ZIP7_INC_XZ_H
@@ -18,6 +18,7 @@ EXTERN_C_BEGIN
18#define XZ_ID_ARMT 8 18#define XZ_ID_ARMT 8
19#define XZ_ID_SPARC 9 19#define XZ_ID_SPARC 9
20#define XZ_ID_ARM64 0xa 20#define XZ_ID_ARM64 0xa
21#define XZ_ID_RISCV 0xb
21#define XZ_ID_LZMA2 0x21 22#define XZ_ID_LZMA2 0x21
22 23
23unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value); 24unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value);
@@ -233,13 +234,13 @@ typedef enum
233typedef struct 234typedef struct
234{ 235{
235 EXzState state; 236 EXzState state;
236 UInt32 pos; 237 unsigned pos;
237 unsigned alignPos; 238 unsigned alignPos;
238 unsigned indexPreSize; 239 unsigned indexPreSize;
239 240
240 CXzStreamFlags streamFlags; 241 CXzStreamFlags streamFlags;
241 242
242 UInt32 blockHeaderSize; 243 unsigned blockHeaderSize;
243 UInt64 packSize; 244 UInt64 packSize;
244 UInt64 unpackSize; 245 UInt64 unpackSize;
245 246
diff --git a/C/XzCrc64.c b/C/XzCrc64.c
index c2fad6c..94fc1af 100644
--- a/C/XzCrc64.c
+++ b/C/XzCrc64.c
@@ -1,5 +1,5 @@
1/* XzCrc64.c -- CRC64 calculation 1/* XzCrc64.c -- CRC64 calculation
22023-04-02 : Igor Pavlov : Public domain */ 22023-12-08 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -8,36 +8,76 @@
8 8
9#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42) 9#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42)
10 10
11#ifdef MY_CPU_LE 11// for debug only : define Z7_CRC64_DEBUG_BE to test big-endian code in little-endian cpu
12 #define CRC64_NUM_TABLES 4 12// #define Z7_CRC64_DEBUG_BE
13#ifdef Z7_CRC64_DEBUG_BE
14#undef MY_CPU_LE
15#define MY_CPU_BE
16#endif
17
18#ifdef Z7_CRC64_NUM_TABLES
19 #define Z7_CRC64_NUM_TABLES_USE Z7_CRC64_NUM_TABLES
13#else 20#else
14 #define CRC64_NUM_TABLES 5 21 #define Z7_CRC64_NUM_TABLES_USE 12
22#endif
15 23
16 UInt64 Z7_FASTCALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table); 24#if Z7_CRC64_NUM_TABLES_USE < 1
25 #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
17#endif 26#endif
18 27
28
29#if Z7_CRC64_NUM_TABLES_USE != 1
30
19#ifndef MY_CPU_BE 31#ifndef MY_CPU_BE
20 UInt64 Z7_FASTCALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); 32 #define FUNC_NAME_LE_2(s) XzCrc64UpdateT ## s
33 #define FUNC_NAME_LE_1(s) FUNC_NAME_LE_2(s)
34 #define FUNC_NAME_LE FUNC_NAME_LE_1(Z7_CRC64_NUM_TABLES_USE)
35 UInt64 Z7_FASTCALL FUNC_NAME_LE (UInt64 v, const void *data, size_t size, const UInt64 *table);
36#endif
37#ifndef MY_CPU_LE
38 #define FUNC_NAME_BE_2(s) XzCrc64UpdateBeT ## s
39 #define FUNC_NAME_BE_1(s) FUNC_NAME_BE_2(s)
40 #define FUNC_NAME_BE FUNC_NAME_BE_1(Z7_CRC64_NUM_TABLES_USE)
41 UInt64 Z7_FASTCALL FUNC_NAME_BE (UInt64 v, const void *data, size_t size, const UInt64 *table);
21#endif 42#endif
22 43
23typedef UInt64 (Z7_FASTCALL *CRC64_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table); 44#if defined(MY_CPU_LE)
45 #define FUNC_REF FUNC_NAME_LE
46#elif defined(MY_CPU_BE)
47 #define FUNC_REF FUNC_NAME_BE
48#else
49 #define FUNC_REF g_Crc64Update
50 static UInt64 (Z7_FASTCALL *FUNC_REF)(UInt64 v, const void *data, size_t size, const UInt64 *table);
51#endif
52
53#endif
54
55
56MY_ALIGN(64)
57static UInt64 g_Crc64Table[256 * Z7_CRC64_NUM_TABLES_USE];
24 58
25static CRC64_FUNC g_Crc64Update;
26UInt64 g_Crc64Table[256 * CRC64_NUM_TABLES];
27 59
28UInt64 Z7_FASTCALL Crc64Update(UInt64 v, const void *data, size_t size) 60UInt64 Z7_FASTCALL Crc64Update(UInt64 v, const void *data, size_t size)
29{ 61{
30 return g_Crc64Update(v, data, size, g_Crc64Table); 62#if Z7_CRC64_NUM_TABLES_USE == 1
63 #define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
64 const UInt64 *table = g_Crc64Table;
65 const Byte *p = (const Byte *)data;
66 const Byte *lim = p + size;
67 for (; p != lim; p++)
68 v = CRC64_UPDATE_BYTE_2(v, *p);
69 return v;
70 #undef CRC64_UPDATE_BYTE_2
71#else
72 return FUNC_REF (v, data, size, g_Crc64Table);
73#endif
31} 74}
32 75
33UInt64 Z7_FASTCALL Crc64Calc(const void *data, size_t size)
34{
35 return g_Crc64Update(CRC64_INIT_VAL, data, size, g_Crc64Table) ^ CRC64_INIT_VAL;
36}
37 76
77Z7_NO_INLINE
38void Z7_FASTCALL Crc64GenerateTable(void) 78void Z7_FASTCALL Crc64GenerateTable(void)
39{ 79{
40 UInt32 i; 80 unsigned i;
41 for (i = 0; i < 256; i++) 81 for (i = 0; i < 256; i++)
42 { 82 {
43 UInt64 r = i; 83 UInt64 r = i;
@@ -46,35 +86,55 @@ void Z7_FASTCALL Crc64GenerateTable(void)
46 r = (r >> 1) ^ (kCrc64Poly & ((UInt64)0 - (r & 1))); 86 r = (r >> 1) ^ (kCrc64Poly & ((UInt64)0 - (r & 1)));
47 g_Crc64Table[i] = r; 87 g_Crc64Table[i] = r;
48 } 88 }
49 for (i = 256; i < 256 * CRC64_NUM_TABLES; i++) 89
90#if Z7_CRC64_NUM_TABLES_USE != 1
91#if 1 || 1 && defined(MY_CPU_X86) // low register count
92 for (i = 0; i < 256 * (Z7_CRC64_NUM_TABLES_USE - 1); i++)
50 { 93 {
51 const UInt64 r = g_Crc64Table[(size_t)i - 256]; 94 const UInt64 r0 = g_Crc64Table[(size_t)i];
52 g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8); 95 g_Crc64Table[(size_t)i + 256] = g_Crc64Table[(Byte)r0] ^ (r0 >> 8);
53 } 96 }
54 97#else
55 #ifdef MY_CPU_LE 98 for (i = 0; i < 256 * (Z7_CRC64_NUM_TABLES_USE - 1); i += 2)
56 99 {
57 g_Crc64Update = XzCrc64UpdateT4; 100 UInt64 r0 = g_Crc64Table[(size_t)(i) ];
101 UInt64 r1 = g_Crc64Table[(size_t)(i) + 1];
102 r0 = g_Crc64Table[(Byte)r0] ^ (r0 >> 8);
103 r1 = g_Crc64Table[(Byte)r1] ^ (r1 >> 8);
104 g_Crc64Table[(size_t)i + 256 ] = r0;
105 g_Crc64Table[(size_t)i + 256 + 1] = r1;
106 }
107#endif
58 108
59 #else 109#ifndef MY_CPU_LE
60 { 110 {
61 #ifndef MY_CPU_BE 111#ifndef MY_CPU_BE
62 UInt32 k = 1; 112 UInt32 k = 1;
63 if (*(const Byte *)&k == 1) 113 if (*(const Byte *)&k == 1)
64 g_Crc64Update = XzCrc64UpdateT4; 114 FUNC_REF = FUNC_NAME_LE;
65 else 115 else
66 #endif 116#endif
67 { 117 {
68 for (i = 256 * CRC64_NUM_TABLES - 1; i >= 256; i--) 118#ifndef MY_CPU_BE
119 FUNC_REF = FUNC_NAME_BE;
120#endif
121 for (i = 0; i < 256 * Z7_CRC64_NUM_TABLES_USE; i++)
69 { 122 {
70 const UInt64 x = g_Crc64Table[(size_t)i - 256]; 123 const UInt64 x = g_Crc64Table[i];
71 g_Crc64Table[i] = Z7_BSWAP64(x); 124 g_Crc64Table[i] = Z7_BSWAP64(x);
72 } 125 }
73 g_Crc64Update = XzCrc64UpdateT1_BeT4;
74 } 126 }
75 } 127 }
76 #endif 128#endif // ndef MY_CPU_LE
129#endif // Z7_CRC64_NUM_TABLES_USE != 1
77} 130}
78 131
79#undef kCrc64Poly 132#undef kCrc64Poly
80#undef CRC64_NUM_TABLES 133#undef Z7_CRC64_NUM_TABLES_USE
134#undef FUNC_REF
135#undef FUNC_NAME_LE_2
136#undef FUNC_NAME_LE_1
137#undef FUNC_NAME_LE
138#undef FUNC_NAME_BE_2
139#undef FUNC_NAME_BE_1
140#undef FUNC_NAME_BE
diff --git a/C/XzCrc64.h b/C/XzCrc64.h
index ca46869..04f8153 100644
--- a/C/XzCrc64.h
+++ b/C/XzCrc64.h
@@ -1,5 +1,5 @@
1/* XzCrc64.h -- CRC64 calculation 1/* XzCrc64.h -- CRC64 calculation
22023-04-02 : Igor Pavlov : Public domain */ 22023-12-08 : Igor Pavlov : Public domain */
3 3
4#ifndef ZIP7_INC_XZ_CRC64_H 4#ifndef ZIP7_INC_XZ_CRC64_H
5#define ZIP7_INC_XZ_CRC64_H 5#define ZIP7_INC_XZ_CRC64_H
@@ -10,16 +10,16 @@
10 10
11EXTERN_C_BEGIN 11EXTERN_C_BEGIN
12 12
13extern UInt64 g_Crc64Table[]; 13// extern UInt64 g_Crc64Table[];
14 14
15void Z7_FASTCALL Crc64GenerateTable(void); 15void Z7_FASTCALL Crc64GenerateTable(void);
16 16
17#define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF) 17#define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF)
18#define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL) 18#define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL)
19#define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) 19// #define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
20 20
21UInt64 Z7_FASTCALL Crc64Update(UInt64 crc, const void *data, size_t size); 21UInt64 Z7_FASTCALL Crc64Update(UInt64 crc, const void *data, size_t size);
22UInt64 Z7_FASTCALL Crc64Calc(const void *data, size_t size); 22// UInt64 Z7_FASTCALL Crc64Calc(const void *data, size_t size);
23 23
24EXTERN_C_END 24EXTERN_C_END
25 25
diff --git a/C/XzCrc64Opt.c b/C/XzCrc64Opt.c
index d03374c..0c1fc2f 100644
--- a/C/XzCrc64Opt.c
+++ b/C/XzCrc64Opt.c
@@ -1,61 +1,261 @@
1/* XzCrc64Opt.c -- CRC64 calculation 1/* XzCrc64Opt.c -- CRC64 calculation (optimized functions)
22023-04-02 : Igor Pavlov : Public domain */ 22023-12-08 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
6#include "CpuArch.h" 6#include "CpuArch.h"
7 7
8#if !defined(Z7_CRC64_NUM_TABLES) || Z7_CRC64_NUM_TABLES > 1
9
10// for debug only : define Z7_CRC64_DEBUG_BE to test big-endian code in little-endian cpu
11// #define Z7_CRC64_DEBUG_BE
12#ifdef Z7_CRC64_DEBUG_BE
13#undef MY_CPU_LE
14#define MY_CPU_BE
15#endif
16
17#if defined(MY_CPU_64BIT)
18#define Z7_CRC64_USE_64BIT
19#endif
20
21// the value Z7_CRC64_NUM_TABLES_USE must be defined to same value as in XzCrc64.c
22#ifdef Z7_CRC64_NUM_TABLES
23#define Z7_CRC64_NUM_TABLES_USE Z7_CRC64_NUM_TABLES
24#else
25#define Z7_CRC64_NUM_TABLES_USE 12
26#endif
27
28#if Z7_CRC64_NUM_TABLES_USE % 4 || \
29 Z7_CRC64_NUM_TABLES_USE < 4 || \
30 Z7_CRC64_NUM_TABLES_USE > 4 * 4
31 #error Stop_Compiling_Bad_CRC64_NUM_TABLES
32#endif
33
34
8#ifndef MY_CPU_BE 35#ifndef MY_CPU_BE
9 36
10#define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) 37#define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
38
39#if defined(Z7_CRC64_USE_64BIT) && (Z7_CRC64_NUM_TABLES_USE % 8 == 0)
11 40
12UInt64 Z7_FASTCALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); 41#define Q64LE(n, d) \
13UInt64 Z7_FASTCALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table) 42 ( (table + ((n) * 8 + 7) * 0x100)[((d) ) & 0xFF] \
43 ^ (table + ((n) * 8 + 6) * 0x100)[((d) >> 1 * 8) & 0xFF] \
44 ^ (table + ((n) * 8 + 5) * 0x100)[((d) >> 2 * 8) & 0xFF] \
45 ^ (table + ((n) * 8 + 4) * 0x100)[((d) >> 3 * 8) & 0xFF] \
46 ^ (table + ((n) * 8 + 3) * 0x100)[((d) >> 4 * 8) & 0xFF] \
47 ^ (table + ((n) * 8 + 2) * 0x100)[((d) >> 5 * 8) & 0xFF] \
48 ^ (table + ((n) * 8 + 1) * 0x100)[((d) >> 6 * 8) & 0xFF] \
49 ^ (table + ((n) * 8 + 0) * 0x100)[((d) >> 7 * 8)] )
50
51#define R64(a) *((const UInt64 *)(const void *)p + (a))
52
53#else
54
55#define Q32LE(n, d) \
56 ( (table + ((n) * 4 + 3) * 0x100)[((d) ) & 0xFF] \
57 ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \
58 ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \
59 ^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] )
60
61#define R32(a) *((const UInt32 *)(const void *)p + (a))
62
63#endif
64
65
66#define CRC64_FUNC_PRE_LE2(step) \
67UInt64 Z7_FASTCALL XzCrc64UpdateT ## step (UInt64 v, const void *data, size_t size, const UInt64 *table)
68
69#define CRC64_FUNC_PRE_LE(step) \
70 CRC64_FUNC_PRE_LE2(step); \
71 CRC64_FUNC_PRE_LE2(step)
72
73CRC64_FUNC_PRE_LE(Z7_CRC64_NUM_TABLES_USE)
14{ 74{
15 const Byte *p = (const Byte *)data; 75 const Byte *p = (const Byte *)data;
16 for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) 76 const Byte *lim;
77 for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC64_NUM_TABLES_USE & 4))) != 0; size--, p++)
17 v = CRC64_UPDATE_BYTE_2(v, *p); 78 v = CRC64_UPDATE_BYTE_2(v, *p);
18 for (; size >= 4; size -= 4, p += 4) 79 lim = p + size;
80 if (size >= Z7_CRC64_NUM_TABLES_USE)
19 { 81 {
20 const UInt32 d = (UInt32)v ^ *(const UInt32 *)(const void *)p; 82 lim -= Z7_CRC64_NUM_TABLES_USE;
21 v = (v >> 32) 83 do
22 ^ (table + 0x300)[((d ) & 0xFF)] 84 {
23 ^ (table + 0x200)[((d >> 8) & 0xFF)] 85#if Z7_CRC64_NUM_TABLES_USE == 4
24 ^ (table + 0x100)[((d >> 16) & 0xFF)] 86 const UInt32 d = (UInt32)v ^ R32(0);
25 ^ (table + 0x000)[((d >> 24))]; 87 v = (v >> 32) ^ Q32LE(0, d);
88#elif Z7_CRC64_NUM_TABLES_USE == 8
89#ifdef Z7_CRC64_USE_64BIT
90 v ^= R64(0);
91 v = Q64LE(0, v);
92#else
93 UInt32 v0, v1;
94 v0 = (UInt32)v ^ R32(0);
95 v1 = (UInt32)(v >> 32) ^ R32(1);
96 v = Q32LE(1, v0) ^ Q32LE(0, v1);
97#endif
98#elif Z7_CRC64_NUM_TABLES_USE == 12
99 UInt32 w;
100 UInt32 v0, v1;
101 v0 = (UInt32)v ^ R32(0);
102 v1 = (UInt32)(v >> 32) ^ R32(1);
103 w = R32(2);
104 v = Q32LE(0, w);
105 v ^= Q32LE(2, v0) ^ Q32LE(1, v1);
106#elif Z7_CRC64_NUM_TABLES_USE == 16
107#ifdef Z7_CRC64_USE_64BIT
108 UInt64 w;
109 UInt64 x;
110 w = R64(1); x = Q64LE(0, w);
111 v ^= R64(0); v = x ^ Q64LE(1, v);
112#else
113 UInt32 v0, v1;
114 UInt32 r0, r1;
115 v0 = (UInt32)v ^ R32(0);
116 v1 = (UInt32)(v >> 32) ^ R32(1);
117 r0 = R32(2);
118 r1 = R32(3);
119 v = Q32LE(1, r0) ^ Q32LE(0, r1);
120 v ^= Q32LE(3, v0) ^ Q32LE(2, v1);
121#endif
122#else
123#error Stop_Compiling_Bad_CRC64_NUM_TABLES
124#endif
125 p += Z7_CRC64_NUM_TABLES_USE;
126 }
127 while (p <= lim);
128 lim += Z7_CRC64_NUM_TABLES_USE;
26 } 129 }
27 for (; size > 0; size--, p++) 130 for (; p < lim; p++)
28 v = CRC64_UPDATE_BYTE_2(v, *p); 131 v = CRC64_UPDATE_BYTE_2(v, *p);
29 return v; 132 return v;
30} 133}
31 134
135#undef CRC64_UPDATE_BYTE_2
136#undef R32
137#undef R64
138#undef Q32LE
139#undef Q64LE
140#undef CRC64_FUNC_PRE_LE
141#undef CRC64_FUNC_PRE_LE2
142
32#endif 143#endif
33 144
34 145
146
147
35#ifndef MY_CPU_LE 148#ifndef MY_CPU_LE
36 149
37#define CRC64_UPDATE_BYTE_2_BE(crc, b) (table[(Byte)((crc) >> 56) ^ (b)] ^ ((crc) << 8)) 150#define CRC64_UPDATE_BYTE_2_BE(crc, b) (table[((crc) >> 56) ^ (b)] ^ ((crc) << 8))
151
152#if defined(Z7_CRC64_USE_64BIT) && (Z7_CRC64_NUM_TABLES_USE % 8 == 0)
153
154#define Q64BE(n, d) \
155 ( (table + ((n) * 8 + 0) * 0x100)[(Byte)(d)] \
156 ^ (table + ((n) * 8 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \
157 ^ (table + ((n) * 8 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \
158 ^ (table + ((n) * 8 + 3) * 0x100)[((d) >> 3 * 8) & 0xFF] \
159 ^ (table + ((n) * 8 + 4) * 0x100)[((d) >> 4 * 8) & 0xFF] \
160 ^ (table + ((n) * 8 + 5) * 0x100)[((d) >> 5 * 8) & 0xFF] \
161 ^ (table + ((n) * 8 + 6) * 0x100)[((d) >> 6 * 8) & 0xFF] \
162 ^ (table + ((n) * 8 + 7) * 0x100)[((d) >> 7 * 8)] )
163
164#ifdef Z7_CRC64_DEBUG_BE
165 #define R64BE(a) GetBe64a((const UInt64 *)(const void *)p + (a))
166#else
167 #define R64BE(a) *((const UInt64 *)(const void *)p + (a))
168#endif
169
170#else
171
172#define Q32BE(n, d) \
173 ( (table + ((n) * 4 + 0) * 0x100)[(Byte)(d)] \
174 ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \
175 ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \
176 ^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] )
38 177
39UInt64 Z7_FASTCALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table); 178#ifdef Z7_CRC64_DEBUG_BE
40UInt64 Z7_FASTCALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table) 179 #define R32BE(a) GetBe32a((const UInt32 *)(const void *)p + (a))
180#else
181 #define R32BE(a) *((const UInt32 *)(const void *)p + (a))
182#endif
183
184#endif
185
186#define CRC64_FUNC_PRE_BE2(step) \
187UInt64 Z7_FASTCALL XzCrc64UpdateBeT ## step (UInt64 v, const void *data, size_t size, const UInt64 *table)
188
189#define CRC64_FUNC_PRE_BE(step) \
190 CRC64_FUNC_PRE_BE2(step); \
191 CRC64_FUNC_PRE_BE2(step)
192
193CRC64_FUNC_PRE_BE(Z7_CRC64_NUM_TABLES_USE)
41{ 194{
42 const Byte *p = (const Byte *)data; 195 const Byte *p = (const Byte *)data;
43 table += 0x100; 196 const Byte *lim;
44 v = Z7_BSWAP64(v); 197 v = Z7_BSWAP64(v);
45 for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) 198 for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC64_NUM_TABLES_USE & 4))) != 0; size--, p++)
46 v = CRC64_UPDATE_BYTE_2_BE(v, *p); 199 v = CRC64_UPDATE_BYTE_2_BE(v, *p);
47 for (; size >= 4; size -= 4, p += 4) 200 lim = p + size;
201 if (size >= Z7_CRC64_NUM_TABLES_USE)
48 { 202 {
49 const UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)(const void *)p; 203 lim -= Z7_CRC64_NUM_TABLES_USE;
50 v = (v << 32) 204 do
51 ^ (table + 0x000)[((d ) & 0xFF)] 205 {
52 ^ (table + 0x100)[((d >> 8) & 0xFF)] 206#if Z7_CRC64_NUM_TABLES_USE == 4
53 ^ (table + 0x200)[((d >> 16) & 0xFF)] 207 const UInt32 d = (UInt32)(v >> 32) ^ R32BE(0);
54 ^ (table + 0x300)[((d >> 24))]; 208 v = (v << 32) ^ Q32BE(0, d);
209#elif Z7_CRC64_NUM_TABLES_USE == 12
210 const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0);
211 const UInt32 d0 = (UInt32)(v ) ^ R32BE(1);
212 const UInt32 w = R32BE(2);
213 v = Q32BE(0, w);
214 v ^= Q32BE(2, d1) ^ Q32BE(1, d0);
215
216#elif Z7_CRC64_NUM_TABLES_USE == 8
217 #ifdef Z7_CRC64_USE_64BIT
218 v ^= R64BE(0);
219 v = Q64BE(0, v);
220 #else
221 const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0);
222 const UInt32 d0 = (UInt32)(v ) ^ R32BE(1);
223 v = Q32BE(1, d1) ^ Q32BE(0, d0);
224 #endif
225#elif Z7_CRC64_NUM_TABLES_USE == 16
226 #ifdef Z7_CRC64_USE_64BIT
227 const UInt64 w = R64BE(1);
228 v ^= R64BE(0);
229 v = Q64BE(0, w) ^ Q64BE(1, v);
230 #else
231 const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0);
232 const UInt32 d0 = (UInt32)(v ) ^ R32BE(1);
233 const UInt32 w1 = R32BE(2);
234 const UInt32 w0 = R32BE(3);
235 v = Q32BE(1, w1) ^ Q32BE(0, w0);
236 v ^= Q32BE(3, d1) ^ Q32BE(2, d0);
237 #endif
238#elif
239#error Stop_Compiling_Bad_CRC64_NUM_TABLES
240#endif
241 p += Z7_CRC64_NUM_TABLES_USE;
242 }
243 while (p <= lim);
244 lim += Z7_CRC64_NUM_TABLES_USE;
55 } 245 }
56 for (; size > 0; size--, p++) 246 for (; p < lim; p++)
57 v = CRC64_UPDATE_BYTE_2_BE(v, *p); 247 v = CRC64_UPDATE_BYTE_2_BE(v, *p);
58 return Z7_BSWAP64(v); 248 return Z7_BSWAP64(v);
59} 249}
60 250
251#undef CRC64_UPDATE_BYTE_2_BE
252#undef R32BE
253#undef R64BE
254#undef Q32BE
255#undef Q64BE
256#undef CRC64_FUNC_PRE_BE
257#undef CRC64_FUNC_PRE_BE2
258
259#endif
260#undef Z7_CRC64_NUM_TABLES_USE
61#endif 261#endif
diff --git a/C/XzDec.c b/C/XzDec.c
index a5f7039..3d1c98e 100644
--- a/C/XzDec.c
+++ b/C/XzDec.c
@@ -1,5 +1,5 @@
1/* XzDec.c -- Xz Decode 1/* XzDec.c -- Xz Decode
22023-04-13 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -105,30 +105,32 @@ static SRes XzBcFilterState_SetProps(void *pp, const Byte *props, size_t propSiz
105 { 105 {
106 if (propSize != 1) 106 if (propSize != 1)
107 return SZ_ERROR_UNSUPPORTED; 107 return SZ_ERROR_UNSUPPORTED;
108 p->delta = (unsigned)props[0] + 1; 108 p->delta = (UInt32)props[0] + 1;
109 } 109 }
110 else 110 else
111 { 111 {
112 if (propSize == 4) 112 if (propSize == 4)
113 { 113 {
114 UInt32 v = GetUi32(props); 114 const UInt32 v = GetUi32(props);
115 switch (p->methodId) 115 switch (p->methodId)
116 { 116 {
117 case XZ_ID_PPC: 117 case XZ_ID_PPC:
118 case XZ_ID_ARM: 118 case XZ_ID_ARM:
119 case XZ_ID_SPARC: 119 case XZ_ID_SPARC:
120 case XZ_ID_ARM64: 120 case XZ_ID_ARM64:
121 if ((v & 3) != 0) 121 if (v & 3)
122 return SZ_ERROR_UNSUPPORTED; 122 return SZ_ERROR_UNSUPPORTED;
123 break; 123 break;
124 case XZ_ID_ARMT: 124 case XZ_ID_ARMT:
125 if ((v & 1) != 0) 125 case XZ_ID_RISCV:
126 if (v & 1)
126 return SZ_ERROR_UNSUPPORTED; 127 return SZ_ERROR_UNSUPPORTED;
127 break; 128 break;
128 case XZ_ID_IA64: 129 case XZ_ID_IA64:
129 if ((v & 0xF) != 0) 130 if (v & 0xf)
130 return SZ_ERROR_UNSUPPORTED; 131 return SZ_ERROR_UNSUPPORTED;
131 break; 132 break;
133 default: break;
132 } 134 }
133 p->ip = v; 135 p->ip = v;
134 } 136 }
@@ -151,12 +153,13 @@ static void XzBcFilterState_Init(void *pp)
151 153
152static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Dec[] = 154static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Dec[] =
153{ 155{
154 Z7_BRANCH_CONV_DEC(PPC), 156 Z7_BRANCH_CONV_DEC_2 (BranchConv_PPC),
155 Z7_BRANCH_CONV_DEC(IA64), 157 Z7_BRANCH_CONV_DEC_2 (BranchConv_IA64),
156 Z7_BRANCH_CONV_DEC(ARM), 158 Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM),
157 Z7_BRANCH_CONV_DEC(ARMT), 159 Z7_BRANCH_CONV_DEC_2 (BranchConv_ARMT),
158 Z7_BRANCH_CONV_DEC(SPARC), 160 Z7_BRANCH_CONV_DEC_2 (BranchConv_SPARC),
159 Z7_BRANCH_CONV_DEC(ARM64) 161 Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM64),
162 Z7_BRANCH_CONV_DEC_2 (BranchConv_RISCV)
160}; 163};
161 164
162static SizeT XzBcFilterStateBase_Filter_Dec(CXzBcFilterStateBase *p, Byte *data, SizeT size) 165static SizeT XzBcFilterStateBase_Filter_Dec(CXzBcFilterStateBase *p, Byte *data, SizeT size)
@@ -262,7 +265,7 @@ static SRes XzBcFilterState_Code2(void *pp,
262 265
263 266
264#define XZ_IS_SUPPORTED_FILTER_ID(id) \ 267#define XZ_IS_SUPPORTED_FILTER_ID(id) \
265 ((id) >= XZ_ID_Delta && (id) <= XZ_ID_ARM64) 268 ((id) >= XZ_ID_Delta && (id) <= XZ_ID_RISCV)
266 269
267SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id, 270SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id,
268 Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc) 271 Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc)
@@ -541,13 +544,12 @@ static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 met
541{ 544{
542 IStateCoder *sc = &p->coders[coderIndex]; 545 IStateCoder *sc = &p->coders[coderIndex];
543 p->ids[coderIndex] = methodId; 546 p->ids[coderIndex] = methodId;
544 switch (methodId) 547 if (methodId == XZ_ID_LZMA2)
545 { 548 return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);
546 case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc); 549#ifdef USE_SUBBLOCK
547 #ifdef USE_SUBBLOCK 550 if (methodId == XZ_ID_Subblock)
548 case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc); 551 return SbState_SetFromMethod(sc, p->alloc);
549 #endif 552#endif
550 }
551 if (coderIndex == 0) 553 if (coderIndex == 0)
552 return SZ_ERROR_UNSUPPORTED; 554 return SZ_ERROR_UNSUPPORTED;
553 return Xz_StateCoder_Bc_SetFromMethod_Func(sc, methodId, 555 return Xz_StateCoder_Bc_SetFromMethod_Func(sc, methodId,
@@ -558,10 +560,8 @@ static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 met
558static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) 560static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
559{ 561{
560 IStateCoder *sc = &p->coders[coderIndex]; 562 IStateCoder *sc = &p->coders[coderIndex];
561 switch (methodId) 563 if (methodId == XZ_ID_LZMA2)
562 { 564 return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
563 case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
564 }
565 return SZ_ERROR_UNSUPPORTED; 565 return SZ_ERROR_UNSUPPORTED;
566} 566}
567 567
@@ -804,7 +804,7 @@ static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte
804} 804}
805 805
806#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ 806#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
807 { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ 807 { const unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
808 if (s == 0) return SZ_ERROR_ARCHIVE; \ 808 if (s == 0) return SZ_ERROR_ARCHIVE; \
809 pos += s; } 809 pos += s; }
810 810
@@ -1034,7 +1034,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1034 SRes res; 1034 SRes res;
1035 1035
1036 ECoderFinishMode finishMode2 = finishMode; 1036 ECoderFinishMode finishMode2 = finishMode;
1037 BoolInt srcFinished2 = srcFinished; 1037 BoolInt srcFinished2 = (BoolInt)srcFinished;
1038 BoolInt destFinish = False; 1038 BoolInt destFinish = False;
1039 1039
1040 if (p->block.packSize != (UInt64)(Int64)-1) 1040 if (p->block.packSize != (UInt64)(Int64)-1)
@@ -1127,7 +1127,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1127 return SZ_OK; 1127 return SZ_OK;
1128 } 1128 }
1129 1129
1130 switch (p->state) 1130 switch ((int)p->state)
1131 { 1131 {
1132 case XZ_STATE_STREAM_HEADER: 1132 case XZ_STATE_STREAM_HEADER:
1133 { 1133 {
@@ -1172,15 +1172,15 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1172 p->state = XZ_STATE_STREAM_INDEX; 1172 p->state = XZ_STATE_STREAM_INDEX;
1173 break; 1173 break;
1174 } 1174 }
1175 p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4; 1175 p->blockHeaderSize = ((unsigned)p->buf[0] << 2) + 4;
1176 break; 1176 break;
1177 } 1177 }
1178 1178
1179 if (p->pos != p->blockHeaderSize) 1179 if (p->pos != p->blockHeaderSize)
1180 { 1180 {
1181 UInt32 cur = p->blockHeaderSize - p->pos; 1181 unsigned cur = p->blockHeaderSize - p->pos;
1182 if (cur > srcRem) 1182 if (cur > srcRem)
1183 cur = (UInt32)srcRem; 1183 cur = (unsigned)srcRem;
1184 memcpy(p->buf + p->pos, src, cur); 1184 memcpy(p->buf + p->pos, src, cur);
1185 p->pos += cur; 1185 p->pos += cur;
1186 (*srcLen) += cur; 1186 (*srcLen) += cur;
@@ -1222,8 +1222,8 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1222 } 1222 }
1223 else 1223 else
1224 { 1224 {
1225 UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags); 1225 const unsigned checkSize = XzFlags_GetCheckSize(p->streamFlags);
1226 UInt32 cur = checkSize - p->pos; 1226 unsigned cur = checkSize - p->pos;
1227 if (cur != 0) 1227 if (cur != 0)
1228 { 1228 {
1229 if (srcRem == 0) 1229 if (srcRem == 0)
@@ -1232,7 +1232,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1232 return SZ_OK; 1232 return SZ_OK;
1233 } 1233 }
1234 if (cur > srcRem) 1234 if (cur > srcRem)
1235 cur = (UInt32)srcRem; 1235 cur = (unsigned)srcRem;
1236 memcpy(p->buf + p->pos, src, cur); 1236 memcpy(p->buf + p->pos, src, cur);
1237 p->pos += cur; 1237 p->pos += cur;
1238 (*srcLen) += cur; 1238 (*srcLen) += cur;
@@ -1321,9 +1321,9 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1321 1321
1322 case XZ_STATE_STREAM_FOOTER: 1322 case XZ_STATE_STREAM_FOOTER:
1323 { 1323 {
1324 UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos; 1324 unsigned cur = XZ_STREAM_FOOTER_SIZE - p->pos;
1325 if (cur > srcRem) 1325 if (cur > srcRem)
1326 cur = (UInt32)srcRem; 1326 cur = (unsigned)srcRem;
1327 memcpy(p->buf + p->pos, src, cur); 1327 memcpy(p->buf + p->pos, src, cur);
1328 p->pos += cur; 1328 p->pos += cur;
1329 (*srcLen) += cur; 1329 (*srcLen) += cur;
@@ -1358,6 +1358,8 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1358 } 1358 }
1359 1359
1360 case XZ_STATE_BLOCK: break; /* to disable GCC warning */ 1360 case XZ_STATE_BLOCK: break; /* to disable GCC warning */
1361
1362 default: return SZ_ERROR_FAIL;
1361 } 1363 }
1362 } 1364 }
1363 /* 1365 /*
@@ -1773,10 +1775,10 @@ static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbac
1773 } 1775 }
1774 } 1776 }
1775 { 1777 {
1776 UInt64 packSize = block->packSize; 1778 const UInt64 packSize = block->packSize;
1777 UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); 1779 const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
1778 UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags); 1780 const unsigned checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);
1779 UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize; 1781 const UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;
1780 // if (blockPackSum <= me->props.inBlockMax) 1782 // if (blockPackSum <= me->props.inBlockMax)
1781 // unpackBlockMaxSize 1783 // unpackBlockMaxSize
1782 { 1784 {
@@ -2381,7 +2383,7 @@ static SRes XzDecMt_Decode_ST(CXzDecMt *p
2381 if (tMode) 2383 if (tMode)
2382 { 2384 {
2383 XzDecMt_FreeOutBufs(p); 2385 XzDecMt_FreeOutBufs(p);
2384 tMode = MtDec_PrepareRead(&p->mtc); 2386 tMode = (BoolInt)MtDec_PrepareRead(&p->mtc);
2385 } 2387 }
2386 #endif 2388 #endif
2387 2389
@@ -2644,7 +2646,7 @@ SRes XzDecMt_Decode(CXzDecMtHandle p,
2644 p->outSize = *outDataSize; 2646 p->outSize = *outDataSize;
2645 } 2647 }
2646 2648
2647 p->finishMode = finishMode; 2649 p->finishMode = (BoolInt)finishMode;
2648 2650
2649 // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test 2651 // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
2650 2652
diff --git a/C/XzEnc.c b/C/XzEnc.c
index 22408e2..c1affad 100644
--- a/C/XzEnc.c
+++ b/C/XzEnc.c
@@ -1,5 +1,5 @@
1/* XzEnc.c -- Xz Encode 1/* XzEnc.c -- Xz Encode
22023-04-13 : Igor Pavlov : Public domain */ 22024-03-01 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -29,8 +29,9 @@
29 29
30#define XZ_GET_PAD_SIZE(dataSize) ((4 - ((unsigned)(dataSize) & 3)) & 3) 30#define XZ_GET_PAD_SIZE(dataSize) ((4 - ((unsigned)(dataSize) & 3)) & 3)
31 31
32/* max pack size for LZMA2 block + check-64bytrs: */ 32#define XZ_CHECK_SIZE_MAX 64
33#define XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize) ((unpackSize) + ((unpackSize) >> 10) + 16 + 64) 33/* max pack size for LZMA2 block + pad4 + check_size: */
34#define XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize) ((unpackSize) + ((unpackSize) >> 10) + 16 + XZ_CHECK_SIZE_MAX)
34 35
35#define XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(unpackSize) (XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize)) 36#define XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(unpackSize) (XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize))
36 37
@@ -325,12 +326,13 @@ typedef struct
325 326
326static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Enc[] = 327static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Enc[] =
327{ 328{
328 Z7_BRANCH_CONV_ENC(PPC), 329 Z7_BRANCH_CONV_ENC_2 (BranchConv_PPC),
329 Z7_BRANCH_CONV_ENC(IA64), 330 Z7_BRANCH_CONV_ENC_2 (BranchConv_IA64),
330 Z7_BRANCH_CONV_ENC(ARM), 331 Z7_BRANCH_CONV_ENC_2 (BranchConv_ARM),
331 Z7_BRANCH_CONV_ENC(ARMT), 332 Z7_BRANCH_CONV_ENC_2 (BranchConv_ARMT),
332 Z7_BRANCH_CONV_ENC(SPARC), 333 Z7_BRANCH_CONV_ENC_2 (BranchConv_SPARC),
333 Z7_BRANCH_CONV_ENC(ARM64) 334 Z7_BRANCH_CONV_ENC_2 (BranchConv_ARM64),
335 Z7_BRANCH_CONV_ENC_2 (BranchConv_RISCV)
334}; 336};
335 337
336static SizeT XzBcFilterStateBase_Filter_Enc(CXzBcFilterStateBase *p, Byte *data, SizeT size) 338static SizeT XzBcFilterStateBase_Filter_Enc(CXzBcFilterStateBase *p, Byte *data, SizeT size)
@@ -888,9 +890,9 @@ static SRes Xz_CompressBlock(
888 blockSizes->unpackSize = checkInStream.processed; 890 blockSizes->unpackSize = checkInStream.processed;
889 } 891 }
890 { 892 {
891 Byte buf[4 + 64]; 893 Byte buf[4 + XZ_CHECK_SIZE_MAX];
892 unsigned padSize = XZ_GET_PAD_SIZE(seqSizeOutStream.processed); 894 const unsigned padSize = XZ_GET_PAD_SIZE(seqSizeOutStream.processed);
893 UInt64 packSize = seqSizeOutStream.processed; 895 const UInt64 packSize = seqSizeOutStream.processed;
894 896
895 buf[0] = 0; 897 buf[0] = 0;
896 buf[1] = 0; 898 buf[1] = 0;
@@ -898,7 +900,8 @@ static SRes Xz_CompressBlock(
898 buf[3] = 0; 900 buf[3] = 0;
899 901
900 SeqCheckInStream_GetDigest(&checkInStream, buf + 4); 902 SeqCheckInStream_GetDigest(&checkInStream, buf + 4);
901 RINOK(WriteBytes(&seqSizeOutStream.vt, buf + (4 - padSize), padSize + XzFlags_GetCheckSize((CXzStreamFlags)props->checkId))) 903 RINOK(WriteBytes(&seqSizeOutStream.vt, buf + (4 - padSize),
904 padSize + XzFlags_GetCheckSize((CXzStreamFlags)props->checkId)))
902 905
903 blockSizes->totalSize = seqSizeOutStream.processed - padSize; 906 blockSizes->totalSize = seqSizeOutStream.processed - padSize;
904 907
@@ -1083,18 +1086,19 @@ static SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBuf
1083 CXzEnc *me = (CXzEnc *)pp; 1086 CXzEnc *me = (CXzEnc *)pp;
1084 SRes res; 1087 SRes res;
1085 CMtProgressThunk progressThunk; 1088 CMtProgressThunk progressThunk;
1086 1089 Byte *dest;
1087 Byte *dest = me->outBufs[outBufIndex];
1088
1089 UNUSED_VAR(finished) 1090 UNUSED_VAR(finished)
1090
1091 { 1091 {
1092 CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; 1092 CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex];
1093 bInfo->totalSize = 0; 1093 bInfo->totalSize = 0;
1094 bInfo->unpackSize = 0; 1094 bInfo->unpackSize = 0;
1095 bInfo->headerSize = 0; 1095 bInfo->headerSize = 0;
1096 // v23.02: we don't compress empty blocks
1097 // also we must ignore that empty block in XzEnc_MtCallback_Write()
1098 if (srcSize == 0)
1099 return SZ_OK;
1096 } 1100 }
1097 1101 dest = me->outBufs[outBufIndex];
1098 if (!dest) 1102 if (!dest)
1099 { 1103 {
1100 dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); 1104 dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);
@@ -1140,18 +1144,20 @@ static SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBuf
1140static SRes XzEnc_MtCallback_Write(void *pp, unsigned outBufIndex) 1144static SRes XzEnc_MtCallback_Write(void *pp, unsigned outBufIndex)
1141{ 1145{
1142 CXzEnc *me = (CXzEnc *)pp; 1146 CXzEnc *me = (CXzEnc *)pp;
1143
1144 const CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; 1147 const CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex];
1145 const Byte *data = me->outBufs[outBufIndex]; 1148 // v23.02: we don't write empty blocks
1146 1149 // note: if (bInfo->unpackSize == 0) then there is no compressed data of block
1147 RINOK(WriteBytes(me->outStream, data, bInfo->headerSize)) 1150 if (bInfo->unpackSize == 0)
1148 1151 return SZ_OK;
1149 { 1152 {
1150 UInt64 totalPackFull = bInfo->totalSize + XZ_GET_PAD_SIZE(bInfo->totalSize); 1153 const Byte *data = me->outBufs[outBufIndex];
1151 RINOK(WriteBytes(me->outStream, data + XZ_BLOCK_HEADER_SIZE_MAX, (size_t)totalPackFull - bInfo->headerSize)) 1154 RINOK(WriteBytes(me->outStream, data, bInfo->headerSize))
1155 {
1156 const UInt64 totalPackFull = bInfo->totalSize + XZ_GET_PAD_SIZE(bInfo->totalSize);
1157 RINOK(WriteBytes(me->outStream, data + XZ_BLOCK_HEADER_SIZE_MAX, (size_t)totalPackFull - bInfo->headerSize))
1158 }
1159 return XzEncIndex_AddIndexRecord(&me->xzIndex, bInfo->unpackSize, bInfo->totalSize, me->alloc);
1152 } 1160 }
1153
1154 return XzEncIndex_AddIndexRecord(&me->xzIndex, bInfo->unpackSize, bInfo->totalSize, me->alloc);
1155} 1161}
1156 1162
1157#endif 1163#endif
diff --git a/C/XzIn.c b/C/XzIn.c
index d0fc763..b68af96 100644
--- a/C/XzIn.c
+++ b/C/XzIn.c
@@ -1,5 +1,5 @@
1/* XzIn.c - Xz input 1/* XzIn.c - Xz input
22023-04-02 : Igor Pavlov : Public domain */ 22023-09-07 : Igor Pavlov : Public domain */
3 3
4#include "Precomp.h" 4#include "Precomp.h"
5 5
@@ -27,7 +27,7 @@ SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream)
27} 27}
28 28
29#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ 29#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
30 { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ 30 { const unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
31 if (s == 0) return SZ_ERROR_ARCHIVE; \ 31 if (s == 0) return SZ_ERROR_ARCHIVE; \
32 pos += s; } 32 pos += s; }
33 33
@@ -37,7 +37,7 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex,
37 unsigned headerSize; 37 unsigned headerSize;
38 *headerSizeRes = 0; 38 *headerSizeRes = 0;
39 RINOK(SeqInStream_ReadByte(inStream, &header[0])) 39 RINOK(SeqInStream_ReadByte(inStream, &header[0]))
40 headerSize = (unsigned)header[0]; 40 headerSize = header[0];
41 if (headerSize == 0) 41 if (headerSize == 0)
42 { 42 {
43 *headerSizeRes = 1; 43 *headerSizeRes = 1;
@@ -47,7 +47,7 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex,
47 47
48 *isIndex = False; 48 *isIndex = False;
49 headerSize = (headerSize << 2) + 4; 49 headerSize = (headerSize << 2) + 4;
50 *headerSizeRes = headerSize; 50 *headerSizeRes = (UInt32)headerSize;
51 { 51 {
52 size_t processedSize = headerSize - 1; 52 size_t processedSize = headerSize - 1;
53 RINOK(SeqInStream_ReadMax(inStream, header + 1, &processedSize)) 53 RINOK(SeqInStream_ReadMax(inStream, header + 1, &processedSize))
@@ -58,7 +58,7 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex,
58} 58}
59 59
60#define ADD_SIZE_CHECK(size, val) \ 60#define ADD_SIZE_CHECK(size, val) \
61 { UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; } 61 { const UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; }
62 62
63UInt64 Xz_GetUnpackSize(const CXzStream *p) 63UInt64 Xz_GetUnpackSize(const CXzStream *p)
64{ 64{
diff --git a/C/ZstdDec.c b/C/ZstdDec.c
new file mode 100644
index 0000000..ecf6d22
--- /dev/null
+++ b/C/ZstdDec.c
@@ -0,0 +1,4064 @@
1/* ZstdDec.c -- Zstd Decoder
22024-01-21 : the code was developed by Igor Pavlov, using Zstandard format
3 specification and original zstd decoder code as reference code.
4original zstd decoder code: Copyright (c) Facebook, Inc. All rights reserved.
5This source code is licensed under BSD 3-Clause License.
6*/
7
8#include "Precomp.h"
9
10#include <string.h>
11#include <stdlib.h>
12// #include <stdio.h>
13
14#include "Alloc.h"
15#include "Xxh64.h"
16#include "ZstdDec.h"
17#include "CpuArch.h"
18
19#if defined(MY_CPU_ARM64)
20#include <arm_neon.h>
21#endif
22
23/* original-zstd still doesn't support window larger than 2 GiB.
24 So we also limit our decoder for 2 GiB window: */
25#if defined(MY_CPU_64BIT) && 0 == 1
26 #define MAX_WINDOW_SIZE_LOG 41
27#else
28 #define MAX_WINDOW_SIZE_LOG 31
29#endif
30
31typedef
32 #if MAX_WINDOW_SIZE_LOG < 32
33 UInt32
34 #else
35 size_t
36 #endif
37 CZstdDecOffset;
38
39// for debug: simpler and smaller code but slow:
40// #define Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS
41
42// #define SHOW_STAT
43#ifdef SHOW_STAT
44#include <stdio.h>
45static unsigned g_Num_Blocks_Compressed = 0;
46static unsigned g_Num_Blocks_memcpy = 0;
47static unsigned g_Num_Wrap_memmove_Num = 0;
48static unsigned g_Num_Wrap_memmove_Bytes = 0;
49static unsigned g_NumSeqs_total = 0;
50// static unsigned g_NumCopy = 0;
51static unsigned g_NumOver = 0;
52static unsigned g_NumOver2 = 0;
53static unsigned g_Num_Match = 0;
54static unsigned g_Num_Lits = 0;
55static unsigned g_Num_LitsBig = 0;
56static unsigned g_Num_Lit0 = 0;
57static unsigned g_Num_Rep0 = 0;
58static unsigned g_Num_Rep1 = 0;
59static unsigned g_Num_Rep2 = 0;
60static unsigned g_Num_Rep3 = 0;
61static unsigned g_Num_Threshold_0 = 0;
62static unsigned g_Num_Threshold_1 = 0;
63static unsigned g_Num_Threshold_0sum = 0;
64static unsigned g_Num_Threshold_1sum = 0;
65#define STAT_UPDATE(v) v
66#else
67#define STAT_UPDATE(v)
68#endif
69#define STAT_INC(v) STAT_UPDATE(v++;)
70
71
72typedef struct
73{
74 const Byte *ptr;
75 size_t len;
76}
77CInBufPair;
78
79
80#if defined(MY_CPU_ARM_OR_ARM64) || defined(MY_CPU_X86_OR_AMD64)
81 #if (defined(__clang__) && (__clang_major__ >= 6)) \
82 || (defined(__GNUC__) && (__GNUC__ >= 6))
83 // disable for debug:
84 #define Z7_ZSTD_DEC_USE_BSR
85 #elif defined(_MSC_VER) && (_MSC_VER >= 1300)
86 // #if defined(MY_CPU_ARM_OR_ARM64)
87 #if (_MSC_VER >= 1600)
88 #include <intrin.h>
89 #endif
90 // disable for debug:
91 #define Z7_ZSTD_DEC_USE_BSR
92 #endif
93#endif
94
95#ifdef Z7_ZSTD_DEC_USE_BSR
96 #if defined(__clang__) || defined(__GNUC__)
97 #define MY_clz(x) ((unsigned)__builtin_clz((UInt32)x))
98 #else // #if defined(_MSC_VER)
99 #ifdef MY_CPU_ARM_OR_ARM64
100 #define MY_clz _CountLeadingZeros
101 #endif // MY_CPU_X86_OR_AMD64
102 #endif // _MSC_VER
103#elif !defined(Z7_ZSTD_DEC_USE_LOG_TABLE)
104 #define Z7_ZSTD_DEC_USE_LOG_TABLE
105#endif
106
107
108static
109Z7_FORCE_INLINE
110unsigned GetHighestSetBit_32_nonzero_big(UInt32 num)
111{
112 // (num != 0)
113 #ifdef MY_clz
114 return 31 - MY_clz(num);
115 #elif defined(Z7_ZSTD_DEC_USE_BSR)
116 {
117 unsigned long zz;
118 _BitScanReverse(&zz, num);
119 return zz;
120 }
121 #else
122 {
123 int i = -1;
124 for (;;)
125 {
126 i++;
127 num >>= 1;
128 if (num == 0)
129 return (unsigned)i;
130 }
131 }
132 #endif
133}
134
135#ifdef Z7_ZSTD_DEC_USE_LOG_TABLE
136
137#define R1(a) a, a
138#define R2(a) R1(a), R1(a)
139#define R3(a) R2(a), R2(a)
140#define R4(a) R3(a), R3(a)
141#define R5(a) R4(a), R4(a)
142#define R6(a) R5(a), R5(a)
143#define R7(a) R6(a), R6(a)
144#define R8(a) R7(a), R7(a)
145#define R9(a) R8(a), R8(a)
146
147#define Z7_ZSTD_FSE_MAX_ACCURACY 9
148// states[] values in FSE_Generate() can use (Z7_ZSTD_FSE_MAX_ACCURACY + 1) bits.
149static const Byte k_zstd_LogTable[2 << Z7_ZSTD_FSE_MAX_ACCURACY] =
150{
151 R1(0), R1(1), R2(2), R3(3), R4(4), R5(5), R6(6), R7(7), R8(8), R9(9)
152};
153
154#define GetHighestSetBit_32_nonzero_small(num) (k_zstd_LogTable[num])
155#else
156#define GetHighestSetBit_32_nonzero_small GetHighestSetBit_32_nonzero_big
157#endif
158
159
160#ifdef MY_clz
161 #define UPDATE_BIT_OFFSET_FOR_PADDING(b, bitOffset) \
162 bitOffset -= (CBitCtr)(MY_clz(b) - 23);
163#elif defined(Z7_ZSTD_DEC_USE_BSR)
164 #define UPDATE_BIT_OFFSET_FOR_PADDING(b, bitOffset) \
165 { unsigned long zz; _BitScanReverse(&zz, b); bitOffset -= 8; bitOffset += zz; }
166#else
167 #define UPDATE_BIT_OFFSET_FOR_PADDING(b, bitOffset) \
168 for (;;) { bitOffset--; if (b & 0x80) { break; } b <<= 1; }
169#endif
170
171#define SET_bitOffset_TO_PAD(bitOffset, src, srcLen) \
172{ \
173 unsigned lastByte = (src)[(size_t)(srcLen) - 1]; \
174 if (lastByte == 0) return SZ_ERROR_DATA; \
175 bitOffset = (CBitCtr)((srcLen) * 8); \
176 UPDATE_BIT_OFFSET_FOR_PADDING(lastByte, bitOffset) \
177}
178
179#ifndef Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS
180
181#define SET_bitOffset_TO_PAD_and_SET_BIT_SIZE(bitOffset, src, srcLen_res) \
182{ \
183 unsigned lastByte = (src)[(size_t)(srcLen_res) - 1]; \
184 if (lastByte == 0) return SZ_ERROR_DATA; \
185 srcLen_res *= 8; \
186 bitOffset = (CBitCtr)srcLen_res; \
187 UPDATE_BIT_OFFSET_FOR_PADDING(lastByte, bitOffset) \
188}
189
190#endif
191
192/*
193typedef Int32 CBitCtr_signed;
194typedef Int32 CBitCtr;
195*/
196// /*
197typedef ptrdiff_t CBitCtr_signed;
198typedef ptrdiff_t CBitCtr;
199// */
200
201
202#define MATCH_LEN_MIN 3
203#define kBlockSizeMax (1u << 17)
204
205// #define Z7_ZSTD_DEC_PRINT_TABLE
206
207#ifdef Z7_ZSTD_DEC_PRINT_TABLE
208#define NUM_OFFSET_SYMBOLS_PREDEF 29
209#endif
210#define NUM_OFFSET_SYMBOLS_MAX (MAX_WINDOW_SIZE_LOG + 1) // 32
211#define NUM_LL_SYMBOLS 36
212#define NUM_ML_SYMBOLS 53
213#define FSE_NUM_SYMBOLS_MAX 53 // NUM_ML_SYMBOLS
214
215// /*
216#if !defined(MY_CPU_X86) || defined(__PIC__) || defined(MY_CPU_64BIT)
217#define Z7_ZSTD_DEC_USE_BASES_IN_OBJECT
218#endif
219// */
220// for debug:
221// #define Z7_ZSTD_DEC_USE_BASES_LOCAL
222// #define Z7_ZSTD_DEC_USE_BASES_IN_OBJECT
223
224#define GLOBAL_TABLE(n) k_ ## n
225
226#if defined(Z7_ZSTD_DEC_USE_BASES_LOCAL)
227 #define BASES_TABLE(n) a_ ## n
228#elif defined(Z7_ZSTD_DEC_USE_BASES_IN_OBJECT)
229 #define BASES_TABLE(n) p->m_ ## n
230#else
231 #define BASES_TABLE(n) GLOBAL_TABLE(n)
232#endif
233
234#define Z7_ZSTD_DEC_USE_ML_PLUS3
235
236#if defined(Z7_ZSTD_DEC_USE_BASES_LOCAL) || \
237 defined(Z7_ZSTD_DEC_USE_BASES_IN_OBJECT)
238
239#define SEQ_EXTRA_TABLES(n) \
240 Byte n ## SEQ_LL_EXTRA [NUM_LL_SYMBOLS]; \
241 Byte n ## SEQ_ML_EXTRA [NUM_ML_SYMBOLS]; \
242 UInt32 n ## SEQ_LL_BASES [NUM_LL_SYMBOLS]; \
243 UInt32 n ## SEQ_ML_BASES [NUM_ML_SYMBOLS]; \
244
245#define Z7_ZSTD_DEC_USE_BASES_CALC
246
247#ifdef Z7_ZSTD_DEC_USE_BASES_CALC
248
249 #define FILL_LOC_BASES(n, startSum) \
250 { unsigned i; UInt32 sum = startSum; \
251 for (i = 0; i != Z7_ARRAY_SIZE(GLOBAL_TABLE(n ## _EXTRA)); i++) \
252 { const unsigned a = GLOBAL_TABLE(n ## _EXTRA)[i]; \
253 BASES_TABLE(n ## _BASES)[i] = sum; \
254 /* if (sum != GLOBAL_TABLE(n ## _BASES)[i]) exit(1); */ \
255 sum += (UInt32)1 << a; \
256 BASES_TABLE(n ## _EXTRA)[i] = (Byte)a; }}
257
258 #define FILL_LOC_BASES_ALL \
259 FILL_LOC_BASES (SEQ_LL, 0) \
260 FILL_LOC_BASES (SEQ_ML, MATCH_LEN_MIN) \
261
262#else
263 #define COPY_GLOBAL_ARR(n) \
264 memcpy(BASES_TABLE(n), GLOBAL_TABLE(n), sizeof(GLOBAL_TABLE(n)));
265 #define FILL_LOC_BASES_ALL \
266 COPY_GLOBAL_ARR (SEQ_LL_EXTRA) \
267 COPY_GLOBAL_ARR (SEQ_ML_EXTRA) \
268 COPY_GLOBAL_ARR (SEQ_LL_BASES) \
269 COPY_GLOBAL_ARR (SEQ_ML_BASES) \
270
271#endif
272
273#endif
274
275
276
277/// The sequence decoding baseline and number of additional bits to read/add
278#if !defined(Z7_ZSTD_DEC_USE_BASES_CALC)
279static const UInt32 GLOBAL_TABLE(SEQ_LL_BASES) [NUM_LL_SYMBOLS] =
280{
281 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
282 16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
283 0x2000, 0x4000, 0x8000, 0x10000
284};
285#endif
286
287static const Byte GLOBAL_TABLE(SEQ_LL_EXTRA) [NUM_LL_SYMBOLS] =
288{
289 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
290 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9, 10, 11, 12,
291 13, 14, 15, 16
292};
293
294#if !defined(Z7_ZSTD_DEC_USE_BASES_CALC)
295static const UInt32 GLOBAL_TABLE(SEQ_ML_BASES) [NUM_ML_SYMBOLS] =
296{
297 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
298 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
299 35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
300 0x1003, 0x2003, 0x4003, 0x8003, 0x10003
301};
302#endif
303
304static const Byte GLOBAL_TABLE(SEQ_ML_EXTRA) [NUM_ML_SYMBOLS] =
305{
306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
307 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
308 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9, 10, 11,
309 12, 13, 14, 15, 16
310};
311
312
313#ifdef Z7_ZSTD_DEC_PRINT_TABLE
314
315static const Int16 SEQ_LL_PREDEF_DIST [NUM_LL_SYMBOLS] =
316{
317 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
318 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,
319 -1,-1,-1,-1
320};
321static const Int16 SEQ_OFFSET_PREDEF_DIST [NUM_OFFSET_SYMBOLS_PREDEF] =
322{
323 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
324 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1
325};
326static const Int16 SEQ_ML_PREDEF_DIST [NUM_ML_SYMBOLS] =
327{
328 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
329 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
330 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,
331 -1,-1,-1,-1,-1
332};
333
334#endif
335
336// typedef int FastInt;
337// typedef Int32 FastInt32;
338typedef unsigned FastInt;
339typedef UInt32 FastInt32;
340typedef FastInt32 CFseRecord;
341
342
343#define FSE_REC_LEN_OFFSET 8
344#define FSE_REC_STATE_OFFSET 16
345#define GET_FSE_REC_SYM(st) ((Byte)(st))
346#define GET_FSE_REC_LEN(st) ((Byte)((st) >> FSE_REC_LEN_OFFSET))
347#define GET_FSE_REC_STATE(st) ((st) >> FSE_REC_STATE_OFFSET)
348
349// #define FSE_REC_SYM_MASK (0xff)
350// #define GET_FSE_REC_SYM(st) (st & FSE_REC_SYM_MASK)
351
352#define W_BASE(state, len, sym) \
353 (((UInt32)state << (4 + FSE_REC_STATE_OFFSET)) + \
354 (len << FSE_REC_LEN_OFFSET) + (sym))
355#define W(state, len, sym) W_BASE(state, len, sym)
356static const CFseRecord k_PredefRecords_LL[1 << 6] = {
357W(0,4, 0),W(1,4, 0),W(2,5, 1),W(0,5, 3),W(0,5, 4),W(0,5, 6),W(0,5, 7),W(0,5, 9),
358W(0,5,10),W(0,5,12),W(0,6,14),W(0,5,16),W(0,5,18),W(0,5,19),W(0,5,21),W(0,5,22),
359W(0,5,24),W(2,5,25),W(0,5,26),W(0,6,27),W(0,6,29),W(0,6,31),W(2,4, 0),W(0,4, 1),
360W(0,5, 2),W(2,5, 4),W(0,5, 5),W(2,5, 7),W(0,5, 8),W(2,5,10),W(0,5,11),W(0,6,13),
361W(2,5,16),W(0,5,17),W(2,5,19),W(0,5,20),W(2,5,22),W(0,5,23),W(0,4,25),W(1,4,25),
362W(2,5,26),W(0,6,28),W(0,6,30),W(3,4, 0),W(1,4, 1),W(2,5, 2),W(2,5, 3),W(2,5, 5),
363W(2,5, 6),W(2,5, 8),W(2,5, 9),W(2,5,11),W(2,5,12),W(0,6,15),W(2,5,17),W(2,5,18),
364W(2,5,20),W(2,5,21),W(2,5,23),W(2,5,24),W(0,6,35),W(0,6,34),W(0,6,33),W(0,6,32)
365};
366static const CFseRecord k_PredefRecords_OF[1 << 5] = {
367W(0,5, 0),W(0,4, 6),W(0,5, 9),W(0,5,15),W(0,5,21),W(0,5, 3),W(0,4, 7),W(0,5,12),
368W(0,5,18),W(0,5,23),W(0,5, 5),W(0,4, 8),W(0,5,14),W(0,5,20),W(0,5, 2),W(1,4, 7),
369W(0,5,11),W(0,5,17),W(0,5,22),W(0,5, 4),W(1,4, 8),W(0,5,13),W(0,5,19),W(0,5, 1),
370W(1,4, 6),W(0,5,10),W(0,5,16),W(0,5,28),W(0,5,27),W(0,5,26),W(0,5,25),W(0,5,24)
371};
372#if defined(Z7_ZSTD_DEC_USE_ML_PLUS3)
373#undef W
374#define W(state, len, sym) W_BASE(state, len, (sym + MATCH_LEN_MIN))
375#endif
376static const CFseRecord k_PredefRecords_ML[1 << 6] = {
377W(0,6, 0),W(0,4, 1),W(2,5, 2),W(0,5, 3),W(0,5, 5),W(0,5, 6),W(0,5, 8),W(0,6,10),
378W(0,6,13),W(0,6,16),W(0,6,19),W(0,6,22),W(0,6,25),W(0,6,28),W(0,6,31),W(0,6,33),
379W(0,6,35),W(0,6,37),W(0,6,39),W(0,6,41),W(0,6,43),W(0,6,45),W(1,4, 1),W(0,4, 2),
380W(2,5, 3),W(0,5, 4),W(2,5, 6),W(0,5, 7),W(0,6, 9),W(0,6,12),W(0,6,15),W(0,6,18),
381W(0,6,21),W(0,6,24),W(0,6,27),W(0,6,30),W(0,6,32),W(0,6,34),W(0,6,36),W(0,6,38),
382W(0,6,40),W(0,6,42),W(0,6,44),W(2,4, 1),W(3,4, 1),W(1,4, 2),W(2,5, 4),W(2,5, 5),
383W(2,5, 7),W(2,5, 8),W(0,6,11),W(0,6,14),W(0,6,17),W(0,6,20),W(0,6,23),W(0,6,26),
384W(0,6,29),W(0,6,52),W(0,6,51),W(0,6,50),W(0,6,49),W(0,6,48),W(0,6,47),W(0,6,46)
385};
386
387
388// sum of freqs[] must be correct
389// (numSyms != 0)
390// (accuracy >= 5)
391static
392Z7_NO_INLINE
393// Z7_FORCE_INLINE
394void FSE_Generate(CFseRecord *table,
395 const Int16 *const freqs, const size_t numSyms,
396 const unsigned accuracy, UInt32 delta)
397{
398 size_t size = (size_t)1 << accuracy;
399 // max value in states[x] is ((1 << accuracy) * 2)
400 UInt16 states[FSE_NUM_SYMBOLS_MAX];
401 {
402 /* Symbols with "less than 1" probability get a single cell,
403 starting from the end of the table.
404 These symbols define a full state reset, reading (accuracy) bits. */
405 size_t threshold = size;
406 {
407 size_t s = 0;
408 do
409 if (freqs[s] == -1)
410 {
411 table[--threshold] = (CFseRecord)s;
412 states[s] = 1;
413 }
414 while (++s != numSyms);
415 }
416
417 #ifdef SHOW_STAT
418 if (threshold == size)
419 {
420 STAT_INC(g_Num_Threshold_0)
421 STAT_UPDATE(g_Num_Threshold_0sum += (unsigned)size;)
422 }
423 else
424 {
425 STAT_INC(g_Num_Threshold_1)
426 STAT_UPDATE(g_Num_Threshold_1sum += (unsigned)size;)
427 }
428 #endif
429
430 // { unsigned uuu; for (uuu = 0; uuu < 400; uuu++)
431 {
432 // Each (symbol) gets freqs[symbol] cells.
433 // Cell allocation is spread, not linear.
434 const size_t step = (size >> 1) + (size >> 3) + 3;
435 size_t pos = 0;
436 // const unsigned mask = size - 1;
437 /*
438 if (threshold == size)
439 {
440 size_t s = 0;
441 size--;
442 do
443 {
444 int freq = freqs[s];
445 if (freq <= 0)
446 continue;
447 states[s] = (UInt16)freq;
448 do
449 {
450 table[pos] (CFseRecord)s;
451 pos = (pos + step) & size; // & mask;
452 }
453 while (--freq);
454 }
455 while (++s != numSyms);
456 }
457 else
458 */
459 {
460 size_t s = 0;
461 size--;
462 do
463 {
464 int freq = freqs[s];
465 if (freq <= 0)
466 continue;
467 states[s] = (UInt16)freq;
468 do
469 {
470 table[pos] = (CFseRecord)s;
471 // we skip position, if it's already occupied by a "less than 1" probability symbol.
472 // (step) is coprime to table size, so the cycle will visit each position exactly once
473 do
474 pos = (pos + step) & size; // & mask;
475 while (pos >= threshold);
476 }
477 while (--freq);
478 }
479 while (++s != numSyms);
480 }
481 size++;
482 // (pos != 0) is unexpected case that means that freqs[] are not correct.
483 // so it's some failure in code (for example, incorrect predefined freq[] table)
484 // if (pos != 0) return SZ_ERROR_FAIL;
485 }
486 // }
487 }
488 {
489 const CFseRecord * const limit = table + size;
490 delta = ((UInt32)size << FSE_REC_STATE_OFFSET) - delta;
491 /* State increases by symbol over time, decreasing number of bits.
492 Baseline increases until the bit threshold is passed, at which point it resets to 0 */
493 do
494 {
495 #define TABLE_ITER(a) \
496 { \
497 const FastInt sym = (FastInt)table[a]; \
498 const unsigned nextState = states[sym]; \
499 unsigned nb; \
500 states[sym] = (UInt16)(nextState + 1); \
501 nb = accuracy - GetHighestSetBit_32_nonzero_small(nextState); \
502 table[a] = (CFseRecord)(sym - delta \
503 + ((UInt32)nb << FSE_REC_LEN_OFFSET) \
504 + ((UInt32)nextState << FSE_REC_STATE_OFFSET << nb)); \
505 }
506 TABLE_ITER(0)
507 TABLE_ITER(1)
508 table += 2;
509 }
510 while (table != limit);
511 }
512}
513
514
515#ifdef Z7_ZSTD_DEC_PRINT_TABLE
516
517static void Print_Predef(unsigned predefAccuracy,
518 const unsigned numSymsPredef,
519 const Int16 * const predefFreqs,
520 const CFseRecord *checkTable)
521{
522 CFseRecord table[1 << 6];
523 unsigned i;
524 FSE_Generate(table, predefFreqs, numSymsPredef, predefAccuracy,
525 #if defined(Z7_ZSTD_DEC_USE_ML_PLUS3)
526 numSymsPredef == NUM_ML_SYMBOLS ? MATCH_LEN_MIN :
527 #endif
528 0
529 );
530 if (memcmp(table, checkTable, sizeof(UInt32) << predefAccuracy) != 0)
531 exit(1);
532 for (i = 0; i < (1u << predefAccuracy); i++)
533 {
534 const UInt32 v = table[i];
535 const unsigned state = (unsigned)(GET_FSE_REC_STATE(v));
536 if (state & 0xf)
537 exit(1);
538 if (i != 0)
539 {
540 printf(",");
541 if (i % 8 == 0)
542 printf("\n");
543 }
544 printf("W(%d,%d,%2d)",
545 (unsigned)(state >> 4),
546 (unsigned)((v >> FSE_REC_LEN_OFFSET) & 0xff),
547 (unsigned)GET_FSE_REC_SYM(v));
548 }
549 printf("\n\n");
550}
551
552#endif
553
554
555#define GET16(dest, p) { const Byte *ptr = p; dest = GetUi16(ptr); }
556#define GET32(dest, p) { const Byte *ptr = p; dest = GetUi32(ptr); }
557
558// (1 <= numBits <= 9)
559#define FORWARD_READ_BITS(destVal, numBits, mask) \
560 { const CBitCtr_signed bos3 = (bitOffset) >> 3; \
561 if (bos3 >= 0) return SZ_ERROR_DATA; \
562 GET16(destVal, src + bos3) \
563 destVal >>= (bitOffset) & 7; \
564 bitOffset += (CBitCtr_signed)(numBits); \
565 mask = (1u << (numBits)) - 1; \
566 destVal &= mask; \
567 }
568
569#define FORWARD_READ_1BIT(destVal) \
570 { const CBitCtr_signed bos3 = (bitOffset) >> 3; \
571 if (bos3 >= 0) return SZ_ERROR_DATA; \
572 destVal = *(src + bos3); \
573 destVal >>= (bitOffset) & 7; \
574 (bitOffset)++; \
575 destVal &= 1; \
576 }
577
578
579// in: (accuracyMax <= 9)
580// at least 2 bytes will be processed from (in) stream.
581// at return: (in->len > 0)
582static
583Z7_NO_INLINE
584SRes FSE_DecodeHeader(CFseRecord *const table,
585 CInBufPair *const in,
586 const unsigned accuracyMax,
587 Byte *const accuracyRes,
588 unsigned numSymbolsMax)
589{
590 unsigned accuracy;
591 unsigned remain1;
592 unsigned syms;
593 Int16 freqs[FSE_NUM_SYMBOLS_MAX + 3]; // +3 for overwrite (repeat)
594 const Byte *src = in->ptr;
595 CBitCtr_signed bitOffset = (CBitCtr_signed)in->len - 1;
596 if (bitOffset <= 0)
597 return SZ_ERROR_DATA;
598 accuracy = *src & 0xf;
599 accuracy += 5;
600 if (accuracy > accuracyMax)
601 return SZ_ERROR_DATA;
602 *accuracyRes = (Byte)accuracy;
603 remain1 = (1u << accuracy) + 1; // (it's remain_freqs_sum + 1)
604 syms = 0;
605 src += bitOffset; // src points to last byte
606 bitOffset = 4 - (bitOffset << 3);
607
608 for (;;)
609 {
610 // (2 <= remain1)
611 const unsigned bits = GetHighestSetBit_32_nonzero_small((unsigned)remain1);
612 // (1 <= bits <= accuracy)
613 unsigned val; // it must be unsigned or int
614 unsigned mask;
615 FORWARD_READ_BITS(val, bits, mask)
616 {
617 const unsigned val2 = remain1 + val - mask;
618 if (val2 > mask)
619 {
620 unsigned bit;
621 FORWARD_READ_1BIT(bit)
622 if (bit)
623 val = val2;
624 }
625 }
626 {
627 // (remain1 >= 2)
628 // (0 <= (int)val <= remain1)
629 val = (unsigned)((int)val - 1);
630 // val now is "probability" of symbol
631 // (probability == -1) means "less than 1" frequency.
632 // (-1 <= (int)val <= remain1 - 1)
633 freqs[syms++] = (Int16)(int)val;
634 if (val != 0)
635 {
636 remain1 -= (int)val < 0 ? 1u : (unsigned)val;
637 // remain1 -= val;
638 // val >>= (sizeof(val) * 8 - 2);
639 // remain1 -= val & 2;
640 // freqs[syms++] = (Int16)(int)val;
641 // syms++;
642 if (remain1 == 1)
643 break;
644 if (syms >= FSE_NUM_SYMBOLS_MAX)
645 return SZ_ERROR_DATA;
646 }
647 else // if (val == 0)
648 {
649 // freqs[syms++] = 0;
650 // syms++;
651 for (;;)
652 {
653 unsigned repeat;
654 FORWARD_READ_BITS(repeat, 2, mask)
655 freqs[syms ] = 0;
656 freqs[syms + 1] = 0;
657 freqs[syms + 2] = 0;
658 syms += repeat;
659 if (syms >= FSE_NUM_SYMBOLS_MAX)
660 return SZ_ERROR_DATA;
661 if (repeat != 3)
662 break;
663 }
664 }
665 }
666 }
667
668 if (syms > numSymbolsMax)
669 return SZ_ERROR_DATA;
670 bitOffset += 7;
671 bitOffset >>= 3;
672 if (bitOffset > 0)
673 return SZ_ERROR_DATA;
674 in->ptr = src + bitOffset;
675 in->len = (size_t)(1 - bitOffset);
676 {
677 // unsigned uuu; for (uuu = 0; uuu < 50; uuu++)
678 FSE_Generate(table, freqs, syms, accuracy,
679 #if defined(Z7_ZSTD_DEC_USE_ML_PLUS3)
680 numSymbolsMax == NUM_ML_SYMBOLS ? MATCH_LEN_MIN :
681 #endif
682 0
683 );
684 }
685 return SZ_OK;
686}
687
688
689// ---------- HUFFMAN ----------
690
691#define HUF_MAX_BITS 12
692#define HUF_MAX_SYMBS 256
693#define HUF_DUMMY_SIZE (128 + 8 * 2) // it must multiple of 8
694// #define HUF_DUMMY_SIZE 0
695#define HUF_TABLE_SIZE ((2 << HUF_MAX_BITS) + HUF_DUMMY_SIZE)
696#define HUF_GET_SYMBOLS(table) ((table) + (1 << HUF_MAX_BITS) + HUF_DUMMY_SIZE)
697// #define HUF_GET_LENS(table) (table)
698
699typedef struct
700{
701 // Byte table[HUF_TABLE_SIZE];
702 UInt64 table64[HUF_TABLE_SIZE / sizeof(UInt64)];
703}
704CZstdDecHufTable;
705
706/*
707Input:
708 numSyms != 0
709 (bits) array size must be aligned for 2
710 if (numSyms & 1), then bits[numSyms] == 0,
711 Huffman tree must be correct before Huf_Build() call:
712 (sum (1/2^bits[i]) == 1).
713 && (bits[i] <= HUF_MAX_BITS)
714*/
715static
716Z7_FORCE_INLINE
717void Huf_Build(Byte * const table,
718 const Byte *bits, const unsigned numSyms)
719{
720 unsigned counts0[HUF_MAX_BITS + 1];
721 unsigned counts1[HUF_MAX_BITS + 1];
722 const Byte * const bitsEnd = bits + numSyms;
723 // /*
724 {
725 unsigned t;
726 for (t = 0; t < Z7_ARRAY_SIZE(counts0); t++) counts0[t] = 0;
727 for (t = 0; t < Z7_ARRAY_SIZE(counts1); t++) counts1[t] = 0;
728 }
729 // */
730 // memset(counts0, 0, sizeof(counts0));
731 // memset(counts1, 0, sizeof(counts1));
732 {
733 const Byte *bits2 = bits;
734 // we access additional bits[symbol] if (numSyms & 1)
735 do
736 {
737 counts0[bits2[0]]++;
738 counts1[bits2[1]]++;
739 }
740 while ((bits2 += 2) < bitsEnd);
741 }
742 {
743 unsigned r = 0;
744 unsigned i = HUF_MAX_BITS;
745 // Byte *lens = HUF_GET_LENS(symbols);
746 do
747 {
748 const unsigned num = (counts0[i] + counts1[i]) << (HUF_MAX_BITS - i);
749 counts0[i] = r;
750 if (num)
751 {
752 Byte *lens = &table[r];
753 r += num;
754 memset(lens, (int)i, num);
755 }
756 }
757 while (--i);
758 counts0[0] = 0; // for speculated loads
759 // no need for check:
760 // if (r != (UInt32)1 << HUF_MAX_BITS) exit(0);
761 }
762 {
763 #ifdef MY_CPU_64BIT
764 UInt64
765 #else
766 UInt32
767 #endif
768 v = 0;
769 Byte *symbols = HUF_GET_SYMBOLS(table);
770 do
771 {
772 const unsigned nb = *bits++;
773 if (nb)
774 {
775 const unsigned code = counts0[nb];
776 const unsigned num = (1u << HUF_MAX_BITS) >> nb;
777 counts0[nb] = code + num;
778 // memset(&symbols[code], i, num);
779 // /*
780 {
781 Byte *s2 = &symbols[code];
782 if (num <= 2)
783 {
784 s2[0] = (Byte)v;
785 s2[(size_t)num - 1] = (Byte)v;
786 }
787 else if (num <= 8)
788 {
789 *(UInt32 *)(void *)s2 = (UInt32)v;
790 *(UInt32 *)(void *)(s2 + (size_t)num - 4) = (UInt32)v;
791 }
792 else
793 {
794 #ifdef MY_CPU_64BIT
795 UInt64 *s = (UInt64 *)(void *)s2;
796 const UInt64 *lim = (UInt64 *)(void *)(s2 + num);
797 do
798 {
799 s[0] = v; s[1] = v; s += 2;
800 }
801 while (s != lim);
802 #else
803 UInt32 *s = (UInt32 *)(void *)s2;
804 const UInt32 *lim = (const UInt32 *)(const void *)(s2 + num);
805 do
806 {
807 s[0] = v; s[1] = v; s += 2;
808 s[0] = v; s[1] = v; s += 2;
809 }
810 while (s != lim);
811 #endif
812 }
813 }
814 // */
815 }
816 v +=
817 #ifdef MY_CPU_64BIT
818 0x0101010101010101;
819 #else
820 0x01010101;
821 #endif
822 }
823 while (bits != bitsEnd);
824 }
825}
826
827
828
829// how many bytes (src) was moved back from original value.
830// we need (HUF_SRC_OFFSET == 3) for optimized 32-bit memory access
831#define HUF_SRC_OFFSET 3
832
833// v <<= 8 - (bitOffset & 7) + numBits;
834// v >>= 32 - HUF_MAX_BITS;
835#define HUF_GET_STATE(v, bitOffset, numBits) \
836 GET32(v, src + (HUF_SRC_OFFSET - 3) + ((CBitCtr_signed)bitOffset >> 3)) \
837 v >>= 32 - HUF_MAX_BITS - 8 + ((unsigned)bitOffset & 7) - numBits; \
838 v &= (1u << HUF_MAX_BITS) - 1; \
839
840
841#ifndef Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS
842#if defined(MY_CPU_AMD64) && defined(_MSC_VER) && _MSC_VER == 1400 \
843 || !defined(MY_CPU_X86_OR_AMD64) \
844 // || 1 == 1 /* for debug : to force STREAM4_PRELOAD mode */
845 // we need big number (>=16) of registers for PRELOAD4
846 #define Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD4
847 // #define Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD2 // for debug
848#endif
849#endif
850
851// for debug: simpler and smaller code but slow:
852// #define Z7_ZSTD_DEC_USE_HUF_STREAM1_SIMPLE
853
854#if defined(Z7_ZSTD_DEC_USE_HUF_STREAM1_SIMPLE) || \
855 !defined(Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS)
856
857#define HUF_DECODE(bitOffset, dest) \
858{ \
859 UInt32 v; \
860 HUF_GET_STATE(v, bitOffset, 0) \
861 bitOffset -= table[v]; \
862 *(dest) = symbols[v]; \
863 if ((CBitCtr_signed)bitOffset < 0) return SZ_ERROR_DATA; \
864}
865
866#endif
867
868#if !defined(Z7_ZSTD_DEC_USE_HUF_STREAM1_SIMPLE) || \
869 defined(Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD4) || \
870 defined(Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD2) \
871
872#define HUF_DECODE_2_INIT(v, bitOffset) \
873 HUF_GET_STATE(v, bitOffset, 0)
874
875#define HUF_DECODE_2(v, bitOffset, dest) \
876{ \
877 unsigned numBits; \
878 numBits = table[v]; \
879 *(dest) = symbols[v]; \
880 HUF_GET_STATE(v, bitOffset, numBits) \
881 bitOffset -= (CBitCtr)numBits; \
882 if ((CBitCtr_signed)bitOffset < 0) return SZ_ERROR_DATA; \
883}
884
885#endif
886
887
888// src == ptr - HUF_SRC_OFFSET
889// we are allowed to access 3 bytes before start of input buffer
890static
891Z7_NO_INLINE
892SRes Huf_Decompress_1stream(const Byte * const table,
893 const Byte *src, const size_t srcLen,
894 Byte *dest, const size_t destLen)
895{
896 CBitCtr bitOffset;
897 if (srcLen == 0)
898 return SZ_ERROR_DATA;
899 SET_bitOffset_TO_PAD (bitOffset, src + HUF_SRC_OFFSET, srcLen)
900 if (destLen)
901 {
902 const Byte *symbols = HUF_GET_SYMBOLS(table);
903 const Byte *destLim = dest + destLen;
904 #ifdef Z7_ZSTD_DEC_USE_HUF_STREAM1_SIMPLE
905 {
906 do
907 {
908 HUF_DECODE (bitOffset, dest)
909 }
910 while (++dest != destLim);
911 }
912 #else
913 {
914 UInt32 v;
915 HUF_DECODE_2_INIT (v, bitOffset)
916 do
917 {
918 HUF_DECODE_2 (v, bitOffset, dest)
919 }
920 while (++dest != destLim);
921 }
922 #endif
923 }
924 return bitOffset == 0 ? SZ_OK : SZ_ERROR_DATA;
925}
926
927
928// for debug : it reduces register pressure : by array copy can be slow :
929// #define Z7_ZSTD_DEC_USE_HUF_LOCAL
930
931// src == ptr + (6 - HUF_SRC_OFFSET)
932// srcLen >= 10
933// we are allowed to access 3 bytes before start of input buffer
934static
935Z7_NO_INLINE
936SRes Huf_Decompress_4stream(const Byte * const
937 #ifdef Z7_ZSTD_DEC_USE_HUF_LOCAL
938 table2,
939 #else
940 table,
941 #endif
942 const Byte *src, size_t srcLen,
943 Byte *dest, size_t destLen)
944{
945 #ifdef Z7_ZSTD_DEC_USE_HUF_LOCAL
946 Byte table[HUF_TABLE_SIZE];
947 #endif
948 UInt32 sizes[3];
949 const size_t delta = (destLen + 3) / 4;
950 if ((sizes[0] = GetUi16(src + (0 + HUF_SRC_OFFSET - 6))) == 0) return SZ_ERROR_DATA;
951 if ((sizes[1] = GetUi16(src + (2 + HUF_SRC_OFFSET - 6))) == 0) return SZ_ERROR_DATA;
952 sizes[1] += sizes[0];
953 if ((sizes[2] = GetUi16(src + (4 + HUF_SRC_OFFSET - 6))) == 0) return SZ_ERROR_DATA;
954 sizes[2] += sizes[1];
955 srcLen -= 6;
956 if (srcLen <= sizes[2])
957 return SZ_ERROR_DATA;
958
959 #ifdef Z7_ZSTD_DEC_USE_HUF_LOCAL
960 {
961 // unsigned i = 0; for(; i < 1000; i++)
962 memcpy(table, table2, HUF_TABLE_SIZE);
963 }
964 #endif
965
966 #ifndef Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS
967 {
968 CBitCtr bitOffset_0,
969 bitOffset_1,
970 bitOffset_2,
971 bitOffset_3;
972 {
973 SET_bitOffset_TO_PAD_and_SET_BIT_SIZE (bitOffset_0, src + HUF_SRC_OFFSET, sizes[0])
974 SET_bitOffset_TO_PAD_and_SET_BIT_SIZE (bitOffset_1, src + HUF_SRC_OFFSET, sizes[1])
975 SET_bitOffset_TO_PAD_and_SET_BIT_SIZE (bitOffset_2, src + HUF_SRC_OFFSET, sizes[2])
976 SET_bitOffset_TO_PAD (bitOffset_3, src + HUF_SRC_OFFSET, srcLen)
977 }
978 {
979 const Byte * const symbols = HUF_GET_SYMBOLS(table);
980 Byte *destLim = dest + destLen - delta * 3;
981
982 if (dest != destLim)
983 #ifdef Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD4
984 {
985 UInt32 v_0, v_1, v_2, v_3;
986 HUF_DECODE_2_INIT (v_0, bitOffset_0)
987 HUF_DECODE_2_INIT (v_1, bitOffset_1)
988 HUF_DECODE_2_INIT (v_2, bitOffset_2)
989 HUF_DECODE_2_INIT (v_3, bitOffset_3)
990 // #define HUF_DELTA (1 << 17) / 4
991 do
992 {
993 HUF_DECODE_2 (v_3, bitOffset_3, dest + delta * 3)
994 HUF_DECODE_2 (v_2, bitOffset_2, dest + delta * 2)
995 HUF_DECODE_2 (v_1, bitOffset_1, dest + delta)
996 HUF_DECODE_2 (v_0, bitOffset_0, dest)
997 }
998 while (++dest != destLim);
999 /*
1000 {// unsigned y = 0; for (;y < 1; y++)
1001 {
1002 const size_t num = destLen - delta * 3;
1003 Byte *orig = dest - num;
1004 memmove (orig + delta , orig + HUF_DELTA, num);
1005 memmove (orig + delta * 2, orig + HUF_DELTA * 2, num);
1006 memmove (orig + delta * 3, orig + HUF_DELTA * 3, num);
1007 }}
1008 */
1009 }
1010 #elif defined(Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD2)
1011 {
1012 UInt32 v_0, v_1, v_2, v_3;
1013 HUF_DECODE_2_INIT (v_0, bitOffset_0)
1014 HUF_DECODE_2_INIT (v_1, bitOffset_1)
1015 do
1016 {
1017 HUF_DECODE_2 (v_0, bitOffset_0, dest)
1018 HUF_DECODE_2 (v_1, bitOffset_1, dest + delta)
1019 }
1020 while (++dest != destLim);
1021 dest = destLim - (destLen - delta * 3);
1022 dest += delta * 2;
1023 destLim += delta * 2;
1024 HUF_DECODE_2_INIT (v_2, bitOffset_2)
1025 HUF_DECODE_2_INIT (v_3, bitOffset_3)
1026 do
1027 {
1028 HUF_DECODE_2 (v_2, bitOffset_2, dest)
1029 HUF_DECODE_2 (v_3, bitOffset_3, dest + delta)
1030 }
1031 while (++dest != destLim);
1032 dest -= delta * 2;
1033 destLim -= delta * 2;
1034 }
1035 #else
1036 {
1037 do
1038 {
1039 HUF_DECODE (bitOffset_3, dest + delta * 3)
1040 HUF_DECODE (bitOffset_2, dest + delta * 2)
1041 HUF_DECODE (bitOffset_1, dest + delta)
1042 HUF_DECODE (bitOffset_0, dest)
1043 }
1044 while (++dest != destLim);
1045 }
1046 #endif
1047
1048 if (bitOffset_3 != (CBitCtr)sizes[2])
1049 return SZ_ERROR_DATA;
1050 if (destLen &= 3)
1051 {
1052 destLim = dest + 4 - destLen;
1053 do
1054 {
1055 HUF_DECODE (bitOffset_2, dest + delta * 2)
1056 HUF_DECODE (bitOffset_1, dest + delta)
1057 HUF_DECODE (bitOffset_0, dest)
1058 }
1059 while (++dest != destLim);
1060 }
1061 if ( bitOffset_0 != 0
1062 || bitOffset_1 != (CBitCtr)sizes[0]
1063 || bitOffset_2 != (CBitCtr)sizes[1])
1064 return SZ_ERROR_DATA;
1065 }
1066 }
1067 #else // Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS
1068 {
1069 unsigned i;
1070 for (i = 0; i < 4; i++)
1071 {
1072 size_t d = destLen;
1073 size_t size = srcLen;
1074 if (i != 3)
1075 {
1076 d = delta;
1077 size = sizes[i];
1078 }
1079 if (i != 0)
1080 size -= sizes[i - 1];
1081 destLen -= d;
1082 RINOK(Huf_Decompress_1stream(table, src, size, dest, d))
1083 dest += d;
1084 src += size;
1085 }
1086 }
1087 #endif
1088
1089 return SZ_OK;
1090}
1091
1092
1093
1094// (in->len != 0)
1095// we are allowed to access in->ptr[-3]
1096// at least 2 bytes in (in->ptr) will be processed
1097static SRes Huf_DecodeTable(CZstdDecHufTable *const p, CInBufPair *const in)
1098{
1099 Byte weights[HUF_MAX_SYMBS + 1]; // +1 for extra write for loop unroll
1100 unsigned numSyms;
1101 const unsigned header = *(in->ptr)++;
1102 in->len--;
1103 // memset(weights, 0, sizeof(weights));
1104 if (header >= 128)
1105 {
1106 // direct representation: 4 bits field (0-15) per weight
1107 numSyms = header - 127;
1108 // numSyms != 0
1109 {
1110 const size_t numBytes = (numSyms + 1) / 2;
1111 const Byte *const ws = in->ptr;
1112 size_t i = 0;
1113 if (in->len < numBytes)
1114 return SZ_ERROR_DATA;
1115 in->ptr += numBytes;
1116 in->len -= numBytes;
1117 do
1118 {
1119 const unsigned b = ws[i];
1120 weights[i * 2 ] = (Byte)(b >> 4);
1121 weights[i * 2 + 1] = (Byte)(b & 0xf);
1122 }
1123 while (++i != numBytes);
1124 /* 7ZIP: we can restore correct zero value for weights[numSyms],
1125 if we want to use zero values starting from numSyms in code below. */
1126 // weights[numSyms] = 0;
1127 }
1128 }
1129 else
1130 {
1131 #define MAX_ACCURACY_LOG_FOR_WEIGHTS 6
1132 CFseRecord table[1 << MAX_ACCURACY_LOG_FOR_WEIGHTS];
1133
1134 Byte accuracy;
1135 const Byte *src;
1136 size_t srcLen;
1137 if (in->len < header)
1138 return SZ_ERROR_DATA;
1139 {
1140 CInBufPair fse_stream;
1141 fse_stream.len = header;
1142 fse_stream.ptr = in->ptr;
1143 in->ptr += header;
1144 in->len -= header;
1145 RINOK(FSE_DecodeHeader(table, &fse_stream,
1146 MAX_ACCURACY_LOG_FOR_WEIGHTS,
1147 &accuracy,
1148 16 // num weight symbols max (max-symbol is 15)
1149 ))
1150 // at least 2 bytes were processed in fse_stream.
1151 // (srcLen > 0) after FSE_DecodeHeader()
1152 // if (srcLen == 0) return SZ_ERROR_DATA;
1153 src = fse_stream.ptr;
1154 srcLen = fse_stream.len;
1155 }
1156 // we are allowed to access src[-5]
1157 {
1158 // unsigned yyy = 200; do {
1159 CBitCtr bitOffset;
1160 FastInt32 state1, state2;
1161 SET_bitOffset_TO_PAD (bitOffset, src, srcLen)
1162 state1 = accuracy;
1163 src -= state1 >> 2; // src -= 1; // for GET16() optimization
1164 state1 <<= FSE_REC_LEN_OFFSET;
1165 state2 = state1;
1166 numSyms = 0;
1167 for (;;)
1168 {
1169 #define FSE_WEIGHT_DECODE(st) \
1170 { \
1171 const unsigned bits = GET_FSE_REC_LEN(st); \
1172 FastInt r; \
1173 GET16(r, src + (bitOffset >> 3)) \
1174 r >>= (unsigned)bitOffset & 7; \
1175 if ((CBitCtr_signed)(bitOffset -= (CBitCtr)bits) < 0) \
1176 { if (bitOffset + (CBitCtr)bits != 0) \
1177 return SZ_ERROR_DATA; \
1178 break; } \
1179 r &= 0xff; \
1180 r >>= 8 - bits; \
1181 st = table[GET_FSE_REC_STATE(st) + r]; \
1182 weights[numSyms++] = (Byte)GET_FSE_REC_SYM(st); \
1183 }
1184 FSE_WEIGHT_DECODE (state1)
1185 FSE_WEIGHT_DECODE (state2)
1186 if (numSyms == HUF_MAX_SYMBS)
1187 return SZ_ERROR_DATA;
1188 }
1189 // src += (unsigned)accuracy >> 2; } while (--yyy);
1190 }
1191 }
1192
1193 // Build using weights:
1194 {
1195 UInt32 sum = 0;
1196 {
1197 // numSyms >= 1
1198 unsigned i = 0;
1199 weights[numSyms] = 0;
1200 do
1201 {
1202 sum += ((UInt32)1 << weights[i ]) & ~(UInt32)1;
1203 sum += ((UInt32)1 << weights[i + 1]) & ~(UInt32)1;
1204 i += 2;
1205 }
1206 while (i < numSyms);
1207 if (sum == 0)
1208 return SZ_ERROR_DATA;
1209 }
1210 {
1211 const unsigned maxBits = GetHighestSetBit_32_nonzero_big(sum) + 1;
1212 {
1213 const UInt32 left = ((UInt32)1 << maxBits) - sum;
1214 // (left != 0)
1215 // (left) must be power of 2 in correct stream
1216 if (left & (left - 1))
1217 return SZ_ERROR_DATA;
1218 weights[numSyms++] = (Byte)GetHighestSetBit_32_nonzero_big(left);
1219 }
1220 // if (numSyms & 1)
1221 weights[numSyms] = 0; // for loop unroll
1222 // numSyms >= 2
1223 {
1224 unsigned i = 0;
1225 do
1226 {
1227 /*
1228 #define WEIGHT_ITER(a) \
1229 { unsigned w = weights[i + (a)]; \
1230 const unsigned t = maxBits - w; \
1231 w = w ? t: w; \
1232 if (w > HUF_MAX_BITS) return SZ_ERROR_DATA; \
1233 weights[i + (a)] = (Byte)w; }
1234 */
1235 // /*
1236 #define WEIGHT_ITER(a) \
1237 { unsigned w = weights[i + (a)]; \
1238 if (w) { \
1239 w = maxBits - w; \
1240 if (w > HUF_MAX_BITS) return SZ_ERROR_DATA; \
1241 weights[i + (a)] = (Byte)w; }}
1242 // */
1243 WEIGHT_ITER(0)
1244 // WEIGHT_ITER(1)
1245 // i += 2;
1246 }
1247 while (++i != numSyms);
1248 }
1249 }
1250 }
1251 {
1252 // unsigned yyy; for (yyy = 0; yyy < 100; yyy++)
1253 Huf_Build((Byte *)(void *)p->table64, weights, numSyms);
1254 }
1255 return SZ_OK;
1256}
1257
1258
1259typedef enum
1260{
1261 k_SeqMode_Predef = 0,
1262 k_SeqMode_RLE = 1,
1263 k_SeqMode_FSE = 2,
1264 k_SeqMode_Repeat = 3
1265}
1266z7_zstd_enum_SeqMode;
1267
1268// predefAccuracy == 5 for OFFSET symbols
1269// predefAccuracy == 6 for MATCH/LIT LEN symbols
1270static
1271SRes
1272Z7_NO_INLINE
1273// Z7_FORCE_INLINE
1274FSE_Decode_SeqTable(CFseRecord * const table,
1275 CInBufPair * const in,
1276 unsigned predefAccuracy,
1277 Byte * const accuracyRes,
1278 unsigned numSymbolsMax,
1279 const CFseRecord * const predefs,
1280 const unsigned seqMode)
1281{
1282 // UNUSED_VAR(numSymsPredef)
1283 // UNUSED_VAR(predefFreqs)
1284 if (seqMode == k_SeqMode_FSE)
1285 {
1286 // unsigned y = 50; CInBufPair in2 = *in; do { *in = in2; RINOK(
1287 return
1288 FSE_DecodeHeader(table, in,
1289 predefAccuracy + 3, // accuracyMax
1290 accuracyRes,
1291 numSymbolsMax)
1292 ;
1293 // )} while (--y); return SZ_OK;
1294 }
1295 // numSymsMax = numSymsPredef + ((predefAccuracy & 1) * (32 - 29))); // numSymsMax
1296 // numSymsMax == 32 for offsets
1297
1298 if (seqMode == k_SeqMode_Predef)
1299 {
1300 *accuracyRes = (Byte)predefAccuracy;
1301 memcpy(table, predefs, sizeof(UInt32) << predefAccuracy);
1302 return SZ_OK;
1303 }
1304
1305 // (seqMode == k_SeqMode_RLE)
1306 if (in->len == 0)
1307 return SZ_ERROR_DATA;
1308 in->len--;
1309 {
1310 const Byte *ptr = in->ptr;
1311 const Byte sym = ptr[0];
1312 in->ptr = ptr + 1;
1313 table[0] = (FastInt32)sym
1314 #if defined(Z7_ZSTD_DEC_USE_ML_PLUS3)
1315 + (numSymbolsMax == NUM_ML_SYMBOLS ? MATCH_LEN_MIN : 0)
1316 #endif
1317 ;
1318 *accuracyRes = 0;
1319 }
1320 return SZ_OK;
1321}
1322
1323
1324typedef struct
1325{
1326 CFseRecord of[1 << 8];
1327 CFseRecord ll[1 << 9];
1328 CFseRecord ml[1 << 9];
1329}
1330CZstdDecFseTables;
1331
1332
1333typedef struct
1334{
1335 Byte *win;
1336 SizeT cycSize;
1337 /*
1338 if (outBuf_fromCaller) : cycSize = outBufSize_fromCaller
1339 else {
1340 if ( isCyclicMode) : cycSize = cyclic_buffer_size = (winSize + extra_space)
1341 if (!isCyclicMode) : cycSize = ContentSize,
1342 (isCyclicMode == true) if (ContetSize >= winSize) or ContetSize is unknown
1343 }
1344 */
1345 SizeT winPos;
1346
1347 CZstdDecOffset reps[3];
1348
1349 Byte ll_accuracy;
1350 Byte of_accuracy;
1351 Byte ml_accuracy;
1352 // Byte seqTables_wereSet;
1353 Byte litHuf_wasSet;
1354
1355 Byte *literalsBase;
1356
1357 size_t winSize; // from header
1358 size_t totalOutCheck; // totalOutCheck <= winSize
1359
1360 #ifdef Z7_ZSTD_DEC_USE_BASES_IN_OBJECT
1361 SEQ_EXTRA_TABLES(m_)
1362 #endif
1363 // UInt64 _pad_Alignment; // is not required now
1364 CZstdDecFseTables fse;
1365 CZstdDecHufTable huf;
1366}
1367CZstdDec1;
1368
1369#define ZstdDec1_GET_BLOCK_SIZE_LIMIT(p) \
1370 ((p)->winSize < kBlockSizeMax ? (UInt32)(p)->winSize : kBlockSizeMax)
1371
1372#define SEQ_TABLES_WERE_NOT_SET_ml_accuracy 1 // accuracy=1 is not used by zstd
1373#define IS_SEQ_TABLES_WERE_SET(p) (((p)->ml_accuracy != SEQ_TABLES_WERE_NOT_SET_ml_accuracy))
1374// #define IS_SEQ_TABLES_WERE_SET(p) ((p)->seqTables_wereSet)
1375
1376
1377static void ZstdDec1_Construct(CZstdDec1 *p)
1378{
1379 #ifdef Z7_ZSTD_DEC_PRINT_TABLE
1380 Print_Predef(6, NUM_LL_SYMBOLS, SEQ_LL_PREDEF_DIST, k_PredefRecords_LL);
1381 Print_Predef(5, NUM_OFFSET_SYMBOLS_PREDEF, SEQ_OFFSET_PREDEF_DIST, k_PredefRecords_OF);
1382 Print_Predef(6, NUM_ML_SYMBOLS, SEQ_ML_PREDEF_DIST, k_PredefRecords_ML);
1383 #endif
1384
1385 p->win = NULL;
1386 p->cycSize = 0;
1387 p->literalsBase = NULL;
1388 #ifdef Z7_ZSTD_DEC_USE_BASES_IN_OBJECT
1389 FILL_LOC_BASES_ALL
1390 #endif
1391}
1392
1393
1394static void ZstdDec1_Init(CZstdDec1 *p)
1395{
1396 p->reps[0] = 1;
1397 p->reps[1] = 4;
1398 p->reps[2] = 8;
1399 // p->seqTables_wereSet = False;
1400 p->ml_accuracy = SEQ_TABLES_WERE_NOT_SET_ml_accuracy;
1401 p->litHuf_wasSet = False;
1402 p->totalOutCheck = 0;
1403}
1404
1405
1406
1407#ifdef MY_CPU_LE_UNALIGN
1408 #define Z7_ZSTD_DEC_USE_UNALIGNED_COPY
1409#endif
1410
1411#ifdef Z7_ZSTD_DEC_USE_UNALIGNED_COPY
1412
1413 #define COPY_CHUNK_SIZE 16
1414
1415 #define COPY_CHUNK_4_2(dest, src) \
1416 { \
1417 ((UInt32 *)(void *)dest)[0] = ((const UInt32 *)(const void *)src)[0]; \
1418 ((UInt32 *)(void *)dest)[1] = ((const UInt32 *)(const void *)src)[1]; \
1419 src += 4 * 2; \
1420 dest += 4 * 2; \
1421 }
1422
1423 /* sse2 doesn't help here in GCC and CLANG.
1424 so we disabled sse2 here */
1425 /*
1426 #if defined(MY_CPU_AMD64)
1427 #define Z7_ZSTD_DEC_USE_SSE2
1428 #elif defined(MY_CPU_X86)
1429 #if defined(_MSC_VER) && _MSC_VER >= 1300 && defined(_M_IX86_FP) && (_M_IX86_FP >= 2) \
1430 || defined(__SSE2__) \
1431 // || 1 == 1 // for debug only
1432 #define Z7_ZSTD_DEC_USE_SSE2
1433 #endif
1434 #endif
1435 */
1436
1437 #if defined(MY_CPU_ARM64)
1438 #define COPY_OFFSET_MIN 16
1439 #define COPY_CHUNK1(dest, src) \
1440 { \
1441 vst1q_u8((uint8_t *)(void *)dest, \
1442 vld1q_u8((const uint8_t *)(const void *)src)); \
1443 src += 16; \
1444 dest += 16; \
1445 }
1446
1447 #define COPY_CHUNK(dest, src) \
1448 { \
1449 COPY_CHUNK1(dest, src) \
1450 if ((len -= COPY_CHUNK_SIZE) == 0) break; \
1451 COPY_CHUNK1(dest, src) \
1452 }
1453
1454 #elif defined(Z7_ZSTD_DEC_USE_SSE2)
1455 #include <emmintrin.h> // sse2
1456 #define COPY_OFFSET_MIN 16
1457
1458 #define COPY_CHUNK1(dest, src) \
1459 { \
1460 _mm_storeu_si128((__m128i *)(void *)dest, \
1461 _mm_loadu_si128((const __m128i *)(const void *)src)); \
1462 src += 16; \
1463 dest += 16; \
1464 }
1465
1466 #define COPY_CHUNK(dest, src) \
1467 { \
1468 COPY_CHUNK1(dest, src) \
1469 if ((len -= COPY_CHUNK_SIZE) == 0) break; \
1470 COPY_CHUNK1(dest, src) \
1471 }
1472
1473 #elif defined(MY_CPU_64BIT)
1474 #define COPY_OFFSET_MIN 8
1475
1476 #define COPY_CHUNK(dest, src) \
1477 { \
1478 ((UInt64 *)(void *)dest)[0] = ((const UInt64 *)(const void *)src)[0]; \
1479 ((UInt64 *)(void *)dest)[1] = ((const UInt64 *)(const void *)src)[1]; \
1480 src += 8 * 2; \
1481 dest += 8 * 2; \
1482 }
1483
1484 #else
1485 #define COPY_OFFSET_MIN 4
1486
1487 #define COPY_CHUNK(dest, src) \
1488 { \
1489 COPY_CHUNK_4_2(dest, src); \
1490 COPY_CHUNK_4_2(dest, src); \
1491 }
1492
1493 #endif
1494#endif
1495
1496
1497#ifndef COPY_CHUNK_SIZE
1498 #define COPY_OFFSET_MIN 4
1499 #define COPY_CHUNK_SIZE 8
1500 #define COPY_CHUNK_2(dest, src) \
1501 { \
1502 const Byte a0 = src[0]; \
1503 const Byte a1 = src[1]; \
1504 dest[0] = a0; \
1505 dest[1] = a1; \
1506 src += 2; \
1507 dest += 2; \
1508 }
1509 #define COPY_CHUNK(dest, src) \
1510 { \
1511 COPY_CHUNK_2(dest, src) \
1512 COPY_CHUNK_2(dest, src) \
1513 COPY_CHUNK_2(dest, src) \
1514 COPY_CHUNK_2(dest, src) \
1515 }
1516#endif
1517
1518
1519#define COPY_PREPARE \
1520 len += (COPY_CHUNK_SIZE - 1); \
1521 len &= ~(size_t)(COPY_CHUNK_SIZE - 1); \
1522 { if (len > rem) \
1523 { len = rem; \
1524 rem &= (COPY_CHUNK_SIZE - 1); \
1525 if (rem) { \
1526 len -= rem; \
1527 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \
1528 do *dest++ = *src++; while (--rem); \
1529 if (len == 0) return; }}}
1530
1531#define COPY_CHUNKS \
1532{ \
1533 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \
1534 do { COPY_CHUNK(dest, src) } \
1535 while (len -= COPY_CHUNK_SIZE); \
1536}
1537
1538// (len != 0)
1539// (len <= rem)
1540static
1541Z7_FORCE_INLINE
1542// Z7_ATTRIB_NO_VECTOR
1543void CopyLiterals(Byte *dest, Byte const *src, size_t len, size_t rem)
1544{
1545 COPY_PREPARE
1546 COPY_CHUNKS
1547}
1548
1549
1550/* we can define Z7_STD_DEC_USE_AFTER_CYC_BUF, if we want to use additional
1551 space after cycSize that can be used to reduce the code in CopyMatch(): */
1552// for debug:
1553// #define Z7_STD_DEC_USE_AFTER_CYC_BUF
1554
1555/*
1556CopyMatch()
1557if wrap (offset > winPos)
1558{
1559 then we have at least (COPY_CHUNK_SIZE) avail in (dest) before we will overwrite (src):
1560 (cycSize >= offset + COPY_CHUNK_SIZE)
1561 if defined(Z7_STD_DEC_USE_AFTER_CYC_BUF)
1562 we are allowed to read win[cycSize + COPY_CHUNK_SIZE - 1],
1563}
1564(len != 0)
1565*/
1566static
1567Z7_FORCE_INLINE
1568// Z7_ATTRIB_NO_VECTOR
1569void CopyMatch(size_t offset, size_t len,
1570 Byte *win, size_t winPos, size_t rem, const size_t cycSize)
1571{
1572 Byte *dest = win + winPos;
1573 const Byte *src;
1574 // STAT_INC(g_NumCopy)
1575
1576 if (offset > winPos)
1577 {
1578 size_t back = offset - winPos;
1579 // src = win + cycSize - back;
1580 // cycSize -= offset;
1581 STAT_INC(g_NumOver)
1582 src = dest + (cycSize - offset);
1583 // (src >= dest) here
1584 #ifdef Z7_STD_DEC_USE_AFTER_CYC_BUF
1585 if (back < len)
1586 {
1587 #else
1588 if (back < len + (COPY_CHUNK_SIZE - 1))
1589 {
1590 if (back >= len)
1591 {
1592 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
1593 do
1594 *dest++ = *src++;
1595 while (--len);
1596 return;
1597 }
1598 #endif
1599 // back < len
1600 STAT_INC(g_NumOver2)
1601 len -= back;
1602 rem -= back;
1603 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
1604 do
1605 *dest++ = *src++;
1606 while (--back);
1607 src = dest - offset;
1608 // src = win;
1609 // we go to MAIN-COPY
1610 }
1611 }
1612 else
1613 src = dest - offset;
1614
1615 // len != 0
1616 // do *dest++ = *src++; while (--len); return;
1617
1618 // --- MAIN COPY ---
1619 // if (src >= dest), then ((size_t)(src - dest) >= COPY_CHUNK_SIZE)
1620 // so we have at least COPY_CHUNK_SIZE space before overlap for writing.
1621 COPY_PREPARE
1622
1623 /* now (len == COPY_CHUNK_SIZE * x)
1624 so we can unroll for aligned copy */
1625 {
1626 // const unsigned b0 = src[0];
1627 // (COPY_OFFSET_MIN >= 4)
1628
1629 if (offset >= COPY_OFFSET_MIN)
1630 {
1631 COPY_CHUNKS
1632 // return;
1633 }
1634 else
1635 #if (COPY_OFFSET_MIN > 4)
1636 #if COPY_CHUNK_SIZE < 8
1637 #error Stop_Compiling_Bad_COPY_CHUNK_SIZE
1638 #endif
1639 if (offset >= 4)
1640 {
1641 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
1642 do
1643 {
1644 COPY_CHUNK_4_2(dest, src)
1645 #if COPY_CHUNK_SIZE != 16
1646 if (len == 8) break;
1647 #endif
1648 COPY_CHUNK_4_2(dest, src)
1649 }
1650 while (len -= 16);
1651 // return;
1652 }
1653 else
1654 #endif
1655 {
1656 // (offset < 4)
1657 const unsigned b0 = src[0];
1658 if (offset < 2)
1659 {
1660 #if defined(Z7_ZSTD_DEC_USE_UNALIGNED_COPY) && (COPY_CHUNK_SIZE == 16)
1661 #if defined(MY_CPU_64BIT)
1662 {
1663 const UInt64 v64 = (UInt64)b0 * 0x0101010101010101;
1664 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
1665 do
1666 {
1667 ((UInt64 *)(void *)dest)[0] = v64;
1668 ((UInt64 *)(void *)dest)[1] = v64;
1669 dest += 16;
1670 }
1671 while (len -= 16);
1672 }
1673 #else
1674 {
1675 UInt32 v = b0;
1676 v |= v << 8;
1677 v |= v << 16;
1678 do
1679 {
1680 ((UInt32 *)(void *)dest)[0] = v;
1681 ((UInt32 *)(void *)dest)[1] = v;
1682 dest += 8;
1683 ((UInt32 *)(void *)dest)[0] = v;
1684 ((UInt32 *)(void *)dest)[1] = v;
1685 dest += 8;
1686 }
1687 while (len -= 16);
1688 }
1689 #endif
1690 #else
1691 do
1692 {
1693 dest[0] = (Byte)b0;
1694 dest[1] = (Byte)b0;
1695 dest += 2;
1696 dest[0] = (Byte)b0;
1697 dest[1] = (Byte)b0;
1698 dest += 2;
1699 }
1700 while (len -= 4);
1701 #endif
1702 }
1703 else if (offset == 2)
1704 {
1705 const Byte b1 = src[1];
1706 {
1707 do
1708 {
1709 dest[0] = (Byte)b0;
1710 dest[1] = b1;
1711 dest += 2;
1712 }
1713 while (len -= 2);
1714 }
1715 }
1716 else // (offset == 3)
1717 {
1718 const Byte *lim = dest + len - 2;
1719 const Byte b1 = src[1];
1720 const Byte b2 = src[2];
1721 do
1722 {
1723 dest[0] = (Byte)b0;
1724 dest[1] = b1;
1725 dest[2] = b2;
1726 dest += 3;
1727 }
1728 while (dest < lim);
1729 lim++; // points to last byte that must be written
1730 if (dest <= lim)
1731 {
1732 *dest = (Byte)b0;
1733 if (dest != lim)
1734 dest[1] = b1;
1735 }
1736 }
1737 }
1738 }
1739}
1740
1741
1742
1743#define UPDATE_TOTAL_OUT(p, size) \
1744{ \
1745 size_t _toc = (p)->totalOutCheck + (size); \
1746 const size_t _ws = (p)->winSize; \
1747 if (_toc >= _ws) _toc = _ws; \
1748 (p)->totalOutCheck = _toc; \
1749}
1750
1751
1752#if defined(MY_CPU_64BIT) && defined(MY_CPU_LE_UNALIGN)
1753// we can disable it for debug:
1754#define Z7_ZSTD_DEC_USE_64BIT_LOADS
1755#endif
1756// #define Z7_ZSTD_DEC_USE_64BIT_LOADS // for debug : slow in 32-bit
1757
1758// SEQ_SRC_OFFSET: how many bytes (src) (seqSrc) was moved back from original value.
1759// we need (SEQ_SRC_OFFSET != 0) for optimized memory access
1760#ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
1761 #define SEQ_SRC_OFFSET 7
1762#else
1763 #define SEQ_SRC_OFFSET 3
1764#endif
1765#define SRC_PLUS_FOR_4BYTES(bitOffset) (SEQ_SRC_OFFSET - 3) + ((CBitCtr_signed)(bitOffset) >> 3)
1766#define BIT_OFFSET_7BITS(bitOffset) ((unsigned)(bitOffset) & 7)
1767/*
1768 if (BIT_OFFSET_DELTA_BITS == 0) : bitOffset == number_of_unprocessed_bits
1769 if (BIT_OFFSET_DELTA_BITS == 1) : bitOffset == number_of_unprocessed_bits - 1
1770 and we can read 1 bit more in that mode : (8 * n + 1).
1771*/
1772// #define BIT_OFFSET_DELTA_BITS 0
1773#define BIT_OFFSET_DELTA_BITS 1
1774#if BIT_OFFSET_DELTA_BITS == 1
1775 #define GET_SHIFT_FROM_BOFFS7(boff7) (7 ^ (boff7))
1776#else
1777 #define GET_SHIFT_FROM_BOFFS7(boff7) (8 - BIT_OFFSET_DELTA_BITS - (boff7))
1778#endif
1779
1780#define UPDATE_BIT_OFFSET(bitOffset, numBits) \
1781 (bitOffset) -= (CBitCtr)(numBits);
1782
1783#define GET_SHIFT(bitOffset) GET_SHIFT_FROM_BOFFS7(BIT_OFFSET_7BITS(bitOffset))
1784
1785
1786#if defined(Z7_ZSTD_DEC_USE_64BIT_LOADS)
1787 #if (NUM_OFFSET_SYMBOLS_MAX - BIT_OFFSET_DELTA_BITS < 32)
1788 /* if (NUM_OFFSET_SYMBOLS_MAX == 32 && BIT_OFFSET_DELTA_BITS == 1),
1789 we have depth 31 + 9 + 9 + 8 = 57 bits that can b read with single read. */
1790 #define Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF
1791 #endif
1792 #ifndef Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF
1793 #if (BIT_OFFSET_DELTA_BITS == 1)
1794 /* if (winLimit - winPos <= (kBlockSizeMax = (1 << 17)))
1795 {
1796 the case (16 bits literal extra + 16 match extra) is not possible
1797 in correct stream. So error will be detected for (16 + 16) case.
1798 And longest correct sequence after offset reading is (31 + 9 + 9 + 8 = 57 bits).
1799 So we can use just one 64-bit load here in that case.
1800 }
1801 */
1802 #define Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML
1803 #endif
1804 #endif
1805#endif
1806
1807
1808#if !defined(Z7_ZSTD_DEC_USE_64BIT_LOADS) || \
1809 (!defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF) && \
1810 !defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML))
1811// in : (0 < bits <= (24 or 25)):
1812#define STREAM_READ_BITS(dest, bits) \
1813{ \
1814 GET32(dest, src + SRC_PLUS_FOR_4BYTES(bitOffset)) \
1815 dest <<= GET_SHIFT(bitOffset); \
1816 UPDATE_BIT_OFFSET(bitOffset, bits) \
1817 dest >>= 32 - bits; \
1818}
1819#endif
1820
1821
1822#define FSE_Peek_1(table, state) table[state]
1823
1824#define STATE_VAR(name) state_ ## name
1825
1826// in : (0 <= accuracy <= (24 or 25))
1827#define FSE_INIT_STATE(name, cond) \
1828{ \
1829 UInt32 r; \
1830 const unsigned bits = p->name ## _accuracy; \
1831 GET32(r, src + SRC_PLUS_FOR_4BYTES(bitOffset)) \
1832 r <<= GET_SHIFT(bitOffset); \
1833 r >>= 1; \
1834 r >>= 31 ^ bits; \
1835 UPDATE_BIT_OFFSET(bitOffset, bits) \
1836 cond \
1837 STATE_VAR(name) = FSE_Peek_1(FSE_TABLE(name), r); \
1838 /* STATE_VAR(name) = dest << 16; */ \
1839}
1840
1841
1842#define FSE_Peek_Plus(name, r) \
1843 STATE_VAR(name) = FSE_Peek_1(FSE_TABLE(name), \
1844 GET_FSE_REC_STATE(STATE_VAR(name)) + r);
1845
1846#define LZ_LOOP_ERROR_EXIT { return SZ_ERROR_DATA; }
1847
1848#define BO_OVERFLOW_CHECK \
1849 { if ((CBitCtr_signed)bitOffset < 0) LZ_LOOP_ERROR_EXIT }
1850
1851
1852#ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
1853
1854#define GET64(dest, p) { const Byte *ptr = p; dest = GetUi64(ptr); }
1855
1856#define FSE_PRELOAD \
1857{ \
1858 GET64(v, src - 4 + SRC_PLUS_FOR_4BYTES(bitOffset)) \
1859 v <<= GET_SHIFT(bitOffset); \
1860}
1861
1862#define FSE_UPDATE_STATE_2(name, cond) \
1863{ \
1864 const unsigned bits = GET_FSE_REC_LEN(STATE_VAR(name)); \
1865 UInt64 r = v; \
1866 v <<= bits; \
1867 r >>= 1; \
1868 UPDATE_BIT_OFFSET(bitOffset, bits) \
1869 cond \
1870 r >>= 63 ^ bits; \
1871 FSE_Peek_Plus(name, r); \
1872}
1873
1874#define FSE_UPDATE_STATES \
1875 FSE_UPDATE_STATE_2 (ll, {} ) \
1876 FSE_UPDATE_STATE_2 (ml, {} ) \
1877 FSE_UPDATE_STATE_2 (of, BO_OVERFLOW_CHECK) \
1878
1879#else // Z7_ZSTD_DEC_USE_64BIT_LOADS
1880
1881// it supports 8 bits accuracy for any code
1882// it supports 9 bits accuracy, if (BIT_OFFSET_DELTA_BITS == 1)
1883#define FSE_UPDATE_STATE_0(name, cond) \
1884{ \
1885 UInt32 r; \
1886 const unsigned bits = GET_FSE_REC_LEN(STATE_VAR(name)); \
1887 GET16(r, src + 2 + SRC_PLUS_FOR_4BYTES(bitOffset)) \
1888 r >>= (bitOffset & 7); \
1889 r &= (1 << (8 + BIT_OFFSET_DELTA_BITS)) - 1; \
1890 UPDATE_BIT_OFFSET(bitOffset, bits) \
1891 cond \
1892 r >>= (8 + BIT_OFFSET_DELTA_BITS) - bits; \
1893 FSE_Peek_Plus(name, r); \
1894}
1895
1896// for debug (slow):
1897// #define Z7_ZSTD_DEC_USE_FSE_FUSION_FORCE
1898#if BIT_OFFSET_DELTA_BITS == 0 || defined(Z7_ZSTD_DEC_USE_FSE_FUSION_FORCE)
1899 #define Z7_ZSTD_DEC_USE_FSE_FUSION
1900#endif
1901
1902#ifdef Z7_ZSTD_DEC_USE_FSE_FUSION
1903#define FSE_UPDATE_STATE_1(name) \
1904{ UInt32 rest2; \
1905{ \
1906 UInt32 r; \
1907 unsigned bits; \
1908 GET32(r, src + SRC_PLUS_FOR_4BYTES(bitOffset)) \
1909 bits = GET_FSE_REC_LEN(STATE_VAR(name)); \
1910 r <<= GET_SHIFT(bitOffset); \
1911 rest2 = r << bits; \
1912 r >>= 1; \
1913 UPDATE_BIT_OFFSET(bitOffset, bits) \
1914 r >>= 31 ^ bits; \
1915 FSE_Peek_Plus(name, r); \
1916}
1917
1918#define FSE_UPDATE_STATE_3(name) \
1919{ \
1920 const unsigned bits = GET_FSE_REC_LEN(STATE_VAR(name)); \
1921 rest2 >>= 1; \
1922 UPDATE_BIT_OFFSET(bitOffset, bits) \
1923 rest2 >>= 31 ^ bits; \
1924 FSE_Peek_Plus(name, rest2); \
1925}}
1926
1927#define FSE_UPDATE_STATES \
1928 FSE_UPDATE_STATE_1 (ll) \
1929 FSE_UPDATE_STATE_3 (ml) \
1930 FSE_UPDATE_STATE_0 (of, BO_OVERFLOW_CHECK) \
1931
1932#else // Z7_ZSTD_DEC_USE_64BIT_LOADS
1933
1934#define FSE_UPDATE_STATES \
1935 FSE_UPDATE_STATE_0 (ll, {} ) \
1936 FSE_UPDATE_STATE_0 (ml, {} ) \
1937 FSE_UPDATE_STATE_0 (of, BO_OVERFLOW_CHECK) \
1938
1939#endif // Z7_ZSTD_DEC_USE_FSE_FUSION
1940#endif // Z7_ZSTD_DEC_USE_64BIT_LOADS
1941
1942
1943
1944typedef struct
1945{
1946 UInt32 numSeqs;
1947 UInt32 literalsLen;
1948 const Byte *literals;
1949}
1950CZstdDec1_Vars;
1951
1952
1953// if (BIT_OFFSET_DELTA_BITS != 0), we need (BIT_OFFSET_DELTA_BYTES > 0)
1954#define BIT_OFFSET_DELTA_BYTES BIT_OFFSET_DELTA_BITS
1955
1956/* if (NUM_OFFSET_SYMBOLS_MAX == 32)
1957 max_seq_bit_length = (31) + 16 + 16 + 9 + 8 + 9 = 89 bits
1958 if defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF) we have longest backward
1959 lookahead offset, and we read UInt64 after literal_len reading.
1960 if (BIT_OFFSET_DELTA_BITS == 1 && NUM_OFFSET_SYMBOLS_MAX == 32)
1961 MAX_BACKWARD_DEPTH = 16 bytes
1962*/
1963#define MAX_BACKWARD_DEPTH \
1964 ((NUM_OFFSET_SYMBOLS_MAX - 1 + 16 + 16 + 7) / 8 + 7 + BIT_OFFSET_DELTA_BYTES)
1965
1966/* srcLen != 0
1967 src == real_data_ptr - SEQ_SRC_OFFSET - BIT_OFFSET_DELTA_BYTES
1968 if defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML) then
1969 (winLimit - p->winPos <= (1 << 17)) is required
1970*/
1971static
1972Z7_NO_INLINE
1973// Z7_ATTRIB_NO_VECTOR
1974SRes Decompress_Sequences(CZstdDec1 * const p,
1975 const Byte *src, const size_t srcLen,
1976 const size_t winLimit,
1977 const CZstdDec1_Vars * const vars)
1978{
1979#ifdef Z7_ZSTD_DEC_USE_BASES_LOCAL
1980 SEQ_EXTRA_TABLES(a_)
1981#endif
1982
1983 // for debug:
1984 // #define Z7_ZSTD_DEC_USE_LOCAL_FSE_TABLES
1985#ifdef Z7_ZSTD_DEC_USE_LOCAL_FSE_TABLES
1986 #define FSE_TABLE(n) fse. n
1987 const CZstdDecFseTables fse = p->fse;
1988 /*
1989 CZstdDecFseTables fse;
1990 #define COPY_FSE_TABLE(n) \
1991 memcpy(fse. n, p->fse. n, (size_t)4 << p-> n ## _accuracy);
1992 COPY_FSE_TABLE(of)
1993 COPY_FSE_TABLE(ll)
1994 COPY_FSE_TABLE(ml)
1995 */
1996#else
1997 #define FSE_TABLE(n) (p->fse. n)
1998#endif
1999
2000#ifdef Z7_ZSTD_DEC_USE_BASES_LOCAL
2001 FILL_LOC_BASES_ALL
2002#endif
2003
2004 {
2005 unsigned numSeqs = vars->numSeqs;
2006 const Byte *literals = vars->literals;
2007 ptrdiff_t literalsLen = (ptrdiff_t)vars->literalsLen;
2008 Byte * const win = p->win;
2009 size_t winPos = p->winPos;
2010 const size_t cycSize = p->cycSize;
2011 size_t totalOutCheck = p->totalOutCheck;
2012 const size_t winSize = p->winSize;
2013 size_t reps_0 = p->reps[0];
2014 size_t reps_1 = p->reps[1];
2015 size_t reps_2 = p->reps[2];
2016 UInt32 STATE_VAR(ll), STATE_VAR(of), STATE_VAR(ml);
2017 CBitCtr bitOffset;
2018
2019 SET_bitOffset_TO_PAD (bitOffset, src + SEQ_SRC_OFFSET, srcLen + BIT_OFFSET_DELTA_BYTES)
2020
2021 bitOffset -= BIT_OFFSET_DELTA_BITS;
2022
2023 FSE_INIT_STATE(ll, {} )
2024 FSE_INIT_STATE(of, {} )
2025 FSE_INIT_STATE(ml, BO_OVERFLOW_CHECK)
2026
2027 for (;;)
2028 {
2029 size_t matchLen;
2030 #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2031 UInt64 v;
2032 #endif
2033
2034 #ifdef Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF
2035 FSE_PRELOAD
2036 #endif
2037
2038 // if (of_code == 0)
2039 if ((Byte)STATE_VAR(of) == 0)
2040 {
2041 if (GET_FSE_REC_SYM(STATE_VAR(ll)) == 0)
2042 {
2043 const size_t offset = reps_1;
2044 reps_1 = reps_0;
2045 reps_0 = offset;
2046 STAT_INC(g_Num_Rep1)
2047 }
2048 STAT_UPDATE(else g_Num_Rep0++;)
2049 }
2050 else
2051 {
2052 const unsigned of_code = (Byte)STATE_VAR(of);
2053
2054 #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2055 #if !defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF)
2056 FSE_PRELOAD
2057 #endif
2058 #else
2059 UInt32 v;
2060 {
2061 const Byte *src4 = src + SRC_PLUS_FOR_4BYTES(bitOffset);
2062 const unsigned skip = GET_SHIFT(bitOffset);
2063 GET32(v, src4)
2064 v <<= skip;
2065 v |= (UInt32)src4[-1] >> (8 - skip);
2066 }
2067 #endif
2068
2069 UPDATE_BIT_OFFSET(bitOffset, of_code)
2070
2071 if (of_code == 1)
2072 {
2073 // read 1 bit
2074 #if defined(Z7_MSC_VER_ORIGINAL) || defined(MY_CPU_X86_OR_AMD64)
2075 #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2076 #define CHECK_HIGH_BIT_64(a) ((Int64)(UInt64)(a) < 0)
2077 #else
2078 #define CHECK_HIGH_BIT_32(a) ((Int32)(UInt32)(a) < 0)
2079 #endif
2080 #else
2081 #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2082 #define CHECK_HIGH_BIT_64(a) ((UInt64)(a) & ((UInt64)1 << 63))
2083 #else
2084 #define CHECK_HIGH_BIT_32(a) ((UInt32)(a) & ((UInt32)1 << 31))
2085 #endif
2086 #endif
2087
2088 if
2089 #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2090 CHECK_HIGH_BIT_64 (((UInt64)GET_FSE_REC_SYM(STATE_VAR(ll)) - 1) ^ v)
2091 #else
2092 CHECK_HIGH_BIT_32 (((UInt32)GET_FSE_REC_SYM(STATE_VAR(ll)) - 1) ^ v)
2093 #endif
2094 {
2095 v <<= 1;
2096 {
2097 const size_t offset = reps_2;
2098 reps_2 = reps_1;
2099 reps_1 = reps_0;
2100 reps_0 = offset;
2101 STAT_INC(g_Num_Rep2)
2102 }
2103 }
2104 else
2105 {
2106 if (GET_FSE_REC_SYM(STATE_VAR(ll)) == 0)
2107 {
2108 // litLen == 0 && bit == 1
2109 STAT_INC(g_Num_Rep3)
2110 v <<= 1;
2111 reps_2 = reps_1;
2112 reps_1 = reps_0;
2113 if (--reps_0 == 0)
2114 {
2115 // LZ_LOOP_ERROR_EXIT
2116 // original-zstd decoder : input is corrupted; force offset to 1
2117 // reps_0 = 1;
2118 reps_0++;
2119 }
2120 }
2121 else
2122 {
2123 // litLen != 0 && bit == 0
2124 v <<= 1;
2125 {
2126 const size_t offset = reps_1;
2127 reps_1 = reps_0;
2128 reps_0 = offset;
2129 STAT_INC(g_Num_Rep1)
2130 }
2131 }
2132 }
2133 }
2134 else
2135 {
2136 // (2 <= of_code)
2137 // if (of_code >= 32) LZ_LOOP_ERROR_EXIT // optional check
2138 // we don't allow (of_code >= 32) cases in another code
2139 reps_2 = reps_1;
2140 reps_1 = reps_0;
2141 reps_0 = ((size_t)1 << of_code) - 3 + (size_t)
2142 #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2143 (v >> (64 - of_code));
2144 v <<= of_code;
2145 #else
2146 (v >> (32 - of_code));
2147 #endif
2148 }
2149 }
2150
2151 #ifdef Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML
2152 FSE_PRELOAD
2153 #endif
2154
2155 matchLen = (size_t)GET_FSE_REC_SYM(STATE_VAR(ml))
2156 #ifndef Z7_ZSTD_DEC_USE_ML_PLUS3
2157 + MATCH_LEN_MIN
2158 #endif
2159 ;
2160 {
2161 {
2162 if (matchLen >= 32 + MATCH_LEN_MIN) // if (state_ml & 0x20)
2163 {
2164 const unsigned extra = BASES_TABLE(SEQ_ML_EXTRA) [(size_t)matchLen - MATCH_LEN_MIN];
2165 matchLen = BASES_TABLE(SEQ_ML_BASES) [(size_t)matchLen - MATCH_LEN_MIN];
2166 #if defined(Z7_ZSTD_DEC_USE_64BIT_LOADS) && \
2167 (defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML) || \
2168 defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF))
2169 {
2170 UPDATE_BIT_OFFSET(bitOffset, extra)
2171 matchLen += (size_t)(v >> (64 - extra));
2172 #if defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF)
2173 FSE_PRELOAD
2174 #else
2175 v <<= extra;
2176 #endif
2177 }
2178 #else
2179 {
2180 UInt32 v32;
2181 STREAM_READ_BITS(v32, extra)
2182 matchLen += v32;
2183 }
2184 #endif
2185 STAT_INC(g_Num_Match)
2186 }
2187 }
2188 }
2189
2190 #if defined(Z7_ZSTD_DEC_USE_64BIT_LOADS) && \
2191 !defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF) && \
2192 !defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML)
2193 FSE_PRELOAD
2194 #endif
2195
2196 {
2197 size_t litLen = GET_FSE_REC_SYM(STATE_VAR(ll));
2198 if (litLen)
2199 {
2200 // if (STATE_VAR(ll) & 0x70)
2201 if (litLen >= 16)
2202 {
2203 const unsigned extra = BASES_TABLE(SEQ_LL_EXTRA) [litLen];
2204 litLen = BASES_TABLE(SEQ_LL_BASES) [litLen];
2205 #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2206 {
2207 UPDATE_BIT_OFFSET(bitOffset, extra)
2208 litLen += (size_t)(v >> (64 - extra));
2209 #if defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF)
2210 FSE_PRELOAD
2211 #else
2212 v <<= extra;
2213 #endif
2214 }
2215 #else
2216 {
2217 UInt32 v32;
2218 STREAM_READ_BITS(v32, extra)
2219 litLen += v32;
2220 }
2221 #endif
2222 STAT_INC(g_Num_LitsBig)
2223 }
2224
2225 if ((literalsLen -= (ptrdiff_t)litLen) < 0)
2226 LZ_LOOP_ERROR_EXIT
2227 totalOutCheck += litLen;
2228 {
2229 const size_t rem = winLimit - winPos;
2230 if (litLen > rem)
2231 LZ_LOOP_ERROR_EXIT
2232 {
2233 const Byte *literals_temp = literals;
2234 Byte *d = win + winPos;
2235 literals += litLen;
2236 winPos += litLen;
2237 CopyLiterals(d, literals_temp, litLen, rem);
2238 }
2239 }
2240 }
2241 STAT_UPDATE(else g_Num_Lit0++;)
2242 }
2243
2244 #define COPY_MATCH \
2245 { if (reps_0 > winSize || reps_0 > totalOutCheck) LZ_LOOP_ERROR_EXIT \
2246 totalOutCheck += matchLen; \
2247 { const size_t rem = winLimit - winPos; \
2248 if (matchLen > rem) LZ_LOOP_ERROR_EXIT \
2249 { const size_t winPos_temp = winPos; \
2250 winPos += matchLen; \
2251 CopyMatch(reps_0, matchLen, win, winPos_temp, rem, cycSize); }}}
2252
2253 if (--numSeqs == 0)
2254 {
2255 COPY_MATCH
2256 break;
2257 }
2258 FSE_UPDATE_STATES
2259 COPY_MATCH
2260 } // for
2261
2262 if ((CBitCtr_signed)bitOffset != BIT_OFFSET_DELTA_BYTES * 8 - BIT_OFFSET_DELTA_BITS)
2263 return SZ_ERROR_DATA;
2264
2265 if (literalsLen)
2266 {
2267 const size_t rem = winLimit - winPos;
2268 if ((size_t)literalsLen > rem)
2269 return SZ_ERROR_DATA;
2270 {
2271 Byte *d = win + winPos;
2272 winPos += (size_t)literalsLen;
2273 totalOutCheck += (size_t)literalsLen;
2274 CopyLiterals
2275 // memcpy
2276 (d, literals, (size_t)literalsLen, rem);
2277 }
2278 }
2279 if (totalOutCheck >= winSize)
2280 totalOutCheck = winSize;
2281 p->totalOutCheck = totalOutCheck;
2282 p->winPos = winPos;
2283 p->reps[0] = (CZstdDecOffset)reps_0;
2284 p->reps[1] = (CZstdDecOffset)reps_1;
2285 p->reps[2] = (CZstdDecOffset)reps_2;
2286 }
2287 return SZ_OK;
2288}
2289
2290
2291// for debug: define to check that ZstdDec1_NeedTempBufferForInput() works correctly:
2292// #define Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP // define it for debug only
2293#ifdef Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP
2294static unsigned g_numSeqs;
2295#endif
2296
2297
2298#define k_LitBlockType_Flag_RLE_or_Treeless 1
2299#define k_LitBlockType_Flag_Compressed 2
2300
2301// outLimit : is strong limit
2302// outLimit <= ZstdDec1_GET_BLOCK_SIZE_LIMIT(p)
2303// inSize != 0
2304static
2305Z7_NO_INLINE
2306SRes ZstdDec1_DecodeBlock(CZstdDec1 *p,
2307 const Byte *src, SizeT inSize, SizeT afterAvail,
2308 const size_t outLimit)
2309{
2310 CZstdDec1_Vars vars;
2311 vars.literals = p->literalsBase;
2312 {
2313 const unsigned b0 = *src++;
2314 UInt32 numLits, compressedSize;
2315 const Byte *litStream;
2316 Byte *literalsDest;
2317 inSize--;
2318
2319 if ((b0 & k_LitBlockType_Flag_Compressed) == 0)
2320 {
2321 // we need at least one additional byte for (numSeqs).
2322 // so we check for that additional byte in conditions.
2323 numLits = b0 >> 3;
2324 if (b0 & 4)
2325 {
2326 UInt32 v;
2327 if (inSize < 1 + 1) // we need at least 1 byte here and 1 byte for (numSeqs).
2328 return SZ_ERROR_DATA;
2329 numLits >>= 1;
2330 v = GetUi16(src);
2331 src += 2;
2332 inSize -= 2;
2333 if ((b0 & 8) == 0)
2334 {
2335 src--;
2336 inSize++;
2337 v = (Byte)v;
2338 }
2339 numLits += v << 4;
2340 }
2341 compressedSize = 1;
2342 if ((b0 & k_LitBlockType_Flag_RLE_or_Treeless) == 0)
2343 compressedSize = numLits;
2344 }
2345 else if (inSize < 4)
2346 return SZ_ERROR_DATA;
2347 else
2348 {
2349 const unsigned mode4Streams = b0 & 0xc;
2350 const unsigned numBytes = (3 * mode4Streams + 32) >> 4;
2351 const unsigned numBits = 4 * numBytes - 2;
2352 const UInt32 mask = ((UInt32)16 << numBits) - 1;
2353 compressedSize = GetUi32(src);
2354 numLits = ((
2355 #ifdef MY_CPU_LE_UNALIGN
2356 GetUi32(src - 1)
2357 #else
2358 ((compressedSize << 8) + b0)
2359 #endif
2360 ) >> 4) & mask;
2361 src += numBytes;
2362 inSize -= numBytes;
2363 compressedSize >>= numBits;
2364 compressedSize &= mask;
2365 /*
2366 if (numLits != 0) printf("inSize = %7u num_lits=%7u compressed=%7u ratio = %u ratio2 = %u\n",
2367 i1, numLits, (unsigned)compressedSize * 1, (unsigned)compressedSize * 100 / numLits,
2368 (unsigned)numLits * 100 / (unsigned)inSize);
2369 }
2370 */
2371 if (compressedSize == 0)
2372 return SZ_ERROR_DATA; // (compressedSize == 0) is not allowed
2373 }
2374
2375 STAT_UPDATE(g_Num_Lits += numLits;)
2376
2377 vars.literalsLen = numLits;
2378
2379 if (compressedSize >= inSize)
2380 return SZ_ERROR_DATA;
2381 litStream = src;
2382 src += compressedSize;
2383 inSize -= compressedSize;
2384 // inSize != 0
2385 {
2386 UInt32 numSeqs = *src++;
2387 inSize--;
2388 if (numSeqs > 127)
2389 {
2390 UInt32 b1;
2391 if (inSize == 0)
2392 return SZ_ERROR_DATA;
2393 numSeqs -= 128;
2394 b1 = *src++;
2395 inSize--;
2396 if (numSeqs == 127)
2397 {
2398 if (inSize == 0)
2399 return SZ_ERROR_DATA;
2400 numSeqs = (UInt32)(*src++) + 127;
2401 inSize--;
2402 }
2403 numSeqs = (numSeqs << 8) + b1;
2404 }
2405 if (numSeqs * MATCH_LEN_MIN + numLits > outLimit)
2406 return SZ_ERROR_DATA;
2407 vars.numSeqs = numSeqs;
2408
2409 STAT_UPDATE(g_NumSeqs_total += numSeqs;)
2410 /*
2411 #ifdef SHOW_STAT
2412 printf("\n %5u : %8u, %8u : %5u", (int)g_Num_Blocks_Compressed, (int)numSeqs, (int)g_NumSeqs_total,
2413 (int)g_NumSeqs_total / g_Num_Blocks_Compressed);
2414 #endif
2415 // printf("\nnumSeqs2 = %d", numSeqs);
2416 */
2417 #ifdef Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP
2418 if (numSeqs != g_numSeqs) return SZ_ERROR_DATA; // for debug
2419 #endif
2420 if (numSeqs == 0)
2421 {
2422 if (inSize != 0)
2423 return SZ_ERROR_DATA;
2424 literalsDest = p->win + p->winPos;
2425 }
2426 else
2427 literalsDest = p->literalsBase;
2428 }
2429
2430 if ((b0 & k_LitBlockType_Flag_Compressed) == 0)
2431 {
2432 if (b0 & k_LitBlockType_Flag_RLE_or_Treeless)
2433 {
2434 memset(literalsDest, litStream[0], numLits);
2435 if (vars.numSeqs)
2436 {
2437 // literalsDest == p->literalsBase == vars.literals
2438 #if COPY_CHUNK_SIZE > 1
2439 memset(p->literalsBase + numLits, 0, COPY_CHUNK_SIZE);
2440 #endif
2441 }
2442 }
2443 else
2444 {
2445 // unsigned y;
2446 // for (y = 0; y < 10000; y++)
2447 memcpy(literalsDest, litStream, numLits);
2448 if (vars.numSeqs)
2449 {
2450 /* we need up to (15 == COPY_CHUNK_SIZE - 1) space for optimized CopyLiterals().
2451 If we have additional space in input stream after literals stream,
2452 we use direct copy of rar literals in input stream */
2453 if ((size_t)(src + inSize - litStream) - numLits + afterAvail >= (COPY_CHUNK_SIZE - 1))
2454 vars.literals = litStream;
2455 else
2456 {
2457 // literalsDest == p->literalsBase == vars.literals
2458 #if COPY_CHUNK_SIZE > 1
2459 /* CopyLiterals():
2460 1) we don't want reading non-initialized data
2461 2) we will copy only zero byte after literals buffer */
2462 memset(p->literalsBase + numLits, 0, COPY_CHUNK_SIZE);
2463 #endif
2464 }
2465 }
2466 }
2467 }
2468 else
2469 {
2470 CInBufPair hufStream;
2471 hufStream.ptr = litStream;
2472 hufStream.len = compressedSize;
2473
2474 if ((b0 & k_LitBlockType_Flag_RLE_or_Treeless) == 0)
2475 {
2476 // unsigned y = 100; CInBufPair hs2 = hufStream; do { hufStream = hs2;
2477 RINOK(Huf_DecodeTable(&p->huf, &hufStream))
2478 p->litHuf_wasSet = True;
2479 // } while (--y);
2480 }
2481 else if (!p->litHuf_wasSet)
2482 return SZ_ERROR_DATA;
2483
2484 {
2485 // int yyy; for (yyy = 0; yyy < 34; yyy++) {
2486 SRes sres;
2487 if ((b0 & 0xc) == 0) // mode4Streams
2488 sres = Huf_Decompress_1stream((const Byte *)(const void *)p->huf.table64,
2489 hufStream.ptr - HUF_SRC_OFFSET, hufStream.len, literalsDest, numLits);
2490 else
2491 {
2492 // 6 bytes for the jump table + 4x1 bytes of end-padding Bytes)
2493 if (hufStream.len < 6 + 4)
2494 return SZ_ERROR_DATA;
2495 // the condition from original-zstd decoder:
2496 #define Z7_ZSTD_MIN_LITERALS_FOR_4_STREAMS 6
2497 if (numLits < Z7_ZSTD_MIN_LITERALS_FOR_4_STREAMS)
2498 return SZ_ERROR_DATA;
2499 sres = Huf_Decompress_4stream((const Byte *)(const void *)p->huf.table64,
2500 hufStream.ptr + (6 - HUF_SRC_OFFSET), hufStream.len, literalsDest, numLits);
2501 }
2502 RINOK(sres)
2503 // }
2504 }
2505 }
2506
2507 if (vars.numSeqs == 0)
2508 {
2509 p->winPos += numLits;
2510 return SZ_OK;
2511 }
2512 }
2513 {
2514 CInBufPair in;
2515 unsigned mode;
2516 unsigned seqMode;
2517
2518 in.ptr = src;
2519 in.len = inSize;
2520 if (in.len == 0)
2521 return SZ_ERROR_DATA;
2522 in.len--;
2523 mode = *in.ptr++;
2524 if (mode & 3) // Reserved bits
2525 return SZ_ERROR_DATA;
2526
2527 seqMode = (mode >> 6);
2528 if (seqMode == k_SeqMode_Repeat)
2529 { if (!IS_SEQ_TABLES_WERE_SET(p)) return SZ_ERROR_DATA; }
2530 else RINOK(FSE_Decode_SeqTable(
2531 p->fse.ll,
2532 &in,
2533 6, // predefAccuracy
2534 &p->ll_accuracy,
2535 NUM_LL_SYMBOLS,
2536 k_PredefRecords_LL,
2537 seqMode))
2538
2539 seqMode = (mode >> 4) & 3;
2540 if (seqMode == k_SeqMode_Repeat)
2541 { if (!IS_SEQ_TABLES_WERE_SET(p)) return SZ_ERROR_DATA; }
2542 else RINOK(FSE_Decode_SeqTable(
2543 p->fse.of,
2544 &in,
2545 5, // predefAccuracy
2546 &p->of_accuracy,
2547 NUM_OFFSET_SYMBOLS_MAX,
2548 k_PredefRecords_OF,
2549 seqMode))
2550
2551 seqMode = (mode >> 2) & 3;
2552 if (seqMode == k_SeqMode_Repeat)
2553 { if (!IS_SEQ_TABLES_WERE_SET(p)) return SZ_ERROR_DATA; }
2554 else
2555 {
2556 RINOK(FSE_Decode_SeqTable(
2557 p->fse.ml,
2558 &in,
2559 6, // predefAccuracy
2560 &p->ml_accuracy,
2561 NUM_ML_SYMBOLS,
2562 k_PredefRecords_ML,
2563 seqMode))
2564 /*
2565 #if defined(Z7_ZSTD_DEC_USE_ML_PLUS3)
2566 // { unsigned y = 1 << 10; do
2567 {
2568 const unsigned accuracy = p->ml_accuracy;
2569 if (accuracy == 0)
2570 p->fse.ml[0] += 3;
2571 else
2572 #ifdef MY_CPU_64BIT
2573 {
2574 // alignemt (UInt64 _pad_Alignment) in fse.ml is required for that code
2575 UInt64 *table = (UInt64 *)(void *)p->fse.ml;
2576 const UInt64 *end = (const UInt64 *)(const void *)
2577 ((const Byte *)(const void *)table + ((size_t)sizeof(CFseRecord) << accuracy));
2578 do
2579 {
2580 table[0] += ((UInt64)MATCH_LEN_MIN << 32) + MATCH_LEN_MIN;
2581 table[1] += ((UInt64)MATCH_LEN_MIN << 32) + MATCH_LEN_MIN;
2582 table += 2;
2583 }
2584 while (table != end);
2585 }
2586 #else
2587 {
2588 UInt32 *table = p->fse.ml;
2589 const UInt32 *end = (const UInt32 *)(const void *)
2590 ((const Byte *)(const void *)table + ((size_t)sizeof(CFseRecord) << accuracy));
2591 do
2592 {
2593 table[0] += MATCH_LEN_MIN;
2594 table[1] += MATCH_LEN_MIN;
2595 table += 2;
2596 table[0] += MATCH_LEN_MIN;
2597 table[1] += MATCH_LEN_MIN;
2598 table += 2;
2599 }
2600 while (table != end);
2601 }
2602 #endif
2603 }
2604 // while (--y); }
2605 #endif
2606 */
2607 }
2608
2609 // p->seqTables_wereSet = True;
2610 if (in.len == 0)
2611 return SZ_ERROR_DATA;
2612 return Decompress_Sequences(p,
2613 in.ptr - SEQ_SRC_OFFSET - BIT_OFFSET_DELTA_BYTES, in.len,
2614 p->winPos + outLimit, &vars);
2615 }
2616}
2617
2618
2619
2620
2621// inSize != 0
2622// it must do similar to ZstdDec1_DecodeBlock()
2623static size_t ZstdDec1_NeedTempBufferForInput(
2624 const SizeT beforeSize, const Byte * const src, const SizeT inSize)
2625{
2626 unsigned b0;
2627 UInt32 pos;
2628
2629 #ifdef Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP
2630 g_numSeqs = 1 << 24;
2631 #else
2632 // we have at least 3 bytes before seq data: litBlockType, numSeqs, seqMode
2633 #define MIN_BLOCK_LZ_HEADERS_SIZE 3
2634 if (beforeSize >= MAX_BACKWARD_DEPTH - MIN_BLOCK_LZ_HEADERS_SIZE)
2635 return 0;
2636 #endif
2637
2638 b0 = src[0];
2639
2640 if ((b0 & k_LitBlockType_Flag_Compressed) == 0)
2641 {
2642 UInt32 numLits = b0 >> 3;
2643 pos = 1;
2644 if (b0 & 4)
2645 {
2646 UInt32 v;
2647 if (inSize < 3)
2648 return 0;
2649 numLits >>= 1;
2650 v = GetUi16(src + 1);
2651 pos = 3;
2652 if ((b0 & 8) == 0)
2653 {
2654 pos = 2;
2655 v = (Byte)v;
2656 }
2657 numLits += v << 4;
2658 }
2659 if (b0 & k_LitBlockType_Flag_RLE_or_Treeless)
2660 numLits = 1;
2661 pos += numLits;
2662 }
2663 else if (inSize < 5)
2664 return 0;
2665 else
2666 {
2667 const unsigned mode4Streams = b0 & 0xc;
2668 const unsigned numBytes = (3 * mode4Streams + 48) >> 4;
2669 const unsigned numBits = 4 * numBytes - 6;
2670 UInt32 cs = GetUi32(src + 1);
2671 cs >>= numBits;
2672 cs &= ((UInt32)16 << numBits) - 1;
2673 if (cs == 0)
2674 return 0;
2675 pos = numBytes + cs;
2676 }
2677
2678 if (pos >= inSize)
2679 return 0;
2680 {
2681 UInt32 numSeqs = src[pos++];
2682 if (numSeqs > 127)
2683 {
2684 UInt32 b1;
2685 if (pos >= inSize)
2686 return 0;
2687 numSeqs -= 128;
2688 b1 = src[pos++];
2689 if (numSeqs == 127)
2690 {
2691 if (pos >= inSize)
2692 return 0;
2693 numSeqs = (UInt32)(src[pos++]) + 127;
2694 }
2695 numSeqs = (numSeqs << 8) + b1;
2696 }
2697 #ifdef Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP
2698 g_numSeqs = numSeqs; // for debug
2699 #endif
2700 if (numSeqs == 0)
2701 return 0;
2702 }
2703 /*
2704 if (pos >= inSize)
2705 return 0;
2706 pos++;
2707 */
2708 // we will have one additional byte for seqMode:
2709 if (beforeSize + pos >= MAX_BACKWARD_DEPTH - 1)
2710 return 0;
2711 return 1;
2712}
2713
2714
2715
2716// ---------- ZSTD FRAME ----------
2717
2718#define kBlockType_Raw 0
2719#define kBlockType_RLE 1
2720#define kBlockType_Compressed 2
2721#define kBlockType_Reserved 3
2722
2723typedef enum
2724{
2725 // begin: states that require 4 bytes:
2726 ZSTD2_STATE_SIGNATURE,
2727 ZSTD2_STATE_HASH,
2728 ZSTD2_STATE_SKIP_HEADER,
2729 // end of states that require 4 bytes
2730
2731 ZSTD2_STATE_SKIP_DATA,
2732 ZSTD2_STATE_FRAME_HEADER,
2733 ZSTD2_STATE_AFTER_HEADER,
2734 ZSTD2_STATE_BLOCK,
2735 ZSTD2_STATE_DATA,
2736 ZSTD2_STATE_FINISHED
2737} EZstd2State;
2738
2739
2740struct CZstdDec
2741{
2742 EZstd2State frameState;
2743 unsigned tempSize;
2744
2745 Byte temp[14]; // 14 is required
2746
2747 Byte descriptor;
2748 Byte windowDescriptor;
2749 Byte isLastBlock;
2750 Byte blockType;
2751 Byte isErrorState;
2752 Byte hashError;
2753 Byte disableHash;
2754 Byte isCyclicMode;
2755
2756 UInt32 blockSize;
2757 UInt32 dictionaryId;
2758 UInt32 curBlockUnpackRem; // for compressed blocks only
2759 UInt32 inTempPos;
2760
2761 UInt64 contentSize;
2762 UInt64 contentProcessed;
2763 CXxh64State xxh64;
2764
2765 Byte *inTemp;
2766 SizeT winBufSize_Allocated;
2767 Byte *win_Base;
2768
2769 ISzAllocPtr alloc_Small;
2770 ISzAllocPtr alloc_Big;
2771
2772 CZstdDec1 decoder;
2773};
2774
2775#define ZstdDec_GET_UNPROCESSED_XXH64_SIZE(p) \
2776 ((unsigned)(p)->contentProcessed & (Z7_XXH64_BLOCK_SIZE - 1))
2777
2778#define ZSTD_DEC_IS_LAST_BLOCK(p) ((p)->isLastBlock)
2779
2780
2781static void ZstdDec_FreeWindow(CZstdDec * const p)
2782{
2783 if (p->win_Base)
2784 {
2785 ISzAlloc_Free(p->alloc_Big, p->win_Base);
2786 p->win_Base = NULL;
2787 // p->decoder.win = NULL;
2788 p->winBufSize_Allocated = 0;
2789 }
2790}
2791
2792
2793CZstdDecHandle ZstdDec_Create(ISzAllocPtr alloc_Small, ISzAllocPtr alloc_Big)
2794{
2795 CZstdDec *p = (CZstdDec *)ISzAlloc_Alloc(alloc_Small, sizeof(CZstdDec));
2796 if (!p)
2797 return NULL;
2798 p->alloc_Small = alloc_Small;
2799 p->alloc_Big = alloc_Big;
2800 // ZstdDec_CONSTRUCT(p)
2801 p->inTemp = NULL;
2802 p->win_Base = NULL;
2803 p->winBufSize_Allocated = 0;
2804 p->disableHash = False;
2805 ZstdDec1_Construct(&p->decoder);
2806 return p;
2807}
2808
2809void ZstdDec_Destroy(CZstdDecHandle p)
2810{
2811 #ifdef SHOW_STAT
2812 #define PRINT_STAT1(name, v) \
2813 printf("\n%25s = %9u", name, v);
2814 PRINT_STAT1("g_Num_Blocks_Compressed", g_Num_Blocks_Compressed)
2815 PRINT_STAT1("g_Num_Blocks_memcpy", g_Num_Blocks_memcpy)
2816 PRINT_STAT1("g_Num_Wrap_memmove_Num", g_Num_Wrap_memmove_Num)
2817 PRINT_STAT1("g_Num_Wrap_memmove_Bytes", g_Num_Wrap_memmove_Bytes)
2818 if (g_Num_Blocks_Compressed)
2819 {
2820 #define PRINT_STAT(name, v) \
2821 printf("\n%17s = %9u, per_block = %8u", name, v, v / g_Num_Blocks_Compressed);
2822 PRINT_STAT("g_NumSeqs", g_NumSeqs_total)
2823 // PRINT_STAT("g_NumCopy", g_NumCopy)
2824 PRINT_STAT("g_NumOver", g_NumOver)
2825 PRINT_STAT("g_NumOver2", g_NumOver2)
2826 PRINT_STAT("g_Num_Match", g_Num_Match)
2827 PRINT_STAT("g_Num_Lits", g_Num_Lits)
2828 PRINT_STAT("g_Num_LitsBig", g_Num_LitsBig)
2829 PRINT_STAT("g_Num_Lit0", g_Num_Lit0)
2830 PRINT_STAT("g_Num_Rep_0", g_Num_Rep0)
2831 PRINT_STAT("g_Num_Rep_1", g_Num_Rep1)
2832 PRINT_STAT("g_Num_Rep_2", g_Num_Rep2)
2833 PRINT_STAT("g_Num_Rep_3", g_Num_Rep3)
2834 PRINT_STAT("g_Num_Threshold_0", g_Num_Threshold_0)
2835 PRINT_STAT("g_Num_Threshold_1", g_Num_Threshold_1)
2836 PRINT_STAT("g_Num_Threshold_0sum", g_Num_Threshold_0sum)
2837 PRINT_STAT("g_Num_Threshold_1sum", g_Num_Threshold_1sum)
2838 }
2839 printf("\n");
2840 #endif
2841
2842 ISzAlloc_Free(p->alloc_Small, p->decoder.literalsBase);
2843 // p->->decoder.literalsBase = NULL;
2844 ISzAlloc_Free(p->alloc_Small, p->inTemp);
2845 // p->inTemp = NULL;
2846 ZstdDec_FreeWindow(p);
2847 ISzAlloc_Free(p->alloc_Small, p);
2848}
2849
2850
2851
2852#define kTempBuffer_PreSize (1u << 6)
2853#if kTempBuffer_PreSize < MAX_BACKWARD_DEPTH
2854 #error Stop_Compiling_Bad_kTempBuffer_PreSize
2855#endif
2856
2857static SRes ZstdDec_AllocateMisc(CZstdDec *p)
2858{
2859 #define k_Lit_AfterAvail (1u << 6)
2860 #if k_Lit_AfterAvail < (COPY_CHUNK_SIZE - 1)
2861 #error Stop_Compiling_Bad_k_Lit_AfterAvail
2862 #endif
2863 // return ZstdDec1_Allocate(&p->decoder, p->alloc_Small);
2864 if (!p->decoder.literalsBase)
2865 {
2866 p->decoder.literalsBase = (Byte *)ISzAlloc_Alloc(p->alloc_Small,
2867 kBlockSizeMax + k_Lit_AfterAvail);
2868 if (!p->decoder.literalsBase)
2869 return SZ_ERROR_MEM;
2870 }
2871 if (!p->inTemp)
2872 {
2873 // we need k_Lit_AfterAvail here for owerread from raw literals stream
2874 p->inTemp = (Byte *)ISzAlloc_Alloc(p->alloc_Small,
2875 kBlockSizeMax + kTempBuffer_PreSize + k_Lit_AfterAvail);
2876 if (!p->inTemp)
2877 return SZ_ERROR_MEM;
2878 }
2879 return SZ_OK;
2880}
2881
2882
2883static void ZstdDec_Init_ForNewFrame(CZstdDec *p)
2884{
2885 p->frameState = ZSTD2_STATE_SIGNATURE;
2886 p->tempSize = 0;
2887
2888 p->isErrorState = False;
2889 p->hashError = False;
2890 p->isCyclicMode = False;
2891 p->contentProcessed = 0;
2892 Xxh64State_Init(&p->xxh64);
2893 ZstdDec1_Init(&p->decoder);
2894}
2895
2896
2897void ZstdDec_Init(CZstdDec *p)
2898{
2899 ZstdDec_Init_ForNewFrame(p);
2900 p->decoder.winPos = 0;
2901 memset(p->temp, 0, sizeof(p->temp));
2902}
2903
2904
2905#define DESCRIPTOR_Get_DictionaryId_Flag(d) ((d) & 3)
2906#define DESCRIPTOR_FLAG_CHECKSUM (1 << 2)
2907#define DESCRIPTOR_FLAG_RESERVED (1 << 3)
2908// #define DESCRIPTOR_FLAG_UNUSED (1 << 4)
2909#define DESCRIPTOR_FLAG_SINGLE (1 << 5)
2910#define DESCRIPTOR_Get_ContentSize_Flag3(d) ((d) >> 5)
2911#define DESCRIPTOR_Is_ContentSize_Defined(d) (((d) & 0xe0) != 0)
2912
2913
2914static EZstd2State ZstdDec_UpdateState(CZstdDec * const p, const Byte b, CZstdDecInfo * const info)
2915{
2916 unsigned tempSize = p->tempSize;
2917 p->temp[tempSize++] = b;
2918 p->tempSize = tempSize;
2919
2920 if (p->frameState == ZSTD2_STATE_BLOCK)
2921 {
2922 if (tempSize < 3)
2923 return ZSTD2_STATE_BLOCK;
2924 {
2925 UInt32 b0 = GetUi32(p->temp);
2926 const unsigned type = ((unsigned)b0 >> 1) & 3;
2927 if (type == kBlockType_RLE && tempSize == 3)
2928 return ZSTD2_STATE_BLOCK;
2929 // info->num_Blocks_forType[type]++;
2930 info->num_Blocks++;
2931 if (type == kBlockType_Reserved)
2932 {
2933 p->isErrorState = True; // SZ_ERROR_UNSUPPORTED
2934 return ZSTD2_STATE_BLOCK;
2935 }
2936 p->blockType = (Byte)type;
2937 p->isLastBlock = (Byte)(b0 & 1);
2938 p->inTempPos = 0;
2939 p->tempSize = 0;
2940 b0 >>= 3;
2941 b0 &= 0x1fffff;
2942 // info->num_BlockBytes_forType[type] += b0;
2943 if (b0 == 0)
2944 {
2945 // empty RAW/RLE blocks are allowed in original-zstd decoder
2946 if (type == kBlockType_Compressed)
2947 {
2948 p->isErrorState = True;
2949 return ZSTD2_STATE_BLOCK;
2950 }
2951 if (!ZSTD_DEC_IS_LAST_BLOCK(p))
2952 return ZSTD2_STATE_BLOCK;
2953 if (p->descriptor & DESCRIPTOR_FLAG_CHECKSUM)
2954 return ZSTD2_STATE_HASH;
2955 return ZSTD2_STATE_FINISHED;
2956 }
2957 p->blockSize = b0;
2958 {
2959 UInt32 blockLim = ZstdDec1_GET_BLOCK_SIZE_LIMIT(&p->decoder);
2960 // compressed and uncompressed block sizes cannot be larger than min(kBlockSizeMax, window_size)
2961 if (b0 > blockLim)
2962 {
2963 p->isErrorState = True; // SZ_ERROR_UNSUPPORTED;
2964 return ZSTD2_STATE_BLOCK;
2965 }
2966 if (DESCRIPTOR_Is_ContentSize_Defined(p->descriptor))
2967 {
2968 const UInt64 rem = p->contentSize - p->contentProcessed;
2969 if (blockLim > rem)
2970 blockLim = (UInt32)rem;
2971 }
2972 p->curBlockUnpackRem = blockLim;
2973 // uncompressed block size cannot be larger than remain data size:
2974 if (type != kBlockType_Compressed)
2975 {
2976 if (b0 > blockLim)
2977 {
2978 p->isErrorState = True; // SZ_ERROR_UNSUPPORTED;
2979 return ZSTD2_STATE_BLOCK;
2980 }
2981 }
2982 }
2983 }
2984 return ZSTD2_STATE_DATA;
2985 }
2986
2987 if ((unsigned)p->frameState < ZSTD2_STATE_SKIP_DATA)
2988 {
2989 UInt32 v;
2990 if (tempSize != 4)
2991 return p->frameState;
2992 v = GetUi32(p->temp);
2993 if ((unsigned)p->frameState < ZSTD2_STATE_HASH) // == ZSTD2_STATE_SIGNATURE
2994 {
2995 if (v == 0xfd2fb528)
2996 {
2997 p->tempSize = 0;
2998 info->num_DataFrames++;
2999 return ZSTD2_STATE_FRAME_HEADER;
3000 }
3001 if ((v & 0xfffffff0) == 0x184d2a50)
3002 {
3003 p->tempSize = 0;
3004 info->num_SkipFrames++;
3005 return ZSTD2_STATE_SKIP_HEADER;
3006 }
3007 p->isErrorState = True;
3008 return ZSTD2_STATE_SIGNATURE;
3009 // return ZSTD2_STATE_ERROR; // is not ZSTD stream
3010 }
3011 if (p->frameState == ZSTD2_STATE_HASH)
3012 {
3013 info->checksum_Defined = True;
3014 info->checksum = v;
3015 // #ifndef DISABLE_XXH_CHECK
3016 if (!p->disableHash)
3017 {
3018 if (p->decoder.winPos < ZstdDec_GET_UNPROCESSED_XXH64_SIZE(p))
3019 {
3020 // unexpected code failure
3021 p->isErrorState = True;
3022 // SZ_ERROR_FAIL;
3023 }
3024 else
3025 if ((UInt32)Xxh64State_Digest(&p->xxh64,
3026 p->decoder.win + (p->decoder.winPos - ZstdDec_GET_UNPROCESSED_XXH64_SIZE(p)),
3027 p->contentProcessed) != v)
3028 {
3029 p->hashError = True;
3030 // return ZSTD2_STATE_ERROR; // hash error
3031 }
3032 }
3033 // #endif
3034 return ZSTD2_STATE_FINISHED;
3035 }
3036 // (p->frameState == ZSTD2_STATE_SKIP_HEADER)
3037 {
3038 p->blockSize = v;
3039 info->skipFrames_Size += v;
3040 p->tempSize = 0;
3041 /* we want the caller could know that there was finished frame
3042 finished frame. So we allow the case where
3043 we have ZSTD2_STATE_SKIP_DATA state with (blockSize == 0).
3044 */
3045 // if (v == 0) return ZSTD2_STATE_SIGNATURE;
3046 return ZSTD2_STATE_SKIP_DATA;
3047 }
3048 }
3049
3050 // if (p->frameState == ZSTD2_STATE_FRAME_HEADER)
3051 {
3052 unsigned descriptor;
3053 const Byte *h;
3054 descriptor = p->temp[0];
3055 p->descriptor = (Byte)descriptor;
3056 if (descriptor & DESCRIPTOR_FLAG_RESERVED) // reserved bit
3057 {
3058 p->isErrorState = True;
3059 return ZSTD2_STATE_FRAME_HEADER;
3060 // return ZSTD2_STATE_ERROR;
3061 }
3062 {
3063 const unsigned n = DESCRIPTOR_Get_ContentSize_Flag3(descriptor);
3064 // tempSize -= 1 + ((1u << (n >> 1)) | ((n + 1) & 1));
3065 tempSize -= (0x9a563422u >> (n * 4)) & 0xf;
3066 }
3067 if (tempSize != (4u >> (3 - DESCRIPTOR_Get_DictionaryId_Flag(descriptor))))
3068 return ZSTD2_STATE_FRAME_HEADER;
3069
3070 info->descriptor_OR = (Byte)(info->descriptor_OR | descriptor);
3071 info->descriptor_NOT_OR = (Byte)(info->descriptor_NOT_OR | ~descriptor);
3072
3073 h = &p->temp[1];
3074 {
3075 Byte w = 0;
3076 if ((descriptor & DESCRIPTOR_FLAG_SINGLE) == 0)
3077 {
3078 w = *h++;
3079 if (info->windowDescriptor_MAX < w)
3080 info->windowDescriptor_MAX = w;
3081 // info->are_WindowDescriptors = True;
3082 // info->num_WindowDescriptors++;
3083 }
3084 else
3085 {
3086 // info->are_SingleSegments = True;
3087 // info->num_SingleSegments++;
3088 }
3089 p->windowDescriptor = w;
3090 }
3091 {
3092 unsigned n = DESCRIPTOR_Get_DictionaryId_Flag(descriptor);
3093 UInt32 d = 0;
3094 if (n)
3095 {
3096 n = 1u << (n - 1);
3097 d = GetUi32(h) & ((UInt32)(Int32)-1 >> (32 - 8u * n));
3098 h += n;
3099 }
3100 p->dictionaryId = d;
3101 // info->dictionaryId_Cur = d;
3102 if (d != 0)
3103 {
3104 if (info->dictionaryId == 0)
3105 info->dictionaryId = d;
3106 else if (info->dictionaryId != d)
3107 info->are_DictionaryId_Different = True;
3108 }
3109 }
3110 {
3111 unsigned n = DESCRIPTOR_Get_ContentSize_Flag3(descriptor);
3112 UInt64 v = 0;
3113 if (n)
3114 {
3115 n >>= 1;
3116 if (n == 1)
3117 v = 256;
3118 v += GetUi64(h) & ((UInt64)(Int64)-1 >> (64 - (8u << n)));
3119 // info->are_ContentSize_Known = True;
3120 // info->num_Frames_with_ContentSize++;
3121 if (info->contentSize_MAX < v)
3122 info->contentSize_MAX = v;
3123 info->contentSize_Total += v;
3124 }
3125 else
3126 {
3127 info->are_ContentSize_Unknown = True;
3128 // info->num_Frames_without_ContentSize++;
3129 }
3130 p->contentSize = v;
3131 }
3132 // if ((size_t)(h - p->temp) != headerSize) return ZSTD2_STATE_ERROR; // it's unexpected internal code failure
3133 p->tempSize = 0;
3134
3135 info->checksum_Defined = False;
3136 /*
3137 if (descriptor & DESCRIPTOR_FLAG_CHECKSUM)
3138 info->are_Checksums = True;
3139 else
3140 info->are_Non_Checksums = True;
3141 */
3142
3143 return ZSTD2_STATE_AFTER_HEADER; // ZSTD2_STATE_BLOCK;
3144 }
3145}
3146
3147
3148static void ZstdDec_Update_XXH(CZstdDec * const p, size_t xxh64_winPos)
3149{
3150 /*
3151 #ifdef DISABLE_XXH_CHECK
3152 UNUSED_VAR(data)
3153 #else
3154 */
3155 if (!p->disableHash && (p->descriptor & DESCRIPTOR_FLAG_CHECKSUM))
3156 {
3157 // const size_t pos = p->xxh64_winPos;
3158 const size_t size = (p->decoder.winPos - xxh64_winPos) & ~(size_t)31;
3159 if (size)
3160 {
3161 // p->xxh64_winPos = pos + size;
3162 Xxh64State_UpdateBlocks(&p->xxh64,
3163 p->decoder.win + xxh64_winPos,
3164 p->decoder.win + xxh64_winPos + size);
3165 }
3166 }
3167}
3168
3169
3170/*
3171in:
3172 (winLimit) : is relaxed limit, where this function is allowed to stop writing of decoded data (if possible).
3173 - this function uses (winLimit) for RAW/RLE blocks only,
3174 because this function can decode single RAW/RLE block in several different calls.
3175 - this function DOESN'T use (winLimit) for Compressed blocks,
3176 because this function decodes full compressed block in single call.
3177 (CZstdDec1::winPos <= winLimit)
3178 (winLimit <= CZstdDec1::cycSize).
3179 Note: if (ds->outBuf_fromCaller) mode is used, then
3180 {
3181 (strong_limit) is stored in CZstdDec1::cycSize.
3182 So (winLimit) is more strong than (strong_limit).
3183 }
3184
3185exit:
3186 Note: (CZstdDecState::winPos) will be set by caller after exit of this function.
3187
3188 This function can exit for any of these conditions:
3189 - (frameState == ZSTD2_STATE_AFTER_HEADER)
3190 - (frameState == ZSTD2_STATE_FINISHED) : frame was finished : (status == ZSTD_STATUS_FINISHED_FRAME) is set
3191 - finished non-empty non-last block. So (CZstdDec1::winPos_atExit != winPos_atFuncStart).
3192 - ZSTD_STATUS_NEEDS_MORE_INPUT in src
3193 - (CZstdDec1::winPos) have reached (winLimit) in non-finished RAW/RLE block
3194
3195 This function decodes no more than one non-empty block.
3196 So it fulfills the condition at exit:
3197 (CZstdDec1::winPos_atExit - winPos_atFuncStart <= block_size_max)
3198 Note: (winPos_atExit > winLimit) is possible in some cases after compressed block decoding.
3199
3200 if (ds->outBuf_fromCaller) mode (useAdditionalWinLimit medo)
3201 {
3202 then this function uses additional strong limit from (CZstdDec1::cycSize).
3203 So this function will not write any data after (CZstdDec1::cycSize)
3204 And it fulfills the condition at exit:
3205 (CZstdDec1::winPos_atExit <= CZstdDec1::cycSize)
3206 }
3207*/
3208static SRes ZstdDec_DecodeBlock(CZstdDec * const p, CZstdDecState * const ds,
3209 SizeT winLimitAdd)
3210{
3211 const Byte *src = ds->inBuf;
3212 SizeT * const srcLen = &ds->inPos;
3213 const SizeT inSize = ds->inLim;
3214 // const int useAdditionalWinLimit = ds->outBuf_fromCaller ? 1 : 0;
3215 enum_ZstdStatus * const status = &ds->status;
3216 CZstdDecInfo * const info = &ds->info;
3217 SizeT winLimit;
3218
3219 const SizeT winPos_atFuncStart = p->decoder.winPos;
3220 src += *srcLen;
3221 *status = ZSTD_STATUS_NOT_SPECIFIED;
3222
3223 // finishMode = ZSTD_FINISH_ANY;
3224 if (ds->outSize_Defined)
3225 {
3226 if (ds->outSize < ds->outProcessed)
3227 {
3228 // p->isAfterSizeMode = 2; // we have extra bytes already
3229 *status = ZSTD_STATUS_OUT_REACHED;
3230 return SZ_OK;
3231 // size = 0;
3232 }
3233 else
3234 {
3235 // p->outSize >= p->outProcessed
3236 const UInt64 rem = ds->outSize - ds->outProcessed;
3237 /*
3238 if (rem == 0)
3239 p->isAfterSizeMode = 1; // we have reached exact required size
3240 */
3241 if (winLimitAdd >= rem)
3242 {
3243 winLimitAdd = (SizeT)rem;
3244 // if (p->finishMode) finishMode = ZSTD_FINISH_END;
3245 }
3246 }
3247 }
3248
3249 winLimit = p->decoder.winPos + winLimitAdd;
3250 // (p->decoder.winPos <= winLimit)
3251
3252 // while (p->frameState != ZSTD2_STATE_ERROR)
3253 while (!p->isErrorState)
3254 {
3255 SizeT inCur = inSize - *srcLen;
3256
3257 if (p->frameState == ZSTD2_STATE_DATA)
3258 {
3259 /* (p->decoder.winPos == winPos_atFuncStart) is expected,
3260 because this function doesn't start new block.
3261 if it have finished some non-empty block in this call. */
3262 if (p->decoder.winPos != winPos_atFuncStart)
3263 return SZ_ERROR_FAIL; // it's unexpected
3264
3265 /*
3266 if (p->decoder.winPos > winLimit)
3267 {
3268 // we can be here, if in this function call
3269 // - we have extracted non-empty compressed block, and (winPos > winLimit) after that.
3270 // - we have started new block decoding after that.
3271 // It's unexpected case, because we exit after non-empty non-last block.
3272 *status = (inSize == *srcLen) ?
3273 ZSTD_STATUS_NEEDS_MORE_INPUT :
3274 ZSTD_STATUS_NOT_FINISHED;
3275 return SZ_OK;
3276 }
3277 */
3278 // p->decoder.winPos <= winLimit
3279
3280 if (p->blockType != kBlockType_Compressed)
3281 {
3282 // it's RLE or RAW block.
3283 // p->BlockSize != 0_
3284 // winLimit <= p->decoder.cycSize
3285 /* So here we use more strong (winLimit), even for
3286 (ds->outBuf_fromCaller) mode. */
3287 SizeT outCur = winLimit - p->decoder.winPos;
3288 {
3289 const UInt32 rem = p->blockSize;
3290 if (outCur > rem)
3291 outCur = rem;
3292 }
3293 if (p->blockType == kBlockType_Raw)
3294 {
3295 if (outCur > inCur)
3296 outCur = inCur;
3297 /* output buffer is better aligned for XXH code.
3298 So we use hash for output buffer data */
3299 // ZstdDec_Update_XXH(p, src, outCur); // for debug:
3300 memcpy(p->decoder.win + p->decoder.winPos, src, outCur);
3301 src += outCur;
3302 *srcLen += outCur;
3303 }
3304 else // kBlockType_RLE
3305 {
3306 #define RLE_BYTE_INDEX_IN_temp 3
3307 memset(p->decoder.win + p->decoder.winPos,
3308 p->temp[RLE_BYTE_INDEX_IN_temp], outCur);
3309 }
3310 {
3311 const SizeT xxh64_winPos = p->decoder.winPos - ZstdDec_GET_UNPROCESSED_XXH64_SIZE(p);
3312 p->decoder.winPos += outCur;
3313 p->contentProcessed += outCur;
3314 ZstdDec_Update_XXH(p, xxh64_winPos);
3315 }
3316 // ds->winPos = p->decoder.winPos; // the caller does it instead. for debug:
3317 UPDATE_TOTAL_OUT(&p->decoder, outCur)
3318 ds->outProcessed += outCur;
3319 if (p->blockSize -= (UInt32)outCur)
3320 {
3321 /*
3322 if (ds->outSize_Defined)
3323 {
3324 if (ds->outSize <= ds->outProcessed) ds->isAfterSizeMode = (enum_ZstdStatus)
3325 (ds->outSize == ds->outProcessed ? 1u: 2u);
3326 }
3327 */
3328 *status = (enum_ZstdStatus)
3329 (ds->outSize_Defined && ds->outSize <= ds->outProcessed ?
3330 ZSTD_STATUS_OUT_REACHED : (p->blockType == kBlockType_Raw && inSize == *srcLen) ?
3331 ZSTD_STATUS_NEEDS_MORE_INPUT :
3332 ZSTD_STATUS_NOT_FINISHED);
3333 return SZ_OK;
3334 }
3335 }
3336 else // kBlockType_Compressed
3337 {
3338 // p->blockSize != 0
3339 // (uncompressed_size_of_block == 0) is allowed
3340 // (p->curBlockUnpackRem == 0) is allowed
3341 /*
3342 if (p->decoder.winPos >= winLimit)
3343 {
3344 if (p->decoder.winPos != winPos_atFuncStart)
3345 {
3346 // it's unexpected case
3347 // We already have some data in finished blocks in this function call.
3348 // So we don't decompress new block after (>=winLimit),
3349 // even if it's empty block.
3350 *status = (inSize == *srcLen) ?
3351 ZSTD_STATUS_NEEDS_MORE_INPUT :
3352 ZSTD_STATUS_NOT_FINISHED;
3353 return SZ_OK;
3354 }
3355 // (p->decoder.winPos == winLimit == winPos_atFuncStart)
3356 // we will decode current block, because that current
3357 // block can be empty block and we want to make some visible
3358 // change of (src) stream after function start.
3359 }
3360 */
3361 /*
3362 if (ds->outSize_Defined && ds->outSize < ds->outProcessed)
3363 {
3364 // we don't want to start new block, if we have more extra decoded bytes already
3365 *status = ZSTD_STATUS_OUT_REACHED;
3366 return SZ_OK;
3367 }
3368 */
3369 {
3370 const Byte *comprStream;
3371 size_t afterAvail;
3372 UInt32 inTempPos = p->inTempPos;
3373 const UInt32 rem = p->blockSize - inTempPos;
3374 // rem != 0
3375 if (inTempPos != 0 // (inTemp) buffer already contains some input data
3376 || inCur < rem // available input data size is smaller than compressed block size
3377 || ZstdDec1_NeedTempBufferForInput(*srcLen, src, rem))
3378 {
3379 if (inCur > rem)
3380 inCur = rem;
3381 if (inCur)
3382 {
3383 STAT_INC(g_Num_Blocks_memcpy)
3384 // we clear data for backward lookahead reading
3385 if (inTempPos == 0)
3386 memset(p->inTemp + kTempBuffer_PreSize - MAX_BACKWARD_DEPTH, 0, MAX_BACKWARD_DEPTH);
3387 // { unsigned y = 0; for(;y < 1000; y++)
3388 memcpy(p->inTemp + inTempPos + kTempBuffer_PreSize, src, inCur);
3389 // }
3390 src += inCur;
3391 *srcLen += inCur;
3392 inTempPos += (UInt32)inCur;
3393 p->inTempPos = inTempPos;
3394 }
3395 if (inTempPos != p->blockSize)
3396 {
3397 *status = ZSTD_STATUS_NEEDS_MORE_INPUT;
3398 return SZ_OK;
3399 }
3400 #if COPY_CHUNK_SIZE > 1
3401 memset(p->inTemp + kTempBuffer_PreSize + inTempPos, 0, COPY_CHUNK_SIZE);
3402 #endif
3403 comprStream = p->inTemp + kTempBuffer_PreSize;
3404 afterAvail = k_Lit_AfterAvail;
3405 // we don't want to read non-initialized data or junk in CopyMatch():
3406 }
3407 else
3408 {
3409 // inCur >= rem
3410 // we use direct decoding from (src) buffer:
3411 afterAvail = inCur - rem;
3412 comprStream = src;
3413 src += rem;
3414 *srcLen += rem;
3415 }
3416
3417 #ifdef Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP
3418 ZstdDec1_NeedTempBufferForInput(*srcLen, comprStream, p->blockSize);
3419 #endif
3420 // printf("\nblockSize=%u", p->blockSize);
3421 // printf("%x\n", (unsigned)p->contentProcessed);
3422 STAT_INC(g_Num_Blocks_Compressed)
3423 {
3424 SRes sres;
3425 const size_t winPos = p->decoder.winPos;
3426 /*
3427 if ( useAdditionalWinLimit), we use strong unpack limit: smallest from
3428 - limit from stream : (curBlockUnpackRem)
3429 - limit from caller : (cycSize - winPos)
3430 if (!useAdditionalWinLimit), we use only relaxed limit:
3431 - limit from stream : (curBlockUnpackRem)
3432 */
3433 SizeT outLimit = p->curBlockUnpackRem;
3434 if (ds->outBuf_fromCaller)
3435 // if (useAdditionalWinLimit)
3436 {
3437 const size_t limit = p->decoder.cycSize - winPos;
3438 if (outLimit > limit)
3439 outLimit = limit;
3440 }
3441 sres = ZstdDec1_DecodeBlock(&p->decoder,
3442 comprStream, p->blockSize, afterAvail, outLimit);
3443 // ds->winPos = p->decoder.winPos; // the caller does it instead. for debug:
3444 if (sres)
3445 {
3446 p->isErrorState = True;
3447 return sres;
3448 }
3449 {
3450 const SizeT xxh64_winPos = winPos - ZstdDec_GET_UNPROCESSED_XXH64_SIZE(p);
3451 const size_t num = p->decoder.winPos - winPos;
3452 ds->outProcessed += num;
3453 p->contentProcessed += num;
3454 ZstdDec_Update_XXH(p, xxh64_winPos);
3455 }
3456 }
3457 // printf("\nwinPos=%x", (int)(unsigned)p->decoder.winPos);
3458 }
3459 }
3460
3461 /*
3462 if (ds->outSize_Defined)
3463 {
3464 if (ds->outSize <= ds->outProcessed) ds->isAfterSizeMode = (enum_ZstdStatus)
3465 (ds->outSize == ds->outProcessed ? 1u: 2u);
3466 }
3467 */
3468
3469 if (!ZSTD_DEC_IS_LAST_BLOCK(p))
3470 {
3471 p->frameState = ZSTD2_STATE_BLOCK;
3472 if (ds->outSize_Defined && ds->outSize < ds->outProcessed)
3473 {
3474 *status = ZSTD_STATUS_OUT_REACHED;
3475 return SZ_OK;
3476 }
3477 // we exit only if (winPos) was changed in this function call:
3478 if (p->decoder.winPos != winPos_atFuncStart)
3479 {
3480 // decoded block was not empty. So we exit:
3481 *status = (enum_ZstdStatus)(
3482 (inSize == *srcLen) ?
3483 ZSTD_STATUS_NEEDS_MORE_INPUT :
3484 ZSTD_STATUS_NOT_FINISHED);
3485 return SZ_OK;
3486 }
3487 // (p->decoder.winPos == winPos_atFuncStart)
3488 // so current decoded block was empty.
3489 // we will try to decode more blocks in this function.
3490 continue;
3491 }
3492
3493 // decoded block was last in frame
3494 if (p->descriptor & DESCRIPTOR_FLAG_CHECKSUM)
3495 {
3496 p->frameState = ZSTD2_STATE_HASH;
3497 if (ds->outSize_Defined && ds->outSize < ds->outProcessed)
3498 {
3499 *status = ZSTD_STATUS_OUT_REACHED;
3500 return SZ_OK; // disable if want to
3501 /* We want to get same return codes for any input buffer sizes.
3502 We want to get faster ZSTD_STATUS_OUT_REACHED status.
3503 So we exit with ZSTD_STATUS_OUT_REACHED here,
3504 instead of ZSTD2_STATE_HASH and ZSTD2_STATE_FINISHED processing.
3505 that depends from input buffer size and that can set
3506 ZSTD_STATUS_NEEDS_MORE_INPUT or return SZ_ERROR_DATA or SZ_ERROR_CRC.
3507 */
3508 }
3509 }
3510 else
3511 {
3512 /* ZSTD2_STATE_FINISHED proccesing doesn't depend from input buffer */
3513 p->frameState = ZSTD2_STATE_FINISHED;
3514 }
3515 /*
3516 p->frameState = (p->descriptor & DESCRIPTOR_FLAG_CHECKSUM) ?
3517 ZSTD2_STATE_HASH :
3518 ZSTD2_STATE_FINISHED;
3519 */
3520 /* it's required to process ZSTD2_STATE_FINISHED state in this function call,
3521 because we must check contentSize and hashError in ZSTD2_STATE_FINISHED code,
3522 while the caller can reinit full state for ZSTD2_STATE_FINISHED
3523 So we can't exit from function here. */
3524 continue;
3525 }
3526
3527 if (p->frameState == ZSTD2_STATE_FINISHED)
3528 {
3529 *status = ZSTD_STATUS_FINISHED_FRAME;
3530 if (DESCRIPTOR_Is_ContentSize_Defined(p->descriptor)
3531 && p->contentSize != p->contentProcessed)
3532 return SZ_ERROR_DATA;
3533 if (p->hashError) // for debug
3534 return SZ_ERROR_CRC;
3535 return SZ_OK;
3536 // p->frameState = ZSTD2_STATE_SIGNATURE;
3537 // continue;
3538 }
3539
3540 if (p->frameState == ZSTD2_STATE_AFTER_HEADER)
3541 return SZ_OK; // we need memory allocation for that state
3542
3543 if (p->frameState == ZSTD2_STATE_SKIP_DATA)
3544 {
3545 UInt32 blockSize = p->blockSize;
3546 // (blockSize == 0) is possible
3547 if (inCur > blockSize)
3548 inCur = blockSize;
3549 src += inCur;
3550 *srcLen += inCur;
3551 blockSize -= (UInt32)inCur;
3552 p->blockSize = blockSize;
3553 if (blockSize == 0)
3554 {
3555 p->frameState = ZSTD2_STATE_SIGNATURE;
3556 // continue; // for debug: we can continue without return to caller.
3557 // we notify the caller that skip frame was finished:
3558 *status = ZSTD_STATUS_FINISHED_FRAME;
3559 return SZ_OK;
3560 }
3561 // blockSize != 0
3562 // (inCur) was smaller than previous value of p->blockSize.
3563 // (inSize == *srcLen) now
3564 *status = ZSTD_STATUS_NEEDS_MORE_INPUT;
3565 return SZ_OK;
3566 }
3567
3568 if (inCur == 0)
3569 {
3570 *status = ZSTD_STATUS_NEEDS_MORE_INPUT;
3571 return SZ_OK;
3572 }
3573
3574 {
3575 (*srcLen)++;
3576 p->frameState = ZstdDec_UpdateState(p, *src++, info);
3577 }
3578 }
3579
3580 *status = ZSTD_STATUS_NOT_SPECIFIED;
3581 p->isErrorState = True;
3582 // p->frameState = ZSTD2_STATE_ERROR;
3583 // if (p->frameState = ZSTD2_STATE_SIGNATURE) return SZ_ERROR_NO_ARCHIVE
3584 return SZ_ERROR_DATA;
3585}
3586
3587
3588
3589
3590SRes ZstdDec_Decode(CZstdDecHandle dec, CZstdDecState *p)
3591{
3592 p->needWrite_Size = 0;
3593 p->status = ZSTD_STATUS_NOT_SPECIFIED;
3594 dec->disableHash = p->disableHash;
3595
3596 if (p->outBuf_fromCaller)
3597 {
3598 dec->decoder.win = p->outBuf_fromCaller;
3599 dec->decoder.cycSize = p->outBufSize_fromCaller;
3600 }
3601
3602 // p->winPos = dec->decoder.winPos;
3603
3604 for (;;)
3605 {
3606 SizeT winPos, size;
3607 // SizeT outProcessed;
3608 SRes res;
3609
3610 if (p->wrPos > dec->decoder.winPos)
3611 return SZ_ERROR_FAIL;
3612
3613 if (dec->frameState == ZSTD2_STATE_FINISHED)
3614 {
3615 if (!p->outBuf_fromCaller)
3616 {
3617 // we need to set positions to zero for new frame.
3618 if (p->wrPos != dec->decoder.winPos)
3619 {
3620 /* We have already asked the caller to flush all data
3621 with (p->needWrite_Size) and (ZSTD_STATUS_FINISHED_FRAME) status.
3622 So it's unexpected case */
3623 // p->winPos = dec->decoder.winPos;
3624 // p->needWrite_Size = dec->decoder.winPos - p->wrPos; // flush size asking
3625 // return SZ_OK; // ask to flush again
3626 return SZ_ERROR_FAIL;
3627 }
3628 // (p->wrPos == dec->decoder.winPos), and we wrap to zero:
3629 dec->decoder.winPos = 0;
3630 p->winPos = 0;
3631 p->wrPos = 0;
3632 }
3633 ZstdDec_Init_ForNewFrame(dec);
3634 // continue;
3635 }
3636
3637 winPos = dec->decoder.winPos;
3638 {
3639 SizeT next = dec->decoder.cycSize;
3640 /* cycSize == 0, if no buffer was allocated still,
3641 or, if (outBuf_fromCaller) mode and (outBufSize_fromCaller == 0) */
3642 if (!p->outBuf_fromCaller
3643 && next
3644 && next <= winPos
3645 && dec->isCyclicMode)
3646 {
3647 // (0 < decoder.cycSize <= winPos) in isCyclicMode.
3648 // so we need to wrap (winPos) and (wrPos) over (cycSize).
3649 const size_t delta = next;
3650 // (delta) is how many bytes we remove from buffer.
3651 /*
3652 // we don't need data older than last (cycSize) bytes.
3653 size_t delta = winPos - next; // num bytes after (cycSize)
3654 if (delta <= next) // it's expected case
3655 delta = next;
3656 // delta == Max(cycSize, winPos - cycSize)
3657 */
3658 if (p->wrPos < delta)
3659 {
3660 // (wrPos < decoder.cycSize)
3661 // We have asked already the caller to flush required data
3662 // p->status = ZSTD_STATUS_NOT_SPECIFIED;
3663 // p->winPos = winPos;
3664 // p->needWrite_Size = delta - p->wrPos; // flush size asking
3665 // return SZ_OK; // ask to flush again
3666 return SZ_ERROR_FAIL;
3667 }
3668 // p->wrPos >= decoder.cycSize
3669 // we move extra data after (decoder.cycSize) to start of cyclic buffer:
3670 winPos -= delta;
3671 if (winPos)
3672 {
3673 if (winPos >= delta)
3674 return SZ_ERROR_FAIL;
3675 memmove(dec->decoder.win, dec->decoder.win + delta, winPos);
3676 // printf("\nmemmove processed=%8x winPos=%8x\n", (unsigned)p->outProcessed, (unsigned)dec->decoder.winPos);
3677 STAT_INC(g_Num_Wrap_memmove_Num)
3678 STAT_UPDATE(g_Num_Wrap_memmove_Bytes += (unsigned)winPos;)
3679 }
3680 dec->decoder.winPos = winPos;
3681 p->winPos = winPos;
3682 p->wrPos -= delta;
3683 // dec->xxh64_winPos -= delta;
3684
3685 // (winPos < delta)
3686 #ifdef Z7_STD_DEC_USE_AFTER_CYC_BUF
3687 /* we set the data after cycSize, because
3688 we don't want to read non-initialized data or junk in CopyMatch(). */
3689 memset(dec->decoder.win + next, 0, COPY_CHUNK_SIZE);
3690 #endif
3691
3692 /*
3693 if (winPos == next)
3694 {
3695 if (winPos != p->wrPos)
3696 {
3697 // we already requested before to flush full data for that case.
3698 // but we give the caller a second chance to flush data:
3699 p->needWrite_Size = winPos - p->wrPos;
3700 return SZ_OK;
3701 }
3702 // (decoder.cycSize == winPos == p->wrPos)
3703 // so we do second wrapping to zero:
3704 winPos = 0;
3705 dec->decoder.winPos = 0;
3706 p->winPos = 0;
3707 p->wrPos = 0;
3708 }
3709 */
3710 // (winPos < next)
3711 }
3712
3713 if (winPos > next)
3714 return SZ_ERROR_FAIL; // it's unexpected case
3715 /*
3716 if (!outBuf_fromCaller && isCyclicMode && cycSize != 0)
3717 then (winPos < cycSize)
3718 else (winPos <= cycSize)
3719 */
3720 if (!p->outBuf_fromCaller)
3721 {
3722 // that code is optional. We try to optimize write chunk sizes.
3723 /* (next2) is expected next write position in the caller,
3724 if the caller writes by kBlockSizeMax chunks.
3725 */
3726 /*
3727 const size_t next2 = (winPos + kBlockSizeMax) & (kBlockSizeMax - 1);
3728 if (winPos < next2 && next2 < next)
3729 next = next2;
3730 */
3731 }
3732 size = next - winPos;
3733 }
3734
3735 // note: ZstdDec_DecodeBlock() uses (winLimit = winPos + size) only for RLE and RAW blocks
3736 res = ZstdDec_DecodeBlock(dec, p, size);
3737 /*
3738 after one block decoding:
3739 if (!outBuf_fromCaller && isCyclicMode && cycSize != 0)
3740 then (winPos < cycSize + max_block_size)
3741 else (winPos <= cycSize)
3742 */
3743
3744 if (!p->outBuf_fromCaller)
3745 p->win = dec->decoder.win;
3746 p->winPos = dec->decoder.winPos;
3747
3748 // outProcessed = dec->decoder.winPos - winPos;
3749 // p->outProcessed += outProcessed;
3750
3751 if (res != SZ_OK)
3752 return res;
3753
3754 if (dec->frameState != ZSTD2_STATE_AFTER_HEADER)
3755 {
3756 if (p->outBuf_fromCaller)
3757 return SZ_OK;
3758 {
3759 // !p->outBuf_fromCaller
3760 /*
3761 if (ZSTD_STATUS_FINISHED_FRAME), we request full flushing here because
3762 1) it's simpler to work with allocation and extracting of next frame,
3763 2) it's better to start writing to next new frame with aligned memory
3764 for faster xxh 64-bit reads.
3765 */
3766 size_t end = dec->decoder.winPos; // end pos for all data flushing
3767 if (p->status != ZSTD_STATUS_FINISHED_FRAME)
3768 {
3769 // we will request flush here only for cases when wrap in cyclic buffer can be required in next call.
3770 if (!dec->isCyclicMode)
3771 return SZ_OK;
3772 // isCyclicMode
3773 {
3774 const size_t delta = dec->decoder.cycSize;
3775 if (end < delta)
3776 return SZ_OK; // (winPos < cycSize). no need for flush
3777 // cycSize <= winPos
3778 // So we ask the caller to flush of (cycSize - wrPos) bytes,
3779 // and then we will wrap cylicBuffer in next call
3780 end = delta;
3781 }
3782 }
3783 p->needWrite_Size = end - p->wrPos;
3784 }
3785 return SZ_OK;
3786 }
3787
3788 // ZSTD2_STATE_AFTER_HEADER
3789 {
3790 BoolInt useCyclic = False;
3791 size_t cycSize;
3792
3793 // p->status = ZSTD_STATUS_NOT_FINISHED;
3794 if (dec->dictionaryId != 0)
3795 {
3796 /* actually we can try to decode some data,
3797 because it's possible that some data doesn't use dictionary */
3798 // p->status = ZSTD_STATUS_NOT_SPECIFIED;
3799 return SZ_ERROR_UNSUPPORTED;
3800 }
3801
3802 {
3803 UInt64 winSize = dec->contentSize;
3804 UInt64 winSize_Allocate = winSize;
3805 const unsigned descriptor = dec->descriptor;
3806
3807 if ((descriptor & DESCRIPTOR_FLAG_SINGLE) == 0)
3808 {
3809 const Byte wd = dec->windowDescriptor;
3810 winSize = (UInt64)(8 + (wd & 7)) << ((wd >> 3) + 10 - 3);
3811 if (!DESCRIPTOR_Is_ContentSize_Defined(descriptor)
3812 || winSize_Allocate > winSize)
3813 {
3814 winSize_Allocate = winSize;
3815 useCyclic = True;
3816 }
3817 }
3818 /*
3819 else
3820 {
3821 if (p->info.singleSegment_ContentSize_MAX < winSize)
3822 p->info.singleSegment_ContentSize_MAX = winSize;
3823 // p->info.num_SingleSegments++;
3824 }
3825 */
3826 if (p->info.windowSize_MAX < winSize)
3827 p->info.windowSize_MAX = winSize;
3828 if (p->info.windowSize_Allocate_MAX < winSize_Allocate)
3829 p->info.windowSize_Allocate_MAX = winSize_Allocate;
3830 /*
3831 winSize_Allocate is MIN(content_size, window_size_from_descriptor).
3832 Wven if (content_size < (window_size_from_descriptor))
3833 original-zstd still uses (window_size_from_descriptor) to check that decoding is allowed.
3834 We try to follow original-zstd, and here we check (winSize) instead of (winSize_Allocate))
3835 */
3836 if (
3837 // winSize_Allocate // it's relaxed check
3838 winSize // it's more strict check to be compatible with original-zstd
3839 > ((UInt64)1 << MAX_WINDOW_SIZE_LOG))
3840 return SZ_ERROR_UNSUPPORTED; // SZ_ERROR_MEM
3841 cycSize = (size_t)winSize_Allocate;
3842 if (cycSize != winSize_Allocate)
3843 return SZ_ERROR_MEM;
3844 // cycSize <= winSize
3845 /* later we will use (CZstdDec1::winSize) to check match offsets and check block sizes.
3846 if (there is window descriptor)
3847 {
3848 We will check block size with (window_size_from_descriptor) instead of (winSize_Allocate).
3849 Does original-zstd do it that way also?
3850 }
3851 Here we must reduce full real 64-bit (winSize) to size_t for (CZstdDec1::winSize).
3852 Also we don't want too big values for (CZstdDec1::winSize).
3853 our (CZstdDec1::winSize) will meet the condition:
3854 (CZstdDec1::winSize < kBlockSizeMax || CZstdDec1::winSize <= cycSize).
3855 */
3856 dec->decoder.winSize = (winSize < kBlockSizeMax) ? (size_t)winSize: cycSize;
3857 // note: (CZstdDec1::winSize > cycSize) is possible, if (!useCyclic)
3858 }
3859
3860 RINOK(ZstdDec_AllocateMisc(dec))
3861
3862 if (p->outBuf_fromCaller)
3863 dec->isCyclicMode = False;
3864 else
3865 {
3866 size_t d = cycSize;
3867
3868 if (dec->decoder.winPos != p->wrPos)
3869 return SZ_ERROR_FAIL;
3870
3871 dec->decoder.winPos = 0;
3872 p->wrPos = 0;
3873 p->winPos = dec->decoder.winPos;
3874
3875 /*
3876 const size_t needWrite = dec->decoder.winPos - p->wrPos;
3877 if (!needWrite)
3878 {
3879 dec->decoder.winPos = 0;
3880 p->wrPos = 0;
3881 p->winPos = dec->decoder.winPos;
3882 }
3883 */
3884 /* if (!useCyclic) we allocate only cycSize = ContentSize.
3885 But if we want to support the case where new frame starts with winPos != 0,
3886 then we will wrap over zero, and we still need
3887 to set (useCyclic) and allocate additional buffer spaces.
3888 Now we don't allow new frame starting with (winPos != 0).
3889 so (dec->decoder->winPos == 0)
3890 can use (!useCyclic) with reduced buffer sizes.
3891 */
3892 /*
3893 if (dec->decoder->winPos != 0)
3894 useCyclic = True;
3895 */
3896
3897 if (useCyclic)
3898 {
3899 /* cyclyc buffer size must be at least (COPY_CHUNK_SIZE - 1) bytes
3900 larger than window size, because CopyMatch() can write additional
3901 (COPY_CHUNK_SIZE - 1) bytes and overwrite oldests data in cyclyc buffer.
3902 But for performance reasons we align (cycSize) for (kBlockSizeMax).
3903 also we must provide (cycSize >= max_decoded_data_after_cycSize),
3904 because after data move wrapping over zero we must provide (winPos < cycSize).
3905 */
3906 const size_t alignSize = kBlockSizeMax;
3907 /* here we add (1 << 7) instead of (COPY_CHUNK_SIZE - 1), because
3908 we want to get same (cycSize) for different COPY_CHUNK_SIZE values. */
3909 // cycSize += (COPY_CHUNK_SIZE - 1) + (alignSize - 1); // for debug : we can get smallest (cycSize)
3910 cycSize += (1 << 7) + alignSize;
3911 cycSize &= ~(size_t)(alignSize - 1);
3912 // cycSize must be aligned for 32, because xxh requires 32-bytes blocks.
3913 // cycSize += 12345; // for debug
3914 // cycSize += 1 << 10; // for debug
3915 // cycSize += 32; // for debug
3916 // cycSize += kBlockSizeMax; // for debug
3917 if (cycSize < d)
3918 return SZ_ERROR_MEM;
3919 /*
3920 in cyclic buffer mode we allow to decode one additional block
3921 that exceeds (cycSize).
3922 So we must allocate additional (kBlockSizeMax) bytes after (cycSize).
3923 if defined(Z7_STD_DEC_USE_AFTER_CYC_BUF)
3924 {
3925 we can read (COPY_CHUNK_SIZE - 1) bytes after (cycSize)
3926 but we aready allocate additional kBlockSizeMax that
3927 is larger than COPY_CHUNK_SIZE.
3928 So we don't need additional space of COPY_CHUNK_SIZE after (cycSize).
3929 }
3930 */
3931 /*
3932 #ifdef Z7_STD_DEC_USE_AFTER_CYC_BUF
3933 d = cycSize + (1 << 7); // we must add at least (COPY_CHUNK_SIZE - 1)
3934 #endif
3935 */
3936 d = cycSize + kBlockSizeMax;
3937 if (d < cycSize)
3938 return SZ_ERROR_MEM;
3939 }
3940
3941 {
3942 const size_t kMinWinAllocSize = 1 << 12;
3943 if (d < kMinWinAllocSize)
3944 d = kMinWinAllocSize;
3945 }
3946
3947 if (d > dec->winBufSize_Allocated)
3948 {
3949 /*
3950 if (needWrite)
3951 {
3952 p->needWrite_Size = needWrite;
3953 return SZ_OK;
3954 // return SZ_ERROR_FAIL;
3955 }
3956 */
3957
3958 if (dec->winBufSize_Allocated != 0)
3959 {
3960 const size_t k_extra = (useCyclic || d >= (1u << 20)) ?
3961 2 * kBlockSizeMax : 0;
3962 unsigned i = useCyclic ? 17 : 12;
3963 for (; i < sizeof(size_t) * 8; i++)
3964 {
3965 const size_t d2 = ((size_t)1 << i) + k_extra;
3966 if (d2 >= d)
3967 {
3968 d = d2;
3969 break;
3970 }
3971 }
3972 }
3973 // RINOK(ZstdDec_AllocateWindow(dec, d))
3974 ZstdDec_FreeWindow(dec);
3975 dec->win_Base = (Byte *)ISzAlloc_Alloc(dec->alloc_Big, d);
3976 if (!dec->win_Base)
3977 return SZ_ERROR_MEM;
3978 dec->decoder.win = dec->win_Base;
3979 dec->winBufSize_Allocated = d;
3980 }
3981 /*
3982 else
3983 {
3984 // for non-cyclycMode we want flush data, and set winPos = 0
3985 if (needWrite)
3986 {
3987 if (!useCyclic || dec->decoder.winPos >= cycSize)
3988 {
3989 p->needWrite_Size = needWrite;
3990 return SZ_OK;
3991 // return SZ_ERROR_FAIL;
3992 }
3993 }
3994 }
3995 */
3996
3997 dec->decoder.cycSize = cycSize;
3998 p->win = dec->decoder.win;
3999 // p->cycSize = dec->decoder.cycSize;
4000 dec->isCyclicMode = (Byte)useCyclic;
4001 } // (!p->outBuf_fromCaller) end
4002
4003 // p->winPos = dec->decoder.winPos;
4004 dec->frameState = ZSTD2_STATE_BLOCK;
4005 // continue;
4006 } // ZSTD2_STATE_AFTER_HEADER end
4007 }
4008}
4009
4010
4011void ZstdDec_GetResInfo(const CZstdDec *dec,
4012 const CZstdDecState *p,
4013 SRes res,
4014 CZstdDecResInfo *stat)
4015{
4016 // ZstdDecInfo_CLEAR(stat);
4017 stat->extraSize = 0;
4018 stat->is_NonFinishedFrame = False;
4019 if (dec->frameState != ZSTD2_STATE_FINISHED)
4020 {
4021 if (dec->frameState == ZSTD2_STATE_SIGNATURE)
4022 {
4023 stat->extraSize = (Byte)dec->tempSize;
4024 if (ZstdDecInfo_GET_NUM_FRAMES(&p->info) == 0)
4025 res = SZ_ERROR_NO_ARCHIVE;
4026 }
4027 else
4028 {
4029 stat->is_NonFinishedFrame = True;
4030 if (res == SZ_OK && p->status == ZSTD_STATUS_NEEDS_MORE_INPUT)
4031 res = SZ_ERROR_INPUT_EOF;
4032 }
4033 }
4034 stat->decode_SRes = res;
4035}
4036
4037
4038size_t ZstdDec_ReadUnusedFromInBuf(
4039 CZstdDecHandle dec,
4040 size_t afterDecoding_tempPos,
4041 void *data, size_t size)
4042{
4043 size_t processed = 0;
4044 if (dec->frameState == ZSTD2_STATE_SIGNATURE)
4045 {
4046 Byte *dest = (Byte *)data;
4047 const size_t tempSize = dec->tempSize;
4048 while (afterDecoding_tempPos < tempSize)
4049 {
4050 if (size == 0)
4051 break;
4052 size--;
4053 *dest++ = dec->temp[afterDecoding_tempPos++];
4054 processed++;
4055 }
4056 }
4057 return processed;
4058}
4059
4060
4061void ZstdDecState_Clear(CZstdDecState *p)
4062{
4063 memset(p, 0 , sizeof(*p));
4064}
diff --git a/C/ZstdDec.h b/C/ZstdDec.h
new file mode 100644
index 0000000..cd26131
--- /dev/null
+++ b/C/ZstdDec.h
@@ -0,0 +1,173 @@
1/* ZstdDec.h -- Zstd Decoder interfaces
22024-01-21 : Igor Pavlov : Public domain */
3
4#ifndef ZIP7_INC_ZSTD_DEC_H
5#define ZIP7_INC_ZSTD_DEC_H
6
7EXTERN_C_BEGIN
8
9typedef struct CZstdDec CZstdDec;
10typedef CZstdDec * CZstdDecHandle;
11
12CZstdDecHandle ZstdDec_Create(ISzAllocPtr alloc_Small, ISzAllocPtr alloc_Big);
13void ZstdDec_Destroy(CZstdDecHandle p);
14
15typedef enum
16{
17 ZSTD_STATUS_NOT_SPECIFIED, /* use main error code instead */
18 ZSTD_STATUS_FINISHED_FRAME, /* data frame or skip frame was finished */
19 ZSTD_STATUS_NOT_FINISHED, /* just finished non-empty block or unfinished RAW/RLE block */
20 ZSTD_STATUS_NEEDS_MORE_INPUT, /* the callee needs more input bytes. It has more priority over ZSTD_STATUS_NOT_FINISHED */
21 ZSTD_STATUS_OUT_REACHED /* is not finihed frame and ((outProcessed > outSize) || (outProcessed == outSize && unfinished RAW/RLE block) */
22} enum_ZstdStatus_Dummy;
23
24#define ZstdDecState_DOES_NEED_MORE_INPUT_OR_FINISHED_FRAME(p) \
25 ((p)->status & ZSTD_STATUS_FINISHED_FRAME)
26/*
27 ((p)->status == ZSTD_STATUS_NEEDS_MORE_INPUT || \
28 (p)->status == ZSTD_STATUS_FINISHED_FRAME)
29*/
30
31typedef Byte enum_ZstdStatus;
32
33
34void ZstdDec_Init(CZstdDecHandle p);
35
36typedef struct
37{
38 UInt64 num_Blocks;
39 Byte descriptor_OR;
40 Byte descriptor_NOT_OR;
41 Byte are_ContentSize_Unknown;
42 Byte windowDescriptor_MAX;
43
44 // Byte are_ContentSize_Known;
45 // Byte are_SingleSegments;
46 // Byte are_WindowDescriptors;
47 Byte checksum_Defined;
48 // Byte are_Checksums;
49 // Byte are_Non_Checksums;
50
51 // Byte are_DictionaryId;
52 Byte are_DictionaryId_Different;
53
54 // Byte reserved[3];
55
56 UInt32 checksum; // checksum of last data frame
57 /// UInt32 dictionaryId_Cur;
58 UInt32 dictionaryId; // if there are non-zero dictionary IDs, then it's first dictionaryId
59
60 UInt64 num_DataFrames;
61 UInt64 num_SkipFrames;
62 UInt64 skipFrames_Size;
63 UInt64 contentSize_Total;
64 UInt64 contentSize_MAX;
65 // UInt64 num_Checksums;
66 // UInt64 num_Non_Checksums; // frames without checksum
67 // UInt64 num_WindowDescriptors;
68 // UInt64 num_SingleSegments;
69 // UInt64 num_Frames_with_ContentSize;
70 // UInt64 num_Frames_without_ContentSize;
71 UInt64 windowSize_MAX;
72 UInt64 windowSize_Allocate_MAX;
73 // UInt64 num_DictionaryIds;
74 // UInt64 num_Blocks_forType[4];
75 // UInt64 num_BlockBytes_forType[4];
76 // UInt64 num_SingleSegments;
77 // UInt64 singleSegment_ContentSize_MAX;
78} CZstdDecInfo;
79
80#define ZstdDecInfo_CLEAR(p) { memset(p, 0, sizeof(*(p))); }
81
82#define ZstdDecInfo_GET_NUM_FRAMES(p) ((p)->num_DataFrames + (p)->num_SkipFrames)
83
84
85typedef struct CZstdDecState
86{
87 enum_ZstdStatus status; // out
88 Byte disableHash;
89 // Byte mustBeFinished;
90 Byte outSize_Defined;
91 // Byte isAfterSizeMode;
92 // UInt64 inProcessed;
93 // SRes codeRes;
94 // Byte needWrite_IsStrong;
95
96 const Byte *inBuf;
97 size_t inPos; // in/out
98 size_t inLim;
99
100 const Byte *win; // out
101 size_t winPos; // out
102 size_t wrPos; // in/out
103 // size_t cycSize; // out : if (!outBuf_fromCaller)
104 size_t needWrite_Size; // out
105
106 Byte *outBuf_fromCaller;
107 size_t outBufSize_fromCaller;
108 /* (outBufSize_fromCaller >= full_uncompressed_size_of_all_frames) is required
109 for success decoding.
110 If outBufSize_fromCaller < full_uncompressed_size_of_all_frames),
111 decoding can give error message, because we decode per block basis.
112 */
113
114 // size_t outStep;
115 UInt64 outSize; // total in all frames
116 UInt64 outProcessed; // out decoded in all frames (it can be >= outSize)
117
118 CZstdDecInfo info;
119} CZstdDecState;
120
121void ZstdDecState_Clear(CZstdDecState *p);
122
123/*
124ZstdDec_Decode()
125return:
126 SZ_OK - no error
127 SZ_ERROR_DATA - Data Error
128 SZ_ERROR_MEM - Memory allocation error
129 SZ_ERROR_UNSUPPORTED - Unsupported method or method properties
130 SZ_ERROR_CRC - XXH hash Error
131 // SZ_ERROR_ARCHIVE - Headers error (not used now)
132*/
133SRes ZstdDec_Decode(CZstdDecHandle dec, CZstdDecState *p);
134
135/*
136ZstdDec_ReadUnusedFromInBuf():
137returns: the number of bytes that were read from InBuf
138(*afterDecoding_tempPos) must be set to zero before first call of ZstdDec_ReadUnusedFromInBuf()
139*/
140size_t ZstdDec_ReadUnusedFromInBuf(
141 CZstdDecHandle dec,
142 size_t afterDecoding_tempPos, // in/out
143 void *data, size_t size);
144
145typedef struct
146{
147 SRes decode_SRes; // error code of data decoding
148 Byte is_NonFinishedFrame; // there is unfinished decoding for data frame or skip frame
149 Byte extraSize;
150} CZstdDecResInfo;
151
152/*
153#define ZstdDecResInfo_CLEAR(p) \
154{ (p)->decode_SRes = 0; \
155 (p)->is_NonFinishedFrame; \
156 (p)->extraSize = 0; \
157}
158// memset(p, 0, sizeof(*p));
159*/
160
161/*
162additional error codes for CZstdDecResInfo::decode_SRes:
163 SZ_ERROR_NO_ARCHIVE - is not zstd stream (no frames)
164 SZ_ERROR_INPUT_EOF - need more data in input stream
165*/
166void ZstdDec_GetResInfo(const CZstdDec *dec,
167 const CZstdDecState *p,
168 SRes res, // it's result from ZstdDec_Decode()
169 CZstdDecResInfo *info);
170
171EXTERN_C_END
172
173#endif
diff --git a/C/var_clang_arm64.mak b/C/var_clang_arm64.mak
index 4b35409..971101a 100644
--- a/C/var_clang_arm64.mak
+++ b/C/var_clang_arm64.mak
@@ -6,6 +6,7 @@ IS_ARM64=1
6CROSS_COMPILE= 6CROSS_COMPILE=
7MY_ARCH= 7MY_ARCH=
8USE_ASM=1 8USE_ASM=1
9ASM_FLAGS=-Wno-unused-macros
9CC=$(CROSS_COMPILE)clang 10CC=$(CROSS_COMPILE)clang
10CXX=$(CROSS_COMPILE)clang++ 11CXX=$(CROSS_COMPILE)clang++
11USE_CLANG=1 12USE_CLANG=1
diff --git a/CPP/7zip/7zip.mak b/CPP/7zip/7zip.mak
index 6f4a0a1..8bf7e73 100644
--- a/CPP/7zip/7zip.mak
+++ b/CPP/7zip/7zip.mak
@@ -124,7 +124,7 @@ $(WIM_OBJS): ../../Archive/Wim/$(*B).cpp
124 124
125!IFDEF ZIP_OBJS 125!IFDEF ZIP_OBJS
126$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp 126$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp
127 $(COMPL) 127 $(COMPL) $(ZIP_FLAGS)
128!ENDIF 128!ENDIF
129 129
130!IFDEF COMPRESS_OBJS 130!IFDEF COMPRESS_OBJS
@@ -149,7 +149,7 @@ $(AGENT_OBJS): ../../UI/Agent/$(*B).cpp
149 149
150!IFDEF CONSOLE_OBJS 150!IFDEF CONSOLE_OBJS
151$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp 151$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp
152 $(COMPL) 152 $(COMPL) $(CONSOLE_VARIANT_FLAGS)
153!ENDIF 153!ENDIF
154 154
155!IFDEF EXPLORER_OBJS 155!IFDEF EXPLORER_OBJS
@@ -191,7 +191,7 @@ $(C_OBJS): ../../../../C/$(*B).c
191{../../UI/Agent}.cpp{$O}.obj:: 191{../../UI/Agent}.cpp{$O}.obj::
192 $(COMPLB) 192 $(COMPLB)
193{../../UI/Console}.cpp{$O}.obj:: 193{../../UI/Console}.cpp{$O}.obj::
194 $(COMPLB) 194 $(COMPLB) $(CONSOLE_VARIANT_FLAGS)
195{../../UI/Explorer}.cpp{$O}.obj:: 195{../../UI/Explorer}.cpp{$O}.obj::
196 $(COMPLB) 196 $(COMPLB)
197{../../UI/FileManager}.cpp{$O}.obj:: 197{../../UI/FileManager}.cpp{$O}.obj::
@@ -226,7 +226,7 @@ $(C_OBJS): ../../../../C/$(*B).c
226{../../Archive/Wim}.cpp{$O}.obj:: 226{../../Archive/Wim}.cpp{$O}.obj::
227 $(COMPLB) 227 $(COMPLB)
228{../../Archive/Zip}.cpp{$O}.obj:: 228{../../Archive/Zip}.cpp{$O}.obj::
229 $(COMPLB) 229 $(COMPLB) $(ZIP_FLAGS)
230 230
231{../../Compress}.cpp{$O}.obj:: 231{../../Compress}.cpp{$O}.obj::
232 $(COMPLB_O2) 232 $(COMPLB_O2)
diff --git a/CPP/7zip/7zip_gcc.mak b/CPP/7zip/7zip_gcc.mak
index 8bf0594..f6a044f 100644
--- a/CPP/7zip/7zip_gcc.mak
+++ b/CPP/7zip/7zip_gcc.mak
@@ -30,16 +30,33 @@ endif
30# for object file 30# for object file
31# -Wa,-aln=test.s 31# -Wa,-aln=test.s
32# -save-temps 32# -save-temps
33FLAGS_BASE = -mbranch-protection=standard -march=armv8.5-a
34FLAGS_BASE = -mbranch-protection=standard
35FLAGS_BASE =
36# FLAGS_BASE = -DZ7_NO_UNICODE
37
33CFLAGS_BASE_LIST = -c 38CFLAGS_BASE_LIST = -c
39
40
41#DEBUG_BUILD=1
42
43ifdef DEBUG_BUILD
44CFLAGS_DEBUG = -g
45else
46CFLAGS_DEBUG = -DNDEBUG
47ifneq ($(CC), $(CROSS_COMPILE)clang)
48LFLAGS_STRIP = -s
49endif
50endif
51
34# CFLAGS_BASE_LIST = -S 52# CFLAGS_BASE_LIST = -S
35CFLAGS_BASE = -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \ 53CFLAGS_BASE = -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \
36 -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ 54 $(CFLAGS_DEBUG) -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
37 -fPIC 55 -fPIC
38 56
39FLAGS_FLTO = -ffunction-sections 57FLAGS_FLTO = -ffunction-sections
40FLAGS_FLTO = -flto 58FLAGS_FLTO = -flto
41FLAGS_FLTO = 59FLAGS_FLTO = $(FLAGS_BASE)
42#
43# -DZ7_AFFINITY_DISABLE 60# -DZ7_AFFINITY_DISABLE
44 61
45 62
@@ -68,7 +85,7 @@ endif
68endif 85endif
69endif 86endif
70 87
71LDFLAGS_STATIC = -DNDEBUG $(LDFLAGS_STATIC_2) 88LDFLAGS_STATIC = $(CFLAGS_DEBUG) $(LDFLAGS_STATIC_2) $(LDFLAGS_STATIC_3)
72 89
73ifndef O 90ifndef O
74 ifdef IS_MINGW 91 ifdef IS_MINGW
@@ -95,6 +112,7 @@ endif
95else 112else
96 113
97LDFLAGS = $(LDFLAGS_STATIC) 114LDFLAGS = $(LDFLAGS_STATIC)
115# -z force-bti
98# -s is not required for clang, do we need it for GCC ??? 116# -s is not required for clang, do we need it for GCC ???
99 117
100#-static -static-libgcc -static-libstdc++ 118#-static -static-libgcc -static-libstdc++
@@ -127,7 +145,8 @@ endif
127LIB2_GUI = -lOle32 -lGdi32 -lComctl32 -lComdlg32 -lShell32 $(LIB_HTMLHELP) 145LIB2_GUI = -lOle32 -lGdi32 -lComctl32 -lComdlg32 -lShell32 $(LIB_HTMLHELP)
128LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 $(LIB2_GUI) 146LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 $(LIB2_GUI)
129 147
130CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE 148# v24.00: -DUNICODE and -D_UNICODE are defined in precompilation header files
149# CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE
131# -Wno-delete-non-virtual-dtor 150# -Wno-delete-non-virtual-dtor
132 151
133 152
@@ -142,6 +161,7 @@ DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS)
142 161
143# LOCAL_LIBS=-lpthread 162# LOCAL_LIBS=-lpthread
144# LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl 163# LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl
164LIB2 = -lpthread
145LIB2 = -lpthread -ldl 165LIB2 = -lpthread -ldl
146 166
147 167
@@ -190,7 +210,7 @@ CXX_WARN_FLAGS =
190#-Wno-invalid-offsetof 210#-Wno-invalid-offsetof
191#-Wno-reorder 211#-Wno-reorder
192 212
193CXXFLAGS = $(MY_ARCH_2) $(LOCAL_FLAGS) $(CXXFLAGS_BASE2) $(CFLAGS_BASE) $(FLAGS_FLTO) $(CXXFLAGS_EXTRA) $(CC_SHARED) $(CXX_WARN_FLAGS) $(CXX_STD_FLAGS) -o $@ 213CXXFLAGS = $(MY_ARCH_2) $(LOCAL_FLAGS) $(CXXFLAGS_BASE2) $(CFLAGS_BASE) $(FLAGS_FLTO) $(CXXFLAGS_EXTRA) $(CC_SHARED) $(CXX_WARN_FLAGS) $(CXX_STD_FLAGS) $(CXX_INCLUDE_FLAGS) -o $@
194 214
195STATIC_TARGET= 215STATIC_TARGET=
196ifdef COMPL_STATIC 216ifdef COMPL_STATIC
@@ -207,11 +227,28 @@ $(O):
207# LDFLAGS3= -Wl,--gc-sections 227# LDFLAGS3= -Wl,--gc-sections
208# -Wl,--print-gc-sections 228# -Wl,--print-gc-sections
209 229
210ifneq ($(CC), $(CROSS_COMPILE)clang) 230ifndef IS_MINGW
211LFLAGS_STRIP = -s 231
232# LFLAGS_NOEXECSTACK=
233
234ifdef Z7_USE_OS_UNAME_FOR_NOEXECSTACK
235Z7_OS := $(shell uname)
236show_os:
237 echo $(Z7_OS)
238
239# ifeq ($(CXX), $(CROSS_COMPILE)g++)
240ifeq ($(Z7_OS), Linux)
241LFLAGS_NOEXECSTACK ?= -z noexecstack
242endif
243
244else
245LFLAGS_NOEXECSTACK ?= $(shell echo 'int main(){return 0;}' | $(CC) $(MY_ARCH_2) -z noexecstack -o /dev/null -x c - 2>/dev/null && echo -z noexecstack || echo)
246endif
247
212endif 248endif
213 249
214LFLAGS_ALL = $(LFLAGS_STRIP) $(MY_ARCH_2) $(LDFLAGS) $(FLAGS_FLTO) $(LD_arch) $(OBJS) $(MY_LIBS) $(LIB2) 250
251LFLAGS_ALL = $(LFLAGS_STRIP) $(MY_ARCH_2) $(LDFLAGS) $(FLAGS_FLTO) $(LD_arch) $(LFLAGS_NOEXECSTACK) $(OBJS) $(MY_LIBS) $(LIB2)
215 252
216# -s : GCC : Remove all symbol table and relocation information from the executable. 253# -s : GCC : Remove all symbol table and relocation information from the executable.
217# -s : CLANG : unsupported 254# -s : CLANG : unsupported
@@ -304,6 +341,8 @@ $O/XzCrc64Init.o: ../../../Common/XzCrc64Init.cpp
304 $(CXX) $(CXXFLAGS) $< 341 $(CXX) $(CXXFLAGS) $<
305$O/XzCrc64Reg.o: ../../../Common/XzCrc64Reg.cpp 342$O/XzCrc64Reg.o: ../../../Common/XzCrc64Reg.cpp
306 $(CXX) $(CXXFLAGS) $< 343 $(CXX) $(CXXFLAGS) $<
344$O/Xxh64Reg.o: ../../../Common/Xxh64Reg.cpp
345 $(CXX) $(CXXFLAGS) $<
307 346
308 347
309 348
@@ -490,6 +529,8 @@ $O/IhexHandler.o: ../../Archive/IhexHandler.cpp
490 $(CXX) $(CXXFLAGS) $< 529 $(CXX) $(CXXFLAGS) $<
491$O/LpHandler.o: ../../Archive/LpHandler.cpp 530$O/LpHandler.o: ../../Archive/LpHandler.cpp
492 $(CXX) $(CXXFLAGS) $< 531 $(CXX) $(CXXFLAGS) $<
532$O/LvmHandler.o: ../../Archive/LvmHandler.cpp
533 $(CXX) $(CXXFLAGS) $<
493$O/LzhHandler.o: ../../Archive/LzhHandler.cpp 534$O/LzhHandler.o: ../../Archive/LzhHandler.cpp
494 $(CXX) $(CXXFLAGS) $< 535 $(CXX) $(CXXFLAGS) $<
495$O/LzmaHandler.o: ../../Archive/LzmaHandler.cpp 536$O/LzmaHandler.o: ../../Archive/LzmaHandler.cpp
@@ -536,6 +577,8 @@ $O/XzHandler.o: ../../Archive/XzHandler.cpp
536 $(CXX) $(CXXFLAGS) $< 577 $(CXX) $(CXXFLAGS) $<
537$O/ZHandler.o: ../../Archive/ZHandler.cpp 578$O/ZHandler.o: ../../Archive/ZHandler.cpp
538 $(CXX) $(CXXFLAGS) $< 579 $(CXX) $(CXXFLAGS) $<
580$O/ZstdHandler.o: ../../Archive/ZstdHandler.cpp
581 $(CXX) $(CXXFLAGS) $<
539 582
540 583
541$O/7zCompressionMode.o: ../../Archive/7z/7zCompressionMode.cpp 584$O/7zCompressionMode.o: ../../Archive/7z/7zCompressionMode.cpp
@@ -642,7 +685,7 @@ $O/WimRegister.o: ../../Archive/Wim/WimRegister.cpp
642$O/ZipAddCommon.o: ../../Archive/Zip/ZipAddCommon.cpp 685$O/ZipAddCommon.o: ../../Archive/Zip/ZipAddCommon.cpp
643 $(CXX) $(CXXFLAGS) $< 686 $(CXX) $(CXXFLAGS) $<
644$O/ZipHandler.o: ../../Archive/Zip/ZipHandler.cpp 687$O/ZipHandler.o: ../../Archive/Zip/ZipHandler.cpp
645 $(CXX) $(CXXFLAGS) $< 688 $(CXX) $(CXXFLAGS) $(ZIP_FLAGS) $<
646$O/ZipHandlerOut.o: ../../Archive/Zip/ZipHandlerOut.cpp 689$O/ZipHandlerOut.o: ../../Archive/Zip/ZipHandlerOut.cpp
647 $(CXX) $(CXXFLAGS) $< 690 $(CXX) $(CXXFLAGS) $<
648$O/ZipIn.o: ../../Archive/Zip/ZipIn.cpp 691$O/ZipIn.o: ../../Archive/Zip/ZipIn.cpp
@@ -763,6 +806,10 @@ $O/ZlibDecoder.o: ../../Compress/ZlibDecoder.cpp
763 $(CXX) $(CXXFLAGS) $< 806 $(CXX) $(CXXFLAGS) $<
764$O/ZlibEncoder.o: ../../Compress/ZlibEncoder.cpp 807$O/ZlibEncoder.o: ../../Compress/ZlibEncoder.cpp
765 $(CXX) $(CXXFLAGS) $< 808 $(CXX) $(CXXFLAGS) $<
809$O/ZstdDecoder.o: ../../Compress/ZstdDecoder.cpp
810 $(CXX) $(CXXFLAGS) $<
811$O/ZstdRegister.o: ../../Compress/ZstdRegister.cpp
812 $(CXX) $(CXXFLAGS) $<
766 813
767 814
768$O/7zAes.o: ../../Crypto/7zAes.cpp 815$O/7zAes.o: ../../Crypto/7zAes.cpp
@@ -953,6 +1000,8 @@ $O/App.o: ../../UI/FileManager/App.cpp
953 $(CXX) $(CXXFLAGS) $< 1000 $(CXX) $(CXXFLAGS) $<
954$O/BrowseDialog.o: ../../UI/FileManager/BrowseDialog.cpp 1001$O/BrowseDialog.o: ../../UI/FileManager/BrowseDialog.cpp
955 $(CXX) $(CXXFLAGS) $< 1002 $(CXX) $(CXXFLAGS) $<
1003$O/BrowseDialog2.o: ../../UI/FileManager/BrowseDialog2.cpp
1004 $(CXX) $(CXXFLAGS) $<
956$O/ClassDefs.o: ../../UI/FileManager/ClassDefs.cpp 1005$O/ClassDefs.o: ../../UI/FileManager/ClassDefs.cpp
957 $(CXX) $(CXXFLAGS) $< 1006 $(CXX) $(CXXFLAGS) $<
958$O/ComboDialog.o: ../../UI/FileManager/ComboDialog.cpp 1007$O/ComboDialog.o: ../../UI/FileManager/ComboDialog.cpp
@@ -993,6 +1042,8 @@ $O/LinkDialog.o: ../../UI/FileManager/LinkDialog.cpp
993 $(CXX) $(CXXFLAGS) $< 1042 $(CXX) $(CXXFLAGS) $<
994$O/ListViewDialog.o: ../../UI/FileManager/ListViewDialog.cpp 1043$O/ListViewDialog.o: ../../UI/FileManager/ListViewDialog.cpp
995 $(CXX) $(CXXFLAGS) $< 1044 $(CXX) $(CXXFLAGS) $<
1045$O/MemDialog.o: ../../UI/FileManager/MemDialog.cpp
1046 $(CXX) $(CXXFLAGS) $<
996$O/MenuPage.o: ../../UI/FileManager/MenuPage.cpp 1047$O/MenuPage.o: ../../UI/FileManager/MenuPage.cpp
997 $(CXX) $(CXXFLAGS) $< 1048 $(CXX) $(CXXFLAGS) $<
998$O/MessagesDialog.o: ../../UI/FileManager/MessagesDialog.cpp 1049$O/MessagesDialog.o: ../../UI/FileManager/MessagesDialog.cpp
@@ -1179,6 +1230,8 @@ $O/Sort.o: ../../../../C/Sort.c
1179 $(CC) $(CFLAGS) $< 1230 $(CC) $(CFLAGS) $<
1180$O/SwapBytes.o: ../../../../C/SwapBytes.c 1231$O/SwapBytes.o: ../../../../C/SwapBytes.c
1181 $(CC) $(CFLAGS) $< 1232 $(CC) $(CFLAGS) $<
1233$O/Xxh64.o: ../../../../C/Xxh64.c
1234 $(CC) $(CFLAGS) $<
1182$O/Xz.o: ../../../../C/Xz.c 1235$O/Xz.o: ../../../../C/Xz.c
1183 $(CC) $(CFLAGS) $< 1236 $(CC) $(CFLAGS) $<
1184$O/XzCrc64.o: ../../../../C/XzCrc64.c 1237$O/XzCrc64.o: ../../../../C/XzCrc64.c
@@ -1189,6 +1242,8 @@ $O/XzEnc.o: ../../../../C/XzEnc.c
1189 $(CC) $(CFLAGS) $< 1242 $(CC) $(CFLAGS) $<
1190$O/XzIn.o: ../../../../C/XzIn.c 1243$O/XzIn.o: ../../../../C/XzIn.c
1191 $(CC) $(CFLAGS) $< 1244 $(CC) $(CFLAGS) $<
1245$O/ZstdDec.o: ../../../../C/ZstdDec.c
1246 $(CC) $(CFLAGS) $<
1192 1247
1193 1248
1194ifdef USE_ASM 1249ifdef USE_ASM
@@ -1254,7 +1309,7 @@ endif
1254 1309
1255ifdef IS_ARM64 1310ifdef IS_ARM64
1256$O/LzmaDecOpt.o: ../../../../Asm/arm64/LzmaDecOpt.S ../../../../Asm/arm64/7zAsm.S 1311$O/LzmaDecOpt.o: ../../../../Asm/arm64/LzmaDecOpt.S ../../../../Asm/arm64/7zAsm.S
1257 $(CC) $(CFLAGS) $< 1312 $(CC) $(CFLAGS) $(ASM_FLAGS) $<
1258endif 1313endif
1259 1314
1260$O/LzmaDec.o: ../../../../C/LzmaDec.c 1315$O/LzmaDec.o: ../../../../C/LzmaDec.c
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
index ac1f6ad..737722d 100644
--- a/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -52,31 +52,30 @@ struct CCompressionMethodMode
52 52
53 bool DefaultMethod_was_Inserted; 53 bool DefaultMethod_was_Inserted;
54 bool Filter_was_Inserted; 54 bool Filter_was_Inserted;
55 bool PasswordIsDefined;
56 bool MemoryUsageLimit_WasSet;
55 57
56 #ifndef Z7_ST 58 #ifndef Z7_ST
57 UInt32 NumThreads;
58 bool NumThreads_WasForced; 59 bool NumThreads_WasForced;
59 bool MultiThreadMixer; 60 bool MultiThreadMixer;
61 UInt32 NumThreads;
60 #endif 62 #endif
61 63
62 UInt64 MemoryUsageLimit;
63 bool MemoryUsageLimit_WasSet;
64
65 bool PasswordIsDefined;
66 UString Password; // _Wipe 64 UString Password; // _Wipe
67 65 UInt64 MemoryUsageLimit;
66
68 bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } 67 bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
69 CCompressionMethodMode(): 68 CCompressionMethodMode():
70 DefaultMethod_was_Inserted(false) 69 DefaultMethod_was_Inserted(false)
71 , Filter_was_Inserted(false) 70 , Filter_was_Inserted(false)
71 , PasswordIsDefined(false)
72 , MemoryUsageLimit_WasSet(false)
72 #ifndef Z7_ST 73 #ifndef Z7_ST
73 , NumThreads(1)
74 , NumThreads_WasForced(false) 74 , NumThreads_WasForced(false)
75 , MultiThreadMixer(true) 75 , MultiThreadMixer(true)
76 , NumThreads(1)
76 #endif 77 #endif
77 , MemoryUsageLimit((UInt64)1 << 30) 78 , MemoryUsageLimit((UInt64)1 << 30)
78 , MemoryUsageLimit_WasSet(false)
79 , PasswordIsDefined(false)
80 {} 79 {}
81 80
82#ifdef Z7_CPP_IS_SUPPORTED_default 81#ifdef Z7_CPP_IS_SUPPORTED_default
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
index 5420dce..50cbff6 100644
--- a/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -442,9 +442,10 @@ HRESULT CDecoder::Decode(
442 len = password.Len(); 442 len = password.Len();
443 } 443 }
444 CByteBuffer_Wipe buffer(len * 2); 444 CByteBuffer_Wipe buffer(len * 2);
445 const LPCOLESTR psw = passwordBSTR;
445 for (size_t k = 0; k < len; k++) 446 for (size_t k = 0; k < len; k++)
446 { 447 {
447 const wchar_t c = passwordBSTR[k]; 448 const wchar_t c = psw[k];
448 ((Byte *)buffer)[k * 2] = (Byte)c; 449 ((Byte *)buffer)[k * 2] = (Byte)c;
449 ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8); 450 ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);
450 } 451 }
@@ -501,8 +502,7 @@ HRESULT CDecoder::Decode(
501 502
502 CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; 503 CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
503 504
504 CLockedInStream *lockedInStreamSpec = new CLockedInStream; 505 CMyComPtr2_Create<IUnknown, CLockedInStream> lockedInStream;
505 CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
506 506
507 #ifdef USE_MIXER_MT 507 #ifdef USE_MIXER_MT
508 #ifdef USE_MIXER_ST 508 #ifdef USE_MIXER_ST
@@ -514,8 +514,8 @@ HRESULT CDecoder::Decode(
514 { 514 {
515 // lockedInStream.Pos = (UInt64)(Int64)-1; 515 // lockedInStream.Pos = (UInt64)(Int64)-1;
516 // RINOK(InStream_GetPos(inStream, lockedInStream.Pos)) 516 // RINOK(InStream_GetPos(inStream, lockedInStream.Pos))
517 RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStreamSpec->Pos)) 517 RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStream->Pos))
518 lockedInStreamSpec->Stream = inStream; 518 lockedInStream->Stream = inStream;
519 519
520 #ifdef USE_MIXER_MT 520 #ifdef USE_MIXER_MT
521 #ifdef USE_MIXER_ST 521 #ifdef USE_MIXER_ST
@@ -551,7 +551,7 @@ HRESULT CDecoder::Decode(
551 { 551 {
552 CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT; 552 CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
553 packStream = lockedStreamImpSpec; 553 packStream = lockedStreamImpSpec;
554 lockedStreamImpSpec->Init(lockedInStreamSpec, packPos); 554 lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);
555 } 555 }
556 #ifdef USE_MIXER_ST 556 #ifdef USE_MIXER_ST
557 else 557 else
@@ -561,7 +561,7 @@ HRESULT CDecoder::Decode(
561 #ifdef USE_MIXER_ST 561 #ifdef USE_MIXER_ST
562 CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST; 562 CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
563 packStream = lockedStreamImpSpec; 563 packStream = lockedStreamImpSpec;
564 lockedStreamImpSpec->Init(lockedInStreamSpec, packPos); 564 lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);
565 #endif 565 #endif
566 } 566 }
567 } 567 }
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
index 78c91cf..71d1ddb 100644
--- a/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -299,10 +299,9 @@ static HRESULT FillProps_from_Coder(IUnknown *coder, CByteBuffer &props)
299 writeCoderProperties, coder) 299 writeCoderProperties, coder)
300 if (writeCoderProperties) 300 if (writeCoderProperties)
301 { 301 {
302 CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; 302 CMyComPtr2_Create<ISequentialOutStream, CDynBufSeqOutStream> outStreamSpec;
303 CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
304 outStreamSpec->Init(); 303 outStreamSpec->Init();
305 RINOK(writeCoderProperties->WriteCoderProperties(dynOutStream)) 304 RINOK(writeCoderProperties->WriteCoderProperties(outStreamSpec))
306 outStreamSpec->CopyToBuffer(props); 305 outStreamSpec->CopyToBuffer(props);
307 } 306 }
308 else 307 else
@@ -332,11 +331,8 @@ HRESULT CEncoder::Encode1(
332 331
333 RINOK(_mixer->ReInit2()) 332 RINOK(_mixer->ReInit2())
334 333
335 CMtEncMultiProgress *mtProgressSpec = NULL; 334 CMyComPtr2<ICompressProgressInfo, CMtEncMultiProgress> mtProgress;
336 CMyComPtr<ICompressProgressInfo> mtProgress; 335 CMyComPtr2<ISequentialOutStream, CSequentialOutMtNotify> mtOutStreamNotify;
337
338 CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
339 CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
340 336
341 CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs; 337 CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
342 CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; 338 CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
@@ -454,18 +450,16 @@ HRESULT CEncoder::Encode1(
454 450
455 if (useMtProgress) 451 if (useMtProgress)
456 { 452 {
457 mtProgressSpec = new CMtEncMultiProgress; 453 mtProgress.SetFromCls(new CMtEncMultiProgress);
458 mtProgress = mtProgressSpec; 454 mtProgress->Init(compressProgress);
459 mtProgressSpec->Init(compressProgress);
460 455
461 mtOutStreamNotifySpec = new CSequentialOutMtNotify; 456 mtOutStreamNotify.SetFromCls(new CSequentialOutMtNotify);
462 mtOutStreamNotify = mtOutStreamNotifySpec; 457 mtOutStreamNotify->_stream = outStream;
463 mtOutStreamNotifySpec->_stream = outStream; 458 mtOutStreamNotify->_mtProgressSpec = mtProgress.ClsPtr();
464 mtOutStreamNotifySpec->_mtProgressSpec = mtProgressSpec;
465 459
466 FOR_VECTOR (t, tempBufferSpecs) 460 FOR_VECTOR (t, tempBufferSpecs)
467 { 461 {
468 tempBufferSpecs[t]->_mtProgressSpec = mtProgressSpec; 462 tempBufferSpecs[t]->_mtProgressSpec = mtProgress.ClsPtr();
469 } 463 }
470 } 464 }
471 465
@@ -474,7 +468,8 @@ HRESULT CEncoder::Encode1(
474 { 468 {
475 outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; 469 outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
476 outStreamSizeCount = outStreamSizeCountSpec; 470 outStreamSizeCount = outStreamSizeCountSpec;
477 outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream); 471 outStreamSizeCountSpec->SetStream(mtOutStreamNotify.IsDefined() ?
472 mtOutStreamNotify.Interface() : outStream);
478 outStreamSizeCountSpec->Init(); 473 outStreamSizeCountSpec->Init();
479 outStreamPointers.Add(outStreamSizeCount); 474 outStreamPointers.Add(outStreamSizeCount);
480 } 475 }
@@ -486,8 +481,9 @@ HRESULT CEncoder::Encode1(
486 481
487 RINOK(_mixer->Code( 482 RINOK(_mixer->Code(
488 &inStreamPointer, 483 &inStreamPointer,
489 &outStreamPointers.Front(), 484 outStreamPointers.ConstData(),
490 mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress, dataAfterEnd_Error)) 485 mtProgress.IsDefined() ? mtProgress.Interface() :
486 compressProgress, dataAfterEnd_Error))
491 487
492 if (_bindInfo.PackStreams.Size() != 0) 488 if (_bindInfo.PackStreams.Size() != 0)
493 packSizes.Add(outStreamSizeCountSpec->GetSize()); 489 packSizes.Add(outStreamSizeCountSpec->GetSize());
diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
index 5498c59..1c31e1d 100644
--- a/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -271,8 +271,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
271 271
272 RINOK(extractCallback->SetTotal(importantTotalUnpacked)) 272 RINOK(extractCallback->SetTotal(importantTotalUnpacked))
273 273
274 CLocalProgress *lps = new CLocalProgress; 274 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
275 CMyComPtr<ICompressProgressInfo> progress = lps;
276 lps->Init(extractCallback, false); 275 lps->Init(extractCallback, false);
277 276
278 CDecoder decoder( 277 CDecoder decoder(
@@ -385,7 +384,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
385 &curUnpacked, 384 &curUnpacked,
386 385
387 outStream, 386 outStream,
388 progress, 387 lps,
389 NULL // *inStreamMainRes 388 NULL // *inStreamMainRes
390 , dataAfterEnd_Error 389 , dataAfterEnd_Error
391 390
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
index 23d3a9d..81dd966 100644
--- a/CPP/7zip/Archive/7z/7zHandler.cpp
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -272,6 +272,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
272 prop = true; 272 prop = true;
273 break; 273 break;
274 } 274 }
275 default: break;
275 } 276 }
276 return prop.Detach(value); 277 return prop.Detach(value);
277 #ifndef Z7_SFX 278 #ifndef Z7_SFX
@@ -291,7 +292,7 @@ bool CHandler::IsFolderEncrypted(CNum folderIndex) const
291 if (folderIndex == kNumNoIndex) 292 if (folderIndex == kNumNoIndex)
292 return false; 293 return false;
293 const size_t startPos = _db.FoCodersDataOffset[folderIndex]; 294 const size_t startPos = _db.FoCodersDataOffset[folderIndex];
294 const Byte *p = _db.CodersData + startPos; 295 const Byte *p = _db.CodersData.ConstData() + startPos;
295 const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; 296 const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
296 CInByte2 inByte; 297 CInByte2 inByte;
297 inByte.Init(p, size); 298 inByte.Init(p, size);
@@ -350,11 +351,11 @@ Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
350 { 351 {
351 if (_db.NameOffsets && _db.NamesBuf) 352 if (_db.NameOffsets && _db.NamesBuf)
352 { 353 {
353 size_t offset = _db.NameOffsets[index]; 354 const size_t offset = _db.NameOffsets[index];
354 size_t size = (_db.NameOffsets[index + 1] - offset) * 2; 355 const size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
355 if (size < ((UInt32)1 << 31)) 356 if (size < ((UInt32)1 << 31))
356 { 357 {
357 *data = (const void *)(_db.NamesBuf + offset * 2); 358 *data = (const void *)(_db.NamesBuf.ConstData() + offset * 2);
358 *dataSize = (UInt32)size; 359 *dataSize = (UInt32)size;
359 *propType = NPropDataType::kUtf16z; 360 *propType = NPropDataType::kUtf16z;
360 } 361 }
@@ -395,7 +396,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
395 temp[--pos] = 0; 396 temp[--pos] = 0;
396 397
397 const size_t startPos = _db.FoCodersDataOffset[folderIndex]; 398 const size_t startPos = _db.FoCodersDataOffset[folderIndex];
398 const Byte *p = _db.CodersData + startPos; 399 const Byte *p = _db.CodersData.ConstData() + startPos;
399 const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; 400 const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
400 CInByte2 inByte; 401 CInByte2 inByte;
401 inByte.Init(p, size); 402 inByte.Init(p, size);
@@ -482,9 +483,9 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
482 if (propsSize == 1) 483 if (propsSize == 1)
483 ConvertUInt32ToString((UInt32)props[0] + 1, s); 484 ConvertUInt32ToString((UInt32)props[0] + 1, s);
484 } 485 }
485 else if (id == k_ARM64) 486 else if (id == k_ARM64 || id == k_RISCV)
486 { 487 {
487 name = "ARM64"; 488 name = id == k_ARM64 ? "ARM64" : "RISCV";
488 if (propsSize == 4) 489 if (propsSize == 4)
489 ConvertUInt32ToString(GetUi32(props), s); 490 ConvertUInt32ToString(GetUi32(props), s);
490 /* 491 /*
@@ -666,6 +667,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
666 #endif 667 #endif
667 668
668 #endif 669 #endif
670 default: break;
669 } 671 }
670 // return prop.Detach(value); 672 // return prop.Detach(value);
671 return S_OK; 673 return S_OK;
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
index b1c0466..ed535f7 100644
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -54,11 +54,13 @@ public:
54 CBoolPair Write_Attrib; 54 CBoolPair Write_Attrib;
55 55
56 bool _useMultiThreadMixer; 56 bool _useMultiThreadMixer;
57
58 bool _removeSfxBlock; 57 bool _removeSfxBlock;
59
60 // bool _volumeMode; 58 // bool _volumeMode;
61 59
60 UInt32 _decoderCompatibilityVersion;
61 CUIntVector _enabledFilters;
62 CUIntVector _disabledFilters;
63
62 void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } 64 void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
63 void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } 65 void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
64 void InitSolid() 66 void InitSolid()
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index ff8735f..ea5ea0f 100644
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -20,6 +20,9 @@ using namespace NWindows;
20namespace NArchive { 20namespace NArchive {
21namespace N7z { 21namespace N7z {
22 22
23static const UInt32 k_decoderCompatibilityVersion = 2301;
24// 7-Zip version 2301 supports ARM64 filter
25
23#define k_LZMA_Name "LZMA" 26#define k_LZMA_Name "LZMA"
24#define kDefaultMethodName "LZMA2" 27#define kDefaultMethodName "LZMA2"
25#define k_Copy_Name "Copy" 28#define k_Copy_Name "Copy"
@@ -774,6 +777,11 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
774 options.MaxFilter = (level >= 8); 777 options.MaxFilter = (level >= 8);
775 options.AnalysisLevel = GetAnalysisLevel(); 778 options.AnalysisLevel = GetAnalysisLevel();
776 779
780 options.SetFilterSupporting_ver_enabled_disabled(
781 _decoderCompatibilityVersion,
782 _enabledFilters,
783 _disabledFilters);
784
777 options.HeaderOptions.CompressMainHeader = compressMainHeader; 785 options.HeaderOptions.CompressMainHeader = compressMainHeader;
778 /* 786 /*
779 options.HeaderOptions.WriteCTime = Write_CTime; 787 options.HeaderOptions.WriteCTime = Write_CTime;
@@ -858,6 +866,10 @@ void COutHandler::InitProps7z()
858 866
859 InitSolid(); 867 InitSolid();
860 _useTypeSorting = false; 868 _useTypeSorting = false;
869
870 _decoderCompatibilityVersion = k_decoderCompatibilityVersion;
871 _enabledFilters.Clear();
872 _disabledFilters.Clear();
861} 873}
862 874
863void COutHandler::InitProps() 875void COutHandler::InitProps()
@@ -944,6 +956,29 @@ static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)
944 return S_OK; 956 return S_OK;
945} 957}
946 958
959struct C_Id_Name_pair
960{
961 UInt32 Id;
962 const char *Name;
963};
964
965static const C_Id_Name_pair g_filter_pairs[] =
966{
967 { k_Delta, "Delta" },
968 { k_ARM64, "ARM64" },
969 { k_RISCV, "RISCV" },
970 { k_SWAP2, "SWAP2" },
971 { k_SWAP4, "SWAP4" },
972 { k_BCJ, "BCJ" },
973 { k_BCJ2 , "BCJ2" },
974 { k_PPC, "PPC" },
975 { k_IA64, "IA64" },
976 { k_ARM, "ARM" },
977 { k_ARMT, "ARMT" },
978 { k_SPARC, "SPARC" }
979};
980
981
947HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) 982HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
948{ 983{
949 UString name = nameSpec; 984 UString name = nameSpec;
@@ -1004,6 +1039,43 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
1004 1039
1005 if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting); 1040 if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
1006 1041
1042 if (name.IsPrefixedBy_Ascii_NoCase("yv"))
1043 {
1044 name.Delete(0, 2);
1045 UInt32 v = 1 << 16; // if no number is noit specified, we use big value
1046 RINOK(ParsePropToUInt32(name, value, v))
1047 _decoderCompatibilityVersion = v;
1048 // if (v == 0) _decoderCompatibilityVersion = k_decoderCompatibilityVersion;
1049 return S_OK;
1050 }
1051
1052 if (name.IsPrefixedBy_Ascii_NoCase("yf"))
1053 {
1054 name.Delete(0, 2);
1055 CUIntVector *vec;
1056 if (name.IsEqualTo_Ascii_NoCase("a")) vec = &_enabledFilters;
1057 else if (name.IsEqualTo_Ascii_NoCase("d")) vec = &_disabledFilters;
1058 else return E_INVALIDARG;
1059
1060 if (value.vt != VT_BSTR)
1061 return E_INVALIDARG;
1062 for (unsigned k = 0;; k++)
1063 {
1064 if (k == Z7_ARRAY_SIZE(g_filter_pairs))
1065 {
1066 // maybe we can ignore unsupported filter names here?
1067 return E_INVALIDARG;
1068 }
1069 const C_Id_Name_pair &pair = g_filter_pairs[k];
1070 if (StringsAreEqualNoCase_Ascii(value.bstrVal, pair.Name))
1071 {
1072 vec->AddToUniqueSorted(pair.Id);
1073 break;
1074 }
1075 }
1076 return S_OK;
1077 }
1078
1007 // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); 1079 // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
1008 } 1080 }
1009 return CMultiMethodProps::SetProperty(name, value); 1081 return CMultiMethodProps::SetProperty(name, value);
diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h
index bd96ca3..22e7960 100644
--- a/CPP/7zip/Archive/7z/7zHeader.h
+++ b/CPP/7zip/Archive/7z/7zHeader.h
@@ -100,6 +100,7 @@ namespace NID
100const UInt32 k_Copy = 0; 100const UInt32 k_Copy = 0;
101const UInt32 k_Delta = 3; 101const UInt32 k_Delta = 3;
102const UInt32 k_ARM64 = 0xa; 102const UInt32 k_ARM64 = 0xa;
103const UInt32 k_RISCV = 0xb;
103 104
104const UInt32 k_LZMA2 = 0x21; 105const UInt32 k_LZMA2 = 0x21;
105 106
@@ -126,7 +127,7 @@ const UInt32 k_AES = 0x6F10701;
126// const UInt32 k_ZSTD = 0x4015D; // winzip zstd 127// const UInt32 k_ZSTD = 0x4015D; // winzip zstd
127// 0x4F71101, 7z-zstd 128// 0x4F71101, 7z-zstd
128 129
129static inline bool IsFilterMethod(UInt64 m) 130inline bool IsFilterMethod(UInt64 m)
130{ 131{
131 if (m > (UInt32)0xFFFFFFFF) 132 if (m > (UInt32)0xFFFFFFFF)
132 return false; 133 return false;
@@ -134,6 +135,7 @@ static inline bool IsFilterMethod(UInt64 m)
134 { 135 {
135 case k_Delta: 136 case k_Delta:
136 case k_ARM64: 137 case k_ARM64:
138 case k_RISCV:
137 case k_BCJ: 139 case k_BCJ:
138 case k_BCJ2: 140 case k_BCJ2:
139 case k_PPC: 141 case k_PPC:
@@ -144,6 +146,7 @@ static inline bool IsFilterMethod(UInt64 m)
144 case k_SWAP2: 146 case k_SWAP2:
145 case k_SWAP4: 147 case k_SWAP4:
146 return true; 148 return true;
149 default: break;
147 } 150 }
148 return false; 151 return false;
149} 152}
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
index 4defd27..e2efc52 100644
--- a/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -32,37 +32,45 @@
32using namespace NWindows; 32using namespace NWindows;
33using namespace NCOM; 33using namespace NCOM;
34 34
35namespace NArchive {
36namespace N7z {
37
38#define k_Scan_NumCoders_MAX 64
39#define k_Scan_NumCodersStreams_in_Folder_MAX 64
40
41unsigned BoolVector_CountSum(const CBoolVector &v); 35unsigned BoolVector_CountSum(const CBoolVector &v);
36Z7_NO_INLINE
42unsigned BoolVector_CountSum(const CBoolVector &v) 37unsigned BoolVector_CountSum(const CBoolVector &v)
43{ 38{
44 unsigned sum = 0; 39 unsigned sum = 0;
45 const unsigned size = v.Size(); 40 const unsigned size = v.Size();
46 for (unsigned i = 0; i < size; i++) 41 if (size)
47 if (v[i]) 42 {
48 sum++; 43 const bool *p = v.ConstData();
44 const bool * const lim = p + size;
45 do
46 if (*p)
47 sum++;
48 while (++p != lim);
49 }
49 return sum; 50 return sum;
50} 51}
51 52
52static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i) 53static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i)
53{ 54{
54 return (i < v.Size() ? v[i] : false); 55 return i < v.Size() ? v[i] : false;
55} 56}
56 57
58Z7_NO_INLINE
57static void BoolVector_Fill_False(CBoolVector &v, unsigned size) 59static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
58{ 60{
59 v.ClearAndSetSize(size); 61 v.ClearAndSetSize(size);
60 bool *p = &v[0]; 62 bool *p = v.NonConstData();
61 for (unsigned i = 0; i < size; i++) 63 for (unsigned i = 0; i < size; i++)
62 p[i] = false; 64 p[i] = false;
63} 65}
64 66
65 67
68namespace NArchive {
69namespace N7z {
70
71#define k_Scan_NumCoders_MAX 64
72#define k_Scan_NumCodersStreams_in_Folder_MAX 64
73
66class CInArchiveException {}; 74class CInArchiveException {};
67class CUnsupportedFeatureException: public CInArchiveException {}; 75class CUnsupportedFeatureException: public CInArchiveException {};
68 76
@@ -510,7 +518,7 @@ void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const
510{ 518{
511 const size_t startPos = FoCodersDataOffset[folderIndex]; 519 const size_t startPos = FoCodersDataOffset[folderIndex];
512 CInByte2 inByte; 520 CInByte2 inByte;
513 inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos); 521 inByte.Init(CodersData.ConstData() + startPos, FoCodersDataOffset[folderIndex + 1] - startPos);
514 inByte.ParseFolder(folder); 522 inByte.ParseFolder(folder);
515 if (inByte.GetRem() != 0) 523 if (inByte.GetRem() != 0)
516 throw 20120424; 524 throw 20120424;
@@ -1177,8 +1185,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
1177 ThrowUnsupported(); 1185 ThrowUnsupported();
1178 data.Alloc(unpackSize); 1186 data.Alloc(unpackSize);
1179 1187
1180 CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; 1188 CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStreamSpec;
1181 CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
1182 outStreamSpec->Init(data, unpackSize); 1189 outStreamSpec->Init(data, unpackSize);
1183 1190
1184 bool dataAfterEnd_Error = false; 1191 bool dataAfterEnd_Error = false;
@@ -1189,7 +1196,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
1189 folders, i, 1196 folders, i,
1190 NULL, // &unpackSize64 1197 NULL, // &unpackSize64
1191 1198
1192 outStream, 1199 outStreamSpec,
1193 NULL, // *compressProgress 1200 NULL, // *compressProgress
1194 1201
1195 NULL // **inStreamMainRes 1202 NULL // **inStreamMainRes
@@ -1280,7 +1287,7 @@ HRESULT CInArchive::ReadHeader(
1280 CBoolVector emptyStreamVector; 1287 CBoolVector emptyStreamVector;
1281 CBoolVector emptyFileVector; 1288 CBoolVector emptyFileVector;
1282 CBoolVector antiFileVector; 1289 CBoolVector antiFileVector;
1283 CNum numEmptyStreams = 0; 1290 unsigned numEmptyStreams = 0;
1284 1291
1285 for (;;) 1292 for (;;)
1286 { 1293 {
@@ -1311,7 +1318,7 @@ HRESULT CInArchive::ReadHeader(
1311 for (i = 0; i < numFiles; i++) 1318 for (i = 0; i < numFiles; i++)
1312 { 1319 {
1313 const size_t curRem = (rem - pos) / 2; 1320 const size_t curRem = (rem - pos) / 2;
1314 const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf + pos); 1321 const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf.ConstData() + pos);
1315 size_t j; 1322 size_t j;
1316 for (j = 0; j < curRem && buf[j] != 0; j++); 1323 for (j = 0; j < curRem && buf[j] != 0; j++);
1317 if (j == curRem) 1324 if (j == curRem)
@@ -1457,7 +1464,7 @@ HRESULT CInArchive::ReadHeader(
1457 CNum emptyFileIndex = 0; 1464 CNum emptyFileIndex = 0;
1458 CNum sizeIndex = 0; 1465 CNum sizeIndex = 0;
1459 1466
1460 const CNum numAntiItems = BoolVector_CountSum(antiFileVector); 1467 const unsigned numAntiItems = BoolVector_CountSum(antiFileVector);
1461 1468
1462 if (numAntiItems != 0) 1469 if (numAntiItems != 0)
1463 db.IsAnti.ClearAndSetSize(numFiles); 1470 db.IsAnti.ClearAndSetSize(numFiles);
@@ -1649,7 +1656,7 @@ HRESULT CInArchive::ReadDatabase2(
1649 1656
1650 if (nextHeaderSize == 0) 1657 if (nextHeaderSize == 0)
1651 { 1658 {
1652 if (nextHeaderOffset != 0) 1659 if (nextHeaderOffset != 0 || nextHeaderCRC != 0)
1653 return S_FALSE; 1660 return S_FALSE;
1654 db.IsArc = true; 1661 db.IsArc = true;
1655 db.HeadersSize = HeadersSize; 1662 db.HeadersSize = HeadersSize;
diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
index a9c14fb..ddbe020 100644
--- a/CPP/7zip/Archive/7z/7zIn.h
+++ b/CPP/7zip/Archive/7z/7zIn.h
@@ -273,33 +273,36 @@ struct CDbEx: public CDatabase
273 273
274 void FillLinks(); 274 void FillLinks();
275 275
276 UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const 276 UInt64 GetFolderStreamPos(size_t folderIndex, size_t indexInFolder) const
277 { 277 {
278 return ArcInfo.DataStartPosition + 278 return ArcInfo.DataStartPosition + PackPositions.ConstData()
279 PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; 279 [FoStartPackStreamIndex.ConstData()[folderIndex] + indexInFolder];
280 } 280 }
281 281
282 UInt64 GetFolderFullPackSize(CNum folderIndex) const 282 UInt64 GetFolderFullPackSize(size_t folderIndex) const
283 { 283 {
284 return 284 return
285 PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - 285 PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex + 1]] -
286 PackPositions[FoStartPackStreamIndex[folderIndex]]; 286 PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex]];
287 } 287 }
288 288
289 UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const 289 UInt64 GetFolderPackStreamSize(size_t folderIndex, size_t streamIndex) const
290 { 290 {
291 size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex; 291 const size_t i = FoStartPackStreamIndex.ConstData()[folderIndex] + streamIndex;
292 return PackPositions[i + 1] - PackPositions[i]; 292 return PackPositions.ConstData()[i + 1] -
293 PackPositions.ConstData()[i];
293 } 294 }
294 295
295 UInt64 GetFilePackSize(CNum fileIndex) const 296 /*
297 UInt64 GetFilePackSize(size_t fileIndex) const
296 { 298 {
297 CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; 299 const CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
298 if (folderIndex != kNumNoIndex) 300 if (folderIndex != kNumNoIndex)
299 if (FolderStartFileIndex[folderIndex] == fileIndex) 301 if (FolderStartFileIndex[folderIndex] == fileIndex)
300 return GetFolderFullPackSize(folderIndex); 302 return GetFolderFullPackSize(folderIndex);
301 return 0; 303 return 0;
302 } 304 }
305 */
303}; 306};
304 307
305const unsigned kNumBufLevelsMax = 4; 308const unsigned kNumBufLevelsMax = 4;
diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h
index e8c68be..06737c8 100644
--- a/CPP/7zip/Archive/7z/7zItem.h
+++ b/CPP/7zip/Archive/7z/7zItem.h
@@ -129,7 +129,7 @@ struct CUInt32DefVector
129 bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; } 129 bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
130 130
131 void SetItem(unsigned index, bool defined, UInt32 value); 131 void SetItem(unsigned index, bool defined, UInt32 value);
132 void if_NonEmpty_FillResedue_with_false(unsigned numItems) 132 void if_NonEmpty_FillResidue_with_false(unsigned numItems)
133 { 133 {
134 if (Defs.Size() != 0 && Defs.Size() < numItems) 134 if (Defs.Size() != 0 && Defs.Size() < numItems)
135 SetItem(numItems - 1, false, 0); 135 SetItem(numItems - 1, false, 0);
diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
index 7f8fa5b..d0c8cf2 100644
--- a/CPP/7zip/Archive/7z/7zOut.cpp
+++ b/CPP/7zip/Archive/7z/7zOut.cpp
@@ -3,14 +3,34 @@
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../../../../C/7zCrc.h" 5#include "../../../../C/7zCrc.h"
6#include "../../../../C/CpuArch.h"
6 7
7#include "../../../Common/AutoPtr.h" 8#include "../../../Common/AutoPtr.h"
8// #include "../../../Common/UTFConvert.h" 9// #include "../../../Common/UTFConvert.h"
9 10
10#include "../../Common/StreamObjects.h" 11#include "../../Common/StreamObjects.h"
12#include "../Common/OutStreamWithCRC.h"
11 13
12#include "7zOut.h" 14#include "7zOut.h"
13 15
16unsigned BoolVector_CountSum(const CBoolVector &v);
17
18static UInt64 UInt64Vector_CountSum(const CRecordVector<UInt64> &v)
19{
20 UInt64 sum = 0;
21 const unsigned size = v.Size();
22 if (size)
23 {
24 const UInt64 *p = v.ConstData();
25 const UInt64 * const lim = p + size;
26 do
27 sum += *p++;
28 while (p != lim);
29 }
30 return sum;
31}
32
33
14namespace NArchive { 34namespace NArchive {
15namespace N7z { 35namespace N7z {
16 36
@@ -133,7 +153,7 @@ void COutArchive::WriteBytes(const void *data, size_t size)
133 else if (_writeToStream) 153 else if (_writeToStream)
134 { 154 {
135 _outByte.WriteBytes(data, size); 155 _outByte.WriteBytes(data, size);
136 _crc = CrcUpdate(_crc, data, size); 156 // _crc = CrcUpdate(_crc, data, size);
137 } 157 }
138 else 158 else
139 _outByte2.WriteBytes(data, size); 159 _outByte2.WriteBytes(data, size);
@@ -144,14 +164,12 @@ void COutArchive::WriteByte(Byte b)
144 if (_countMode) 164 if (_countMode)
145 _countSize++; 165 _countSize++;
146 else if (_writeToStream) 166 else if (_writeToStream)
147 { 167 WriteByte_ToStream(b);
148 _outByte.WriteByte(b);
149 _crc = CRC_UPDATE_BYTE(_crc, b);
150 }
151 else 168 else
152 _outByte2.WriteByte(b); 169 _outByte2.WriteByte(b);
153} 170}
154 171
172/*
155void COutArchive::WriteUInt32(UInt32 value) 173void COutArchive::WriteUInt32(UInt32 value)
156{ 174{
157 for (int i = 0; i < 4; i++) 175 for (int i = 0; i < 4; i++)
@@ -169,6 +187,7 @@ void COutArchive::WriteUInt64(UInt64 value)
169 value >>= 8; 187 value >>= 8;
170 } 188 }
171} 189}
190*/
172 191
173void COutArchive::WriteNumber(UInt64 value) 192void COutArchive::WriteNumber(UInt64 value)
174{ 193{
@@ -288,7 +307,7 @@ void COutArchive::WriteFolder(const CFolder &folder)
288 WriteNumber(folder.PackStreams[i]); 307 WriteNumber(folder.PackStreams[i]);
289} 308}
290 309
291void COutArchive::WriteBoolVector(const CBoolVector &boolVector) 310void COutArchive::Write_BoolVector(const CBoolVector &boolVector)
292{ 311{
293 Byte b = 0; 312 Byte b = 0;
294 Byte mask = 0x80; 313 Byte mask = 0x80;
@@ -314,31 +333,32 @@ void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)
314{ 333{
315 WriteByte(id); 334 WriteByte(id);
316 WriteNumber(Bv_GetSizeInBytes(boolVector)); 335 WriteNumber(Bv_GetSizeInBytes(boolVector));
317 WriteBoolVector(boolVector); 336 Write_BoolVector(boolVector);
337}
338
339void COutArchive::Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined)
340{
341 if (numDefined == boolVector.Size())
342 WriteByte(1);
343 else
344 {
345 WriteByte(0);
346 Write_BoolVector(boolVector);
347 }
318} 348}
319 349
320unsigned BoolVector_CountSum(const CBoolVector &v);
321 350
322void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) 351void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
323{ 352{
324 const unsigned numDefined = BoolVector_CountSum(digests.Defs); 353 const unsigned numDefined = BoolVector_CountSum(digests.Defs);
325 if (numDefined == 0) 354 if (numDefined == 0)
326 return; 355 return;
327
328 WriteByte(NID::kCRC); 356 WriteByte(NID::kCRC);
329 if (numDefined == digests.Defs.Size()) 357 Write_BoolVector_numDefined(digests.Defs, numDefined);
330 WriteByte(1); 358 Write_UInt32DefVector_numDefined(digests, numDefined);
331 else
332 {
333 WriteByte(0);
334 WriteBoolVector(digests.Defs);
335 }
336
337 for (unsigned i = 0; i < digests.Defs.Size(); i++)
338 if (digests.Defs[i])
339 WriteUInt32(digests.Vals[i]);
340} 359}
341 360
361
342void COutArchive::WritePackInfo( 362void COutArchive::WritePackInfo(
343 UInt64 dataOffset, 363 UInt64 dataOffset,
344 const CRecordVector<UInt64> &packSizes, 364 const CRecordVector<UInt64> &packSizes,
@@ -467,17 +487,42 @@ void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, B
467 487
468 WriteByte(type); 488 WriteByte(type);
469 WriteNumber(dataSize); 489 WriteNumber(dataSize);
470 if (numDefined == v.Size()) 490 Write_BoolVector_numDefined(v, numDefined);
471 WriteByte(1); 491 WriteByte(0); // 0 means no switching to external stream
472 else 492}
493
494
495void COutArchive::Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined)
496{
497 if (_countMode)
473 { 498 {
474 WriteByte(0); 499 _countSize += (size_t)numDefined * 4;
475 WriteBoolVector(v); 500 return;
476 } 501 }
477 WriteByte(0); // 0 means no switching to external stream 502
503 const bool * const defs = v.Defs.ConstData();
504 const UInt32 * const vals = v.Vals.ConstData();
505 const size_t num = v.Defs.Size();
506
507 for (size_t i = 0; i < num; i++)
508 if (defs[i])
509 {
510 UInt32 value = vals[i];
511 for (int k = 0; k < 4; k++)
512 {
513 if (_writeToStream)
514 WriteByte_ToStream((Byte)value);
515 else
516 _outByte2.WriteByte((Byte)value);
517 // WriteByte((Byte)value);
518 value >>= 8;
519 }
520 // WriteUInt32(v.Vals[i]);
521 }
478} 522}
479 523
480void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) 524
525void COutArchive::Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type)
481{ 526{
482 const unsigned numDefined = BoolVector_CountSum(v.Defs); 527 const unsigned numDefined = BoolVector_CountSum(v.Defs);
483 if (numDefined == 0) 528 if (numDefined == 0)
@@ -485,18 +530,40 @@ void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
485 530
486 WriteAlignedBools(v.Defs, numDefined, type, 3); 531 WriteAlignedBools(v.Defs, numDefined, type, 3);
487 532
488 for (unsigned i = 0; i < v.Defs.Size(); i++) 533 if (_countMode)
489 if (v.Defs[i]) 534 {
490 WriteUInt64(v.Vals[i]); 535 _countSize += (size_t)numDefined * 8;
536 return;
537 }
538
539 const bool * const defs = v.Defs.ConstData();
540 const UInt64 * const vals = v.Vals.ConstData();
541 const size_t num = v.Defs.Size();
542
543 for (size_t i = 0; i < num; i++)
544 if (defs[i])
545 {
546 UInt64 value = vals[i];
547 for (int k = 0; k < 8; k++)
548 {
549 if (_writeToStream)
550 WriteByte_ToStream((Byte)value);
551 else
552 _outByte2.WriteByte((Byte)value);
553 // WriteByte((Byte)value);
554 value >>= 8;
555 }
556 // WriteUInt64(v.Vals[i]);
557 }
491} 558}
492 559
560
493HRESULT COutArchive::EncodeStream( 561HRESULT COutArchive::EncodeStream(
494 DECL_EXTERNAL_CODECS_LOC_VARS 562 DECL_EXTERNAL_CODECS_LOC_VARS
495 CEncoder &encoder, const CByteBuffer &data, 563 CEncoder &encoder, const CByteBuffer &data,
496 CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders) 564 CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)
497{ 565{
498 CBufInStream *streamSpec = new CBufInStream; 566 CMyComPtr2_Create<ISequentialInStream, CBufInStream> streamSpec;
499 CMyComPtr<ISequentialInStream> stream = streamSpec;
500 streamSpec->Init(data, data.Size()); 567 streamSpec->Init(data, data.Size());
501 outFolders.FolderUnpackCRCs.Defs.Add(true); 568 outFolders.FolderUnpackCRCs.Defs.Add(true);
502 outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size())); 569 outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));
@@ -505,7 +572,7 @@ HRESULT COutArchive::EncodeStream(
505 const UInt64 expectSize = data.Size(); 572 const UInt64 expectSize = data.Size();
506 RINOK(encoder.Encode1( 573 RINOK(encoder.Encode1(
507 EXTERNAL_CODECS_LOC_VARS 574 EXTERNAL_CODECS_LOC_VARS
508 stream, 575 streamSpec,
509 // NULL, 576 // NULL,
510 &dataSize64, // inSizeForReduce 577 &dataSize64, // inSizeForReduce
511 expectSize, 578 expectSize,
@@ -528,13 +595,7 @@ void COutArchive::WriteHeader(
528 */ 595 */
529 _useAlign = true; 596 _useAlign = true;
530 597
531 { 598 headerOffset = UInt64Vector_CountSum(db.PackSizes);
532 UInt64 packSize = 0;
533 FOR_VECTOR (i, db.PackSizes)
534 packSize += db.PackSizes[i];
535 headerOffset = packSize;
536 }
537
538 599
539 WriteByte(NID::kHeader); 600 WriteByte(NID::kHeader);
540 601
@@ -655,81 +716,97 @@ void COutArchive::WriteHeader(
655 { 716 {
656 /* ---------- Names ---------- */ 717 /* ---------- Names ---------- */
657 718
658 unsigned numDefined = 0;
659 size_t namesDataSize = 0; 719 size_t namesDataSize = 0;
660 FOR_VECTOR (i, db.Files)
661 { 720 {
662 const UString &name = db.Names[i]; 721 FOR_VECTOR (i, db.Files)
663 if (!name.IsEmpty()) 722 {
664 numDefined++; 723 const UString &name = db.Names[i];
665 const size_t numUtfChars = 724 const size_t numUtfChars =
666 /* 725 /*
667 #if WCHAR_MAX > 0xffff 726 #if WCHAR_MAX > 0xffff
668 Get_Num_Utf16_chars_from_wchar_string(name.Ptr()); 727 Get_Num_Utf16_chars_from_wchar_string(name.Ptr());
669 #else 728 #else
670 */ 729 */
671 name.Len(); 730 name.Len();
672 // #endif 731 // #endif
673 namesDataSize += (numUtfChars + 1) * 2; 732 namesDataSize += numUtfChars;
733 }
674 } 734 }
675 735 if (namesDataSize)
676 if (numDefined > 0)
677 { 736 {
678 namesDataSize++; 737 namesDataSize += db.Files.Size(); // we will write tail zero wchar for each name
738 namesDataSize *= 2; // 2 bytes per wchar for UTF16 encoding
739 namesDataSize++; // for additional switch byte (zero value)
679 SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4); 740 SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4);
680
681 WriteByte(NID::kName); 741 WriteByte(NID::kName);
682 WriteNumber(namesDataSize); 742 WriteNumber(namesDataSize);
683 WriteByte(0); 743
684 FOR_VECTOR (i, db.Files) 744 if (_countMode)
745 _countSize += namesDataSize;
746 else
685 { 747 {
686 const UString &name = db.Names[i]; 748 WriteByte(0);
687 for (unsigned t = 0; t <= name.Len(); t++) 749 FOR_VECTOR (i, db.Files)
688 { 750 {
689 wchar_t c = name[t]; 751 const UString &name = db.Names[i];
690 752 const wchar_t *p = name.Ptr();
691 /* 753 const size_t len = (size_t)name.Len() + 1;
692 #if WCHAR_MAX > 0xffff 754 const wchar_t * const lim = p + len;
693 if (c >= 0x10000) 755 if (_writeToStream)
694 { 756 {
695 c -= 0x10000; 757 do
696 if (c < (1 << 20))
697 { 758 {
698 unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF); 759 const wchar_t c = *p++;
699 WriteByte((Byte)c0); 760 WriteByte_ToStream((Byte)c);
700 WriteByte((Byte)(c0 >> 8)); 761 WriteByte_ToStream((Byte)(c >> 8));
701 c = 0xdc00 + (c & 0x3FF);
702 } 762 }
703 else 763 while (p != lim);
704 c = '_'; // we change character unsupported by UTF16 764 }
765 else
766 {
767 Byte *dest = _outByte2.GetDest_and_Update(len * 2);
768 do
769 {
770 /*
771 #if WCHAR_MAX > 0xffff
772 if (c >= 0x10000)
773 {
774 c -= 0x10000;
775 if (c < (1 << 20))
776 {
777 unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF);
778 WriteByte((Byte)c0);
779 WriteByte((Byte)(c0 >> 8));
780 c = 0xdc00 + (c & 0x3FF);
781 }
782 else
783 c = '_'; // we change character unsupported by UTF16
784 }
785 #endif
786 */
787 const wchar_t c = *p++;
788 SetUi16(dest, (UInt16)c)
789 dest += 2;
790 }
791 while (p != lim);
705 } 792 }
706 #endif
707 */
708
709 WriteByte((Byte)c);
710 WriteByte((Byte)(c >> 8));
711 } 793 }
712 } 794 }
713 } 795 }
714 } 796 }
715 797
716 /* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime); 798 /* if (headerOptions.WriteCTime) */ Write_UInt64DefVector_type(db.CTime, NID::kCTime);
717 /* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime); 799 /* if (headerOptions.WriteATime) */ Write_UInt64DefVector_type(db.ATime, NID::kATime);
718 /* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime); 800 /* if (headerOptions.WriteMTime) */ Write_UInt64DefVector_type(db.MTime, NID::kMTime);
719 WriteUInt64DefVector(db.StartPos, NID::kStartPos); 801 Write_UInt64DefVector_type(db.StartPos, NID::kStartPos);
720 802
721 { 803 {
722 /* ---------- Write Attrib ---------- */ 804 /* ---------- Write Attrib ---------- */
723 const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs); 805 const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs);
724
725 if (numDefined != 0) 806 if (numDefined != 0)
726 { 807 {
727 WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2); 808 WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2);
728 FOR_VECTOR (i, db.Attrib.Defs) 809 Write_UInt32DefVector_numDefined(db.Attrib, numDefined);
729 {
730 if (db.Attrib.Defs[i])
731 WriteUInt32(db.Attrib.Vals[i]);
732 }
733 } 810 }
734 } 811 }
735 812
@@ -765,13 +842,7 @@ void COutArchive::WriteHeader(
765 842
766 WriteByte(NID::kParent); 843 WriteByte(NID::kParent);
767 WriteNumber(dataSize); 844 WriteNumber(dataSize);
768 if (numIsDir == boolVector.Size()) 845 Write_BoolVector_numDefined(boolVector, numIsDir);
769 WriteByte(1);
770 else
771 {
772 WriteByte(0);
773 WriteBoolVector(boolVector);
774 }
775 for (i = 0; i < db.Files.Size(); i++) 846 for (i = 0; i < db.Files.Size(); i++)
776 { 847 {
777 const CFileItem &file = db.Files[i]; 848 const CFileItem &file = db.Files[i];
@@ -818,17 +889,17 @@ HRESULT COutArchive::WriteDatabase(
818 if (!db.CheckNumFiles()) 889 if (!db.CheckNumFiles())
819 return E_FAIL; 890 return E_FAIL;
820 891
821 UInt64 headerOffset; 892 CStartHeader sh;
822 UInt32 headerCRC; 893 sh.NextHeaderOffset = 0;
823 UInt64 headerSize; 894 sh.NextHeaderSize = 0;
824 if (db.IsEmpty()) 895 sh.NextHeaderCRC = 0; // CrcCalc(NULL, 0);
825 { 896
826 headerSize = 0; 897 if (!db.IsEmpty())
827 headerOffset = 0;
828 headerCRC = CrcCalc(NULL, 0);
829 }
830 else
831 { 898 {
899 CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> crcStream;
900 crcStream->SetStream(SeqStream);
901 crcStream->Init();
902
832 bool encodeHeaders = false; 903 bool encodeHeaders = false;
833 if (options) 904 if (options)
834 if (options->IsEmpty()) 905 if (options->IsEmpty())
@@ -837,13 +908,15 @@ HRESULT COutArchive::WriteDatabase(
837 if (options->PasswordIsDefined || headerOptions.CompressMainHeader) 908 if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
838 encodeHeaders = true; 909 encodeHeaders = true;
839 910
840 _outByte.SetStream(SeqStream); 911 if (!_outByte.Create(1 << 16))
912 return E_OUTOFMEMORY;
913 _outByte.SetStream(crcStream.Interface());
841 _outByte.Init(); 914 _outByte.Init();
842 _crc = CRC_INIT_VAL; 915 // _crc = CRC_INIT_VAL;
843 _countMode = encodeHeaders; 916 _countMode = encodeHeaders;
844 _writeToStream = true; 917 _writeToStream = true;
845 _countSize = 0; 918 _countSize = 0;
846 WriteHeader(db, /* headerOptions, */ headerOffset); 919 WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset);
847 920
848 if (encodeHeaders) 921 if (encodeHeaders)
849 { 922 {
@@ -852,7 +925,7 @@ HRESULT COutArchive::WriteDatabase(
852 925
853 _countMode = false; 926 _countMode = false;
854 _writeToStream = false; 927 _writeToStream = false;
855 WriteHeader(db, /* headerOptions, */ headerOffset); 928 WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset);
856 929
857 if (_countSize != _outByte2.GetPos()) 930 if (_countSize != _outByte2.GetPos())
858 return E_FAIL; 931 return E_FAIL;
@@ -876,15 +949,17 @@ HRESULT COutArchive::WriteDatabase(
876 throw 1; 949 throw 1;
877 950
878 WriteID(NID::kEncodedHeader); 951 WriteID(NID::kEncodedHeader);
879 WritePackInfo(headerOffset, packSizes, CUInt32DefVector()); 952 WritePackInfo(sh.NextHeaderOffset, packSizes, CUInt32DefVector());
880 WriteUnpackInfo(folders, outFolders); 953 WriteUnpackInfo(folders, outFolders);
881 WriteByte(NID::kEnd); 954 WriteByte(NID::kEnd);
882 FOR_VECTOR (i, packSizes) 955
883 headerOffset += packSizes[i]; 956 sh.NextHeaderOffset += UInt64Vector_CountSum(packSizes);
884 } 957 }
885 RINOK(_outByte.Flush()) 958 RINOK(_outByte.Flush())
886 headerCRC = CRC_GET_DIGEST(_crc); 959 sh.NextHeaderCRC = crcStream->GetCRC();
887 headerSize = _outByte.GetProcessedSize(); 960 // sh.NextHeaderCRC = CRC_GET_DIGEST(_crc);
961 // if (CRC_GET_DIGEST(_crc) != sh.NextHeaderCRC) throw 1;
962 sh.NextHeaderSize = _outByte.GetProcessedSize();
888 } 963 }
889 #ifdef Z7_7Z_VOL 964 #ifdef Z7_7Z_VOL
890 if (_endMarker) 965 if (_endMarker)
@@ -904,12 +979,8 @@ HRESULT COutArchive::WriteDatabase(
904 #endif 979 #endif
905 if (Stream) 980 if (Stream)
906 { 981 {
907 CStartHeader h;
908 h.NextHeaderSize = headerSize;
909 h.NextHeaderCRC = headerCRC;
910 h.NextHeaderOffset = headerOffset;
911 RINOK(Stream->Seek((Int64)_signatureHeaderPos, STREAM_SEEK_SET, NULL)) 982 RINOK(Stream->Seek((Int64)_signatureHeaderPos, STREAM_SEEK_SET, NULL))
912 return WriteStartHeader(h); 983 return WriteStartHeader(sh);
913 } 984 }
914 return S_OK; 985 return S_OK;
915} 986}
diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h
index 940cafc..c65d268 100644
--- a/CPP/7zip/Archive/7z/7zOut.h
+++ b/CPP/7zip/Archive/7z/7zOut.h
@@ -19,32 +19,41 @@ const unsigned k_StartHeadersRewriteSize = 32;
19class CWriteBufferLoc 19class CWriteBufferLoc
20{ 20{
21 Byte *_data; 21 Byte *_data;
22 size_t _size; 22 Byte *_dataLim;
23 size_t _pos; 23 Byte *_dataBase;
24public: 24public:
25 CWriteBufferLoc(): _size(0), _pos(0) {} 25 // CWriteBufferLoc(): _data(NULL), _dataLim(NULL), _dataBase(NULL) {}
26 void Init(Byte *data, size_t size) 26 void Init(Byte *data, size_t size)
27 { 27 {
28 _data = data; 28 _data = data;
29 _size = size; 29 _dataBase = data;
30 _pos = 0; 30 _dataLim = data + size;
31 }
32
33 Byte *GetDest_and_Update(size_t size)
34 {
35 Byte *dest = _data;
36 if (size > (size_t)(_dataLim - dest))
37 throw 1;
38 _data = dest + size;
39 return dest;
31 } 40 }
32 void WriteBytes(const void *data, size_t size) 41 void WriteBytes(const void *data, size_t size)
33 { 42 {
34 if (size == 0) 43 if (size == 0)
35 return; 44 return;
36 if (size > _size - _pos) 45 Byte *dest = GetDest_and_Update(size);
37 throw 1; 46 memcpy(dest, data, size);
38 memcpy(_data + _pos, data, size);
39 _pos += size;
40 } 47 }
41 void WriteByte(Byte b) 48 void WriteByte(Byte b)
42 { 49 {
43 if (_size == _pos) 50 Byte *dest = _data;
51 if (dest == _dataLim)
44 throw 1; 52 throw 1;
45 _data[_pos++] = b; 53 *dest++ = b;
54 _data = dest;
46 } 55 }
47 size_t GetPos() const { return _pos; } 56 size_t GetPos() const { return (size_t)(_data - _dataBase); }
48}; 57};
49 58
50 59
@@ -248,14 +257,20 @@ class COutArchive
248 void WriteBytes(const void *data, size_t size); 257 void WriteBytes(const void *data, size_t size);
249 void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); } 258 void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); }
250 void WriteByte(Byte b); 259 void WriteByte(Byte b);
251 void WriteUInt32(UInt32 value); 260 void WriteByte_ToStream(Byte b)
252 void WriteUInt64(UInt64 value); 261 {
262 _outByte.WriteByte(b);
263 // _crc = CRC_UPDATE_BYTE(_crc, b);
264 }
265 // void WriteUInt32(UInt32 value);
266 // void WriteUInt64(UInt64 value);
253 void WriteNumber(UInt64 value); 267 void WriteNumber(UInt64 value);
254 void WriteID(UInt64 value) { WriteNumber(value); } 268 void WriteID(UInt64 value) { WriteNumber(value); }
255 269
256 void WriteFolder(const CFolder &folder); 270 void WriteFolder(const CFolder &folder);
257 HRESULT WriteFileHeader(const CFileItem &itemInfo); 271 HRESULT WriteFileHeader(const CFileItem &itemInfo);
258 void WriteBoolVector(const CBoolVector &boolVector); 272 void Write_BoolVector(const CBoolVector &boolVector);
273 void Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined);
259 void WritePropBoolVector(Byte id, const CBoolVector &boolVector); 274 void WritePropBoolVector(Byte id, const CBoolVector &boolVector);
260 275
261 void WriteHashDigests(const CUInt32DefVector &digests); 276 void WriteHashDigests(const CUInt32DefVector &digests);
@@ -277,7 +292,8 @@ class COutArchive
277 292
278 void SkipToAligned(unsigned pos, unsigned alignShifts); 293 void SkipToAligned(unsigned pos, unsigned alignShifts);
279 void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts); 294 void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts);
280 void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); 295 void Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined);
296 void Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type);
281 297
282 HRESULT EncodeStream( 298 HRESULT EncodeStream(
283 DECL_EXTERNAL_CODECS_LOC_VARS 299 DECL_EXTERNAL_CODECS_LOC_VARS
@@ -294,7 +310,7 @@ class COutArchive
294 #ifdef Z7_7Z_VOL 310 #ifdef Z7_7Z_VOL
295 bool _endMarker; 311 bool _endMarker;
296 #endif 312 #endif
297 UInt32 _crc; 313 // UInt32 _crc;
298 size_t _countSize; 314 size_t _countSize;
299 CWriteBufferLoc _outByte2; 315 CWriteBufferLoc _outByte2;
300 COutBuffer _outByte; 316 COutBuffer _outByte;
@@ -310,7 +326,7 @@ class COutArchive
310public: 326public:
311 CMyComPtr<ISequentialOutStream> SeqStream; 327 CMyComPtr<ISequentialOutStream> SeqStream;
312 328
313 COutArchive() { _outByte.Create(1 << 16); } 329 // COutArchive();
314 HRESULT Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */); 330 HRESULT Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */);
315 void Close(); 331 void Close();
316 HRESULT WriteDatabase( 332 HRESULT WriteDatabase(
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index 4e9ea5d..d374a00 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -33,7 +33,7 @@ struct CFilterMode
33 UInt32 Id; 33 UInt32 Id;
34 UInt32 Delta; // required File Size alignment, if Id is not k_Delta. 34 UInt32 Delta; // required File Size alignment, if Id is not k_Delta.
35 // (Delta == 0) means unknown alignment 35 // (Delta == 0) means unknown alignment
36 UInt32 Offset; // for k_ARM64 36 UInt32 Offset; // for k_ARM64 / k_RISCV
37 // UInt32 AlignSizeOpt; // for k_ARM64 37 // UInt32 AlignSizeOpt; // for k_ARM64
38 38
39 CFilterMode(): 39 CFilterMode():
@@ -59,7 +59,7 @@ struct CFilterMode
59 Delta = 16; 59 Delta = 16;
60 else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC) 60 else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC)
61 Delta = 4; 61 Delta = 4;
62 else if (Id == k_ARMT) 62 else if (Id == k_ARMT || Id == k_RISCV)
63 Delta = 2; 63 Delta = 2;
64 else if (Id == k_BCJ || Id == k_BCJ2) 64 else if (Id == k_BCJ || Id == k_BCJ2)
65 Delta = 1; // do we need it? 65 Delta = 1; // do we need it?
@@ -95,7 +95,9 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
95 return 0; 95 return 0;
96 p += 4; 96 p += 4;
97 97
98 switch (GetUi16(p)) 98 const unsigned machine = GetUi16(p);
99
100 switch (machine)
99 { 101 {
100 case 0x014C: 102 case 0x014C:
101 case 0x8664: filterId = k_X86; break; 103 case 0x8664: filterId = k_X86; break;
@@ -112,11 +114,16 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
112 case 0x01C2: filterId = k_ARM; break; // WinCE new 114 case 0x01C2: filterId = k_ARM; break; // WinCE new
113 case 0x01C4: filterId = k_ARMT; break; // WinRT 115 case 0x01C4: filterId = k_ARMT; break; // WinRT
114 116
117 case 0x5032: // RISCV32
118 case 0x5064: // RISCV64
119 // case 0x5128: // RISCV128
120 filterId = k_RISCV; break;
121
115 case 0x0200: filterId = k_IA64; break; 122 case 0x0200: filterId = k_IA64; break;
116 default: return 0; 123 default: return 0;
117 } 124 }
118 125
119 // const UInt32 numSections = GetUi16(p + 2); 126 const UInt32 numSections = GetUi16(p + 2);
120 optHeaderSize = GetUi16(p + 16); 127 optHeaderSize = GetUi16(p + 16);
121 if (optHeaderSize > (1 << 10)) 128 if (optHeaderSize > (1 << 10))
122 return 0; 129 return 0;
@@ -132,34 +139,49 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
132 return 0; 139 return 0;
133 } 140 }
134 141
135 /*
136 // Windows exe file sizes are not aligned for 4 KiB. 142 // Windows exe file sizes are not aligned for 4 KiB.
137 // So we can't use (CFilterMode::Offset != 0) in solid archives. 143 // So we can't use (CFilterMode::Offset != 0) in solid archives.
138 // So we just don't set Offset here. 144 // So we just don't set Offset here.
139#define NUM_SCAN_SECTIONS_MAX (1 << 6) 145#define NUM_SCAN_SECTIONS_MAX (1 << 6)
140#define EXE_SECTION_OFFSET_MAX (1 << 27) 146// #define EXE_SECTION_OFFSET_MAX (1 << 27)
141#define EXE_SECTION_SIZE_MIN (1 << 8) 147// #define EXE_SECTION_SIZE_MIN (1 << 8)
142#define EXE_SECTION_SIZE_MAX (1 << 27) 148// #define EXE_SECTION_SIZE_MAX (1 << 27)
143#define PE_SectHeaderSize 40 149#define PE_SectHeaderSize 40
144#define PE_SECT_EXECUTE 0x20000000 150// #define PE_SECT_EXECUTE 0x20000000
145 151
152/*
146 if (numSections > NUM_SCAN_SECTIONS_MAX) 153 if (numSections > NUM_SCAN_SECTIONS_MAX)
147 return 0; 154 return 0;
155*/
148 156
157 if ((size_t)(p - buf) + optHeaderSize <= size)
158 {
149 p += optHeaderSize; 159 p += optHeaderSize;
160/*
150 // UInt32 numExeSections = 0; 161 // UInt32 numExeSections = 0;
151 // bool execute_finded = false; 162 // bool execute_finded = false;
152 // UInt32 sect_va = 0; 163 // UInt32 sect_va = 0;
153 // UInt32 sect_size = 0; 164 // UInt32 sect_size = 0;
154 // UInt32 sect_offset = 0; 165 // UInt32 sect_offset = 0;
155 166*/
167 if (numSections <= NUM_SCAN_SECTIONS_MAX)
168 if (machine == 0x8664)
156 for (UInt32 i = 0; i < numSections 169 for (UInt32 i = 0; i < numSections
157 // && numExeSections < numSectionsMax
158 ; i++, p += PE_SectHeaderSize) 170 ; i++, p += PE_SectHeaderSize)
159 { 171 {
160 UInt32 characts, rawSize, offset; 172 // UInt32 characts, rawSize, offset;
161 if ((UInt32)(p - buf) + PE_SectHeaderSize > size) 173 if ((UInt32)(p - buf) + PE_SectHeaderSize > size)
162 return 0; 174 {
175 // return 0;
176 break;
177 }
178 if (memcmp(p, ".a64xrm", 8) == 0)
179 {
180 // ARM64EC
181 filterId = k_ARM64;
182 break;
183 }
184/*
163 rawSize = GetUi32(p + 16); 185 rawSize = GetUi32(p + 16);
164 offset = GetUi32(p + 20); 186 offset = GetUi32(p + 20);
165 characts = GetUi32(p + 36); 187 characts = GetUi32(p + 36);
@@ -178,8 +200,11 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
178 break; 200 break;
179 } 201 }
180 } 202 }
203*/
204 }
181 } 205 }
182 206
207 /*
183 filterMode->Offset = 0; 208 filterMode->Offset = 0;
184 if (filterId == k_ARM64) 209 if (filterId == k_ARM64)
185 { 210 {
@@ -243,8 +268,9 @@ static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode)
243 case 43: filterId = k_SPARC; break; 268 case 43: filterId = k_SPARC; break;
244 case 20: 269 case 20:
245 case 21: if (!be) return 0; filterId = k_PPC; break; 270 case 21: if (!be) return 0; filterId = k_PPC; break;
246 case 40: if ( be) return 0; filterId = k_ARM; break; 271 case 40: if (be) return 0; filterId = k_ARM; break;
247 case 183: if (be) return 0; filterId = k_ARM64; break; 272 case 183: if (be) return 0; filterId = k_ARM64; break;
273 case 243: if (be) return 0; filterId = k_RISCV; break;
248 274
249 /* Some IA-64 ELF executables have size that is not aligned for 16 bytes. 275 /* Some IA-64 ELF executables have size that is not aligned for 16 bytes.
250 So we don't use IA-64 filter for IA-64 ELF */ 276 So we don't use IA-64 filter for IA-64 ELF */
@@ -482,6 +508,7 @@ static inline bool IsExeFilter(CMethodId m)
482 switch (m) 508 switch (m)
483 { 509 {
484 case k_ARM64: 510 case k_ARM64:
511 case k_RISCV:
485 case k_BCJ: 512 case k_BCJ:
486 case k_BCJ2: 513 case k_BCJ2:
487 case k_ARM: 514 case k_ARM:
@@ -490,6 +517,7 @@ static inline bool IsExeFilter(CMethodId m)
490 case k_SPARC: 517 case k_SPARC:
491 case k_IA64: 518 case k_IA64:
492 return true; 519 return true;
520 default: break;
493 } 521 }
494 return false; 522 return false;
495} 523}
@@ -521,7 +549,8 @@ static unsigned Get_FilterGroup_for_Folder(
521 if (m.Id == k_BCJ2) 549 if (m.Id == k_BCJ2)
522 m.Id = k_BCJ; 550 m.Id = k_BCJ;
523 m.SetDelta(); 551 m.SetDelta();
524 if (m.Id == k_ARM64) 552 if (m.Id == k_ARM64 ||
553 m.Id == k_RISCV)
525 if (coder.Props.Size() == 4) 554 if (coder.Props.Size() == 4)
526 m.Offset = GetUi32(coder.Props); 555 m.Offset = GetUi32(coder.Props);
527 } 556 }
@@ -537,15 +566,12 @@ static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
537 UInt64 position, UInt64 size, ICompressProgressInfo *progress) 566 UInt64 position, UInt64 size, ICompressProgressInfo *progress)
538{ 567{
539 RINOK(InStream_SeekSet(inStream, position)) 568 RINOK(InStream_SeekSet(inStream, position))
540 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 569 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> streamSpec;
541 CMyComPtr<ISequentialInStream> inStreamLimited(streamSpec);
542 streamSpec->SetStream(inStream); 570 streamSpec->SetStream(inStream);
543 streamSpec->Init(size); 571 streamSpec->Init(size);
544 572 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
545 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 573 RINOK(copyCoder.Interface()->Code(streamSpec, outStream, NULL, NULL, progress))
546 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 574 return (copyCoder->TotalSize == size ? S_OK : E_FAIL);
547 RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress))
548 return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);
549} 575}
550 576
551/* 577/*
@@ -759,9 +785,9 @@ struct CRefItem
759 { 785 {
760 if (sortByType) 786 if (sortByType)
761 { 787 {
762 int slashPos = ui.Name.ReverseFind_PathSepar(); 788 const int slashPos = ui.Name.ReverseFind_PathSepar();
763 NamePos = (unsigned)(slashPos + 1); 789 NamePos = (unsigned)(slashPos + 1);
764 int dotPos = ui.Name.ReverseFind_Dot(); 790 const int dotPos = ui.Name.ReverseFind_Dot();
765 if (dotPos <= slashPos) 791 if (dotPos <= slashPos)
766 ExtensionPos = ui.Name.Len(); 792 ExtensionPos = ui.Name.Len();
767 else 793 else
@@ -772,7 +798,7 @@ struct CRefItem
772 AString s; 798 AString s;
773 for (unsigned pos = ExtensionPos;; pos++) 799 for (unsigned pos = ExtensionPos;; pos++)
774 { 800 {
775 wchar_t c = ui.Name[pos]; 801 const wchar_t c = ui.Name[pos];
776 if (c >= 0x80) 802 if (c >= 0x80)
777 break; 803 break;
778 if (c == 0) 804 if (c == 0)
@@ -780,7 +806,7 @@ struct CRefItem
780 ExtensionIndex = GetExtIndex(s); 806 ExtensionIndex = GetExtIndex(s);
781 break; 807 break;
782 } 808 }
783 s += (char)MyCharLower_Ascii((char)c); 809 s.Add_Char((char)MyCharLower_Ascii((char)c));
784 } 810 }
785 } 811 }
786 } 812 }
@@ -1123,6 +1149,12 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo
1123 #ifdef MY_CPU_ARM64 1149 #ifdef MY_CPU_ARM64
1124 filterModeTemp.Id = k_ARM64; 1150 filterModeTemp.Id = k_ARM64;
1125 #endif 1151 #endif
1152 #ifdef MY_CPU_RISCV
1153 filterModeTemp.Id = k_RISCV;
1154 #endif
1155 #ifdef MY_CPU_SPARC
1156 filterModeTemp.Id = k_SPARC;
1157 #endif
1126 parseRes = true; 1158 parseRes = true;
1127 } 1159 }
1128 1160
@@ -1172,6 +1204,8 @@ static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull
1172 m.NumStreams = numStreams; 1204 m.NumStreams = numStreams;
1173} 1205}
1174 1206
1207
1208// we add bond for mode.Methods[0] that is filter
1175static HRESULT AddBondForFilter(CCompressionMethodMode &mode) 1209static HRESULT AddBondForFilter(CCompressionMethodMode &mode)
1176{ 1210{
1177 for (unsigned c = 1; c < mode.Methods.Size(); c++) 1211 for (unsigned c = 1; c < mode.Methods.Size(); c++)
@@ -1189,16 +1223,19 @@ static HRESULT AddBondForFilter(CCompressionMethodMode &mode)
1189 return E_INVALIDARG; 1223 return E_INVALIDARG;
1190} 1224}
1191 1225
1192static HRESULT AddFilterBond(CCompressionMethodMode &mode) 1226/*
1227static HRESULT AddBondForFilter_if_ThereAreBonds(CCompressionMethodMode &mode)
1193{ 1228{
1194 if (!mode.Bonds.IsEmpty()) 1229 if (!mode.Bonds.IsEmpty())
1195 return AddBondForFilter(mode); 1230 return AddBondForFilter(mode);
1196 return S_OK; 1231 return S_OK;
1197} 1232}
1233*/
1198 1234
1199static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) 1235static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
1200{ 1236{
1201 // mode.Methods[0] must be k_BCJ2 method ! 1237 // mode.Methods[0] must be k_BCJ2 method !
1238 // mode.Methods[1] : we expect that there is at least one method after BCJ2
1202 1239
1203 CMethodFull m; 1240 CMethodFull m;
1204 GetMethodFull(k_LZMA, 1, m); 1241 GetMethodFull(k_LZMA, 1, m);
@@ -1210,7 +1247,7 @@ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
1210 m.AddProp32(NCoderPropID::kLitContextBits, 0); 1247 m.AddProp32(NCoderPropID::kLitContextBits, 0);
1211 // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2"); 1248 // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2");
1212 1249
1213 unsigned methodIndex = mode.Methods.Size(); 1250 const unsigned methodIndex = mode.Methods.Size();
1214 1251
1215 if (mode.Bonds.IsEmpty()) 1252 if (mode.Bonds.IsEmpty())
1216 { 1253 {
@@ -1229,109 +1266,140 @@ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
1229 1266
1230 RINOK(AddBondForFilter(mode)) 1267 RINOK(AddBondForFilter(mode))
1231 CBond2 bond; 1268 CBond2 bond;
1232 bond.OutCoder = 0; 1269 bond.OutCoder = 0; // index of BCJ2 coder
1233 bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond); 1270 bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond);
1234 bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond); 1271 bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond);
1235 return S_OK; 1272 return S_OK;
1236} 1273}
1237 1274
1275
1238static HRESULT MakeExeMethod(CCompressionMethodMode &mode, 1276static HRESULT MakeExeMethod(CCompressionMethodMode &mode,
1239 const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter) 1277 const CFilterMode &filterMode,
1278 const bool bcj2_IsAllowed,
1279 const CUIntVector &disabledFilterIDs)
1240{ 1280{
1241 if (mode.Filter_was_Inserted) 1281 if (mode.Filter_was_Inserted)
1242 { 1282 {
1283 // filter was inserted, but bond for that filter was not added still.
1243 const CMethodFull &m = mode.Methods[0]; 1284 const CMethodFull &m = mode.Methods[0];
1244 const CMethodId id = m.Id; 1285 if (m.Id == k_BCJ2)
1245 if (id == k_BCJ2)
1246 return AddBcj2Methods(mode); 1286 return AddBcj2Methods(mode);
1247 if (!m.IsSimpleCoder()) 1287 if (!m.IsSimpleCoder())
1248 return E_NOTIMPL; 1288 return E_NOTIMPL;
1249 // if (Bonds.IsEmpty()) we can create bonds later 1289 if (mode.Bonds.IsEmpty())
1250 return AddFilterBond(mode); 1290 return S_OK;
1291 return AddBondForFilter(mode);
1251 } 1292 }
1252 1293
1253 if (filterMode.Id == 0) 1294 if (filterMode.Id == 0)
1254 return S_OK; 1295 return S_OK;
1255 1296
1256 CMethodFull &m = mode.Methods.InsertNew(0); 1297 unsigned nextCoder;
1257 1298
1258 { 1299 const bool useBcj2 = bcj2_IsAllowed
1259 FOR_VECTOR (k, mode.Bonds) 1300 && Is86Filter(filterMode.Id)
1260 { 1301 && disabledFilterIDs.FindInSorted(k_BCJ2) < 0;
1261 CBond2 &bond = mode.Bonds[k];
1262 bond.InCoder++;
1263 bond.OutCoder++;
1264 }
1265 }
1266 1302
1267 HRESULT res; 1303 if (!useBcj2 && disabledFilterIDs.FindInSorted(filterMode.Id) >= 0)
1268
1269 if (bcj2Filter && Is86Filter(filterMode.Id))
1270 { 1304 {
1271 GetMethodFull(k_BCJ2, 4, m); 1305 // required filter is disabled,
1272 res = AddBcj2Methods(mode); 1306 // but we still can use information about data alignment.
1307#if 0 // 1 for debug
1308 // we can return here, if we want default lzma properties
1309 return S_OK;
1310#else
1311 // we will try to change lzma/lzma2 properties
1312 nextCoder = 0;
1313 if (!mode.Bonds.IsEmpty())
1314 for (unsigned c = 0;; c++)
1315 {
1316 if (c == mode.Methods.Size())
1317 return S_OK;
1318 if (!mode.IsThereBond_to_Coder(c))
1319 {
1320 nextCoder = c;
1321 break;
1322 }
1323 }
1324#endif
1273 } 1325 }
1274 else 1326 else
1275 { 1327 {
1328 // we insert new filter method:
1329 CMethodFull &m = mode.Methods.InsertNew(0); // 0 == index of new inserted item
1330 {
1331 // we move all coder indexes in bonds up for 1 position:
1332 FOR_VECTOR (k, mode.Bonds)
1333 {
1334 CBond2 &bond = mode.Bonds[k];
1335 bond.InCoder++;
1336 bond.OutCoder++;
1337 }
1338 }
1339 if (useBcj2)
1340 {
1341 GetMethodFull(k_BCJ2, 4, m);
1342 return AddBcj2Methods(mode);
1343 }
1344
1276 GetMethodFull(filterMode.Id, 1, m); 1345 GetMethodFull(filterMode.Id, 1, m);
1346
1277 if (filterMode.Id == k_Delta) 1347 if (filterMode.Id == k_Delta)
1278 m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta); 1348 m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta);
1279 else if (filterMode.Id == k_ARM64) 1349 else if (filterMode.Id == k_ARM64
1350 || filterMode.Id == k_RISCV)
1280 { 1351 {
1281 // if (filterMode.Offset != 0) 1352 // if (filterMode.Offset != 0)
1282 m.AddProp32( 1353 m.AddProp32(
1283 NCoderPropID::kDefaultProp, 1354 NCoderPropID::kDefaultProp,
1284 // NCoderPropID::kBranchOffset, 1355 // NCoderPropID::kBranchOffset,
1285 filterMode.Offset); 1356 filterMode.Offset);
1286 } 1357 }
1287 res = AddFilterBond(mode); 1358
1288 1359 nextCoder = 1;
1289 int alignBits = -1; 1360 if (!mode.Bonds.IsEmpty())
1290 { 1361 {
1291 const UInt32 delta = filterMode.Delta; 1362 RINOK(AddBondForFilter(mode))
1292 if (delta == 0 || delta > 16) 1363 nextCoder = mode.Bonds.Back().InCoder;
1293 {
1294 // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id);
1295 }
1296 else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4;
1297 else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3;
1298 else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2;
1299 else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1;
1300 // else alignBits = 0;
1301 /* alignBits=0 is default mode for lzma/lzma2.
1302 So we don't set alignBits=0 here. */
1303 } 1364 }
1304 if (res == S_OK && alignBits > 0) 1365 }
1366
1367 if (nextCoder >= mode.Methods.Size())
1368 {
1369 // we don't expect that case, if there was non-filter method.
1370 // but we return S_OK to support filter-only case.
1371 return S_OK;
1372 }
1373
1374 int alignBits = -1;
1375 {
1376 const UInt32 delta = filterMode.Delta;
1377 if (delta == 0 || delta > 16)
1305 { 1378 {
1306 unsigned nextCoder = 1; 1379 // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id);
1307 if (!mode.Bonds.IsEmpty())
1308 {
1309 nextCoder = mode.Bonds.Back().InCoder;
1310 }
1311 if (nextCoder < mode.Methods.Size())
1312 {
1313 CMethodFull &nextMethod = mode.Methods[nextCoder];
1314 if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2)
1315 {
1316 if (!nextMethod.Are_Lzma_Model_Props_Defined())
1317 {
1318 if (alignBits != 0)
1319 {
1320 if (alignBits > 2 || filterMode.Id == k_Delta)
1321 nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits);
1322 unsigned lc = 0;
1323 if (alignBits < 3)
1324 lc = (unsigned)(3 - alignBits);
1325 nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);
1326 nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits);
1327 }
1328 }
1329 }
1330 }
1331 } 1380 }
1381 else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4;
1382 else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3;
1383 else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2;
1384 else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1;
1385 // else alignBits = 0;
1386 /* alignBits=0 is default mode for lzma/lzma2.
1387 So we don't set alignBits=0 here. */
1332 } 1388 }
1333 1389 if (alignBits <= 0)
1334 return res; 1390 return S_OK;
1391 // (alignBits > 0)
1392 CMethodFull &nextMethod = mode.Methods[nextCoder];
1393 if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2)
1394 if (!nextMethod.Are_Lzma_Model_Props_Defined())
1395 {
1396 if (alignBits > 2 || filterMode.Id == k_Delta)
1397 nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits);
1398 const unsigned lc = (alignBits < 3) ? (unsigned)(3 - alignBits) : 0u;
1399 nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);
1400 nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits);
1401 }
1402 return S_OK;
1335} 1403}
1336 1404
1337 1405
@@ -1859,6 +1927,7 @@ HRESULT Update(
1859 1927
1860 CIntArr fileIndexToUpdateIndexMap; 1928 CIntArr fileIndexToUpdateIndexMap;
1861 UInt64 complexity = 0; 1929 UInt64 complexity = 0;
1930 bool isThere_UnknownSize = false;
1862 UInt64 inSizeForReduce2 = 0; 1931 UInt64 inSizeForReduce2 = 0;
1863 1932
1864 #ifndef Z7_NO_CRYPTO 1933 #ifndef Z7_NO_CRYPTO
@@ -1971,28 +2040,36 @@ HRESULT Update(
1971 2040
1972 UInt64 inSizeForReduce = 0; 2041 UInt64 inSizeForReduce = 0;
1973 { 2042 {
1974 bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0); 2043 const bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0);
1975 FOR_VECTOR (i, updateItems) 2044 FOR_VECTOR (i, updateItems)
1976 { 2045 {
1977 const CUpdateItem &ui = updateItems[i]; 2046 const CUpdateItem &ui = updateItems[i];
1978 if (ui.NewData) 2047 if (ui.NewData)
1979 { 2048 {
1980 complexity += ui.Size; 2049 if (ui.Size == (UInt64)(Int64)-1)
1981 if (isSolid) 2050 isThere_UnknownSize = true;
1982 inSizeForReduce += ui.Size; 2051 else
1983 else if (inSizeForReduce < ui.Size) 2052 {
1984 inSizeForReduce = ui.Size; 2053 complexity += ui.Size;
2054 if (isSolid)
2055 inSizeForReduce += ui.Size;
2056 else if (inSizeForReduce < ui.Size)
2057 inSizeForReduce = ui.Size;
2058 }
1985 } 2059 }
1986 } 2060 }
1987 } 2061 }
1988 2062
2063 if (isThere_UnknownSize)
2064 inSizeForReduce = (UInt64)(Int64)-1;
2065 else
2066 RINOK(updateCallback->SetTotal(complexity))
2067
1989 if (inSizeForReduce < inSizeForReduce2) 2068 if (inSizeForReduce < inSizeForReduce2)
1990 inSizeForReduce = inSizeForReduce2; 2069 inSizeForReduce = inSizeForReduce2;
1991 2070
1992 RINOK(updateCallback->SetTotal(complexity))
1993 2071
1994 CLocalProgress *lps = new CLocalProgress; 2072 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1995 CMyComPtr<ICompressProgressInfo> progress = lps;
1996 lps->Init(updateCallback, true); 2073 lps->Init(updateCallback, true);
1997 2074
1998 #ifndef Z7_ST 2075 #ifndef Z7_ST
@@ -2232,12 +2309,13 @@ HRESULT Update(
2232 CCompressionMethodMode method = *options.Method; 2309 CCompressionMethodMode method = *options.Method;
2233 { 2310 {
2234 const HRESULT res = MakeExeMethod(method, filterMode, 2311 const HRESULT res = MakeExeMethod(method, filterMode,
2312 // bcj2_IsAllowed:
2235 #ifdef Z7_ST 2313 #ifdef Z7_ST
2236 false 2314 false
2237 #else 2315 #else
2238 options.MaxFilter && options.MultiThreadMixer 2316 options.MaxFilter && options.MultiThreadMixer
2239 #endif 2317 #endif
2240 ); 2318 , options.DisabledFilterIDs);
2241 2319
2242 RINOK(res) 2320 RINOK(res)
2243 } 2321 }
@@ -2299,7 +2377,7 @@ HRESULT Update(
2299 2377
2300 const UInt64 packSize = db->GetFolderFullPackSize(folderIndex); 2378 const UInt64 packSize = db->GetFolderFullPackSize(folderIndex);
2301 RINOK(WriteRange(inStream, archive.SeqStream, 2379 RINOK(WriteRange(inStream, archive.SeqStream,
2302 db->GetFolderStreamPos(folderIndex, 0), packSize, progress)) 2380 db->GetFolderStreamPos(folderIndex, 0), packSize, lps))
2303 lps->ProgressOffset += packSize; 2381 lps->ProgressOffset += packSize;
2304 2382
2305 const unsigned folderIndex_New = newDatabase.Folders.Size(); 2383 const unsigned folderIndex_New = newDatabase.Folders.Size();
@@ -2321,7 +2399,7 @@ HRESULT Update(
2321 size_t indexStart = db->FoToCoderUnpackSizes[folderIndex]; 2399 size_t indexStart = db->FoToCoderUnpackSizes[folderIndex];
2322 const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; 2400 const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];
2323 for (; indexStart < indexEnd; indexStart++) 2401 for (; indexStart < indexEnd; indexStart++)
2324 newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]); 2402 newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes.ConstData()[indexStart]);
2325 } 2403 }
2326 else 2404 else
2327 { 2405 {
@@ -2481,7 +2559,7 @@ HRESULT Update(
2481 sizeToEncode, // expectedDataSize 2559 sizeToEncode, // expectedDataSize
2482 newDatabase.Folders.AddNew(), 2560 newDatabase.Folders.AddNew(),
2483 // newDatabase.CoderUnpackSizes, curUnpackSize, 2561 // newDatabase.CoderUnpackSizes, curUnpackSize,
2484 archive.SeqStream, newDatabase.PackSizes, progress); 2562 archive.SeqStream, newDatabase.PackSizes, lps);
2485 2563
2486 if (encodeRes == k_My_HRESULT_CRC_ERROR) 2564 if (encodeRes == k_My_HRESULT_CRC_ERROR)
2487 return E_FAIL; 2565 return E_FAIL;
@@ -2680,8 +2758,7 @@ HRESULT Update(
2680 */ 2758 */
2681 2759
2682 2760
2683 CFolderInStream *inStreamSpec = new CFolderInStream; 2761 CMyComPtr2_Create<ISequentialInStream, CFolderInStream> inStreamSpec; // solidInStream;
2684 CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
2685 2762
2686 // inStreamSpec->_reportArcProp = reportArcProp; 2763 // inStreamSpec->_reportArcProp = reportArcProp;
2687 2764
@@ -2702,13 +2779,13 @@ HRESULT Update(
2702 2779
2703 RINOK(encoder.Encode1( 2780 RINOK(encoder.Encode1(
2704 EXTERNAL_CODECS_LOC_VARS 2781 EXTERNAL_CODECS_LOC_VARS
2705 solidInStream, 2782 inStreamSpec,
2706 // NULL, 2783 // NULL,
2707 &inSizeForReduce, 2784 &inSizeForReduce,
2708 expectedDataSize, // expected size 2785 expectedDataSize, // expected size
2709 newDatabase.Folders.AddNew(), 2786 newDatabase.Folders.AddNew(),
2710 // newDatabase.CoderUnpackSizes, curFolderUnpackSize, 2787 // newDatabase.CoderUnpackSizes, curFolderUnpackSize,
2711 archive.SeqStream, newDatabase.PackSizes, progress)) 2788 archive.SeqStream, newDatabase.PackSizes, lps))
2712 2789
2713 if (!inStreamSpec->WasFinished()) 2790 if (!inStreamSpec->WasFinished())
2714 return E_FAIL; 2791 return E_FAIL;
@@ -2970,7 +3047,7 @@ HRESULT Update(
2970 if (newDatabase.NumUnpackStreamsVector.Size() != numFolders 3047 if (newDatabase.NumUnpackStreamsVector.Size() != numFolders
2971 || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders) 3048 || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders)
2972 return E_FAIL; 3049 return E_FAIL;
2973 newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResedue_with_false(numFolders); 3050 newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResidue_with_false(numFolders);
2974 } 3051 }
2975 3052
2976 updateItems.ClearAndFree(); 3053 updateItems.ClearAndFree();
diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h
index de4117a..83a2774 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.h
+++ b/CPP/7zip/Archive/7z/7zUpdate.h
@@ -111,6 +111,25 @@ struct CUpdateOptions
111 111
112 CHeaderOptions HeaderOptions; 112 CHeaderOptions HeaderOptions;
113 113
114 CUIntVector DisabledFilterIDs;
115
116 void Add_DisabledFilter_for_id(UInt32 id,
117 const CUIntVector &enabledFilters)
118 {
119 if (enabledFilters.FindInSorted(id) < 0)
120 DisabledFilterIDs.AddToUniqueSorted(id);
121 }
122
123 void SetFilterSupporting_ver_enabled_disabled(
124 UInt32 compatVer,
125 const CUIntVector &enabledFilters,
126 const CUIntVector &disabledFilters)
127 {
128 DisabledFilterIDs = disabledFilters;
129 if (compatVer < 2300) Add_DisabledFilter_for_id(k_ARM64, enabledFilters);
130 if (compatVer < 2402) Add_DisabledFilter_for_id(k_RISCV, enabledFilters);
131 }
132
114 CUpdateOptions(): 133 CUpdateOptions():
115 Method(NULL), 134 Method(NULL),
116 HeaderMethod(NULL), 135 HeaderMethod(NULL),
@@ -128,7 +147,9 @@ struct CUpdateOptions
128 Need_MTime(false), 147 Need_MTime(false),
129 Need_Attrib(false) 148 Need_Attrib(false)
130 // , Need_Crc(true) 149 // , Need_Crc(true)
131 {} 150 {
151 DisabledFilterIDs.Add(k_RISCV);
152 }
132}; 153};
133 154
134HRESULT Update( 155HRESULT Update(
diff --git a/CPP/7zip/Archive/ApfsHandler.cpp b/CPP/7zip/Archive/ApfsHandler.cpp
index 5fb7e0a..62b00ed 100644
--- a/CPP/7zip/Archive/ApfsHandler.cpp
+++ b/CPP/7zip/Archive/ApfsHandler.cpp
@@ -54,31 +54,18 @@
54namespace NArchive { 54namespace NArchive {
55namespace NApfs { 55namespace NApfs {
56 56
57#define ValToHex(t) ((char)(((t) < 10) ? ('0' + (t)) : ('a' + ((t) - 10))))
58
59static void ConvertByteToHex(unsigned val, char *s)
60{
61 unsigned t;
62 t = val >> 4;
63 s[0] = ValToHex(t);
64 t = val & 0xF;
65 s[1] = ValToHex(t);
66}
67
68struct CUuid 57struct CUuid
69{ 58{
70 Byte Data[16]; 59 Byte Data[16];
71 60
72 void SetHex_To_str(char *s) const 61 void SetHex_To_str(char *s) const
73 { 62 {
74 for (unsigned i = 0; i < 16; i++) 63 ConvertDataToHex_Lower(s, Data, sizeof(Data));
75 ConvertByteToHex(Data[i], s + i * 2);
76 s[32] = 0;
77 } 64 }
78 65
79 void AddHexToString(UString &dest) const 66 void AddHexToString(UString &dest) const
80 { 67 {
81 char temp[32 + 4]; 68 char temp[sizeof(Data) * 2 + 4];
82 SetHex_To_str(temp); 69 SetHex_To_str(temp);
83 dest += temp; 70 dest += temp;
84 } 71 }
@@ -2151,7 +2138,7 @@ HRESULT CDatabase::ReadMap(UInt64 oid, bool noHeader,
2151 if (bti.Is_NOHEADER() != noHeader) 2138 if (bti.Is_NOHEADER() != noHeader)
2152 return S_FALSE; 2139 return S_FALSE;
2153 // we don't allow volumes with big number of Keys 2140 // we don't allow volumes with big number of Keys
2154 const UInt32 kNumItemsMax = k_VectorSizeMax; 2141 const unsigned kNumItemsMax = k_VectorSizeMax;
2155 if (map.bti.node_count > kNumItemsMax) 2142 if (map.bti.node_count > kNumItemsMax)
2156 return S_FALSE; 2143 return S_FALSE;
2157 if (map.bti.key_count > kNumItemsMax) 2144 if (map.bti.key_count > kNumItemsMax)
@@ -3759,7 +3746,7 @@ void CDatabase::GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM::
3759 #ifdef APFS_SHOW_ALT_STREAMS 3746 #ifdef APFS_SHOW_ALT_STREAMS
3760 if (IsViDef(ref.AttrIndex) && inode) 3747 if (IsViDef(ref.AttrIndex) && inode)
3761 { 3748 {
3762 s += ':'; 3749 s.Add_Colon();
3763 Utf8Name_to_InterName(inode->Attrs[(unsigned)ref.AttrIndex].Name, s2); 3750 Utf8Name_to_InterName(inode->Attrs[(unsigned)ref.AttrIndex].Name, s2);
3764 // s2 += "a\\b"; // for debug 3751 // s2 += "a\\b"; // for debug
3765 s += s2; 3752 s += s2;
@@ -4094,7 +4081,6 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
4094 if (numItems == 0) 4081 if (numItems == 0)
4095 return S_OK; 4082 return S_OK;
4096 UInt32 i; 4083 UInt32 i;
4097
4098 { 4084 {
4099 UInt64 totalSize = 0; 4085 UInt64 totalSize = 0;
4100 for (i = 0; i < numItems; i++) 4086 for (i = 0; i < numItems; i++)
@@ -4107,14 +4093,15 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
4107 4093
4108 UInt64 currentTotalSize = 0, currentItemSize = 0; 4094 UInt64 currentTotalSize = 0, currentItemSize = 0;
4109 4095
4110 CLocalProgress *lps = new CLocalProgress; 4096 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
4111 CMyComPtr<ICompressProgressInfo> progress = lps;
4112 lps->Init(extractCallback, false); 4097 lps->Init(extractCallback, false);
4113 4098
4114 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 4099 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
4115 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
4116 4100
4117 NHfs::CDecoder decoder; 4101 // We don't know if zlib without Adler is allowed in APFS.
4102 // But zlib without Adler is allowed in HFS.
4103 // So here we allow apfs/zlib without Adler:
4104 NHfs::CDecoder decoder(true); // IsAdlerOptional
4118 4105
4119 for (i = 0;; i++, currentTotalSize += currentItemSize) 4106 for (i = 0;; i++, currentTotalSize += currentItemSize)
4120 { 4107 {
@@ -4131,8 +4118,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
4131 4118
4132 currentItemSize = GetSize(index); 4119 currentItemSize = GetSize(index);
4133 4120
4121 int opRes;
4122 {
4134 CMyComPtr<ISequentialOutStream> realOutStream; 4123 CMyComPtr<ISequentialOutStream> realOutStream;
4135
4136 const Int32 askMode = testMode ? 4124 const Int32 askMode = testMode ?
4137 NExtract::NAskMode::kTest : 4125 NExtract::NAskMode::kTest :
4138 NExtract::NAskMode::kExtract; 4126 NExtract::NAskMode::kExtract;
@@ -4165,7 +4153,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
4165 if (!testMode && !realOutStream) 4153 if (!testMode && !realOutStream)
4166 continue; 4154 continue;
4167 RINOK(extractCallback->PrepareOperation(askMode)) 4155 RINOK(extractCallback->PrepareOperation(askMode))
4168 int opRes = NExtract::NOperationResult::kDataError; 4156 opRes = NExtract::NOperationResult::kDataError;
4169 4157
4170 if (IsViDef(ref.NodeIndex)) 4158 if (IsViDef(ref.NodeIndex))
4171 { 4159 {
@@ -4221,38 +4209,38 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
4221 CMyComPtr<ISequentialInStream> inStream; 4209 CMyComPtr<ISequentialInStream> inStream;
4222 if (GetStream(index, &inStream) == S_OK && inStream) 4210 if (GetStream(index, &inStream) == S_OK && inStream)
4223 { 4211 {
4224 COutStreamWithHash *hashStreamSpec = NULL; 4212 CMyComPtr2<ISequentialOutStream, COutStreamWithHash> hashStream;
4225 CMyComPtr<ISequentialOutStream> hashStream; 4213
4226
4227 if (vol.integrity.Is_SHA256()) 4214 if (vol.integrity.Is_SHA256())
4228 { 4215 {
4229 const int hashIndex = FindHashIndex_for_Item(index); 4216 const int hashIndex = FindHashIndex_for_Item(index);
4230 if (hashIndex != -1) 4217 if (hashIndex != -1)
4231 { 4218 {
4232 hashStreamSpec = new COutStreamWithHash; 4219 hashStream.Create_if_Empty();
4233 hashStream = hashStreamSpec; 4220 hashStream->SetStream(realOutStream);
4234 hashStreamSpec->SetStream(realOutStream); 4221 hashStream->Init(&(vol.Hash_Vectors[(unsigned)hashIndex]), sb.block_size_Log);
4235 hashStreamSpec->Init(&(vol.Hash_Vectors[(unsigned)hashIndex]), sb.block_size_Log);
4236 } 4222 }
4237 } 4223 }
4238 4224
4239 RINOK(copyCoder->Code(inStream, 4225 RINOK(copyCoder.Interface()->Code(inStream,
4240 hashStream ? hashStream : realOutStream, NULL, NULL, progress)) 4226 hashStream.IsDefined() ?
4227 hashStream.Interface() :
4228 realOutStream.Interface(),
4229 NULL, NULL, lps))
4241 opRes = NExtract::NOperationResult::kDataError; 4230 opRes = NExtract::NOperationResult::kDataError;
4242 if (copyCoderSpec->TotalSize == currentItemSize) 4231 if (copyCoder->TotalSize == currentItemSize)
4243 { 4232 {
4244 opRes = NExtract::NOperationResult::kOK; 4233 opRes = NExtract::NOperationResult::kOK;
4245 if (hashStream) 4234 if (hashStream.IsDefined())
4246 if (!hashStreamSpec->FinalCheck()) 4235 if (!hashStream->FinalCheck())
4247 opRes = NExtract::NOperationResult::kCRCError; 4236 opRes = NExtract::NOperationResult::kCRCError;
4248 } 4237 }
4249 else if (copyCoderSpec->TotalSize < currentItemSize) 4238 else if (copyCoder->TotalSize < currentItemSize)
4250 opRes = NExtract::NOperationResult::kUnexpectedEnd; 4239 opRes = NExtract::NOperationResult::kUnexpectedEnd;
4251 } 4240 }
4252 } 4241 }
4253 } 4242 }
4254 4243 }
4255 realOutStream.Release();
4256 RINOK(extractCallback->SetOperationResult(opRes)) 4244 RINOK(extractCallback->SetOperationResult(opRes))
4257 } 4245 }
4258 return S_OK; 4246 return S_OK;
@@ -4340,9 +4328,9 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
4340 const CAttr &attr = inode.Attrs[(unsigned)attrIndex]; 4328 const CAttr &attr = inode.Attrs[(unsigned)attrIndex];
4341 if (!attr.dstream_defined) 4329 if (!attr.dstream_defined)
4342 { 4330 {
4343 CBufInStream *streamSpec = new CBufInStream; 4331 CMyComPtr2<ISequentialInStream, CBufInStream> streamTemp;
4344 CMyComPtr<ISequentialInStream> streamTemp = streamSpec; 4332 streamTemp.Create_if_Empty();
4345 streamSpec->Init(attr.Data, attr.Data.Size(), (IInArchive *)this); 4333 streamTemp->Init(attr.Data, attr.Data.Size(), (IInArchive *)this);
4346 *stream = streamTemp.Detach(); 4334 *stream = streamTemp.Detach();
4347 return S_OK; 4335 return S_OK;
4348 } 4336 }
@@ -4392,9 +4380,9 @@ HRESULT CDatabase::GetAttrStream(IInStream *apfsInStream, const CVol &vol,
4392 *stream = NULL; 4380 *stream = NULL;
4393 if (!attr.dstream_defined) 4381 if (!attr.dstream_defined)
4394 { 4382 {
4395 CBufInStream *streamSpec = new CBufInStream; 4383 CMyComPtr2<ISequentialInStream, CBufInStream> streamTemp;
4396 CMyComPtr<ISequentialInStream> streamTemp = streamSpec; 4384 streamTemp.Create_if_Empty();
4397 streamSpec->Init(attr.Data, attr.Data.Size(), (IInArchive *)this); 4385 streamTemp->Init(attr.Data, attr.Data.Size(), (IInArchive *)this);
4398 *stream = streamTemp.Detach(); 4386 *stream = streamTemp.Detach();
4399 return S_OK; 4387 return S_OK;
4400 } 4388 }
@@ -4427,8 +4415,8 @@ HRESULT CDatabase::GetStream2(
4427 const CRecordVector<CExtent> *extents, UInt64 rem, 4415 const CRecordVector<CExtent> *extents, UInt64 rem,
4428 ISequentialInStream **stream) 4416 ISequentialInStream **stream)
4429{ 4417{
4430 CExtentsStream *extentStreamSpec = new CExtentsStream(); 4418 CMyComPtr2<ISequentialInStream, CExtentsStream> extentStream;
4431 CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec; 4419 extentStream.Create_if_Empty();
4432 4420
4433 UInt64 virt = 0; 4421 UInt64 virt = 0;
4434 FOR_VECTOR (i, *extents) 4422 FOR_VECTOR (i, *extents)
@@ -4452,7 +4440,7 @@ HRESULT CDatabase::GetStream2(
4452 se.Virt = virt; 4440 se.Virt = virt;
4453 virt += cur; 4441 virt += cur;
4454 rem -= cur; 4442 rem -= cur;
4455 extentStreamSpec->Extents.Add(se); 4443 extentStream->Extents.Add(se);
4456 if (rem == 0) 4444 if (rem == 0)
4457 if (i != extents->Size() - 1) 4445 if (i != extents->Size() - 1)
4458 return S_FALSE; 4446 return S_FALSE;
@@ -4464,9 +4452,9 @@ HRESULT CDatabase::GetStream2(
4464 CSeekExtent se; 4452 CSeekExtent se;
4465 se.Phy = 0; 4453 se.Phy = 0;
4466 se.Virt = virt; 4454 se.Virt = virt;
4467 extentStreamSpec->Extents.Add(se); 4455 extentStream->Extents.Add(se);
4468 extentStreamSpec->Stream = apfsInStream; 4456 extentStream->Stream = apfsInStream;
4469 extentStreamSpec->Init(); 4457 extentStream->Init();
4470 *stream = extentStream.Detach(); 4458 *stream = extentStream.Detach();
4471 return S_OK; 4459 return S_OK;
4472} 4460}
diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp
index 6770301..56d9b6e 100644
--- a/CPP/7zip/Archive/ApmHandler.cpp
+++ b/CPP/7zip/Archive/ApmHandler.cpp
@@ -5,36 +5,64 @@
5#include "../../../C/CpuArch.h" 5#include "../../../C/CpuArch.h"
6 6
7#include "../../Common/ComTry.h" 7#include "../../Common/ComTry.h"
8#include "../../Common/Defs.h"
9 8
10#include "../../Windows/PropVariant.h" 9#include "../../Windows/PropVariant.h"
10#include "../../Windows/PropVariantUtils.h"
11 11
12#include "../Common/RegisterArc.h" 12#include "../Common/RegisterArc.h"
13#include "../Common/StreamUtils.h" 13#include "../Common/StreamUtils.h"
14 14
15#include "HandlerCont.h" 15#include "HandlerCont.h"
16 16
17#define Get16(p) GetBe16(p) 17// #define Get16(p) GetBe16(p)
18#define Get32(p) GetBe32(p) 18#define Get32(p) GetBe32(p)
19 19
20using namespace NWindows; 20using namespace NWindows;
21 21
22namespace NArchive { 22namespace NArchive {
23
24namespace NDmg {
25 const char *Find_Apple_FS_Ext(const AString &name);
26 bool Is_Apple_FS_Or_Unknown(const AString &name);
27}
28
23namespace NApm { 29namespace NApm {
24 30
25static const Byte kSig0 = 'E'; 31static const Byte kSig0 = 'E';
26static const Byte kSig1 = 'R'; 32static const Byte kSig1 = 'R';
27 33
34static const CUInt32PCharPair k_Flags[] =
35{
36 { 0, "VALID" },
37 { 1, "ALLOCATED" },
38 { 2, "IN_USE" },
39 { 3, "BOOTABLE" },
40 { 4, "READABLE" },
41 { 5, "WRITABLE" },
42 { 6, "OS_PIC_CODE" },
43 // { 7, "OS_SPECIFIC_2" }, // "Unused"
44 // { 8, "ChainCompatible" }, // "OS_SPECIFIC_1"
45 // { 9, "RealDeviceDriver" },
46 // { 10, "CanChainToNext" },
47 { 30, "MOUNTED_AT_STARTUP" },
48 { 31, "STARTUP" }
49};
50
51#define DPME_FLAGS_VALID (1u << 0)
52#define DPME_FLAGS_ALLOCATED (1u << 1)
53
54static const unsigned k_Str_Size = 32;
55
28struct CItem 56struct CItem
29{ 57{
30 UInt32 StartBlock; 58 UInt32 StartBlock;
31 UInt32 NumBlocks; 59 UInt32 NumBlocks;
32 char Name[32]; 60 UInt32 Flags; // pmPartStatus
33 char Type[32]; 61 char Name[k_Str_Size];
62 char Type[k_Str_Size];
34 /* 63 /*
35 UInt32 DataStartBlock; 64 UInt32 DataStartBlock;
36 UInt32 NumDataBlocks; 65 UInt32 NumDataBlocks;
37 UInt32 Status;
38 UInt32 BootStartBlock; 66 UInt32 BootStartBlock;
39 UInt32 BootSize; 67 UInt32 BootSize;
40 UInt32 BootAddr; 68 UInt32 BootAddr;
@@ -43,25 +71,28 @@ struct CItem
43 char Processor[16]; 71 char Processor[16];
44 */ 72 */
45 73
74 bool Is_Valid_and_Allocated() const
75 { return (Flags & (DPME_FLAGS_VALID | DPME_FLAGS_ALLOCATED)) != 0; }
76
46 bool Parse(const Byte *p, UInt32 &numBlocksInMap) 77 bool Parse(const Byte *p, UInt32 &numBlocksInMap)
47 { 78 {
48 numBlocksInMap = Get32(p + 4); 79 numBlocksInMap = Get32(p + 4);
49 StartBlock = Get32(p + 8); 80 StartBlock = Get32(p + 8);
50 NumBlocks = Get32(p + 0xC); 81 NumBlocks = Get32(p + 0xc);
51 memcpy(Name, p + 0x10, 32); 82 Flags = Get32(p + 0x58);
52 memcpy(Type, p + 0x30, 32); 83 memcpy(Name, p + 0x10, k_Str_Size);
53 if (p[0] != 0x50 || p[1] != 0x4D || p[2] != 0 || p[3] != 0) 84 memcpy(Type, p + 0x30, k_Str_Size);
85 if (GetUi32(p) != 0x4d50) // "PM"
54 return false; 86 return false;
55 /* 87 /*
56 DataStartBlock = Get32(p + 0x50); 88 DataStartBlock = Get32(p + 0x50);
57 NumDataBlocks = Get32(p + 0x54); 89 NumDataBlocks = Get32(p + 0x54);
58 Status = Get32(p + 0x58); 90 BootStartBlock = Get32(p + 0x5c);
59 BootStartBlock = Get32(p + 0x5C);
60 BootSize = Get32(p + 0x60); 91 BootSize = Get32(p + 0x60);
61 BootAddr = Get32(p + 0x64); 92 BootAddr = Get32(p + 0x64);
62 if (Get32(p + 0x68) != 0) 93 if (Get32(p + 0x68) != 0)
63 return false; 94 return false;
64 BootEntry = Get32(p + 0x6C); 95 BootEntry = Get32(p + 0x6c);
65 if (Get32(p + 0x70) != 0) 96 if (Get32(p + 0x70) != 0)
66 return false; 97 return false;
67 BootChecksum = Get32(p + 0x74); 98 BootChecksum = Get32(p + 0x74);
@@ -71,6 +102,7 @@ struct CItem
71 } 102 }
72}; 103};
73 104
105
74Z7_class_CHandler_final: public CHandlerCont 106Z7_class_CHandler_final: public CHandlerCont
75{ 107{
76 Z7_IFACE_COM7_IMP(IInArchive_Cont) 108 Z7_IFACE_COM7_IMP(IInArchive_Cont)
@@ -81,7 +113,6 @@ Z7_class_CHandler_final: public CHandlerCont
81 UInt64 _phySize; 113 UInt64 _phySize;
82 bool _isArc; 114 bool _isArc;
83 115
84 HRESULT ReadTables(IInStream *stream);
85 UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; } 116 UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; }
86 117
87 virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override 118 virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
@@ -95,47 +126,58 @@ Z7_class_CHandler_final: public CHandlerCont
95 126
96static const UInt32 kSectorSize = 512; 127static const UInt32 kSectorSize = 512;
97 128
129// we support only 4 cluster sizes: 512, 1024, 2048, 4096 */
130
98API_FUNC_static_IsArc IsArc_Apm(const Byte *p, size_t size) 131API_FUNC_static_IsArc IsArc_Apm(const Byte *p, size_t size)
99{ 132{
100 if (size < kSectorSize) 133 if (size < kSectorSize)
101 return k_IsArc_Res_NEED_MORE; 134 return k_IsArc_Res_NEED_MORE;
102 if (p[0] != kSig0 || p[1] != kSig1) 135 if (GetUi64(p + 8) != 0)
136 return k_IsArc_Res_NO;
137 UInt32 v = GetUi32(p); // we read as little-endian
138 v ^= (kSig0 | (unsigned)kSig1 << 8);
139 if ((v & ~((UInt32)0xf << 17)))
103 return k_IsArc_Res_NO; 140 return k_IsArc_Res_NO;
104 unsigned i; 141 if ((0x116u >> (v >> 17)) & 1)
105 for (i = 8; i < 16; i++) 142 return k_IsArc_Res_YES;
106 if (p[i] != 0) 143 return k_IsArc_Res_NO;
107 return k_IsArc_Res_NO;
108 UInt32 blockSize = Get16(p + 2);
109 for (i = 9; ((UInt32)1 << i) != blockSize; i++)
110 if (i >= 12)
111 return k_IsArc_Res_NO;
112 return k_IsArc_Res_YES;
113} 144}
114} 145}
115 146
116HRESULT CHandler::ReadTables(IInStream *stream) 147Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */))
117{ 148{
149 COM_TRY_BEGIN
150 Close();
151
118 Byte buf[kSectorSize]; 152 Byte buf[kSectorSize];
153 unsigned numSectors_in_Cluster;
119 { 154 {
120 RINOK(ReadStream_FALSE(stream, buf, kSectorSize)) 155 RINOK(ReadStream_FALSE(stream, buf, kSectorSize))
121 if (buf[0] != kSig0 || buf[1] != kSig1) 156 if (GetUi64(buf + 8) != 0)
122 return S_FALSE; 157 return S_FALSE;
123 UInt32 blockSize = Get16(buf + 2); 158 UInt32 v = GetUi32(buf); // we read as little-endian
124 unsigned i; 159 v ^= (kSig0 | (unsigned)kSig1 << 8);
125 for (i = 9; ((UInt32)1 << i) != blockSize; i++) 160 if ((v & ~((UInt32)0xf << 17)))
126 if (i >= 12) 161 return S_FALSE;
127 return S_FALSE; 162 v >>= 16;
128 _blockSizeLog = i; 163 if (v == 0)
129 _numBlocks = Get32(buf + 4); 164 return S_FALSE;
130 for (i = 8; i < 16; i++) 165 if (v & (v - 1))
131 if (buf[i] != 0) 166 return S_FALSE;
132 return S_FALSE; 167 const unsigned a = (0x30210u >> v) & 3;
168 // a = 0; // for debug
169 numSectors_in_Cluster = 1u << a;
170 _blockSizeLog = 9 + a;
133 } 171 }
134 172
135 unsigned numSkips = (unsigned)1 << (_blockSizeLog - 9); 173 UInt32 numBlocks = Get32(buf + 4);
136 for (unsigned j = 1; j < numSkips; j++) 174 _numBlocks = numBlocks;
175
137 { 176 {
138 RINOK(ReadStream_FALSE(stream, buf, kSectorSize)) 177 for (unsigned k = numSectors_in_Cluster; --k != 0;)
178 {
179 RINOK(ReadStream_FALSE(stream, buf, kSectorSize))
180 }
139 } 181 }
140 182
141 UInt32 numBlocksInMap = 0; 183 UInt32 numBlocksInMap = 0;
@@ -152,19 +194,20 @@ HRESULT CHandler::ReadTables(IInStream *stream)
152 if (i == 0) 194 if (i == 0)
153 { 195 {
154 numBlocksInMap = numBlocksInMap2; 196 numBlocksInMap = numBlocksInMap2;
155 if (numBlocksInMap > (1 << 8)) 197 if (numBlocksInMap > (1 << 8) || numBlocksInMap == 0)
156 return S_FALSE; 198 return S_FALSE;
157 } 199 }
158 else if (numBlocksInMap2 != numBlocksInMap) 200 else if (numBlocksInMap2 != numBlocksInMap)
159 return S_FALSE; 201 return S_FALSE;
160 202
161 UInt32 finish = item.StartBlock + item.NumBlocks; 203 const UInt32 finish = item.StartBlock + item.NumBlocks;
162 if (finish < item.StartBlock) 204 if (finish < item.StartBlock)
163 return S_FALSE; 205 return S_FALSE;
164 _numBlocks = MyMax(_numBlocks, finish); 206 if (numBlocks < finish)
207 numBlocks = finish;
165 208
166 _items.Add(item); 209 _items.Add(item);
167 for (unsigned j = 1; j < numSkips; j++) 210 for (unsigned k = numSectors_in_Cluster; --k != 0;)
168 { 211 {
169 RINOK(ReadStream_FALSE(stream, buf, kSectorSize)) 212 RINOK(ReadStream_FALSE(stream, buf, kSectorSize))
170 } 213 }
@@ -172,21 +215,15 @@ HRESULT CHandler::ReadTables(IInStream *stream)
172 break; 215 break;
173 } 216 }
174 217
175 _phySize = BlocksToBytes(_numBlocks); 218 _phySize = BlocksToBytes(numBlocks);
176 _isArc = true; 219 _isArc = true;
177 return S_OK;
178}
179
180Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */))
181{
182 COM_TRY_BEGIN
183 Close();
184 RINOK(ReadTables(stream))
185 _stream = stream; 220 _stream = stream;
221
186 return S_OK; 222 return S_OK;
187 COM_TRY_END 223 COM_TRY_END
188} 224}
189 225
226
190Z7_COM7F_IMF(CHandler::Close()) 227Z7_COM7F_IMF(CHandler::Close())
191{ 228{
192 _isArc = false; 229 _isArc = false;
@@ -196,16 +233,19 @@ Z7_COM7F_IMF(CHandler::Close())
196 return S_OK; 233 return S_OK;
197} 234}
198 235
236
199static const Byte kProps[] = 237static const Byte kProps[] =
200{ 238{
201 kpidPath, 239 kpidPath,
202 kpidSize, 240 kpidSize,
203 kpidOffset 241 kpidOffset,
242 kpidCharacts
204}; 243};
205 244
206static const Byte kArcProps[] = 245static const Byte kArcProps[] =
207{ 246{
208 kpidClusterSize 247 kpidClusterSize,
248 kpidNumBlocks
209}; 249};
210 250
211IMP_IInArchive_Props 251IMP_IInArchive_Props
@@ -214,8 +254,7 @@ IMP_IInArchive_ArcProps
214static AString GetString(const char *s) 254static AString GetString(const char *s)
215{ 255{
216 AString res; 256 AString res;
217 for (unsigned i = 0; i < 32 && s[i] != 0; i++) 257 res.SetFrom_CalcLen(s, k_Str_Size);
218 res += s[i];
219 return res; 258 return res;
220} 259}
221 260
@@ -230,11 +269,13 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
230 int mainIndex = -1; 269 int mainIndex = -1;
231 FOR_VECTOR (i, _items) 270 FOR_VECTOR (i, _items)
232 { 271 {
233 AString s (GetString(_items[i].Type)); 272 const CItem &item = _items[i];
234 if (s != "Apple_Free" && 273 if (!item.Is_Valid_and_Allocated())
235 s != "Apple_partition_map") 274 continue;
275 AString s (GetString(item.Type));
276 if (NDmg::Is_Apple_FS_Or_Unknown(s))
236 { 277 {
237 if (mainIndex >= 0) 278 if (mainIndex != -1)
238 { 279 {
239 mainIndex = -1; 280 mainIndex = -1;
240 break; 281 break;
@@ -242,12 +283,13 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
242 mainIndex = (int)i; 283 mainIndex = (int)i;
243 } 284 }
244 } 285 }
245 if (mainIndex >= 0) 286 if (mainIndex != -1)
246 prop = (UInt32)(Int32)mainIndex; 287 prop = (UInt32)(Int32)mainIndex;
247 break; 288 break;
248 } 289 }
249 case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break; 290 case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break;
250 case kpidPhySize: prop = _phySize; break; 291 case kpidPhySize: prop = _phySize; break;
292 case kpidNumBlocks: prop = _numBlocks; break;
251 293
252 case kpidErrorFlags: 294 case kpidErrorFlags:
253 { 295 {
@@ -281,8 +323,11 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
281 if (s.IsEmpty()) 323 if (s.IsEmpty())
282 s.Add_UInt32(index); 324 s.Add_UInt32(index);
283 AString type (GetString(item.Type)); 325 AString type (GetString(item.Type));
284 if (type == "Apple_HFS") 326 {
285 type = "hfs"; 327 const char *ext = NDmg::Find_Apple_FS_Ext(type);
328 if (ext)
329 type = ext;
330 }
286 if (!type.IsEmpty()) 331 if (!type.IsEmpty())
287 { 332 {
288 s.Add_Dot(); 333 s.Add_Dot();
@@ -296,6 +341,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
296 prop = BlocksToBytes(item.NumBlocks); 341 prop = BlocksToBytes(item.NumBlocks);
297 break; 342 break;
298 case kpidOffset: prop = BlocksToBytes(item.StartBlock); break; 343 case kpidOffset: prop = BlocksToBytes(item.StartBlock); break;
344 case kpidCharacts: FLAGS_TO_PROP(k_Flags, item.Flags, prop); break;
299 } 345 }
300 prop.Detach(value); 346 prop.Detach(value);
301 return S_OK; 347 return S_OK;
diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp
index 07ecec6..95e4719 100644
--- a/CPP/7zip/Archive/ArHandler.cpp
+++ b/CPP/7zip/Archive/ArHandler.cpp
@@ -274,18 +274,18 @@ HRESULT CInArchive::GetNextItem(CItem &item, bool &filled)
274Z7_CLASS_IMP_CHandler_IInArchive_1( 274Z7_CLASS_IMP_CHandler_IInArchive_1(
275 IInArchiveGetStream 275 IInArchiveGetStream
276) 276)
277 bool _isArc;
277 CObjectVector<CItem> _items; 278 CObjectVector<CItem> _items;
278 CMyComPtr<IInStream> _stream; 279 CMyComPtr<IInStream> _stream;
279 Int32 _mainSubfile;
280 UInt64 _phySize; 280 UInt64 _phySize;
281 Int32 _mainSubfile;
281 282
282 EType _type; 283 EType _type;
283 ESubType _subType; 284 ESubType _subType;
284 int _longNames_FileIndex; 285 int _longNames_FileIndex;
285 AString _libFiles[2];
286 unsigned _numLibFiles; 286 unsigned _numLibFiles;
287 AString _errorMessage; 287 AString _errorMessage;
288 bool _isArc; 288 AString _libFiles[2];
289 289
290 void UpdateErrorMessage(const char *s); 290 void UpdateErrorMessage(const char *s);
291 291
@@ -299,7 +299,7 @@ Z7_CLASS_IMP_CHandler_IInArchive_1(
299void CHandler::UpdateErrorMessage(const char *s) 299void CHandler::UpdateErrorMessage(const char *s)
300{ 300{
301 if (!_errorMessage.IsEmpty()) 301 if (!_errorMessage.IsEmpty())
302 _errorMessage += '\n'; 302 _errorMessage.Add_LF();
303 _errorMessage += s; 303 _errorMessage += s;
304} 304}
305 305
@@ -437,8 +437,8 @@ HRESULT CHandler::AddFunc(UInt32 offset, const Byte *data, size_t size, size_t &
437 s.DeleteBack(); 437 s.DeleteBack();
438 s += " "; 438 s += " ";
439 s += (const char *)(data + pos); 439 s += (const char *)(data + pos);
440 s += (char)0xD; 440 // s.Add_Char((char)0xD);
441 s += (char)0xA; 441 s.Add_LF();
442 pos = i; 442 pos = i;
443 return S_OK; 443 return S_OK;
444} 444}
@@ -473,7 +473,7 @@ HRESULT CHandler::ParseLibSymbols(IInStream *stream, unsigned fileIndex)
473 if (size - pos < tableSize || (tableSize & 7) != 0) 473 if (size - pos < tableSize || (tableSize & 7) != 0)
474 continue; 474 continue;
475 size_t namesStart = pos + tableSize; 475 size_t namesStart = pos + tableSize;
476 const UInt32 namesSize = Get32(p + namesStart, be); 476 const UInt32 namesSize = Get32(p.ConstData() + namesStart, be);
477 namesStart += 4; 477 namesStart += 4;
478 if (namesStart > size || namesStart + namesSize != size) 478 if (namesStart > size || namesStart + namesSize != size)
479 continue; 479 continue;
@@ -582,7 +582,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
582 arc.SkipData(item.Size); 582 arc.SkipData(item.Size);
583 if (callback && (_items.Size() & 0xFF) == 0) 583 if (callback && (_items.Size() & 0xFF) == 0)
584 { 584 {
585 UInt64 numFiles = _items.Size(); 585 const UInt64 numFiles = _items.Size();
586 RINOK(callback->SetCompleted(&numFiles, &arc.Position)) 586 RINOK(callback->SetCompleted(&numFiles, &arc.Position))
587 } 587 }
588 } 588 }
@@ -762,21 +762,21 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
762 762
763 UInt64 currentTotalSize = 0; 763 UInt64 currentTotalSize = 0;
764 764
765 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 765 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
766 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 766 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
767
768 CLocalProgress *lps = new CLocalProgress;
769 CMyComPtr<ICompressProgressInfo> progress = lps;
770 lps->Init(extractCallback, false); 767 lps->Init(extractCallback, false);
771 768
772 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 769 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
773 CMyComPtr<ISequentialInStream> inStream(streamSpec); 770 inStream->SetStream(_stream);
774 streamSpec->SetStream(_stream);
775 771
776 for (i = 0; i < numItems; i++) 772 for (i = 0;; i++)
777 { 773 {
778 lps->InSize = lps->OutSize = currentTotalSize; 774 lps->InSize = lps->OutSize = currentTotalSize;
779 RINOK(lps->SetCur()) 775 RINOK(lps->SetCur())
776 if (i >= numItems)
777 break;
778 Int32 opRes;
779 {
780 CMyComPtr<ISequentialOutStream> realOutStream; 780 CMyComPtr<ISequentialOutStream> realOutStream;
781 const Int32 askMode = testMode ? 781 const Int32 askMode = testMode ?
782 NExtract::NAskMode::kTest : 782 NExtract::NAskMode::kTest :
@@ -795,7 +795,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
795 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 795 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
796 continue; 796 continue;
797 } 797 }
798 bool isOk = true; 798 opRes = NExtract::NOperationResult::kOK;
799 if (item.TextFileIndex >= 0) 799 if (item.TextFileIndex >= 0)
800 { 800 {
801 const AString &f = _libFiles[(unsigned)item.TextFileIndex]; 801 const AString &f = _libFiles[(unsigned)item.TextFileIndex];
@@ -805,14 +805,13 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
805 else 805 else
806 { 806 {
807 RINOK(InStream_SeekSet(_stream, item.GetDataPos())) 807 RINOK(InStream_SeekSet(_stream, item.GetDataPos()))
808 streamSpec->Init(item.Size); 808 inStream->Init(item.Size);
809 RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)) 809 RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
810 isOk = (copyCoderSpec->TotalSize == item.Size); 810 if (copyCoder->TotalSize != item.Size)
811 opRes = NExtract::NOperationResult::kDataError;
811 } 812 }
812 realOutStream.Release(); 813 }
813 RINOK(extractCallback->SetOperationResult(isOk ? 814 RINOK(extractCallback->SetOperationResult(opRes))
814 NExtract::NOperationResult::kOK:
815 NExtract::NOperationResult::kDataError))
816 } 815 }
817 return S_OK; 816 return S_OK;
818 COM_TRY_END 817 COM_TRY_END
diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp
index 2f982c4..1d641e4 100644
--- a/CPP/7zip/Archive/ArjHandler.cpp
+++ b/CPP/7zip/Archive/ArjHandler.cpp
@@ -4,6 +4,7 @@
4 4
5#include "../../../C/CpuArch.h" 5#include "../../../C/CpuArch.h"
6 6
7#include "../../Common/AutoPtr.h"
7#include "../../Common/ComTry.h" 8#include "../../Common/ComTry.h"
8#include "../../Common/StringConvert.h" 9#include "../../Common/StringConvert.h"
9 10
@@ -28,16 +29,13 @@ namespace NArj {
28namespace NDecoder { 29namespace NDecoder {
29 30
30static const unsigned kMatchMinLen = 3; 31static const unsigned kMatchMinLen = 3;
31
32static const UInt32 kWindowSize = 1 << 15; // must be >= (1 << 14) 32static const UInt32 kWindowSize = 1 << 15; // must be >= (1 << 14)
33 33
34 34class CCoder
35Z7_CLASS_IMP_NOQIB_1( 35{
36 CCoder
37 , ICompressCoder
38)
39 CLzOutWindow _outWindow; 36 CLzOutWindow _outWindow;
40 NBitm::CDecoder<CInBuffer> _inBitStream; 37 NBitm::CDecoder<CInBuffer> _inBitStream;
38 // bool FinishMode;
41 39
42 class CCoderReleaser 40 class CCoderReleaser
43 { 41 {
@@ -49,19 +47,20 @@ Z7_CLASS_IMP_NOQIB_1(
49 }; 47 };
50 friend class CCoderReleaser; 48 friend class CCoderReleaser;
51 49
52 HRESULT CodeReal(UInt64 outSize, ICompressProgressInfo *progress); 50 HRESULT CodeReal(UInt32 outSize, ICompressProgressInfo *progress);
53public: 51public:
54 bool FinishMode;
55 52
56 CCoder(): FinishMode(false) {} 53 // CCoder(): FinishMode(true) {}
57 UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); } 54 UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); }
55 HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
56 UInt32 outSize, ICompressProgressInfo *progress);
58}; 57};
59 58
60 59
61HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress) 60HRESULT CCoder::CodeReal(UInt32 rem, ICompressProgressInfo *progress)
62{ 61{
63 const UInt32 kStep = 1 << 20; 62 const UInt32 kStep = 1 << 20;
64 UInt64 next = 0; 63 UInt32 next = 0;
65 if (rem > kStep && progress) 64 if (rem > kStep && progress)
66 next = rem - kStep; 65 next = rem - kStep;
67 66
@@ -71,9 +70,8 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
71 { 70 {
72 if (_inBitStream.ExtraBitsWereRead()) 71 if (_inBitStream.ExtraBitsWereRead())
73 return S_FALSE; 72 return S_FALSE;
74 73 const UInt64 packSize = _inBitStream.GetProcessedSize();
75 UInt64 packSize = _inBitStream.GetProcessedSize(); 74 const UInt64 pos = _outWindow.GetProcessedSize();
76 UInt64 pos = _outWindow.GetProcessedSize();
77 RINOK(progress->SetRatioInfo(&packSize, &pos)) 75 RINOK(progress->SetRatioInfo(&packSize, &pos))
78 next = 0; 76 next = 0;
79 if (rem > kStep) 77 if (rem > kStep)
@@ -81,12 +79,11 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
81 } 79 }
82 80
83 UInt32 len; 81 UInt32 len;
84
85 { 82 {
86 const unsigned kNumBits = 7 + 7; 83 const unsigned kNumBits = 7 + 7;
87 UInt32 val = _inBitStream.GetValue(kNumBits); 84 const UInt32 val = _inBitStream.GetValue(kNumBits);
88 85
89 if ((val & (1 << (kNumBits - 1))) == 0) 86 if ((val & (1u << (kNumBits - 1))) == 0)
90 { 87 {
91 _outWindow.PutByte((Byte)(val >> 5)); 88 _outWindow.PutByte((Byte)(val >> 5));
92 _inBitStream.MovePos(1 + 8); 89 _inBitStream.MovePos(1 + 8);
@@ -94,27 +91,24 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
94 continue; 91 continue;
95 } 92 }
96 93
97 UInt32 mask = 1 << (kNumBits - 2);
98 unsigned w; 94 unsigned w;
99 95 {
100 for (w = 1; w < 7; w++, mask >>= 1) 96 UInt32 flag = (UInt32)1 << (kNumBits - 2);
101 if ((val & mask) == 0) 97 for (w = 1; w < 7; w++, flag >>= 1)
102 break; 98 if ((val & flag) == 0)
103 99 break;
104 unsigned readBits = (w != 7 ? 1 : 0); 100 }
105 readBits += w + w; 101 const unsigned readBits = (w != 7 ? 1 : 0) + w * 2;
106 len = (1 << w) - 1 + kMatchMinLen - 1 + 102 const UInt32 mask = ((UInt32)1 << w) - 1;
107 (((val >> (kNumBits - readBits)) & ((1 << w) - 1))); 103 len = mask + kMatchMinLen - 1 +
104 ((val >> (kNumBits - readBits)) & mask);
108 _inBitStream.MovePos(readBits); 105 _inBitStream.MovePos(readBits);
109 } 106 }
110
111 { 107 {
112 const unsigned kNumBits = 4 + 13; 108 const unsigned kNumBits = 4 + 13;
113 UInt32 val = _inBitStream.GetValue(kNumBits); 109 const UInt32 val = _inBitStream.GetValue(kNumBits);
114
115 unsigned readBits = 1; 110 unsigned readBits = 1;
116 unsigned w; 111 unsigned w;
117
118 if ((val & ((UInt32)1 << 16)) == 0) w = 9; 112 if ((val & ((UInt32)1 << 16)) == 0) w = 9;
119 else if ((val & ((UInt32)1 << 15)) == 0) w = 10; 113 else if ((val & ((UInt32)1 << 15)) == 0) w = 10;
120 else if ((val & ((UInt32)1 << 14)) == 0) w = 11; 114 else if ((val & ((UInt32)1 << 14)) == 0) w = 11;
@@ -122,61 +116,50 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
122 else { w = 13; readBits = 0; } 116 else { w = 13; readBits = 0; }
123 117
124 readBits += w + w - 9; 118 readBits += w + w - 9;
125 119 const UInt32 dist = ((UInt32)1 << w) - (1 << 9) +
126 UInt32 dist = ((UInt32)1 << w) - (1 << 9) +
127 (((val >> (kNumBits - readBits)) & ((1 << w) - 1))); 120 (((val >> (kNumBits - readBits)) & ((1 << w) - 1)));
128 _inBitStream.MovePos(readBits); 121 _inBitStream.MovePos(readBits);
129
130 if (len > rem) 122 if (len > rem)
131 len = (UInt32)rem; 123 {
132 124 // if (FinishMode)
125 return S_FALSE;
126 // else len = (UInt32)rem;
127 }
133 if (!_outWindow.CopyBlock(dist, len)) 128 if (!_outWindow.CopyBlock(dist, len))
134 return S_FALSE; 129 return S_FALSE;
135 rem -= len; 130 rem -= len;
136 } 131 }
137 } 132 }
138 133
139 if (FinishMode) 134 // if (FinishMode)
140 { 135 {
141 if (_inBitStream.ReadAlignBits() != 0) 136 if (_inBitStream.ReadAlignBits() != 0)
142 return S_FALSE; 137 return S_FALSE;
143 } 138 }
144
145 if (_inBitStream.ExtraBitsWereRead()) 139 if (_inBitStream.ExtraBitsWereRead())
146 return S_FALSE; 140 return S_FALSE;
147
148 return S_OK; 141 return S_OK;
149} 142}
150 143
151 144
152 145HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
153Z7_COM7F_IMF(CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 146 UInt32 outSize, ICompressProgressInfo *progress)
154 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress))
155{ 147{
156 try 148 try
157 { 149 {
158 if (!outSize)
159 return E_INVALIDARG;
160
161 if (!_outWindow.Create(kWindowSize)) 150 if (!_outWindow.Create(kWindowSize))
162 return E_OUTOFMEMORY; 151 return E_OUTOFMEMORY;
163 if (!_inBitStream.Create(1 << 17)) 152 if (!_inBitStream.Create(1 << 17))
164 return E_OUTOFMEMORY; 153 return E_OUTOFMEMORY;
165
166 _outWindow.SetStream(outStream); 154 _outWindow.SetStream(outStream);
167 _outWindow.Init(false); 155 _outWindow.Init(false);
168 _inBitStream.SetStream(inStream); 156 _inBitStream.SetStream(inStream);
169 _inBitStream.Init(); 157 _inBitStream.Init();
170
171 CCoderReleaser coderReleaser(this);
172 HRESULT res;
173 { 158 {
174 res = CodeReal(*outSize, progress); 159 CCoderReleaser coderReleaser(this);
175 if (res != S_OK) 160 RINOK(CodeReal(outSize, progress))
176 return res; 161 coderReleaser.Disable();
177 } 162 }
178
179 coderReleaser.Disable();
180 return _outWindow.Flush(); 163 return _outWindow.Flush();
181 } 164 }
182 catch(const CInBufferException &e) { return e.ErrorCode; } 165 catch(const CInBufferException &e) { return e.ErrorCode; }
@@ -858,74 +841,70 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
858 totalUnpacked += item.Size; 841 totalUnpacked += item.Size;
859 // totalPacked += item.PackSize; 842 // totalPacked += item.PackSize;
860 } 843 }
861 extractCallback->SetTotal(totalUnpacked); 844 RINOK(extractCallback->SetTotal(totalUnpacked))
862 845
863 totalUnpacked = totalPacked = 0; 846 totalUnpacked = totalPacked = 0;
864 UInt64 curUnpacked, curPacked; 847 UInt32 curUnpacked, curPacked;
865 848
866 NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = NULL; 849 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
867 CMyComPtr<ICompressCoder> lzhDecoder;
868
869 NCompress::NArj::NDecoder::CCoder *arjDecoderSpec = NULL;
870 CMyComPtr<ICompressCoder> arjDecoder;
871
872 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
873 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
874
875 CLocalProgress *lps = new CLocalProgress;
876 CMyComPtr<ICompressProgressInfo> progress = lps;
877 lps->Init(extractCallback, false); 850 lps->Init(extractCallback, false);
878 851 CMyUniquePtr<NCompress::NLzh::NDecoder::CCoder> lzhDecoder;
879 CLimitedSequentialInStream *inStreamSpec = new CLimitedSequentialInStream; 852 CMyUniquePtr<NCompress::NArj::NDecoder::CCoder> arjDecoder;
880 CMyComPtr<ISequentialInStream> inStream(inStreamSpec); 853 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
881 inStreamSpec->SetStream(_stream); 854 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
882 855 inStream->SetStream(_stream);
883 for (i = 0; i < numItems; i++, totalUnpacked += curUnpacked, totalPacked += curPacked) 856
857 for (i = 0;; i++,
858 totalUnpacked += curUnpacked,
859 totalPacked += curPacked)
884 { 860 {
885 lps->InSize = totalPacked; 861 lps->InSize = totalPacked;
886 lps->OutSize = totalUnpacked; 862 lps->OutSize = totalUnpacked;
887 RINOK(lps->SetCur()) 863 RINOK(lps->SetCur())
864 if (i >= numItems)
865 break;
888 866
889 curUnpacked = curPacked = 0; 867 curUnpacked = curPacked = 0;
890 868
891 CMyComPtr<ISequentialOutStream> realOutStream; 869 Int32 opRes;
892 const Int32 askMode = testMode ?
893 NExtract::NAskMode::kTest :
894 NExtract::NAskMode::kExtract;
895 const UInt32 index = allFilesMode ? i : indices[i];
896 const CItem &item = _items[index];
897 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
898
899 if (item.IsDir())
900 { 870 {
901 // if (!testMode) 871 CMyComPtr<ISequentialOutStream> realOutStream;
872 const Int32 askMode = testMode ?
873 NExtract::NAskMode::kTest :
874 NExtract::NAskMode::kExtract;
875 const UInt32 index = allFilesMode ? i : indices[i];
876 const CItem &item = _items[index];
877 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
878
879 if (item.IsDir())
902 { 880 {
903 RINOK(extractCallback->PrepareOperation(askMode)) 881 // if (!testMode)
904 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 882 {
883 RINOK(extractCallback->PrepareOperation(askMode))
884 // realOutStream.Release();
885 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
886 }
887 continue;
905 } 888 }
906 continue; 889
907 } 890 if (!testMode && !realOutStream)
908 891 continue;
909 if (!testMode && !realOutStream) 892
910 continue; 893 RINOK(extractCallback->PrepareOperation(askMode))
911 894 curUnpacked = item.Size;
912 RINOK(extractCallback->PrepareOperation(askMode)) 895 curPacked = item.PackSize;
913 curUnpacked = item.Size; 896
914 curPacked = item.PackSize; 897 CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;
915 898 outStream->SetStream(realOutStream);
916 { 899 // realOutStream.Release();
917 COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; 900 outStream->Init();
918 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
919 outStreamSpec->SetStream(realOutStream);
920 realOutStream.Release();
921 outStreamSpec->Init();
922 901
923 inStreamSpec->Init(item.PackSize); 902 inStream->Init(item.PackSize);
924 903
925 RINOK(InStream_SeekSet(_stream, item.DataPosition)) 904 RINOK(InStream_SeekSet(_stream, item.DataPosition))
926 905
927 HRESULT result = S_OK; 906 HRESULT result = S_OK;
928 Int32 opRes = NExtract::NOperationResult::kOK; 907 opRes = NExtract::NOperationResult::kOK;
929 908
930 if (item.IsEncrypted()) 909 if (item.IsEncrypted())
931 opRes = NExtract::NOperationResult::kUnsupportedMethod; 910 opRes = NExtract::NOperationResult::kUnsupportedMethod;
@@ -935,8 +914,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
935 { 914 {
936 case NCompressionMethod::kStored: 915 case NCompressionMethod::kStored:
937 { 916 {
938 result = copyCoder->Code(inStream, outStream, NULL, NULL, progress); 917 result = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);
939 if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize) 918 if (result == S_OK && copyCoder->TotalSize != item.PackSize)
940 result = S_FALSE; 919 result = S_FALSE;
941 break; 920 break;
942 } 921 }
@@ -944,29 +923,21 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
944 case NCompressionMethod::kCompressed1b: 923 case NCompressionMethod::kCompressed1b:
945 case NCompressionMethod::kCompressed1c: 924 case NCompressionMethod::kCompressed1c:
946 { 925 {
947 if (!lzhDecoder) 926 lzhDecoder.Create_if_Empty();
948 { 927 // lzhDecoder->FinishMode = true;
949 lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
950 lzhDecoder = lzhDecoderSpec;
951 }
952 lzhDecoderSpec->FinishMode = true;
953 const UInt32 kHistorySize = 26624; 928 const UInt32 kHistorySize = 26624;
954 lzhDecoderSpec->SetDictSize(kHistorySize); 929 lzhDecoder->SetDictSize(kHistorySize);
955 result = lzhDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress); 930 result = lzhDecoder->Code(inStream, outStream, curUnpacked, lps);
956 if (result == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize) 931 if (result == S_OK && lzhDecoder->GetInputProcessedSize() != item.PackSize)
957 result = S_FALSE; 932 result = S_FALSE;
958 break; 933 break;
959 } 934 }
960 case NCompressionMethod::kCompressed2: 935 case NCompressionMethod::kCompressed2:
961 { 936 {
962 if (!arjDecoder) 937 arjDecoder.Create_if_Empty();
963 { 938 // arjDecoderSpec->FinishMode = true;
964 arjDecoderSpec = new NCompress::NArj::NDecoder::CCoder; 939 result = arjDecoder->Code(inStream, outStream, curUnpacked, lps);
965 arjDecoder = arjDecoderSpec; 940 if (result == S_OK && arjDecoder->GetInputProcessedSize() != item.PackSize)
966 }
967 arjDecoderSpec->FinishMode = true;
968 result = arjDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
969 if (result == S_OK && arjDecoderSpec->GetInputProcessedSize() != item.PackSize)
970 result = S_FALSE; 941 result = S_FALSE;
971 break; 942 break;
972 } 943 }
@@ -982,15 +953,13 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
982 else 953 else
983 { 954 {
984 RINOK(result) 955 RINOK(result)
985 opRes = (outStreamSpec->GetCRC() == item.FileCRC) ? 956 opRes = (outStream->GetCRC() == item.FileCRC) ?
986 NExtract::NOperationResult::kOK: 957 NExtract::NOperationResult::kOK:
987 NExtract::NOperationResult::kCRCError; 958 NExtract::NOperationResult::kCRCError;
988 } 959 }
989 } 960 }
990
991 outStream.Release();
992 RINOK(extractCallback->SetOperationResult(opRes))
993 } 961 }
962 RINOK(extractCallback->SetOperationResult(opRes))
994 } 963 }
995 964
996 return S_OK; 965 return S_OK;
diff --git a/CPP/7zip/Archive/AvbHandler.cpp b/CPP/7zip/Archive/AvbHandler.cpp
new file mode 100644
index 0000000..4359fe8
--- /dev/null
+++ b/CPP/7zip/Archive/AvbHandler.cpp
@@ -0,0 +1,596 @@
1// AvbHandler.cpp
2
3#include "StdAfx.h"
4
5#include "../../../C/CpuArch.h"
6
7#include "../../Common/ComTry.h"
8#include "../../Common/MyBuffer.h"
9
10#include "../../Windows/PropVariant.h"
11
12#include "../Common/RegisterArc.h"
13#include "../Common/StreamUtils.h"
14
15#include "HandlerCont.h"
16
17#define Get32(p) GetBe32(p)
18#define Get64(p) GetBe64(p)
19
20#define G32(_offs_, dest) dest = Get32(p + (_offs_))
21#define G64(_offs_, dest) dest = Get64(p + (_offs_))
22
23using namespace NWindows;
24
25namespace NArchive {
26
27namespace NExt {
28API_FUNC_IsArc IsArc_Ext_PhySize(const Byte *p, size_t size, UInt64 *phySize);
29}
30
31namespace NAvb {
32
33static void AddNameToString(AString &s, const Byte *name, unsigned size, bool strictConvert)
34{
35 for (unsigned i = 0; i < size; i++)
36 {
37 Byte c = name[i];
38 if (c == 0)
39 return;
40 if (strictConvert && c < 32)
41 c = '_';
42 s += (char)c;
43 }
44}
45
46/* Maximum size of a vbmeta image - 64 KiB. */
47#define VBMETA_MAX_SIZE (64 * 1024)
48
49#define SIGNATURE { 'A', 'V', 'B', 'f', 0, 0, 0, 1 }
50
51static const unsigned k_SignatureSize = 8;
52static const Byte k_Signature[k_SignatureSize] = SIGNATURE;
53
54// #define AVB_FOOTER_MAGIC "AVBf"
55// #define AVB_FOOTER_MAGIC_LEN 4
56/* The current footer version used - keep in sync with avbtool. */
57#define AVB_FOOTER_VERSION_MAJOR 1
58
59/* The struct used as a footer used on partitions, used to find the
60 * AvbVBMetaImageHeader struct. This struct is always stored at the
61 * end of a partition.
62 */
63// #define AVB_FOOTER_SIZE 64
64static const unsigned kFooterSize = 64;
65
66struct CFooter
67{
68 /* 0: Four bytes equal to "AVBf" (AVB_FOOTER_MAGIC). */
69 // Byte magic[AVB_FOOTER_MAGIC_LEN];
70 /* 4: The major version of the footer struct. */
71 UInt32 version_major;
72 /* 8: The minor version of the footer struct. */
73 UInt32 version_minor;
74
75 /* 12: The original size of the image on the partition. */
76 UInt64 original_image_size;
77
78 /* 20: The offset of the |AvbVBMetaImageHeader| struct. */
79 UInt64 vbmeta_offset;
80
81 /* 28: The size of the vbmeta block (header + auth + aux blocks). */
82 UInt64 vbmeta_size;
83
84 /* 36: Padding to ensure struct is size AVB_FOOTER_SIZE bytes. This
85 * must be set to zeroes.
86 */
87 Byte reserved[28];
88
89 void Parse(const Byte *p)
90 {
91 G32 (4, version_major);
92 G32 (8, version_minor);
93 G64 (12, original_image_size);
94 G64 (20, vbmeta_offset);
95 G64 (28, vbmeta_size);
96 }
97};
98
99
100/* Size of the vbmeta image header. */
101#define AVB_VBMETA_IMAGE_HEADER_SIZE 256
102
103/* Magic for the vbmeta image header. */
104// #define AVB_MAGIC "AVB0"
105// #define AVB_MAGIC_LEN 4
106/* Maximum size of the release string including the terminating NUL byte. */
107#define AVB_RELEASE_STRING_SIZE 48
108
109struct AvbVBMetaImageHeader
110{
111 /* 0: Four bytes equal to "AVB0" (AVB_MAGIC). */
112 // Byte magic[AVB_MAGIC_LEN];
113
114 /* 4: The major version of libavb required for this header. */
115 UInt32 required_libavb_version_major;
116 /* 8: The minor version of libavb required for this header. */
117 UInt32 required_libavb_version_minor;
118
119 /* 12: The size of the signature block. */
120 UInt64 authentication_data_block_size;
121 /* 20: The size of the auxiliary data block. */
122 UInt64 auxiliary_data_block_size;
123
124 /* 28: The verification algorithm used, see |AvbAlgorithmType| enum. */
125 UInt32 algorithm_type;
126
127 /* 32: Offset into the "Authentication data" block of hash data. */
128 UInt64 hash_offset;
129 /* 40: Length of the hash data. */
130 UInt64 hash_size;
131
132 /* 48: Offset into the "Authentication data" block of signature data. */
133 UInt64 signature_offset;
134 /* 56: Length of the signature data. */
135 UInt64 signature_size;
136
137 /* 64: Offset into the "Auxiliary data" block of public key data. */
138 UInt64 public_key_offset;
139 /* 72: Length of the public key data. */
140 UInt64 public_key_size;
141
142 /* 80: Offset into the "Auxiliary data" block of public key metadata. */
143 UInt64 public_key_metadata_offset;
144 /* 88: Length of the public key metadata. Must be set to zero if there
145 * is no public key metadata.
146 */
147 UInt64 public_key_metadata_size;
148
149 /* 96: Offset into the "Auxiliary data" block of descriptor data. */
150 UInt64 descriptors_offset;
151 /* 104: Length of descriptor data. */
152 UInt64 descriptors_size;
153
154 /* 112: The rollback index which can be used to prevent rollback to
155 * older versions.
156 */
157 UInt64 rollback_index;
158
159 /* 120: Flags from the AvbVBMetaImageFlags enumeration. This must be
160 * set to zero if the vbmeta image is not a top-level image.
161 */
162 UInt32 flags;
163
164 /* 124: The location of the rollback index defined in this header.
165 * Only valid for the main vbmeta. For chained partitions, the rollback
166 * index location must be specified in the AvbChainPartitionDescriptor
167 * and this value must be set to 0.
168 */
169 UInt32 rollback_index_location;
170
171 /* 128: The release string from avbtool, e.g. "avbtool 1.0.0" or
172 * "avbtool 1.0.0 xyz_board Git-234abde89". Is guaranteed to be NUL
173 * terminated. Applications must not make assumptions about how this
174 * string is formatted.
175 */
176 Byte release_string[AVB_RELEASE_STRING_SIZE];
177
178 /* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE
179 * bytes. This must be set to zeroes.
180 */
181 // Byte reserved[80];
182 bool Parse(const Byte *p);
183};
184
185bool AvbVBMetaImageHeader::Parse(const Byte *p)
186{
187 // Byte magic[AVB_MAGIC_LEN];
188 if (Get32(p) != 0x41564230) // "AVB0"
189 return false;
190 G32 (4, required_libavb_version_major);
191 if (required_libavb_version_major != AVB_FOOTER_VERSION_MAJOR) // "AVB0"
192 return false;
193 G32 (8, required_libavb_version_minor);
194 G64 (12, authentication_data_block_size);
195 G64 (20, auxiliary_data_block_size);
196 G32 (28, algorithm_type);
197 G64 (32, hash_offset);
198 G64 (40, hash_size);
199 G64 (48, signature_offset);
200 G64 (56, signature_size);
201 G64 (64, public_key_offset);
202 G64 (72, public_key_size);
203 G64 (80, public_key_metadata_offset);
204 G64 (88, public_key_metadata_size);
205 G64 (96, descriptors_offset);
206 G64 (104, descriptors_size);
207 G64 (112, rollback_index);
208 G32 (120, flags);
209 G32 (124, rollback_index_location);
210 memcpy(release_string, p + 128, AVB_RELEASE_STRING_SIZE);
211
212 /* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE
213 * bytes. This must be set to zeroes.
214 */
215 // Byte reserved[80];
216 return true;
217}
218
219
220static const unsigned k_Descriptor_Size = 16;
221
222enum AvbDescriptorTag
223{
224 AVB_DESCRIPTOR_TAG_PROPERTY,
225 AVB_DESCRIPTOR_TAG_HASHTREE,
226 AVB_DESCRIPTOR_TAG_HASH,
227 AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
228 AVB_DESCRIPTOR_TAG_CHAIN_PARTITION
229};
230
231struct AvbDescriptor
232{
233 UInt64 Tag;
234 UInt64 Size;
235
236 void Parse(const Byte *p)
237 {
238 G64 (0, Tag);
239 G64 (8, Size);
240 }
241};
242
243
244enum AvbHashtreeDescriptorFlags
245{
246 AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
247 AVB_HASHTREE_DESCRIPTOR_FLAGS_CHECK_AT_MOST_ONCE = (1 << 1)
248};
249
250/* A descriptor containing information about a dm-verity hashtree.
251 *
252 * Hash-trees are used to verify large partitions typically containing
253 * file systems. See
254 * https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for more
255 * information about dm-verity.
256 *
257 * Following this struct are |partition_name_len| bytes of the
258 * partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
259 * |root_digest_len| bytes of the root digest.
260 *
261 * The |reserved| field is for future expansion and must be set to NUL
262 * bytes.
263 *
264 * Changes in v1.1:
265 * - flags field is added which supports AVB_HASHTREE_DESCRIPTOR_FLAGS_USE_AB
266 * - digest_len may be zero, which indicates the use of a persistent digest
267 */
268
269static const unsigned k_Hashtree_Size_Min = 164;
270
271struct AvbHashtreeDescriptor
272{
273 UInt32 dm_verity_version;
274 UInt64 image_size;
275 UInt64 tree_offset;
276 UInt64 tree_size;
277 UInt32 data_block_size;
278 UInt32 hash_block_size;
279 UInt32 fec_num_roots;
280 UInt64 fec_offset;
281 UInt64 fec_size;
282 Byte hash_algorithm[32];
283 UInt32 partition_name_len;
284 UInt32 salt_len;
285 UInt32 root_digest_len;
286 UInt32 flags;
287 Byte reserved[60];
288 void Parse(const Byte *p)
289 {
290 G32 (0, dm_verity_version);
291 G64 (4, image_size);
292 G64 (12, tree_offset);
293 G64 (20, tree_size);
294 G32 (28, data_block_size);
295 G32 (32, hash_block_size);
296 G32 (36, fec_num_roots);
297 G64 (40, fec_offset);
298 G64 (48, fec_size);
299 memcpy(hash_algorithm, p + 56, 32);
300 G32 (88, partition_name_len);
301 G32 (92, salt_len);
302 G32 (96, root_digest_len);
303 G32 (100, flags);
304 }
305};
306
307static const unsigned k_PropertyDescriptor_Size_Min = 16;
308
309struct AvbPropertyDescriptor
310{
311 UInt64 key_num_bytes;
312 UInt64 value_num_bytes;
313
314 void Parse(const Byte *p)
315 {
316 G64 (0, key_num_bytes);
317 G64 (8, value_num_bytes);
318 }
319};
320
321Z7_class_CHandler_final: public CHandlerCont
322{
323 Z7_IFACE_COM7_IMP(IInArchive_Cont)
324
325 // UInt64 _startOffset;
326 UInt64 _phySize;
327
328 CFooter Footer;
329 AString Name;
330 const char *Ext;
331
332 HRESULT Open2(IInStream *stream);
333
334 virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
335 {
336 if (index != 0)
337 return NExtract::NOperationResult::kUnavailable;
338 // pos = _startOffset;
339 pos = 0;
340 size = Footer.original_image_size;
341 return NExtract::NOperationResult::kOK;
342 }
343};
344
345
346HRESULT CHandler::Open2(IInStream *stream)
347{
348 UInt64 fileSize;
349 {
350 Byte buf[kFooterSize];
351 RINOK(InStream_GetSize_SeekToEnd(stream, fileSize))
352 if (fileSize < kFooterSize)
353 return S_FALSE;
354 RINOK(InStream_SeekSet(stream, fileSize - kFooterSize))
355 RINOK(ReadStream_FALSE(stream, buf, kFooterSize))
356 if (memcmp(buf, k_Signature, k_SignatureSize) != 0)
357 return S_FALSE;
358 Footer.Parse(buf);
359 if (Footer.vbmeta_size > VBMETA_MAX_SIZE ||
360 Footer.vbmeta_size < AVB_VBMETA_IMAGE_HEADER_SIZE)
361 return S_FALSE;
362 for (unsigned i = 36; i < kFooterSize; i++)
363 if (buf[i] != 0)
364 return S_FALSE;
365 }
366 {
367 CByteBuffer buf;
368 buf.Alloc((size_t)Footer.vbmeta_size);
369 RINOK(InStream_SeekSet(stream, Footer.vbmeta_offset))
370 RINOK(ReadStream_FALSE(stream, buf, (size_t)Footer.vbmeta_size))
371
372 AvbVBMetaImageHeader meta;
373 if (!meta.Parse(buf))
374 return S_FALSE;
375
376 unsigned offset = (unsigned)AVB_VBMETA_IMAGE_HEADER_SIZE;
377 unsigned rem = (unsigned)(Footer.vbmeta_size - offset);
378
379 if (meta.authentication_data_block_size != 0)
380 {
381 if (rem < meta.authentication_data_block_size)
382 return S_FALSE;
383 const unsigned u = (unsigned)meta.authentication_data_block_size;
384 offset += u;
385 rem -= u;
386 }
387
388 if (rem < meta.descriptors_offset ||
389 rem - meta.descriptors_offset < meta.descriptors_size)
390 return S_FALSE;
391 rem = (unsigned)meta.descriptors_size;
392 while (rem != 0)
393 {
394 if (rem < k_Descriptor_Size)
395 return S_FALSE;
396 AvbDescriptor desc;
397 desc.Parse(buf + offset);
398 offset += k_Descriptor_Size;
399 rem -= k_Descriptor_Size;
400 if (desc.Size > rem)
401 return S_FALSE;
402 const unsigned descSize = (unsigned)desc.Size;
403 if (desc.Tag == AVB_DESCRIPTOR_TAG_HASHTREE)
404 {
405 if (descSize < k_Hashtree_Size_Min)
406 return S_FALSE;
407 AvbHashtreeDescriptor ht;
408 ht.Parse(buf + offset);
409 unsigned pos = k_Hashtree_Size_Min;
410
411 if (pos + ht.partition_name_len > descSize)
412 return S_FALSE;
413 Name.Empty(); // UTF-8
414 AddNameToString(Name, buf + offset + pos, ht.partition_name_len, false);
415 pos += ht.partition_name_len;
416
417 if (pos + ht.salt_len > descSize)
418 return S_FALSE;
419 CByteBuffer salt;
420 salt.CopyFrom(buf + offset + pos, ht.salt_len);
421 pos += ht.salt_len;
422
423 if (pos + ht.root_digest_len > descSize)
424 return S_FALSE;
425 CByteBuffer digest;
426 digest.CopyFrom(buf + offset + pos, ht.root_digest_len);
427 pos += ht.root_digest_len;
428 // what is that digest?
429 }
430 else if (desc.Tag == AVB_DESCRIPTOR_TAG_PROPERTY)
431 {
432 if (descSize < k_PropertyDescriptor_Size_Min + 2)
433 return S_FALSE;
434 AvbPropertyDescriptor pt;
435 pt.Parse(buf + offset);
436 unsigned pos = k_PropertyDescriptor_Size_Min;
437
438 if (pt.key_num_bytes > descSize - pos - 1)
439 return S_FALSE;
440 AString key; // UTF-8
441 AddNameToString(key, buf + offset + pos, (unsigned)pt.key_num_bytes, false);
442 pos += (unsigned)pt.key_num_bytes + 1;
443
444 if (descSize < pos)
445 return S_FALSE;
446 if (pt.value_num_bytes > descSize - pos - 1)
447 return S_FALSE;
448 AString value; // UTF-8
449 AddNameToString(value, buf + offset + pos, (unsigned)pt.value_num_bytes, false);
450 pos += (unsigned)pt.value_num_bytes + 1;
451 }
452 offset += descSize;
453 rem -= descSize;
454 }
455
456 _phySize = fileSize;
457
458 // _startOffset = 0;
459 return S_OK;
460 }
461}
462
463
464Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
465 const UInt64 * /* maxCheckStartPosition */,
466 IArchiveOpenCallback * /* openArchiveCallback */))
467{
468 COM_TRY_BEGIN
469 Close();
470 try
471 {
472 if (Open2(stream) != S_OK)
473 return S_FALSE;
474 _stream = stream;
475
476 {
477 CMyComPtr<ISequentialInStream> parseStream;
478 if (GetStream(0, &parseStream) == S_OK && parseStream)
479 {
480 const size_t kParseSize = 1 << 11;
481 Byte buf[kParseSize];
482 if (ReadStream_FAIL(parseStream, buf, kParseSize) == S_OK)
483 {
484 UInt64 extSize;
485 if (NExt::IsArc_Ext_PhySize(buf, kParseSize, &extSize) == k_IsArc_Res_YES)
486 if (extSize == Footer.original_image_size)
487 Ext = "ext";
488 }
489 }
490 }
491 }
492 catch(...) { return S_FALSE; }
493 return S_OK;
494 COM_TRY_END
495}
496
497
498Z7_COM7F_IMF(CHandler::Close())
499{
500 _stream.Release();
501 // _startOffset = 0;
502 _phySize = 0;
503 Ext = NULL;
504 Name.Empty();
505 return S_OK;
506}
507
508
509static const Byte kArcProps[] =
510{
511 kpidName
512};
513
514static const Byte kProps[] =
515{
516 kpidSize,
517 kpidPackSize,
518};
519
520IMP_IInArchive_Props
521IMP_IInArchive_ArcProps
522
523
524Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
525{
526 COM_TRY_BEGIN
527 NCOM::CPropVariant prop;
528 switch (propID)
529 {
530 case kpidMainSubfile: prop = (UInt32)0; break;
531 case kpidPhySize: prop = _phySize; break;
532 case kpidName:
533 {
534 if (!Name.IsEmpty())
535 {
536 AString s (Name);
537 s += ".avb";
538 prop = s;
539 }
540 break;
541 }
542 }
543 prop.Detach(value);
544 return S_OK;
545 COM_TRY_END
546}
547
548
549Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
550{
551 COM_TRY_BEGIN
552 NCOM::CPropVariant prop;
553
554 switch (propID)
555 {
556 case kpidPath:
557 {
558 if (!Name.IsEmpty())
559 {
560 AString s (Name);
561 s += '.';
562 s += Ext ? Ext : "img";
563 prop = s;
564 }
565 break;
566 }
567 case kpidPackSize:
568 case kpidSize:
569 prop = Footer.original_image_size;
570 break;
571 case kpidExtension: prop = (Ext ? Ext : "img"); break;
572 }
573
574 prop.Detach(value);
575 return S_OK;
576 COM_TRY_END
577}
578
579
580Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
581{
582 *numItems = 1;
583 return S_OK;
584}
585
586
587REGISTER_ARC_I_NO_SIG(
588 "AVB", "avb img", NULL, 0xc0,
589 /* k_Signature, */
590 0,
591 /* NArcInfoFlags::kUseGlobalOffset | */
592 NArcInfoFlags::kBackwardOpen
593 ,
594 NULL)
595
596}}
diff --git a/CPP/7zip/Archive/Base64Handler.cpp b/CPP/7zip/Archive/Base64Handler.cpp
index 5b06051..4df491c 100644
--- a/CPP/7zip/Archive/Base64Handler.cpp
+++ b/CPP/7zip/Archive/Base64Handler.cpp
@@ -369,18 +369,15 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
369 _data.Alloc(kStartSize); 369 _data.Alloc(kStartSize);
370 size_t size = kStartSize; 370 size_t size = kStartSize;
371 RINOK(ReadStream(stream, _data, &size)) 371 RINOK(ReadStream(stream, _data, &size))
372 UInt32 isArcRes = IsArc_Base64(_data, size); 372 if (IsArc_Base64(_data, size) == k_IsArc_Res_NO)
373 if (isArcRes == k_IsArc_Res_NO)
374 return S_FALSE; 373 return S_FALSE;
375 } 374 }
376 _isArc = true; 375 _isArc = true;
377 376
378 UInt64 packSize64; 377 UInt64 packSize64;
379 RINOK(InStream_GetSize_SeekToEnd(stream, packSize64)) 378 RINOK(InStream_GetSize_SeekToEnd(stream, packSize64))
380
381 if (packSize64 == 0) 379 if (packSize64 == 0)
382 return S_FALSE; 380 return S_FALSE;
383
384 size_t curSize = 1 << 16; 381 size_t curSize = 1 << 16;
385 if (curSize > packSize64) 382 if (curSize > packSize64)
386 curSize = (size_t)packSize64; 383 curSize = (size_t)packSize64;
@@ -447,35 +444,24 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
447 return E_INVALIDARG; 444 return E_INVALIDARG;
448 445
449 RINOK(extractCallback->SetTotal(_size)) 446 RINOK(extractCallback->SetTotal(_size))
450 447 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
451 CLocalProgress *lps = new CLocalProgress;
452 CMyComPtr<ICompressProgressInfo> progress = lps;
453 lps->Init(extractCallback, false); 448 lps->Init(extractCallback, false);
454 449 // RINOK(lps->SetCur())
450 Int32 opRes;
455 { 451 {
456 lps->InSize = lps->OutSize = 0;
457 RINOK(lps->SetCur())
458
459 CMyComPtr<ISequentialOutStream> realOutStream; 452 CMyComPtr<ISequentialOutStream> realOutStream;
460 const Int32 askMode = testMode ? 453 const Int32 askMode = testMode ?
461 NExtract::NAskMode::kTest : 454 NExtract::NAskMode::kTest :
462 NExtract::NAskMode::kExtract; 455 NExtract::NAskMode::kExtract;
463
464 RINOK(extractCallback->GetStream(0, &realOutStream, askMode)) 456 RINOK(extractCallback->GetStream(0, &realOutStream, askMode))
465
466 if (!testMode && !realOutStream) 457 if (!testMode && !realOutStream)
467 return S_OK; 458 return S_OK;
468 459 RINOK(extractCallback->PrepareOperation(askMode))
469 extractCallback->PrepareOperation(askMode);
470
471 if (realOutStream) 460 if (realOutStream)
472 { 461 {
473 RINOK(WriteStream(realOutStream, (const Byte *)_data, _size)) 462 RINOK(WriteStream(realOutStream, (const Byte *)_data, _size))
474 realOutStream.Release();
475 } 463 }
476 464 opRes = NExtract::NOperationResult::kOK;
477 Int32 opRes = NExtract::NOperationResult::kOK;
478
479 if (_sres != k_Base64_RES_Finished) 465 if (_sres != k_Base64_RES_Finished)
480 { 466 {
481 if (_sres == k_Base64_RES_NeedMoreInput) 467 if (_sres == k_Base64_RES_NeedMoreInput)
@@ -483,14 +469,11 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
483 else if (_sres == k_Base64_RES_UnexpectedChar) 469 else if (_sres == k_Base64_RES_UnexpectedChar)
484 opRes = NExtract::NOperationResult::kDataError; 470 opRes = NExtract::NOperationResult::kDataError;
485 } 471 }
486
487 RINOK(extractCallback->SetOperationResult(opRes))
488 } 472 }
489 473 RINOK(extractCallback->SetOperationResult(opRes))
490 lps->InSize = _phySize; 474 lps->InSize = _phySize;
491 lps->OutSize = _size; 475 lps->OutSize = _size;
492 return lps->SetCur(); 476 return lps->SetCur();
493
494 COM_TRY_END 477 COM_TRY_END
495} 478}
496 479
diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp
index 994b1ad..ffd7ad0 100644
--- a/CPP/7zip/Archive/Bz2Handler.cpp
+++ b/CPP/7zip/Archive/Bz2Handler.cpp
@@ -77,7 +77,9 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
77 if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; 77 if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
78 if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; 78 if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
79 prop = v; 79 prop = v;
80 break;
80 } 81 }
82 default: break;
81 } 83 }
82 prop.Detach(value); 84 prop.Detach(value);
83 return S_OK; 85 return S_OK;
@@ -96,6 +98,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
96 { 98 {
97 case kpidPackSize: if (_packSize_Defined) prop = _packSize; break; 99 case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;
98 case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break; 100 case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;
101 default: break;
99 } 102 }
100 prop.Detach(value); 103 prop.Detach(value);
101 return S_OK; 104 return S_OK;
@@ -175,8 +178,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
175 return E_INVALIDARG; 178 return E_INVALIDARG;
176 179
177 if (_packSize_Defined) 180 if (_packSize_Defined)
178 extractCallback->SetTotal(_packSize); 181 {
182 RINOK(extractCallback->SetTotal(_packSize))
183 }
179 184
185 Int32 opRes;
186 {
180 CMyComPtr<ISequentialOutStream> realOutStream; 187 CMyComPtr<ISequentialOutStream> realOutStream;
181 const Int32 askMode = testMode ? 188 const Int32 askMode = testMode ?
182 NExtract::NAskMode::kTest : 189 NExtract::NAskMode::kTest :
@@ -185,7 +192,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
185 if (!testMode && !realOutStream) 192 if (!testMode && !realOutStream)
186 return S_OK; 193 return S_OK;
187 194
188 extractCallback->PrepareOperation(askMode); 195 RINOK(extractCallback->PrepareOperation(askMode))
189 196
190 if (_needSeekToStart) 197 if (_needSeekToStart)
191 { 198 {
@@ -198,90 +205,85 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
198 205
199 // try { 206 // try {
200 207
201 NCompress::NBZip2::CDecoder *decoderSpec = new NCompress::NBZip2::CDecoder; 208 CMyComPtr2_Create<ICompressCoder, NCompress::NBZip2::CDecoder> decoder;
202 CMyComPtr<ICompressCoder> decoder = decoderSpec;
203 209
204 #ifndef Z7_ST 210 #ifndef Z7_ST
205 RINOK(decoderSpec->SetNumberOfThreads(_props._numThreads)) 211 RINOK(decoder->SetNumberOfThreads(_props._numThreads))
206 #endif 212 #endif
207 213
208 CDummyOutStream *outStreamSpec = new CDummyOutStream; 214 CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;
209 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); 215 outStream->SetStream(realOutStream);
210 outStreamSpec->SetStream(realOutStream); 216 outStream->Init();
211 outStreamSpec->Init(); 217 // realOutStream.Release();
212
213 realOutStream.Release();
214 218
215 CLocalProgress *lps = new CLocalProgress; 219 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
216 CMyComPtr<ICompressProgressInfo> progress = lps;
217 lps->Init(extractCallback, true); 220 lps->Init(extractCallback, true);
218 221
219 decoderSpec->FinishMode = true; 222 decoder->FinishMode = true;
220 decoderSpec->Base.DecodeAllStreams = true; 223 decoder->Base.DecodeAllStreams = true;
221 224
222 _dataAfterEnd = false; 225 _dataAfterEnd = false;
223 _needMoreInput = false; 226 _needMoreInput = false;
224 227
225 lps->InSize = 0; 228 HRESULT result = decoder.Interface()->Code(_seqStream, outStream, NULL, NULL, lps);
226 lps->OutSize = 0;
227
228 HRESULT result = decoder->Code(_seqStream, outStream, NULL, NULL, progress);
229 229
230 if (result != S_FALSE && result != S_OK) 230 if (result != S_FALSE && result != S_OK)
231 return result; 231 return result;
232 232
233 if (decoderSpec->Base.NumStreams == 0) 233 if (decoder->Base.NumStreams == 0)
234 { 234 {
235 _isArc = false; 235 _isArc = false;
236 result = S_FALSE; 236 result = S_FALSE;
237 } 237 }
238 else 238 else
239 { 239 {
240 const UInt64 inProcessedSize = decoderSpec->GetInputProcessedSize(); 240 const UInt64 inProcessedSize = decoder->GetInputProcessedSize();
241 UInt64 packSize = inProcessedSize; 241 UInt64 packSize = inProcessedSize;
242 242
243 if (decoderSpec->Base.NeedMoreInput) 243 if (decoder->Base.NeedMoreInput)
244 _needMoreInput = true; 244 _needMoreInput = true;
245 245
246 if (!decoderSpec->Base.IsBz) 246 if (!decoder->Base.IsBz)
247 { 247 {
248 packSize = decoderSpec->Base.FinishedPackSize; 248 packSize = decoder->Base.FinishedPackSize;
249 if (packSize != inProcessedSize) 249 if (packSize != inProcessedSize)
250 _dataAfterEnd = true; 250 _dataAfterEnd = true;
251 } 251 }
252 252
253 _packSize = packSize; 253 _packSize = packSize;
254 _unpackSize = decoderSpec->GetOutProcessedSize(); 254 _unpackSize = decoder->GetOutProcessedSize();
255 _numStreams = decoderSpec->Base.NumStreams; 255 _numStreams = decoder->Base.NumStreams;
256 _numBlocks = decoderSpec->GetNumBlocks(); 256 _numBlocks = decoder->GetNumBlocks();
257 257
258 _packSize_Defined = true; 258 _packSize_Defined = true;
259 _unpackSize_Defined = true; 259 _unpackSize_Defined = true;
260 _numStreams_Defined = true; 260 _numStreams_Defined = true;
261 _numBlocks_Defined = true; 261 _numBlocks_Defined = true;
262
263 // RINOK(
264 lps.Interface()->SetRatioInfo(&packSize, &_unpackSize);
262 } 265 }
263 266
264 outStream.Release(); 267 // outStream.Release();
265
266 Int32 opRes;
267 268
268 if (!_isArc) 269 if (!_isArc)
269 opRes = NExtract::NOperationResult::kIsNotArc; 270 opRes = NExtract::NOperationResult::kIsNotArc;
270 else if (_needMoreInput) 271 else if (_needMoreInput)
271 opRes = NExtract::NOperationResult::kUnexpectedEnd; 272 opRes = NExtract::NOperationResult::kUnexpectedEnd;
272 else if (decoderSpec->GetCrcError()) 273 else if (decoder->GetCrcError())
273 opRes = NExtract::NOperationResult::kCRCError; 274 opRes = NExtract::NOperationResult::kCRCError;
274 else if (_dataAfterEnd) 275 else if (_dataAfterEnd)
275 opRes = NExtract::NOperationResult::kDataAfterEnd; 276 opRes = NExtract::NOperationResult::kDataAfterEnd;
276 else if (result == S_FALSE) 277 else if (result == S_FALSE)
277 opRes = NExtract::NOperationResult::kDataError; 278 opRes = NExtract::NOperationResult::kDataError;
278 else if (decoderSpec->Base.MinorError) 279 else if (decoder->Base.MinorError)
279 opRes = NExtract::NOperationResult::kDataError; 280 opRes = NExtract::NOperationResult::kDataError;
280 else if (result == S_OK) 281 else if (result == S_OK)
281 opRes = NExtract::NOperationResult::kOK; 282 opRes = NExtract::NOperationResult::kOK;
282 else 283 else
283 return result; 284 return result;
284 285
286 }
285 return extractCallback->SetOperationResult(opRes); 287 return extractCallback->SetOperationResult(opRes);
286 288
287 // } catch(...) { return E_FAIL; } 289 // } catch(...) { return E_FAIL; }
@@ -352,14 +354,13 @@ static HRESULT UpdateArchive(
352 } 354 }
353 } 355 }
354 RINOK(updateCallback->SetTotal(unpackSize)) 356 RINOK(updateCallback->SetTotal(unpackSize))
355 CLocalProgress *localProgressSpec = new CLocalProgress; 357
356 CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec; 358 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
357 localProgressSpec->Init(updateCallback, true); 359 lps->Init(updateCallback, true);
358 { 360 {
359 NCompress::NBZip2::CEncoder *encoderSpec = new NCompress::NBZip2::CEncoder; 361 CMyComPtr2_Create<ICompressCoder, NCompress::NBZip2::CEncoder> encoder;
360 CMyComPtr<ICompressCoder> encoder = encoderSpec; 362 RINOK(props.SetCoderProps(encoder.ClsPtr(), NULL))
361 RINOK(props.SetCoderProps(encoderSpec, NULL)) 363 RINOK(encoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps))
362 RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress))
363 /* 364 /*
364 if (reportArcProp) 365 if (reportArcProp)
365 { 366 {
@@ -436,8 +437,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
436 if (indexInArchive != 0) 437 if (indexInArchive != 0)
437 return E_INVALIDARG; 438 return E_INVALIDARG;
438 439
439 CLocalProgress *lps = new CLocalProgress; 440 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
440 CMyComPtr<ICompressProgressInfo> progress = lps;
441 lps->Init(updateCallback, true); 441 lps->Init(updateCallback, true);
442 442
443 Z7_DECL_CMyComPtr_QI_FROM( 443 Z7_DECL_CMyComPtr_QI_FROM(
@@ -453,7 +453,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
453 if (_stream) 453 if (_stream)
454 RINOK(InStream_SeekToBegin(_stream)) 454 RINOK(InStream_SeekToBegin(_stream))
455 455
456 return NCompress::CopyStream(_stream, outStream, progress); 456 return NCompress::CopyStream(_stream, outStream, lps);
457 457
458 // return ReportArcProps(reportArcProp, NULL, NULL); 458 // return ReportArcProps(reportArcProp, NULL, NULL);
459 459
diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
index dc767a4..5e1fe8b 100644
--- a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
+++ b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
@@ -12,89 +12,111 @@
12namespace NArchive { 12namespace NArchive {
13namespace NCab { 13namespace NCab {
14 14
15static const UInt32 kBlockSize = (1 << 16); 15static const UInt32 kBlockSize = 1 << 16;
16static const unsigned k_OverReadPadZone_Size = 32;
17static const unsigned kHeaderSize = 8;
18static const unsigned kReservedMax = 256;
19static const unsigned kHeaderOffset = kBlockSize + k_OverReadPadZone_Size;
16 20
17bool CCabBlockInStream::Create() 21bool CBlockPackData::Create() throw()
18{ 22{
19 if (!_buf) 23 if (!_buf)
20 _buf = (Byte *)::MyAlloc(kBlockSize); 24 _buf = (Byte *)z7_AlignedAlloc(kBlockSize + k_OverReadPadZone_Size + kHeaderSize + kReservedMax);
21 return _buf != NULL; 25 return _buf != NULL;
22} 26}
23 27
24CCabBlockInStream::~CCabBlockInStream() 28CBlockPackData::~CBlockPackData() throw()
25{ 29{
26 ::MyFree(_buf); 30 z7_AlignedFree(_buf);
27} 31}
28 32
29static UInt32 CheckSum(const Byte *p, UInt32 size) 33static UInt32 CheckSum(const Byte *p, UInt32 size) throw()
30{ 34{
35#ifdef MY_CPU_64BIT
36
37 UInt64 sum64 = 0;
38 if (size >= 16)
39 {
40 const Byte *lim = p + (size_t)size - 16;
41 do
42 {
43 sum64 ^= GetUi64(p) ^ GetUi64(p + 8);
44 p += 16;
45 }
46 while (p <= lim);
47 size = (UInt32)(lim + 16 - p);
48 }
49 if (size >= 8)
50 {
51 sum64 ^= GetUi64(p);
52 p += 8;
53 size -= 8;
54 }
55
56 UInt32 sum = (UInt32)(sum64 >> 32) ^ (UInt32)sum64;
57
58#else
59
31 UInt32 sum = 0; 60 UInt32 sum = 0;
32 61 if (size >= 16)
33 for (; size >= 8; size -= 8) 62 {
63 const Byte *lim = p + (size_t)size - 16;
64 do
65 {
66 sum ^= GetUi32(p)
67 ^ GetUi32(p + 4)
68 ^ GetUi32(p + 8)
69 ^ GetUi32(p + 12);
70 p += 16;
71 }
72 while (p <= lim);
73 size = (UInt32)(lim + 16 - p);
74 }
75 if (size >= 8)
34 { 76 {
35 sum ^= GetUi32(p) ^ GetUi32(p + 4); 77 sum ^= GetUi32(p + 0) ^ GetUi32(p + 4);
36 p += 8; 78 p += 8;
79 size -= 8;
37 } 80 }
81
82#endif
38 83
39 if (size >= 4) 84 if (size >= 4)
40 { 85 {
41 sum ^= GetUi32(p); 86 sum ^= GetUi32(p);
42 p += 4; 87 p += 4;
43 } 88 }
44 89 if (size &= 3)
45 size &= 3; 90 {
46 if (size > 2) sum ^= (UInt32)(*p++) << 16; 91 if (size >= 2)
47 if (size > 1) sum ^= (UInt32)(*p++) << 8; 92 {
48 if (size > 0) sum ^= (UInt32)(*p++); 93 if (size > 2)
49 94 sum ^= (UInt32)(*p++) << 16;
95 sum ^= (UInt32)(*p++) << 8;
96 }
97 sum ^= (UInt32)(*p++);
98 }
50 return sum; 99 return sum;
51} 100}
52 101
53HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize) 102
103HRESULT CBlockPackData::Read(ISequentialInStream *stream, Byte ReservedSize, UInt32 &packSizeRes, UInt32 &unpackSize) throw()
54{ 104{
55 const UInt32 kHeaderSize = 8; 105 const UInt32 reserved8 = kHeaderSize + ReservedSize;
56 const UInt32 kReservedMax = 256; 106 const Byte *header = _buf + kHeaderOffset;
57 Byte header[kHeaderSize + kReservedMax]; 107 RINOK(ReadStream_FALSE(stream, (void *)header, reserved8))
58 RINOK(ReadStream_FALSE(stream, header, kHeaderSize + ReservedSize)) 108 unpackSize = GetUi16a(header + 6);
59 packSize = GetUi16(header + 4); 109 const UInt32 packSize = GetUi16a(header + 4);
60 unpackSize = GetUi16(header + 6); 110 packSizeRes = packSize;
61 if (packSize > kBlockSize - _size) 111 if (packSize > kBlockSize - _size)
62 return S_FALSE; 112 return S_FALSE;
63 RINOK(ReadStream_FALSE(stream, _buf + _size, packSize)) 113 RINOK(ReadStream_FALSE(stream, _buf + _size, packSize))
64 114 memset(_buf + _size + packSize, 0xff, k_OverReadPadZone_Size);
65 if (MsZip) 115 if (*(const UInt32 *)(const void *)header != 0) // checkSum
66 { 116 if (CheckSum(header, reserved8) != CheckSum(_buf + _size, packSize))
67 if (_size == 0)
68 {
69 if (packSize < 2 || _buf[0] != 0x43 || _buf[1] != 0x4B)
70 return S_FALSE;
71 _pos = 2;
72 }
73 if (_size + packSize > ((UInt32)1 << 15) + 12) /* v9.31 fix. MSZIP specification */
74 return S_FALSE;
75 }
76
77 if (GetUi32(header) != 0) // checkSum
78 if (CheckSum(header, kHeaderSize + ReservedSize) != CheckSum(_buf + _size, packSize))
79 return S_FALSE; 117 return S_FALSE;
80
81 _size += packSize; 118 _size += packSize;
82 return S_OK; 119 return S_OK;
83} 120}
84 121
85Z7_COM7F_IMF(CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
86{
87 if (size != 0)
88 {
89 UInt32 rem = _size - _pos;
90 if (size > rem)
91 size = rem;
92 memcpy(data, _buf + _pos, size);
93 _pos += size;
94 }
95 if (processedSize)
96 *processedSize = size;
97 return S_OK;
98}
99
100}} 122}}
diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.h b/CPP/7zip/Archive/Cab/CabBlockInStream.h
index d14fff8..7568779 100644
--- a/CPP/7zip/Archive/Cab/CabBlockInStream.h
+++ b/CPP/7zip/Archive/Cab/CabBlockInStream.h
@@ -3,35 +3,24 @@
3#ifndef ZIP7_INC_CAB_BLOCK_IN_STREAM_H 3#ifndef ZIP7_INC_CAB_BLOCK_IN_STREAM_H
4#define ZIP7_INC_CAB_BLOCK_IN_STREAM_H 4#define ZIP7_INC_CAB_BLOCK_IN_STREAM_H
5 5
6#include "../../../Common/MyCom.h"
7#include "../../IStream.h" 6#include "../../IStream.h"
8 7
9namespace NArchive { 8namespace NArchive {
10namespace NCab { 9namespace NCab {
11 10
12Z7_CLASS_IMP_NOQIB_1( 11class CBlockPackData
13 CCabBlockInStream 12{
14 , ISequentialInStream
15)
16 Byte *_buf; 13 Byte *_buf;
17 UInt32 _size; 14 UInt32 _size;
18 UInt32 _pos;
19
20public: 15public:
21 UInt32 ReservedSize; // < 256 16 CBlockPackData(): _buf(NULL), _size(0) {}
22 bool MsZip; 17 ~CBlockPackData() throw();
23 18 bool Create() throw();
24 CCabBlockInStream(): _buf(NULL), ReservedSize(0), MsZip(false) {} 19 void InitForNewBlock() { _size = 0; }
25 ~CCabBlockInStream(); 20 HRESULT Read(ISequentialInStream *stream, Byte ReservedSize, UInt32 &packSize, UInt32 &unpackSize) throw();
26 21 UInt32 GetPackSize() const { return _size; }
27 bool Create(); 22 // 32 bytes of overread zone is available after PackSize:
28 23 const Byte *GetData() const { return _buf; }
29 void InitForNewBlock() { _size = 0; _pos = 0; }
30
31 HRESULT PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize);
32
33 UInt32 GetPackSizeAvail() const { return _size - _pos; }
34 const Byte *GetData() const { return _buf + _pos; }
35}; 24};
36 25
37}} 26}}
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp
index f015145..0ad2a0e 100644
--- a/CPP/7zip/Archive/Cab/CabHandler.cpp
+++ b/CPP/7zip/Archive/Cab/CabHandler.cpp
@@ -5,7 +5,9 @@
5// #include <stdio.h> 5// #include <stdio.h>
6 6
7#include "../../../../C/Alloc.h" 7#include "../../../../C/Alloc.h"
8#include "../../../../C/CpuArch.h"
8 9
10#include "../../../Common/AutoPtr.h"
9#include "../../../Common/ComTry.h" 11#include "../../../Common/ComTry.h"
10#include "../../../Common/IntToString.h" 12#include "../../../Common/IntToString.h"
11#include "../../../Common/StringConvert.h" 13#include "../../../Common/StringConvert.h"
@@ -15,9 +17,9 @@
15#include "../../../Windows/TimeUtils.h" 17#include "../../../Windows/TimeUtils.h"
16 18
17#include "../../Common/ProgressUtils.h" 19#include "../../Common/ProgressUtils.h"
20#include "../../Common/StreamObjects.h"
18#include "../../Common/StreamUtils.h" 21#include "../../Common/StreamUtils.h"
19 22
20#include "../../Compress/CopyCoder.h"
21#include "../../Compress/DeflateDecoder.h" 23#include "../../Compress/DeflateDecoder.h"
22#include "../../Compress/LzxDecoder.h" 24#include "../../Compress/LzxDecoder.h"
23#include "../../Compress/QuantumDecoder.h" 25#include "../../Compress/QuantumDecoder.h"
@@ -112,14 +114,14 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
112 FOR_VECTOR (i, folders) 114 FOR_VECTOR (i, folders)
113 { 115 {
114 const CFolder &folder = folders[i]; 116 const CFolder &folder = folders[i];
115 unsigned method = folder.GetMethod(); 117 const unsigned method = folder.GetMethod();
116 mask |= ((UInt32)1 << method); 118 mask |= ((UInt32)1 << method);
117 if (method == NHeader::NMethod::kLZX || 119 if (method == NHeader::NMethod::kLZX ||
118 method == NHeader::NMethod::kQuantum) 120 method == NHeader::NMethod::kQuantum)
119 { 121 {
120 unsigned di = (method == NHeader::NMethod::kQuantum) ? 0 : 1; 122 const unsigned di = (method == NHeader::NMethod::kQuantum) ? 0 : 1;
121 if (params[di] < folder.MethodMinor) 123 if (params[di] < folder.MethodMinor)
122 params[di] = folder.MethodMinor; 124 params[di] = folder.MethodMinor;
123 } 125 }
124 } 126 }
125 } 127 }
@@ -227,7 +229,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
227 { 229 {
228 AString s; 230 AString s;
229 s.Add_UInt32(ai.SetID); 231 s.Add_UInt32(ai.SetID);
230 s += '_'; 232 s.Add_Char('_');
231 s.Add_UInt32(ai.CabinetNumber + 1); 233 s.Add_UInt32(ai.CabinetNumber + 1);
232 s += ".cab"; 234 s += ".cab";
233 prop = s; 235 prop = s;
@@ -261,6 +263,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
261 } 263 }
262 264
263 // case kpidShortComment: 265 // case kpidShortComment:
266 default: break;
264 } 267 }
265 prop.Detach(value); 268 prop.Detach(value);
266 return S_OK; 269 return S_OK;
@@ -274,7 +277,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
274 277
275 const CMvItem &mvItem = m_Database.Items[index]; 278 const CMvItem &mvItem = m_Database.Items[index];
276 const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex]; 279 const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];
277 unsigned itemIndex = mvItem.ItemIndex; 280 const unsigned itemIndex = mvItem.ItemIndex;
278 const CItem &item = db.Items[itemIndex]; 281 const CItem &item = db.Items[itemIndex];
279 switch (propID) 282 switch (propID)
280 { 283 {
@@ -321,6 +324,8 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
321 case kpidVolume: prop = (UInt32)mvItem.VolumeIndex; break; 324 case kpidVolume: prop = (UInt32)mvItem.VolumeIndex; break;
322 325
323 #endif 326 #endif
327
328 default: break;
324 } 329 }
325 prop.Detach(value); 330 prop.Detach(value);
326 return S_OK; 331 return S_OK;
@@ -361,7 +366,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
361 if (res == S_OK && !m_Database.Volumes.IsEmpty()) 366 if (res == S_OK && !m_Database.Volumes.IsEmpty())
362 { 367 {
363 const CArchInfo &lastArc = m_Database.Volumes.Back().ArcInfo; 368 const CArchInfo &lastArc = m_Database.Volumes.Back().ArcInfo;
364 unsigned cabNumber = db.ArcInfo.CabinetNumber; 369 const unsigned cabNumber = db.ArcInfo.CabinetNumber;
365 if (lastArc.SetID != db.ArcInfo.SetID) 370 if (lastArc.SetID != db.ArcInfo.SetID)
366 res = S_FALSE; 371 res = S_FALSE;
367 else if (prevChecked) 372 else if (prevChecked)
@@ -479,7 +484,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
479 break; 484 break;
480 } 485 }
481 486
482 HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); 487 const HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
483 if (result == S_OK) 488 if (result == S_OK)
484 break; 489 break;
485 if (result != S_FALSE) 490 if (result != S_FALSE)
@@ -539,6 +544,11 @@ Z7_CLASS_IMP_NOQIB_1(
539 CFolderOutStream 544 CFolderOutStream
540 , ISequentialOutStream 545 , ISequentialOutStream
541) 546)
547 bool m_TestMode;
548 bool TempBufMode;
549 bool m_IsOk;
550 bool m_FileIsOpen;
551
542 const CMvDatabaseEx *m_Database; 552 const CMvDatabaseEx *m_Database;
543 const CRecordVector<bool> *m_ExtractStatuses; 553 const CRecordVector<bool> *m_ExtractStatuses;
544 554
@@ -546,21 +556,18 @@ Z7_CLASS_IMP_NOQIB_1(
546 UInt32 TempBufSize; 556 UInt32 TempBufSize;
547 UInt32 TempBufWritten; 557 UInt32 TempBufWritten;
548 unsigned NumIdenticalFiles; 558 unsigned NumIdenticalFiles;
549 bool TempBufMode;
550 559
551 unsigned m_StartIndex; 560 unsigned m_StartIndex;
552 unsigned m_CurrentIndex; 561 unsigned m_CurrentIndex;
553 CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;
554 bool m_TestMode;
555 562
556 CMyComPtr<ISequentialOutStream> m_RealOutStream;
557
558 bool m_IsOk;
559 bool m_FileIsOpen;
560 UInt32 m_RemainFileSize; 563 UInt32 m_RemainFileSize;
564
561 UInt64 m_FolderSize; 565 UInt64 m_FolderSize;
562 UInt64 m_PosInFolder; 566 UInt64 m_PosInFolder;
563 567
568 CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;
569 CMyComPtr<ISequentialOutStream> m_RealOutStream;
570
564 void FreeTempBuf() 571 void FreeTempBuf()
565 { 572 {
566 ::MyFree(TempBuf); 573 ::MyFree(TempBuf);
@@ -707,10 +714,10 @@ HRESULT CFolderOutStream::WriteEmptyFiles()
707 { 714 {
708 const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; 715 const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
709 const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; 716 const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
710 UInt64 fileSize = item.Size; 717 const UInt64 fileSize = item.Size;
711 if (fileSize != 0) 718 if (fileSize != 0)
712 return S_OK; 719 return S_OK;
713 HRESULT result = OpenFile(); 720 const HRESULT result = OpenFile();
714 m_RealOutStream.Release(); 721 m_RealOutStream.Release();
715 RINOK(result) 722 RINOK(result)
716 RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 723 RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
@@ -819,14 +826,14 @@ Z7_COM7F_IMF(CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc
819 826
820 m_RemainFileSize = item.Size; 827 m_RemainFileSize = item.Size;
821 828
822 UInt32 fileOffset = item.Offset; 829 const UInt32 fileOffset = item.Offset;
823 830
824 if (fileOffset < m_PosInFolder) 831 if (fileOffset < m_PosInFolder)
825 return E_FAIL; 832 return E_FAIL;
826 833
827 if (fileOffset > m_PosInFolder) 834 if (fileOffset > m_PosInFolder)
828 { 835 {
829 UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size); 836 const UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size);
830 realProcessed += numBytesToWrite; 837 realProcessed += numBytesToWrite;
831 if (processedSize) 838 if (processedSize)
832 *processedSize = realProcessed; 839 *processedSize = realProcessed;
@@ -869,7 +876,7 @@ HRESULT CFolderOutStream::FlushCorrupted(unsigned folderIndex)
869 { 876 {
870 if (!NeedMoreWrite()) 877 if (!NeedMoreWrite())
871 return S_OK; 878 return S_OK;
872 UInt64 remain = GetRemain(); 879 const UInt64 remain = GetRemain();
873 UInt32 size = (UInt32)1 << 20; 880 UInt32 size = (UInt32)1 << 20;
874 if (size > remain) 881 if (size > remain)
875 size = (UInt32)remain; 882 size = (UInt32)remain;
@@ -883,7 +890,7 @@ HRESULT CFolderOutStream::Unsupported()
883{ 890{
884 while (m_CurrentIndex < m_ExtractStatuses->Size()) 891 while (m_CurrentIndex < m_ExtractStatuses->Size())
885 { 892 {
886 HRESULT result = OpenFile(); 893 const HRESULT result = OpenFile();
887 if (result != S_FALSE && result != S_OK) 894 if (result != S_FALSE && result != S_OK)
888 return result; 895 return result;
889 m_RealOutStream.Release(); 896 m_RealOutStream.Release();
@@ -895,7 +902,7 @@ HRESULT CFolderOutStream::Unsupported()
895 902
896 903
897Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, 904Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
898 Int32 testModeSpec, IArchiveExtractCallback *extractCallback)) 905 Int32 testMode, IArchiveExtractCallback *extractCallback))
899{ 906{
900 COM_TRY_BEGIN 907 COM_TRY_BEGIN
901 const bool allFilesMode = (numItems == (UInt32)(Int32)-1); 908 const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
@@ -903,7 +910,6 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
903 numItems = m_Database.Items.Size(); 910 numItems = m_Database.Items.Size();
904 if (numItems == 0) 911 if (numItems == 0)
905 return S_OK; 912 return S_OK;
906 bool testMode = (testModeSpec != 0);
907 UInt64 totalUnPacked = 0; 913 UInt64 totalUnPacked = 0;
908 914
909 UInt32 i; 915 UInt32 i;
@@ -912,12 +918,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
912 918
913 for (i = 0; i < numItems; i++) 919 for (i = 0; i < numItems; i++)
914 { 920 {
915 unsigned index = allFilesMode ? i : indices[i]; 921 const unsigned index = allFilesMode ? i : indices[i];
916 const CMvItem &mvItem = m_Database.Items[index]; 922 const CMvItem &mvItem = m_Database.Items[index];
917 const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; 923 const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
918 if (item.IsDir()) 924 if (item.IsDir())
919 continue; 925 continue;
920 int folderIndex = m_Database.GetFolderIndex(&mvItem); 926 const int folderIndex = m_Database.GetFolderIndex(&mvItem);
921 if (folderIndex != lastFolder) 927 if (folderIndex != lastFolder)
922 totalUnPacked += lastFolderSize; 928 totalUnPacked += lastFolderSize;
923 lastFolder = folderIndex; 929 lastFolder = folderIndex;
@@ -925,42 +931,31 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
925 } 931 }
926 932
927 totalUnPacked += lastFolderSize; 933 totalUnPacked += lastFolderSize;
934 RINOK(extractCallback->SetTotal(totalUnPacked))
928 935
929 extractCallback->SetTotal(totalUnPacked); 936 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
930
931 totalUnPacked = 0;
932
933 UInt64 totalPacked = 0;
934
935 CLocalProgress *lps = new CLocalProgress;
936 CMyComPtr<ICompressProgressInfo> progress = lps;
937 lps->Init(extractCallback, false); 937 lps->Init(extractCallback, false);
938 938
939 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 939 CMyComPtr2<ICompressCoder, NCompress::NDeflate::NDecoder::CCOMCoder> deflateDecoder;
940 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 940 CMyUniquePtr<NCompress::NLzx::CDecoder> lzxDecoder;
941 941 CMyUniquePtr<NCompress::NQuantum::CDecoder> quantumDecoder;
942 NCompress::NDeflate::NDecoder::CCOMCoder *deflateDecoderSpec = NULL;
943 CMyComPtr<ICompressCoder> deflateDecoder;
944
945 NCompress::NLzx::CDecoder *lzxDecoderSpec = NULL;
946 CMyComPtr<IUnknown> lzxDecoder;
947
948 NCompress::NQuantum::CDecoder *quantumDecoderSpec = NULL;
949 CMyComPtr<IUnknown> quantumDecoder;
950 942
951 CCabBlockInStream *cabBlockInStreamSpec = new CCabBlockInStream(); 943 CBlockPackData blockPackData;
952 CMyComPtr<ISequentialInStream> cabBlockInStream = cabBlockInStreamSpec; 944 if (!blockPackData.Create())
953 if (!cabBlockInStreamSpec->Create())
954 return E_OUTOFMEMORY; 945 return E_OUTOFMEMORY;
955 946
947 CMyComPtr2_Create<ISequentialInStream, CBufInStream> inBufStream;
948
956 CRecordVector<bool> extractStatuses; 949 CRecordVector<bool> extractStatuses;
950
951 totalUnPacked = 0;
952 UInt64 totalPacked = 0;
957 953
958 for (i = 0;;) 954 for (i = 0;;)
959 { 955 {
960 lps->OutSize = totalUnPacked; 956 lps->OutSize = totalUnPacked;
961 lps->InSize = totalPacked; 957 lps->InSize = totalPacked;
962 RINOK(lps->SetCur()) 958 RINOK(lps->SetCur())
963
964 if (i >= numItems) 959 if (i >= numItems)
965 break; 960 break;
966 961
@@ -1028,8 +1023,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1028 curUnpack = item2.GetEndOffset(); 1023 curUnpack = item2.GetEndOffset();
1029 } 1024 }
1030 1025
1031 CFolderOutStream *cabFolderOutStream = new CFolderOutStream; 1026 CMyComPtr2_Create<ISequentialOutStream, CFolderOutStream> cabFolderOutStream;
1032 CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream);
1033 1027
1034 const int folderIndex2 = item.GetFolderIndex(db.Folders.Size()); 1028 const int folderIndex2 = item.GetFolderIndex(db.Folders.Size());
1035 if (folderIndex2 < 0) 1029 if (folderIndex2 < 0)
@@ -1037,9 +1031,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1037 const CFolder &folder = db.Folders[(unsigned)folderIndex2]; 1031 const CFolder &folder = db.Folders[(unsigned)folderIndex2];
1038 1032
1039 cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2, 1033 cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2,
1040 curUnpack, extractCallback, testMode); 1034 curUnpack, extractCallback, testMode != 0);
1041 1035
1042 cabBlockInStreamSpec->MsZip = false;
1043 HRESULT res = S_OK; 1036 HRESULT res = S_OK;
1044 1037
1045 switch (folder.GetMethod()) 1038 switch (folder.GetMethod())
@@ -1048,30 +1041,17 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1048 break; 1041 break;
1049 1042
1050 case NHeader::NMethod::kMSZip: 1043 case NHeader::NMethod::kMSZip:
1051 if (!deflateDecoder) 1044 deflateDecoder.Create_if_Empty();
1052 {
1053 deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder;
1054 deflateDecoder = deflateDecoderSpec;
1055 }
1056 cabBlockInStreamSpec->MsZip = true;
1057 break; 1045 break;
1058 1046
1059 case NHeader::NMethod::kLZX: 1047 case NHeader::NMethod::kLZX:
1060 if (!lzxDecoder) 1048 lzxDecoder.Create_if_Empty();
1061 { 1049 res = lzxDecoder->Set_DictBits_and_Alloc(folder.MethodMinor);
1062 lzxDecoderSpec = new NCompress::NLzx::CDecoder;
1063 lzxDecoder = lzxDecoderSpec;
1064 }
1065 res = lzxDecoderSpec->SetParams_and_Alloc(folder.MethodMinor);
1066 break; 1050 break;
1067 1051
1068 case NHeader::NMethod::kQuantum: 1052 case NHeader::NMethod::kQuantum:
1069 if (!quantumDecoder) 1053 quantumDecoder.Create_if_Empty();
1070 { 1054 res = quantumDecoder->SetParams(folder.MethodMinor);
1071 quantumDecoderSpec = new NCompress::NQuantum::CDecoder;
1072 quantumDecoder = quantumDecoderSpec;
1073 }
1074 res = quantumDecoderSpec->SetParams(folder.MethodMinor);
1075 break; 1055 break;
1076 1056
1077 default: 1057 default:
@@ -1109,7 +1089,6 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1109 1089
1110 if (bl == 0) 1090 if (bl == 0)
1111 { 1091 {
1112 cabBlockInStreamSpec->ReservedSize = db2.ArcInfo.GetDataBlockReserveSize();
1113 RINOK(InStream_SeekSet(db2.Stream, db2.StartPosition + folder2.DataStart)) 1092 RINOK(InStream_SeekSet(db2.Stream, db2.StartPosition + folder2.DataStart))
1114 } 1093 }
1115 1094
@@ -1135,10 +1114,10 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1135 bl++; 1114 bl++;
1136 1115
1137 if (!keepInputBuffer) 1116 if (!keepInputBuffer)
1138 cabBlockInStreamSpec->InitForNewBlock(); 1117 blockPackData.InitForNewBlock();
1139 1118
1140 UInt32 packSize, unpackSize; 1119 UInt32 packSize, unpackSize;
1141 res = cabBlockInStreamSpec->PreRead(db2.Stream, packSize, unpackSize); 1120 res = blockPackData.Read(db2.Stream, db2.ArcInfo.GetDataBlockReserveSize(), packSize, unpackSize);
1142 if (res == S_FALSE) 1121 if (res == S_FALSE)
1143 break; 1122 break;
1144 RINOK(res) 1123 RINOK(res)
@@ -1146,30 +1125,22 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1146 if (keepInputBuffer) 1125 if (keepInputBuffer)
1147 continue; 1126 continue;
1148 1127
1149 UInt64 totalUnPacked2 = totalUnPacked + cabFolderOutStream->GetPosInFolder(); 1128 const UInt64 totalUnPacked2 = totalUnPacked + cabFolderOutStream->GetPosInFolder();
1150 totalPacked += packSize; 1129 totalPacked += packSize;
1151 1130
1152 lps->OutSize = totalUnPacked2; 1131 if (totalUnPacked2 - lps->OutSize >= (1 << 26)
1153 lps->InSize = totalPacked; 1132 || totalPacked - lps->InSize >= (1 << 24))
1154 RINOK(lps->SetCur())
1155
1156 const UInt32 kBlockSizeMax = (1 << 15);
1157
1158 /* We don't try to reduce last block.
1159 Note that LZX converts data with x86 filter.
1160 and filter needs larger input data than reduced size.
1161 It's simpler to decompress full chunk here.
1162 also we need full block for quantum for more integrity checks */
1163
1164 if (unpackSize > kBlockSizeMax)
1165 { 1133 {
1166 res = S_FALSE; 1134 lps->OutSize = totalUnPacked2;
1167 break; 1135 lps->InSize = totalPacked;
1136 RINOK(lps->SetCur())
1168 } 1137 }
1169 1138
1139 const unsigned kBlockSizeMax = 1u << 15;
1140
1170 if (unpackSize != kBlockSizeMax) 1141 if (unpackSize != kBlockSizeMax)
1171 { 1142 {
1172 if (thereWasNotAlignedChunk) 1143 if (unpackSize > kBlockSizeMax || thereWasNotAlignedChunk)
1173 { 1144 {
1174 res = S_FALSE; 1145 res = S_FALSE;
1175 break; 1146 break;
@@ -1177,55 +1148,95 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1177 thereWasNotAlignedChunk = true; 1148 thereWasNotAlignedChunk = true;
1178 } 1149 }
1179 1150
1180 UInt64 unpackSize64 = unpackSize; 1151 /* We don't try to reduce last block.
1181 UInt32 packSizeChunk = cabBlockInStreamSpec->GetPackSizeAvail(); 1152 Note that LZX converts data with x86 filter.
1153 and filter needs larger input data than reduced size.
1154 It's simpler to decompress full chunk here.
1155 also we need full block for quantum for more integrity checks */
1156
1157 const UInt64 unpackSize64 = unpackSize;
1158 const UInt32 packSizeChunk = blockPackData.GetPackSize();
1182 1159
1183 switch (folder2.GetMethod()) 1160 switch (folder2.GetMethod())
1184 { 1161 {
1185 case NHeader::NMethod::kNone: 1162 case NHeader::NMethod::kNone:
1186 res = copyCoder->Code(cabBlockInStream, outStream, NULL, &unpackSize64, NULL); 1163 if (unpackSize != packSizeChunk)
1164 {
1165 res = S_FALSE;
1166 break;
1167 }
1168 res = WriteStream(cabFolderOutStream, blockPackData.GetData(), packSizeChunk);
1187 break; 1169 break;
1188 1170
1189 case NHeader::NMethod::kMSZip: 1171 case NHeader::NMethod::kMSZip:
1190 deflateDecoderSpec->Set_KeepHistory(keepHistory); 1172 {
1191 /* v9.31: now we follow MSZIP specification that requires to finish deflate stream at the end of each block. 1173 /* v24.00 : fixed : we check 2-bytes MSZIP signature only
1192 But PyCabArc can create CAB archives that doesn't have finish marker at the end of block. 1174 when block was constructed from all volumes. */
1175 const Byte *packData = blockPackData.GetData();
1176 if (unpackSize > (1u << 15) + 12 /* MSZIP specification */
1177 || packSizeChunk < 2 || GetUi16(packData) != 0x4b43)
1178 {
1179 res = S_FALSE;
1180 break;
1181 }
1182 const UInt32 packSizeChunk_2 = packSizeChunk - 2;
1183 inBufStream->Init(packData + 2, packSizeChunk_2);
1184
1185 deflateDecoder->Set_KeepHistory(keepHistory);
1186 /* v9.31: now we follow MSZIP specification that requires
1187 to finish deflate stream at the end of each block.
1188 But PyCabArc can create CAB archives that don't have
1189 finish marker at the end of block.
1193 Cabarc probably ignores such errors in cab archives. 1190 Cabarc probably ignores such errors in cab archives.
1194 Maybe we also should ignore that error? 1191 Maybe we also should ignore such error?
1195 Or we should extract full file and show the warning? */ 1192 Or we should extract full file and show the warning? */
1196 deflateDecoderSpec->Set_NeedFinishInput(true); 1193 deflateDecoder->Set_NeedFinishInput(true);
1197 res = deflateDecoder->Code(cabBlockInStream, outStream, NULL, &unpackSize64, NULL); 1194 res = deflateDecoder.Interface()->Code(inBufStream, cabFolderOutStream, NULL, &unpackSize64, NULL);
1198 if (res == S_OK) 1195 if (res == S_OK)
1199 { 1196 {
1200 if (!deflateDecoderSpec->IsFinished()) 1197 if (!deflateDecoder->IsFinished())
1198 res = S_FALSE;
1199 if (!deflateDecoder->IsFinalBlock())
1201 res = S_FALSE; 1200 res = S_FALSE;
1202 if (!deflateDecoderSpec->IsFinalBlock()) 1201 if (deflateDecoder->GetInputProcessedSize() != packSizeChunk_2)
1203 res = S_FALSE; 1202 res = S_FALSE;
1204 } 1203 }
1205 break; 1204 break;
1205 }
1206 1206
1207 case NHeader::NMethod::kLZX: 1207 case NHeader::NMethod::kLZX:
1208 lzxDecoderSpec->SetKeepHistory(keepHistory); 1208 lzxDecoder->Set_KeepHistory(keepHistory);
1209 lzxDecoderSpec->KeepHistoryForNext = true; 1209 lzxDecoder->Set_KeepHistoryForNext(true);
1210 1210 res = lzxDecoder->Code_WithExceedReadWrite(blockPackData.GetData(),
1211 res = lzxDecoderSpec->Code(cabBlockInStreamSpec->GetData(), packSizeChunk, unpackSize); 1211 packSizeChunk, unpackSize);
1212
1213 if (res == S_OK) 1212 if (res == S_OK)
1214 res = WriteStream(outStream, 1213 res = WriteStream(cabFolderOutStream,
1215 lzxDecoderSpec->GetUnpackData(), 1214 lzxDecoder->GetUnpackData(),
1216 lzxDecoderSpec->GetUnpackSize()); 1215 lzxDecoder->GetUnpackSize());
1217 break; 1216 break;
1218 1217
1219 case NHeader::NMethod::kQuantum: 1218 case NHeader::NMethod::kQuantum:
1220 res = quantumDecoderSpec->Code(cabBlockInStreamSpec->GetData(), 1219 {
1221 packSizeChunk, outStream, unpackSize, keepHistory); 1220 res = quantumDecoder->Code(blockPackData.GetData(),
1221 packSizeChunk, unpackSize, keepHistory);
1222 if (res == S_OK)
1223 {
1224 const UInt32 num = unpackSize;
1225 res = WriteStream(cabFolderOutStream,
1226 quantumDecoder->GetDataPtr() - num, num);
1227 }
1228 break;
1229 }
1230 default:
1231 // it's unexpected case, because we checked method before
1232 // res = E_NOTIMPL;
1222 break; 1233 break;
1223 } 1234 }
1224 1235
1225 if (res != S_OK) 1236 if (res != S_OK)
1226 { 1237 {
1227 if (res != S_FALSE) 1238 if (res != S_FALSE)
1228 RINOK(res) 1239 return res;
1229 break; 1240 break;
1230 } 1241 }
1231 1242
diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp
index fb69643..bd6969a 100644
--- a/CPP/7zip/Archive/Cab/CabIn.cpp
+++ b/CPP/7zip/Archive/Cab/CabIn.cpp
@@ -80,11 +80,10 @@ struct CSignatureFinder
80 UInt32 _alignSize; 80 UInt32 _alignSize;
81 UInt32 _bufUseCapacity; 81 UInt32 _bufUseCapacity;
82 82
83 const UInt64 *SearchLimit;
83 ISequentialInStream *Stream; 84 ISequentialInStream *Stream;
84 UInt64 Processed; // Global offset of start of Buf 85 UInt64 Processed; // Global offset of start of Buf
85 86
86 const UInt64 *SearchLimit;
87
88 UInt32 GetTotalCapacity(UInt32 basicSize, UInt32 headerSize) 87 UInt32 GetTotalCapacity(UInt32 basicSize, UInt32 headerSize)
89 { 88 {
90 _headerSize = headerSize; 89 _headerSize = headerSize;
@@ -111,7 +110,7 @@ HRESULT CSignatureFinder::Find()
111 while (End - Pos >= _headerSize) 110 while (End - Pos >= _headerSize)
112 { 111 {
113 const Byte *p = Buf + Pos; 112 const Byte *p = Buf + Pos;
114 Byte b = Signature[0]; 113 const Byte b = Signature[0];
115 for (;;) 114 for (;;)
116 { 115 {
117 if (*p == b) { break; } p++; 116 if (*p == b) { break; } p++;
@@ -132,7 +131,7 @@ HRESULT CSignatureFinder::Find()
132 131
133 if (Pos >= _alignSize) 132 if (Pos >= _alignSize)
134 { 133 {
135 UInt32 num = (Pos & ~(_alignSize - 1)); 134 const UInt32 num = (Pos & ~(_alignSize - 1));
136 Processed += num; 135 Processed += num;
137 Pos -= num; 136 Pos -= num;
138 End -= num; 137 End -= num;
@@ -143,7 +142,7 @@ HRESULT CSignatureFinder::Find()
143 { 142 {
144 if (Processed + Pos > *SearchLimit) 143 if (Processed + Pos > *SearchLimit)
145 return S_FALSE; 144 return S_FALSE;
146 UInt64 rem2 = *SearchLimit - (Processed + End) + _headerSize; 145 const UInt64 rem2 = *SearchLimit - (Processed + End) + _headerSize;
147 if (rem > rem2) 146 if (rem > rem2)
148 rem = (UInt32)rem2; 147 rem = (UInt32)rem2;
149 } 148 }
@@ -248,7 +247,7 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
248 limitedStreamSpec = new CLimitedSequentialInStream; 247 limitedStreamSpec = new CLimitedSequentialInStream;
249 limitedStreamSpec->SetStream(db.Stream); 248 limitedStreamSpec->SetStream(db.Stream);
250 limitedStream = limitedStreamSpec; 249 limitedStream = limitedStreamSpec;
251 UInt32 remInFinder = finder.End - finder.Pos; 250 const UInt32 remInFinder = finder.End - finder.Pos;
252 if (ai.Size <= remInFinder) 251 if (ai.Size <= remInFinder)
253 { 252 {
254 limitedStreamSpec->Init(0); 253 limitedStreamSpec->Init(0);
@@ -273,7 +272,7 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
273 _tempBuf.Alloc(1 << 12); 272 _tempBuf.Alloc(1 << 12);
274 273
275 Byte p[16]; 274 Byte p[16];
276 unsigned nextSize = 4 + (ai.ReserveBlockPresent() ? 4 : 0); 275 const unsigned nextSize = 4 + (ai.ReserveBlockPresent() ? 4 : 0);
277 Read(p, nextSize); 276 Read(p, nextSize);
278 ai.SetID = Get16(p); 277 ai.SetID = Get16(p);
279 ai.CabinetNumber = Get16(p + 2); 278 ai.CabinetNumber = Get16(p + 2);
@@ -325,8 +324,8 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
325 item.Size = Get32(p); 324 item.Size = Get32(p);
326 item.Offset = Get32(p + 4); 325 item.Offset = Get32(p + 4);
327 item.FolderIndex = Get16(p + 8); 326 item.FolderIndex = Get16(p + 8);
328 UInt16 pureDate = Get16(p + 10); 327 const UInt16 pureDate = Get16(p + 10);
329 UInt16 pureTime = Get16(p + 12); 328 const UInt16 pureTime = Get16(p + 12);
330 item.Time = (((UInt32)pureDate << 16)) | pureTime; 329 item.Time = (((UInt32)pureDate << 16)) | pureTime;
331 item.Attributes = Get16(p + 14); 330 item.Attributes = Get16(p + 14);
332 331
@@ -366,12 +365,12 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
366 const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex]; 365 const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex];
367 const CItem &item1 = db1.Items[p1->ItemIndex]; 366 const CItem &item1 = db1.Items[p1->ItemIndex];
368 const CItem &item2 = db2.Items[p2->ItemIndex]; 367 const CItem &item2 = db2.Items[p2->ItemIndex];
369 bool isDir1 = item1.IsDir(); 368 const bool isDir1 = item1.IsDir();
370 bool isDir2 = item2.IsDir(); 369 const bool isDir2 = item2.IsDir();
371 if (isDir1 && !isDir2) return -1; 370 if (isDir1 && !isDir2) return -1;
372 if (isDir2 && !isDir1) return 1; 371 if (isDir2 && !isDir1) return 1;
373 int f1 = mvDb.GetFolderIndex(p1); 372 const int f1 = mvDb.GetFolderIndex(p1);
374 int f2 = mvDb.GetFolderIndex(p2); 373 const int f2 = mvDb.GetFolderIndex(p2);
375 RINOZ(MyCompare(f1, f2)) 374 RINOZ(MyCompare(f1, f2))
376 RINOZ(MyCompare(item1.Offset, item2.Offset)) 375 RINOZ(MyCompare(item1.Offset, item2.Offset))
377 RINOZ(MyCompare(item1.Size, item2.Size)) 376 RINOZ(MyCompare(item1.Size, item2.Size))
@@ -434,7 +433,7 @@ void CMvDatabaseEx::FillSortAndShrink()
434 433
435 FOR_VECTOR (i, Items) 434 FOR_VECTOR (i, Items)
436 { 435 {
437 int folderIndex = GetFolderIndex(&Items[i]); 436 const int folderIndex = GetFolderIndex(&Items[i]);
438 while (folderIndex >= (int)FolderStartFileIndex.Size()) 437 while (folderIndex >= (int)FolderStartFileIndex.Size())
439 FolderStartFileIndex.Add(i); 438 FolderStartFileIndex.Add(i);
440 } 439 }
@@ -452,7 +451,7 @@ bool CMvDatabaseEx::Check()
452 if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty()) 451 if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty())
453 return false; 452 return false;
454 const CFolder &f0 = db0.Folders.Back(); 453 const CFolder &f0 = db0.Folders.Back();
455 const CFolder &f1 = db1.Folders.Front(); 454 const CFolder &f1 = db1.Folders.FrontItem();
456 if (f0.MethodMajor != f1.MethodMajor || 455 if (f0.MethodMajor != f1.MethodMajor ||
457 f0.MethodMinor != f1.MethodMinor) 456 f0.MethodMinor != f1.MethodMinor)
458 return false; 457 return false;
@@ -466,14 +465,14 @@ bool CMvDatabaseEx::Check()
466 FOR_VECTOR (i, Items) 465 FOR_VECTOR (i, Items)
467 { 466 {
468 const CMvItem &mvItem = Items[i]; 467 const CMvItem &mvItem = Items[i];
469 int fIndex = GetFolderIndex(&mvItem); 468 const int fIndex = GetFolderIndex(&mvItem);
470 if (fIndex >= (int)FolderStartFileIndex.Size()) 469 if (fIndex >= (int)FolderStartFileIndex.Size())
471 return false; 470 return false;
472 const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; 471 const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
473 if (item.IsDir()) 472 if (item.IsDir())
474 continue; 473 continue;
475 474
476 int folderIndex = GetFolderIndex(&mvItem); 475 const int folderIndex = GetFolderIndex(&mvItem);
477 476
478 if (folderIndex != prevFolder) 477 if (folderIndex != prevFolder)
479 prevFolder = folderIndex; 478 prevFolder = folderIndex;
diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp
index 38e2543..93c3a85 100644
--- a/CPP/7zip/Archive/Chm/ChmHandler.cpp
+++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp
@@ -2,6 +2,7 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../../../Common/AutoPtr.h"
5#include "../../../Common/ComTry.h" 6#include "../../../Common/ComTry.h"
6#include "../../../Common/StringConvert.h" 7#include "../../../Common/StringConvert.h"
7#include "../../../Common/UTFConvert.h" 8#include "../../../Common/UTFConvert.h"
@@ -414,21 +415,18 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
414 m_Database.Indices.Size()); 415 m_Database.Indices.Size());
415 if (numItems == 0) 416 if (numItems == 0)
416 return S_OK; 417 return S_OK;
417 bool testMode = (testModeSpec != 0); 418 const bool testMode = (testModeSpec != 0);
418 419
419 UInt64 currentTotalSize = 0; 420 UInt64 currentTotalSize = 0;
420 421
421 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 422 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
422 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
423 UInt32 i;
424
425 CLocalProgress *lps = new CLocalProgress;
426 CMyComPtr<ICompressProgressInfo> progress = lps;
427 lps->Init(extractCallback, false); 423 lps->Init(extractCallback, false);
428 424
429 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 425 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
430 CMyComPtr<ISequentialInStream> inStream(streamSpec); 426 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
431 streamSpec->SetStream(m_Stream); 427 inStream->SetStream(m_Stream);
428
429 UInt32 i;
432 430
433 if (m_Database.LowLevel) 431 if (m_Database.LowLevel)
434 { 432 {
@@ -441,7 +439,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
441 for (i = 0; i < numItems; i++) 439 for (i = 0; i < numItems; i++)
442 totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size; 440 totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size;
443 441
444 extractCallback->SetTotal(totalSize); 442 RINOK(extractCallback->SetTotal(totalSize))
445 443
446 for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) 444 for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
447 { 445 {
@@ -465,7 +463,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
465 continue; 463 continue;
466 if (!testMode) 464 if (!testMode)
467 { 465 {
468 UInt32 size = m_Database.NewFormatString.Len(); 466 const unsigned size = m_Database.NewFormatString.Len();
469 RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size)) 467 RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size))
470 } 468 }
471 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 469 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
@@ -492,18 +490,18 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
492 } 490 }
493 491
494 RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset)) 492 RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset))
495 streamSpec->Init(item.Size); 493 inStream->Init(item.Size);
496 494
497 RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)) 495 RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
498 realOutStream.Release(); 496 realOutStream.Release();
499 RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? 497 RINOK(extractCallback->SetOperationResult((copyCoder->TotalSize == item.Size) ?
500 NExtract::NOperationResult::kOK: 498 NExtract::NOperationResult::kOK:
501 NExtract::NOperationResult::kDataError)) 499 NExtract::NOperationResult::kDataError))
502 } 500 }
503 return S_OK; 501 return S_OK;
504 } 502 }
505 503
506 UInt64 lastFolderIndex = ((UInt64)0 - 1); 504 UInt64 lastFolderIndex = (UInt64)0 - 1;
507 505
508 for (i = 0; i < numItems; i++) 506 for (i = 0; i < numItems; i++)
509 { 507 {
@@ -536,10 +534,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
536 534
537 RINOK(extractCallback->SetTotal(currentTotalSize)) 535 RINOK(extractCallback->SetTotal(currentTotalSize))
538 536
539 NCompress::NLzx::CDecoder *lzxDecoderSpec = NULL; 537 CMyUniquePtr<NCompress::NLzx::CDecoder> lzxDecoder;
540 CMyComPtr<IUnknown> lzxDecoder; 538 CMyComPtr2_Create<ISequentialOutStream, CChmFolderOutStream> chmFolderOutStream;
541 CChmFolderOutStream *chmFolderOutStream = NULL;
542 CMyComPtr<ISequentialOutStream> outStream;
543 539
544 currentTotalSize = 0; 540 currentTotalSize = 0;
545 541
@@ -558,7 +554,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
558 i++; 554 i++;
559 const CItem &item = m_Database.Items[m_Database.Indices[index]]; 555 const CItem &item = m_Database.Items[m_Database.Indices[index]];
560 const UInt64 sectionIndex = item.Section; 556 const UInt64 sectionIndex = item.Section;
561 Int32 askMode= testMode ? 557 const Int32 askMode= testMode ?
562 NExtract::NAskMode::kTest : 558 NExtract::NAskMode::kTest :
563 NExtract::NAskMode::kExtract; 559 NExtract::NAskMode::kExtract;
564 560
@@ -586,9 +582,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
586 if (!testMode && item.Size != 0) 582 if (!testMode && item.Size != 0)
587 { 583 {
588 RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset)) 584 RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset))
589 streamSpec->Init(item.Size); 585 inStream->Init(item.Size);
590 RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)) 586 RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
591 if (copyCoderSpec->TotalSize != item.Size) 587 if (copyCoder->TotalSize != item.Size)
592 opRes = NExtract::NOperationResult::kDataError; 588 opRes = NExtract::NOperationResult::kDataError;
593 } 589 }
594 realOutStream.Release(); 590 realOutStream.Release();
@@ -624,24 +620,14 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
624 620
625 const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo; 621 const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
626 622
627 if (!chmFolderOutStream)
628 {
629 chmFolderOutStream = new CChmFolderOutStream;
630 outStream = chmFolderOutStream;
631 }
632
633 chmFolderOutStream->Init(&m_Database, extractCallback, testMode); 623 chmFolderOutStream->Init(&m_Database, extractCallback, testMode);
634 624
635 if (!lzxDecoderSpec) 625 lzxDecoder.Create_if_Empty();
636 {
637 lzxDecoderSpec = new NCompress::NLzx::CDecoder;
638 lzxDecoder = lzxDecoderSpec;
639 }
640 626
641 UInt64 folderIndex = m_Database.GetFolder(index); 627 UInt64 folderIndex = m_Database.GetFolder(index);
642 628
643 const UInt64 compressedPos = m_Database.ContentOffset + section.Offset; 629 const UInt64 compressedPos = m_Database.ContentOffset + section.Offset;
644 RINOK(lzxDecoderSpec->SetParams_and_Alloc(lzxInfo.GetNumDictBits())) 630 RINOK(lzxDecoder->Set_DictBits_and_Alloc(lzxInfo.GetNumDictBits()))
645 631
646 const CItem *lastItem = &item; 632 const CItem *lastItem = &item;
647 extractStatuses.Clear(); 633 extractStatuses.Clear();
@@ -651,12 +637,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
651 { 637 {
652 RINOK(extractCallback->SetCompleted(&currentTotalSize)) 638 RINOK(extractCallback->SetCompleted(&currentTotalSize))
653 639
654 UInt64 startPos = lzxInfo.GetFolderPos(folderIndex); 640 const UInt64 startPos = lzxInfo.GetFolderPos(folderIndex);
655 UInt64 finishPos = lastItem->Offset + lastItem->Size; 641 UInt64 finishPos = lastItem->Offset + lastItem->Size;
656 UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos); 642 const UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos);
657 643
658 lastFolderIndex = m_Database.GetLastFolder(index); 644 lastFolderIndex = m_Database.GetLastFolder(index);
659 UInt64 folderSize = lzxInfo.GetFolderSize(); 645 const UInt64 folderSize = lzxInfo.GetFolderSize();
660 UInt64 unPackSize = folderSize; 646 UInt64 unPackSize = folderSize;
661 647
662 if (extractStatuses.IsEmpty()) 648 if (extractStatuses.IsEmpty())
@@ -697,9 +683,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
697 683
698 try 684 try
699 { 685 {
700 UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex); 686 const UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex);
701 const CResetTable &rt = lzxInfo.ResetTable; 687 const CResetTable &rt = lzxInfo.ResetTable;
702 UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize); 688 const UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize);
703 689
704 for (UInt32 b = 0; b < numBlocks; b++) 690 for (UInt32 b = 0; b < numBlocks; b++)
705 { 691 {
@@ -708,33 +694,37 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
708 UInt64 bCur = startBlock + b; 694 UInt64 bCur = startBlock + b;
709 if (bCur >= rt.ResetOffsets.Size()) 695 if (bCur >= rt.ResetOffsets.Size())
710 return E_FAIL; 696 return E_FAIL;
711 UInt64 offset = rt.ResetOffsets[(unsigned)bCur]; 697 const UInt64 offset = rt.ResetOffsets[(unsigned)bCur];
712 UInt64 compressedSize; 698 UInt64 compressedSize;
713 rt.GetCompressedSizeOfBlock(bCur, compressedSize); 699 rt.GetCompressedSizeOfBlock(bCur, compressedSize);
714 700
715 // chm writes full blocks. So we don't need to use reduced size for last block 701 // chm writes full blocks. So we don't need to use reduced size for last block
716 702
717 RINOK(InStream_SeekSet(m_Stream, compressedPos + offset)) 703 RINOK(InStream_SeekSet(m_Stream, compressedPos + offset))
718 streamSpec->SetStream(m_Stream); 704 inStream->Init(compressedSize);
719 streamSpec->Init(compressedSize);
720 705
721 lzxDecoderSpec->SetKeepHistory(b > 0); 706 lzxDecoder->Set_KeepHistory(b > 0);
722 707
723 size_t compressedSizeT = (size_t)compressedSize; 708 HRESULT res = S_FALSE;
724 if (compressedSizeT != compressedSize) 709 if (compressedSize <= (1u << 30))
725 throw 2;
726 packBuf.AllocAtLeast(compressedSizeT);
727
728 HRESULT res = ReadStream_FALSE(inStream, packBuf, compressedSizeT);
729
730 if (res == S_OK)
731 { 710 {
732 lzxDecoderSpec->KeepHistoryForNext = true; 711 const unsigned kAdditionalInputSize = 32;
733 res = lzxDecoderSpec->Code(packBuf, compressedSizeT, kBlockSize); // rt.BlockSize; 712 const size_t compressedSizeT = (size_t)compressedSize;
713 const size_t allocSize = compressedSizeT + kAdditionalInputSize;
714 if (allocSize <= compressedSize)
715 throw 2;
716 packBuf.AllocAtLeast(allocSize);
717 res = ReadStream_FALSE(inStream, packBuf, compressedSizeT);
734 if (res == S_OK) 718 if (res == S_OK)
735 res = WriteStream(chmFolderOutStream, 719 {
736 lzxDecoderSpec->GetUnpackData(), 720 memset(packBuf + compressedSizeT, 0xff, kAdditionalInputSize);
737 lzxDecoderSpec->GetUnpackSize()); 721 lzxDecoder->Set_KeepHistoryForNext(true);
722 res = lzxDecoder->Code_WithExceedReadWrite(packBuf, compressedSizeT, kBlockSize); // rt.BlockSize;
723 if (res == S_OK)
724 res = WriteStream(chmFolderOutStream,
725 lzxDecoder->GetUnpackData(),
726 lzxDecoder->GetUnpackSize());
727 }
738 } 728 }
739 729
740 if (res != S_OK) 730 if (res != S_OK)
diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp
index 28d512d..0866062 100644
--- a/CPP/7zip/Archive/Chm/ChmIn.cpp
+++ b/CPP/7zip/Archive/Chm/ChmIn.cpp
@@ -47,20 +47,15 @@ static bool inline AreGuidsEqual(const Byte *g1, const Byte *g2)
47 return memcmp(g1, g2, 16) == 0; 47 return memcmp(g1, g2, 16) == 0;
48} 48}
49 49
50static char GetHex(unsigned v) 50static void PrintByte(unsigned b, AString &s)
51{ 51{
52 return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10))); 52 s += (char)GET_HEX_CHAR_UPPER(b >> 4);
53} 53 s += (char)GET_HEX_CHAR_LOWER(b & 0xF);
54
55static void PrintByte(Byte b, AString &s)
56{
57 s += GetHex(b >> 4);
58 s += GetHex(b & 0xF);
59} 54}
60 55
61AString CMethodInfo::GetGuidString() const 56AString CMethodInfo::GetGuidString() const
62{ 57{
63 char s[48]; 58 char s[16 * 2 + 8];
64 RawLeGuidToString_Braced(Guid, s); 59 RawLeGuidToString_Braced(Guid, s);
65 // MyStringUpper_Ascii(s); 60 // MyStringUpper_Ascii(s);
66 return (AString)s; 61 return (AString)s;
@@ -93,12 +88,14 @@ AString CMethodInfo::GetName() const
93 else 88 else
94 { 89 {
95 s = GetGuidString(); 90 s = GetGuidString();
96 if (ControlData.Size() > 0) 91 /*
92 if (ControlData.Size() > 0 && ControlData.Size() <= (1 << 6))
97 { 93 {
98 s += ':'; 94 s.Add_Colon();
99 for (size_t i = 0; i < ControlData.Size(); i++) 95 for (size_t i = 0; i < ControlData.Size(); i++)
100 PrintByte(ControlData[i], s); 96 PrintByte(ControlData[i], s);
101 } 97 }
98 */
102 } 99 }
103 } 100 }
104 return s; 101 return s;
@@ -177,7 +174,7 @@ UInt64 CInArchive::ReadEncInt()
177 UInt64 val = 0; 174 UInt64 val = 0;
178 for (int i = 0; i < 9; i++) 175 for (int i = 0; i < 9; i++)
179 { 176 {
180 Byte b = ReadByte(); 177 const unsigned b = ReadByte();
181 val |= (b & 0x7F); 178 val |= (b & 0x7F);
182 if (b < 0x80) 179 if (b < 0x80)
183 return val; 180 return val;
@@ -206,7 +203,7 @@ void CInArchive::ReadUString(unsigned size, UString &s)
206 s.Empty(); 203 s.Empty();
207 while (size-- != 0) 204 while (size-- != 0)
208 { 205 {
209 wchar_t c = ReadUInt16(); 206 const wchar_t c = ReadUInt16();
210 if (c == 0) 207 if (c == 0)
211 { 208 {
212 Skip(2 * size); 209 Skip(2 * size);
@@ -232,7 +229,7 @@ HRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size)
232HRESULT CInArchive::ReadDirEntry(CDatabase &database) 229HRESULT CInArchive::ReadDirEntry(CDatabase &database)
233{ 230{
234 CItem item; 231 CItem item;
235 UInt64 nameLen = ReadEncInt(); 232 const UInt64 nameLen = ReadEncInt();
236 if (nameLen == 0 || nameLen > (1 << 13)) 233 if (nameLen == 0 || nameLen > (1 << 13))
237 return S_FALSE; 234 return S_FALSE;
238 ReadString((unsigned)nameLen, item.Name); 235 ReadString((unsigned)nameLen, item.Name);
@@ -333,7 +330,7 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
333 // One quickref entry exists for every n entries in the file, where n 330 // One quickref entry exists for every n entries in the file, where n
334 // is calculated as 1 + (1 << quickref density). So for density = 2, n = 5. 331 // is calculated as 1 + (1 << quickref density). So for density = 2, n = 5.
335 332
336 UInt32 quickrefLength = ReadUInt32(); // Len of free space and/or quickref area at end of directory chunk 333 const UInt32 quickrefLength = ReadUInt32(); // Len of free space and/or quickref area at end of directory chunk
337 if (quickrefLength > dirChunkSize || quickrefLength < 2) 334 if (quickrefLength > dirChunkSize || quickrefLength < 2)
338 return S_FALSE; 335 return S_FALSE;
339 ReadUInt32(); // Always 0 336 ReadUInt32(); // Always 0
@@ -345,8 +342,8 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
345 342
346 for (;;) 343 for (;;)
347 { 344 {
348 UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos; 345 const UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;
349 UInt32 offsetLimit = dirChunkSize - quickrefLength; 346 const UInt32 offsetLimit = dirChunkSize - quickrefLength;
350 if (offset > offsetLimit) 347 if (offset > offsetLimit)
351 return S_FALSE; 348 return S_FALSE;
352 if (offset == offsetLimit) 349 if (offset == offsetLimit)
@@ -357,7 +354,7 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
357 354
358 Skip(quickrefLength - 2); 355 Skip(quickrefLength - 2);
359 356
360 unsigned rrr = ReadUInt16(); 357 const unsigned rrr = ReadUInt16();
361 if (rrr != numItems) 358 if (rrr != numItems)
362 { 359 {
363 // Lazarus 9-26-2 chm contains 0 here. 360 // Lazarus 9-26-2 chm contains 0 here.
@@ -538,34 +535,40 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
538 unsigned numItems = 0; 535 unsigned numItems = 0;
539 for (;;) 536 for (;;)
540 { 537 {
541 UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos; 538 const UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;
542 UInt32 offsetLimit = dirChunkSize - quickrefLength; 539 const UInt32 offsetLimit = dirChunkSize - quickrefLength;
543 if (offset > offsetLimit) 540 if (offset > offsetLimit)
544 return S_FALSE; 541 return S_FALSE;
545 if (offset == offsetLimit) 542 if (offset == offsetLimit)
546 break; 543 break;
547 if (database.NewFormat) 544 if (database.NewFormat)
548 { 545 {
549 UInt16 nameLen = ReadUInt16(); 546 const unsigned nameLen = ReadUInt16();
550 if (nameLen == 0) 547 if (nameLen == 0)
551 return S_FALSE; 548 return S_FALSE;
552 UString name; 549 UString name;
553 ReadUString((unsigned)nameLen, name); 550 ReadUString(nameLen, name);
554 AString s; 551 AString s;
555 ConvertUnicodeToUTF8(name, s); 552 ConvertUnicodeToUTF8(name, s);
556 Byte b = ReadByte(); 553 {
557 s.Add_Space(); 554 const unsigned b = ReadByte();
558 PrintByte(b, s); 555 s.Add_Space();
556 PrintByte(b, s);
557 }
559 s.Add_Space(); 558 s.Add_Space();
560 UInt64 len = ReadEncInt(); 559 UInt64 len = ReadEncInt();
561 // then number of items ? 560 // then number of items ?
562 // then length ? 561 // then length ?
563 // then some data (binary encoding?) 562 // then some data (binary encoding?)
564 while (len-- != 0) 563 if (len > 1u << 29) // what limit here we need?
564 return S_FALSE;
565 if (len)
566 do
565 { 567 {
566 b = ReadByte(); 568 const unsigned b = ReadByte();
567 PrintByte(b, s); 569 PrintByte(b, s);
568 } 570 }
571 while (--len);
569 database.NewFormatString += s; 572 database.NewFormatString += s;
570 database.NewFormatString += "\r\n"; 573 database.NewFormatString += "\r\n";
571 } 574 }
@@ -613,7 +616,7 @@ static AString GetSectionPrefix(const AString &name)
613{ 616{
614 AString s (kStorage); 617 AString s (kStorage);
615 s += name; 618 s += name;
616 s += '/'; 619 s.Add_Slash();
617 return s; 620 return s;
618} 621}
619 622
@@ -712,7 +715,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
712 for (unsigned i = 0; i < numSections; i++) 715 for (unsigned i = 0; i < numSections; i++)
713 { 716 {
714 CSectionInfo section; 717 CSectionInfo section;
715 UInt16 nameLen = ReadUInt16(); 718 const unsigned nameLen = ReadUInt16();
716 UString name; 719 UString name;
717 ReadUString(nameLen, name); 720 ReadUString(nameLen, name);
718 if (ReadUInt16() != 0) 721 if (ReadUInt16() != 0)
@@ -799,14 +802,19 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
799 802
800 li.CacheSize = ReadUInt32(); 803 li.CacheSize = ReadUInt32();
801 numDWORDS -= 5; 804 numDWORDS -= 5;
802 while (numDWORDS-- != 0) 805 if (numDWORDS)
806 do
803 ReadUInt32(); 807 ReadUInt32();
808 while (--numDWORDS);
804 } 809 }
805 else 810 else
806 { 811 {
807 UInt32 numBytes = numDWORDS * 4; 812 if (numDWORDS > 1u << 27)
808 method.ControlData.Alloc(numBytes); 813 return S_FALSE;
809 ReadBytes(method.ControlData, numBytes); 814 const size_t numBytes = (size_t)numDWORDS * 4;
815 // method.ControlData.Alloc(numBytes);
816 // ReadBytes(method.ControlData, numBytes);
817 Skip(numBytes);
810 } 818 }
811 } 819 }
812 } 820 }
@@ -841,10 +849,10 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
841 } 849 }
842 else 850 else
843 { 851 {
844 UInt32 ver = ReadUInt32(); // 2 unknown (possibly a version number) 852 const UInt32 ver = ReadUInt32(); // 2 unknown (possibly a version number)
845 if (ver != 2 && ver != 3) 853 if (ver != 2 && ver != 3)
846 return S_FALSE; 854 return S_FALSE;
847 UInt32 numEntries = ReadUInt32(); 855 const UInt32 numEntries = ReadUInt32();
848 const unsigned kEntrySize = 8; 856 const unsigned kEntrySize = 8;
849 if (ReadUInt32() != kEntrySize) 857 if (ReadUInt32() != kEntrySize)
850 return S_FALSE; 858 return S_FALSE;
diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h
index c01ef4d..faf4edf 100644
--- a/CPP/7zip/Archive/Chm/ChmIn.h
+++ b/CPP/7zip/Archive/Chm/ChmIn.h
@@ -45,9 +45,9 @@ struct CItem
45 45
46struct CDatabase 46struct CDatabase
47{ 47{
48 CObjectVector<CItem> Items;
48 UInt64 StartPosition; 49 UInt64 StartPosition;
49 UInt64 ContentOffset; 50 UInt64 ContentOffset;
50 CObjectVector<CItem> Items;
51 AString NewFormatString; 51 AString NewFormatString;
52 bool Help2Format; 52 bool Help2Format;
53 bool NewFormat; 53 bool NewFormat;
@@ -137,14 +137,14 @@ struct CLzxInfo
137 return 0; 137 return 0;
138 } 138 }
139 139
140 UInt64 GetFolderSize() const { return kBlockSize << ResetIntervalBits; } 140 UInt64 GetFolderSize() const { return (UInt64)kBlockSize << ResetIntervalBits; }
141 UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); } 141 UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); }
142 UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); } 142 UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); }
143 UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex << ResetIntervalBits; } 143 UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex << ResetIntervalBits; }
144 144
145 bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const 145 bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const
146 { 146 {
147 UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex); 147 const UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
148 if (blockIndex >= ResetTable.ResetOffsets.Size()) 148 if (blockIndex >= ResetTable.ResetOffsets.Size())
149 return false; 149 return false;
150 offset = ResetTable.ResetOffsets[(unsigned)blockIndex]; 150 offset = ResetTable.ResetOffsets[(unsigned)blockIndex];
@@ -162,7 +162,7 @@ struct CLzxInfo
162struct CMethodInfo 162struct CMethodInfo
163{ 163{
164 Byte Guid[16]; 164 Byte Guid[16];
165 CByteBuffer ControlData; 165 // CByteBuffer ControlData;
166 CLzxInfo LzxInfo; 166 CLzxInfo LzxInfo;
167 167
168 bool IsLzx() const; 168 bool IsLzx() const;
@@ -188,9 +188,9 @@ struct CSectionInfo
188class CFilesDatabase: public CDatabase 188class CFilesDatabase: public CDatabase
189{ 189{
190public: 190public:
191 bool LowLevel;
192 CUIntVector Indices; 191 CUIntVector Indices;
193 CObjectVector<CSectionInfo> Sections; 192 CObjectVector<CSectionInfo> Sections;
193 bool LowLevel;
194 194
195 UInt64 GetFileSize(unsigned fileIndex) const { return Items[Indices[fileIndex]].Size; } 195 UInt64 GetFileSize(unsigned fileIndex) const { return Items[Indices[fileIndex]].Size; }
196 UInt64 GetFileOffset(unsigned fileIndex) const { return Items[Indices[fileIndex]].Offset; } 196 UInt64 GetFileOffset(unsigned fileIndex) const { return Items[Indices[fileIndex]].Offset; }
diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp
index 7aabd65..82d939d 100644
--- a/CPP/7zip/Archive/ComHandler.cpp
+++ b/CPP/7zip/Archive/ComHandler.cpp
@@ -252,9 +252,9 @@ static UString CompoundNameToFileName(const UString &s)
252 const wchar_t c = s[i]; 252 const wchar_t c = s[i];
253 if ((unsigned)(int)c < 0x20) 253 if ((unsigned)(int)c < 0x20)
254 { 254 {
255 res += '['; 255 res.Add_Char('[');
256 res.Add_UInt32((UInt32)(unsigned)(int)c); 256 res.Add_UInt32((UInt32)(unsigned)(int)c);
257 res += ']'; 257 res.Add_Char(']');
258 } 258 }
259 else 259 else
260 res += c; 260 res += c;
@@ -309,20 +309,20 @@ static bool CompoundMsiNameToFileName(const UString &name, UString &res)
309 if (i == 0) 309 if (i == 0)
310 res += k_Msi_ID; 310 res += k_Msi_ID;
311 */ 311 */
312 c -= k_Msi_StartUnicodeChar; 312 c -= (wchar_t)k_Msi_StartUnicodeChar;
313 313
314 unsigned c0 = (unsigned)c & k_Msi_CharMask; 314 const unsigned c0 = (unsigned)c & k_Msi_CharMask;
315 unsigned c1 = (unsigned)c >> k_Msi_NumBits; 315 const unsigned c1 = (unsigned)c >> k_Msi_NumBits;
316 316
317 if (c1 <= k_Msi_NumChars) 317 if (c1 <= k_Msi_NumChars)
318 { 318 {
319 res += k_Msi_Chars[c0]; 319 res.Add_Char(k_Msi_Chars[c0]);
320 if (c1 == k_Msi_NumChars) 320 if (c1 == k_Msi_NumChars)
321 break; 321 break;
322 res += k_Msi_Chars[c1]; 322 res.Add_Char(k_Msi_Chars[c1]);
323 } 323 }
324 else 324 else
325 res += k_Msi_SpecChar; 325 res.Add_Char(k_Msi_SpecChar);
326 } 326 }
327 return true; 327 return true;
328} 328}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
index b6ddeb8..b1c316d 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp
@@ -769,8 +769,8 @@ HRESULT CMixerST::Code(
769 } 769 }
770 } 770 }
771 771
772 const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front(); 772 const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : mainCoder.PackSizePointers.ConstData();
773 const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer; 773 const UInt64 * const *outSizes2 = EncodeMode ? mainCoder.PackSizePointers.ConstData() : &mainCoder.UnpackSizePointer;
774 774
775 HRESULT res; 775 HRESULT res;
776 if (mainCoder.Coder) 776 if (mainCoder.Coder)
@@ -783,8 +783,8 @@ HRESULT CMixerST::Code(
783 else 783 else
784 { 784 {
785 res = mainCoder.Coder2->Code( 785 res = mainCoder.Coder2->Code(
786 &seqInStreamsSpec.Front(), isSizes2, numInStreams, 786 seqInStreamsSpec.ConstData(), isSizes2, numInStreams,
787 &seqOutStreamsSpec.Front(), outSizes2, numOutStreams, 787 seqOutStreamsSpec.ConstData(), outSizes2, numOutStreams,
788 progress); 788 progress);
789 } 789 }
790 790
@@ -909,8 +909,8 @@ void CCoderMT::Code(ICompressProgressInfo *progress)
909 progress); 909 progress);
910 else 910 else
911 Result = Coder2->Code( 911 Result = Coder2->Code(
912 &InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams, 912 InStreamPointers.ConstData(), EncodeMode ? &UnpackSizePointer : PackSizePointers.ConstData(), numInStreams,
913 &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams, 913 OutStreamPointers.ConstData(), EncodeMode ? PackSizePointers.ConstData(): &UnpackSizePointer, numOutStreams,
914 progress); 914 progress);
915} 915}
916 916
diff --git a/CPP/7zip/Archive/Common/FindSignature.cpp b/CPP/7zip/Archive/Common/FindSignature.cpp
index 6c6740f..4f46ee7 100644
--- a/CPP/7zip/Archive/Common/FindSignature.cpp
+++ b/CPP/7zip/Archive/Common/FindSignature.cpp
@@ -21,10 +21,10 @@ HRESULT FindSignatureInStream(ISequentialInStream *stream,
21 if (memcmp(byteBuffer2, signature, signatureSize) == 0) 21 if (memcmp(byteBuffer2, signature, signatureSize) == 0)
22 return S_OK; 22 return S_OK;
23 23
24 const UInt32 kBufferSize = (1 << 16); 24 const size_t kBufferSize = 1 << 16;
25 CByteBuffer byteBuffer(kBufferSize); 25 CByteBuffer byteBuffer(kBufferSize);
26 Byte *buffer = byteBuffer; 26 Byte *buffer = byteBuffer;
27 UInt32 numPrevBytes = signatureSize - 1; 27 size_t numPrevBytes = signatureSize - 1;
28 memcpy(buffer, (const Byte *)byteBuffer2 + 1, numPrevBytes); 28 memcpy(buffer, (const Byte *)byteBuffer2 + 1, numPrevBytes);
29 resPos = 1; 29 resPos = 1;
30 for (;;) 30 for (;;)
@@ -34,16 +34,16 @@ HRESULT FindSignatureInStream(ISequentialInStream *stream,
34 return S_FALSE; 34 return S_FALSE;
35 do 35 do
36 { 36 {
37 const UInt32 numReadBytes = kBufferSize - numPrevBytes; 37 const size_t numReadBytes = kBufferSize - numPrevBytes;
38 UInt32 processedSize; 38 UInt32 processedSize;
39 RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)) 39 RINOK(stream->Read(buffer + numPrevBytes, (UInt32)numReadBytes, &processedSize))
40 numPrevBytes += processedSize; 40 numPrevBytes += (size_t)processedSize;
41 if (processedSize == 0) 41 if (processedSize == 0)
42 return S_FALSE; 42 return S_FALSE;
43 } 43 }
44 while (numPrevBytes < signatureSize); 44 while (numPrevBytes < signatureSize);
45 const UInt32 numTests = numPrevBytes - signatureSize + 1; 45 const size_t numTests = numPrevBytes - signatureSize + 1;
46 for (UInt32 pos = 0; pos < numTests; pos++) 46 for (size_t pos = 0; pos < numTests; pos++)
47 { 47 {
48 const Byte b = signature[0]; 48 const Byte b = signature[0];
49 for (; buffer[pos] != b && pos < numTests; pos++); 49 for (; buffer[pos] != b && pos < numTests; pos++);
@@ -60,3 +60,31 @@ HRESULT FindSignatureInStream(ISequentialInStream *stream,
60 memmove(buffer, buffer + numTests, numPrevBytes); 60 memmove(buffer, buffer + numTests, numPrevBytes);
61 } 61 }
62} 62}
63
64namespace NArchive {
65HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize);
66HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
67{
68 areThereNonZeros = false;
69 numZeros = 0;
70 const size_t kBufSize = 1 << 11;
71 Byte buf[kBufSize];
72 for (;;)
73 {
74 UInt32 size = 0;
75 RINOK(stream->Read(buf, kBufSize, &size))
76 if (size == 0)
77 return S_OK;
78 for (UInt32 i = 0; i < size; i++)
79 if (buf[i] != 0)
80 {
81 areThereNonZeros = true;
82 numZeros += i;
83 return S_OK;
84 }
85 numZeros += size;
86 if (numZeros > maxSize)
87 return S_OK;
88 }
89}
90}
diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.h b/CPP/7zip/Archive/Common/InStreamWithCRC.h
index 2a91d76..4873689 100644
--- a/CPP/7zip/Archive/Common/InStreamWithCRC.h
+++ b/CPP/7zip/Archive/Common/InStreamWithCRC.h
@@ -40,12 +40,9 @@ public:
40}; 40};
41 41
42 42
43Z7_CLASS_IMP_COM_1( 43Z7_CLASS_IMP_IInStream(
44 CInStreamWithCRC, 44 CInStreamWithCRC
45 IInStream
46) 45)
47 Z7_IFACE_COM7_IMP(ISequentialInStream)
48
49 CMyComPtr<IInStream> _stream; 46 CMyComPtr<IInStream> _stream;
50 UInt64 _size; 47 UInt64 _size;
51 UInt32 _crc; 48 UInt32 _crc;
diff --git a/CPP/7zip/Archive/Common/MultiStream.h b/CPP/7zip/Archive/Common/MultiStream.h
index e3096f5..901b6ea 100644
--- a/CPP/7zip/Archive/Common/MultiStream.h
+++ b/CPP/7zip/Archive/Common/MultiStream.h
@@ -9,11 +9,9 @@
9#include "../../IStream.h" 9#include "../../IStream.h"
10#include "../../Archive/IArchive.h" 10#include "../../Archive/IArchive.h"
11 11
12Z7_CLASS_IMP_COM_1( 12Z7_CLASS_IMP_IInStream(
13 CMultiStream 13 CMultiStream
14 , IInStream
15) 14)
16 Z7_IFACE_COM7_IMP(ISequentialInStream)
17 15
18 unsigned _streamIndex; 16 unsigned _streamIndex;
19 UInt64 _pos; 17 UInt64 _pos;
diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
index 57c18ec..2916c30 100644
--- a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
+++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
@@ -16,3 +16,14 @@ Z7_COM7F_IMF(COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *pr
16 *processedSize = size; 16 *processedSize = size;
17 return result; 17 return result;
18} 18}
19
20Z7_COM7F_IMF(CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize))
21{
22 UInt32 realProcessedSize;
23 const HRESULT result = _stream->Read(data, size, &realProcessedSize);
24 _size += realProcessedSize;
25 Sha1_Update(Sha(), (const Byte *)data, realProcessedSize);
26 if (processedSize)
27 *processedSize = realProcessedSize;
28 return result;
29}
diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h
index 74bc53c..28b2587 100644
--- a/CPP/7zip/Archive/Common/OutStreamWithSha1.h
+++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h
@@ -14,11 +14,10 @@ Z7_CLASS_IMP_NOQIB_1(
14 COutStreamWithSha1 14 COutStreamWithSha1
15 , ISequentialOutStream 15 , ISequentialOutStream
16) 16)
17 CMyComPtr<ISequentialOutStream> _stream;
18 UInt64 _size;
19 // CSha1 _sha;
20 bool _calculate; 17 bool _calculate;
18 CMyComPtr<ISequentialOutStream> _stream;
21 CAlignedBuffer1 _sha; 19 CAlignedBuffer1 _sha;
20 UInt64 _size;
22 21
23 CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; } 22 CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; }
24public: 23public:
@@ -27,8 +26,8 @@ public:
27 void ReleaseStream() { _stream.Release(); } 26 void ReleaseStream() { _stream.Release(); }
28 void Init(bool calculate = true) 27 void Init(bool calculate = true)
29 { 28 {
30 _size = 0;
31 _calculate = calculate; 29 _calculate = calculate;
30 _size = 0;
32 Sha1_Init(Sha()); 31 Sha1_Init(Sha());
33 } 32 }
34 void InitSha1() { Sha1_Init(Sha()); } 33 void InitSha1() { Sha1_Init(Sha()); }
@@ -36,4 +35,27 @@ public:
36 void Final(Byte *digest) { Sha1_Final(Sha(), digest); } 35 void Final(Byte *digest) { Sha1_Final(Sha(), digest); }
37}; 36};
38 37
38
39Z7_CLASS_IMP_NOQIB_1(
40 CInStreamWithSha1
41 , ISequentialInStream
42)
43 CMyComPtr<ISequentialInStream> _stream;
44 CAlignedBuffer1 _sha;
45 UInt64 _size;
46
47 CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; }
48public:
49 CInStreamWithSha1(): _sha(sizeof(CSha1)) {}
50 void SetStream(ISequentialInStream *stream) { _stream = stream; }
51 void Init()
52 {
53 _size = 0;
54 Sha1_Init(Sha());
55 }
56 void ReleaseStream() { _stream.Release(); }
57 UInt64 GetSize() const { return _size; }
58 void Final(Byte *digest) { Sha1_Final(Sha(), digest); }
59};
60
39#endif 61#endif
diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp
index 872cea7..2228040 100644
--- a/CPP/7zip/Archive/CpioHandler.cpp
+++ b/CPP/7zip/Archive/CpioHandler.cpp
@@ -30,8 +30,6 @@ namespace NCpio {
30static const Byte kMagicBin0 = 0xC7; 30static const Byte kMagicBin0 = 0xC7;
31static const Byte kMagicBin1 = 0x71; 31static const Byte kMagicBin1 = 0x71;
32 32
33// #define MAGIC_ASCII { '0', '7', '0', '7', '0' }
34
35static const Byte kMagicHex = '1'; // New ASCII Format 33static const Byte kMagicHex = '1'; // New ASCII Format
36static const Byte kMagicHexCrc = '2'; // New CRC Format 34static const Byte kMagicHexCrc = '2'; // New CRC Format
37static const Byte kMagicOct = '7'; // Portable ASCII Format 35static const Byte kMagicOct = '7'; // Portable ASCII Format
@@ -147,8 +145,8 @@ static bool CheckOctRecord(const Byte *p)
147{ 145{
148 for (unsigned i = 6; i < k_OctRecord_Size; i++) 146 for (unsigned i = 6; i < k_OctRecord_Size; i++)
149 { 147 {
150 const Byte c = p[i]; 148 const unsigned c = (unsigned)p[i] - '0';
151 if (c < '0' || c > '7') 149 if (c > 7)
152 return false; 150 return false;
153 } 151 }
154 return true; 152 return true;
@@ -158,11 +156,15 @@ static bool CheckHexRecord(const Byte *p)
158{ 156{
159 for (unsigned i = 6; i < k_HexRecord_Size; i++) 157 for (unsigned i = 6; i < k_HexRecord_Size; i++)
160 { 158 {
161 const Byte c = p[i]; 159 unsigned c = p[i];
162 if ((c < '0' || c > '9') && 160 c -= '0';
163 (c < 'A' || c > 'F') && 161 if (c > 9)
164 (c < 'a' || c > 'f')) 162 {
165 return false; 163 c -= 'A' - '0';
164 c &= ~0x20u;
165 if (c > 5)
166 return false;
167 }
166 } 168 }
167 return true; 169 return true;
168} 170}
@@ -214,7 +216,7 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size)
214 UInt32 namePos; 216 UInt32 namePos;
215 UInt32 nameSize; 217 UInt32 nameSize;
216 UInt32 mode; 218 UInt32 mode;
217 UInt32 rDevMinor; 219 // UInt32 rDevMinor;
218 UInt32 rDevMajor = 0; 220 UInt32 rDevMajor = 0;
219 221
220 if (p[0] == '0') 222 if (p[0] == '0')
@@ -231,7 +233,7 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size)
231 if (!CheckOctRecord(p)) 233 if (!CheckOctRecord(p))
232 return k_IsArc_Res_NO; 234 return k_IsArc_Res_NO;
233 READ_OCT_6 (2 * 6, mode) 235 READ_OCT_6 (2 * 6, mode)
234 READ_OCT_6 (6 * 6, rDevMinor) 236 // READ_OCT_6 (6 * 6, rDevMinor)
235 READ_OCT_6 (7 * 6 + 11, nameSize) 237 READ_OCT_6 (7 * 6 + 11, nameSize)
236 namePos = k_OctRecord_Size; 238 namePos = k_OctRecord_Size;
237 } 239 }
@@ -243,7 +245,7 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size)
243 return k_IsArc_Res_NO; 245 return k_IsArc_Res_NO;
244 READ_HEX (1, mode) 246 READ_HEX (1, mode)
245 READ_HEX (9, rDevMajor) 247 READ_HEX (9, rDevMajor)
246 READ_HEX (10, rDevMinor) 248 // READ_HEX (10, rDevMinor)
247 READ_HEX (11, nameSize) 249 READ_HEX (11, nameSize)
248 namePos = k_HexRecord_Size; 250 namePos = k_HexRecord_Size;
249 } 251 }
@@ -255,13 +257,13 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size)
255 if (p[0] == kMagicBin0 && p[1] == kMagicBin1) 257 if (p[0] == kMagicBin0 && p[1] == kMagicBin1)
256 { 258 {
257 mode = GetUi16(p + 6); 259 mode = GetUi16(p + 6);
258 rDevMinor = GetUi16(p + 14); 260 // rDevMinor = GetUi16(p + 14);
259 nameSize = GetUi16(p + 20); 261 nameSize = GetUi16(p + 20);
260 } 262 }
261 else if (p[0] == kMagicBin1 && p[1] == kMagicBin0) 263 else if (p[0] == kMagicBin1 && p[1] == kMagicBin0)
262 { 264 {
263 mode = GetBe16(p + 6); 265 mode = GetBe16(p + 6);
264 rDevMinor = GetBe16(p + 14); 266 // rDevMinor = GetBe16(p + 14);
265 nameSize = GetBe16(p + 20); 267 nameSize = GetBe16(p + 20);
266 } 268 }
267 else 269 else
@@ -272,8 +274,11 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size)
272 if (mode >= (1 << 16)) 274 if (mode >= (1 << 16))
273 return k_IsArc_Res_NO; 275 return k_IsArc_Res_NO;
274 276
275 if (rDevMajor != 0 || 277 /* v23.02: we have disabled rDevMinor check because real file
276 rDevMinor != 0) 278 from Apple contains rDevMinor==255 by some unknown reason */
279 if (rDevMajor != 0
280 // || rDevMinor != 0
281 )
277 { 282 {
278 if (!MY_LIN_S_ISCHR(mode) && 283 if (!MY_LIN_S_ISCHR(mode) &&
279 !MY_LIN_S_ISBLK(mode)) 284 !MY_LIN_S_ISBLK(mode))
@@ -431,8 +436,11 @@ HRESULT CInArchive::GetNextItem()
431 if (item.Mode >= (1 << 16)) 436 if (item.Mode >= (1 << 16))
432 return S_OK; 437 return S_OK;
433 438
434 if (item.RDevMinor != 0 || 439 /* v23.02: we have disabled rDevMinor check because real file
435 item.RDevMajor != 0) 440 from Apple contains rDevMinor==255 by some unknown reason */
441 if (item.RDevMajor != 0
442 // || item.RDevMinor != 0
443 )
436 { 444 {
437 if (!MY_LIN_S_ISCHR(item.Mode) && 445 if (!MY_LIN_S_ISCHR(item.Mode) &&
438 !MY_LIN_S_ISBLK(item.Mode)) 446 !MY_LIN_S_ISBLK(item.Mode))
@@ -954,38 +962,48 @@ Z7_CLASS_IMP_NOQIB_1(
954 , ISequentialOutStream 962 , ISequentialOutStream
955) 963)
956 CMyComPtr<ISequentialOutStream> _stream; 964 CMyComPtr<ISequentialOutStream> _stream;
957 UInt64 _size; 965 UInt32 _checksum;
958 UInt32 _crc;
959 bool _calculate; 966 bool _calculate;
960public: 967public:
961 void SetStream(ISequentialOutStream *stream) { _stream = stream; } 968 void SetStream(ISequentialOutStream *stream) { _stream = stream; }
962 void ReleaseStream() { _stream.Release(); } 969 void ReleaseStream() { _stream.Release(); }
963 void Init(bool calculate = true) 970 void Init(bool calculate)
964 { 971 {
965 _size = 0;
966 _calculate = calculate; 972 _calculate = calculate;
967 _crc = 0; 973 _checksum = 0;
968 } 974 }
969 void EnableCalc(bool calculate) { _calculate = calculate; } 975 UInt32 GetChecksum() const { return _checksum; }
970 void InitCRC() { _crc = 0; }
971 UInt64 GetSize() const { return _size; }
972 UInt32 GetCRC() const { return _crc; }
973}; 976};
974 977
978
975Z7_COM7F_IMF(COutStreamWithSum::Write(const void *data, UInt32 size, UInt32 *processedSize)) 979Z7_COM7F_IMF(COutStreamWithSum::Write(const void *data, UInt32 size, UInt32 *processedSize))
976{ 980{
977 HRESULT result = S_OK; 981 HRESULT result = S_OK;
978 if (_stream) 982 if (_stream)
979 result = _stream->Write(data, size, &size); 983 result = _stream->Write(data, size, &size);
984 if (processedSize)
985 *processedSize = size;
980 if (_calculate) 986 if (_calculate)
981 { 987 {
982 UInt32 crc = 0; 988 const Byte *p = (const Byte *)data;
983 for (UInt32 i = 0; i < size; i++) 989 const Byte *lim = p + size;
984 crc += (UInt32)(((const Byte *)data)[i]); 990 UInt32 sum = _checksum;
985 _crc += crc; 991 if (size >= 4)
992 {
993 lim -= 4 - 1;
994 do
995 {
996 sum += p[0] + p[1] + p[2] + p[3];
997 p += 4;
998 }
999 while (p < lim);
1000 lim += 4 - 1;
1001 }
1002 if (p != lim) { sum += *p++;
1003 if (p != lim) { sum += *p++;
1004 if (p != lim) { sum += *p++; }}}
1005 _checksum = sum;
986 } 1006 }
987 if (processedSize)
988 *processedSize = size;
989 return result; 1007 return result;
990} 1008}
991 1009
@@ -1009,19 +1027,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1009 } 1027 }
1010 RINOK(extractCallback->SetTotal(totalSize)) 1028 RINOK(extractCallback->SetTotal(totalSize))
1011 1029
1012 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 1030 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
1013 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 1031 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1014
1015 CLocalProgress *lps = new CLocalProgress;
1016 CMyComPtr<ICompressProgressInfo> progress = lps;
1017 lps->Init(extractCallback, false); 1032 lps->Init(extractCallback, false);
1018 1033 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
1019 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 1034 inStream->SetStream(_stream);
1020 CMyComPtr<ISequentialInStream> inStream(streamSpec); 1035 CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSum> outStreamSum;
1021 streamSpec->SetStream(_stream);
1022
1023 COutStreamWithSum *outStreamSumSpec = new COutStreamWithSum;
1024 CMyComPtr<ISequentialOutStream> outStreamSum(outStreamSumSpec);
1025 1036
1026 UInt64 total_PackSize = 0; 1037 UInt64 total_PackSize = 0;
1027 UInt64 total_UnpackSize = 0; 1038 UInt64 total_UnpackSize = 0;
@@ -1033,40 +1044,40 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1033 RINOK(lps->SetCur()) 1044 RINOK(lps->SetCur())
1034 if (i >= numItems) 1045 if (i >= numItems)
1035 break; 1046 break;
1036 CMyComPtr<ISequentialOutStream> outStream;
1037 const Int32 askMode = testMode ? 1047 const Int32 askMode = testMode ?
1038 NExtract::NAskMode::kTest : 1048 NExtract::NAskMode::kTest :
1039 NExtract::NAskMode::kExtract; 1049 NExtract::NAskMode::kExtract;
1040 const UInt32 index = allFilesMode ? i : indices[i]; 1050 const UInt32 index = allFilesMode ? i : indices[i];
1041 const CItem &item2 = _items[index]; 1051 const CItem &item2 = _items[index];
1042 const CItem &item = _items[item2.MainIndex_ForInode]; 1052 const CItem &item = _items[item2.MainIndex_ForInode];
1043 RINOK(extractCallback->GetStream(index, &outStream, askMode))
1044
1045 total_PackSize += item2.GetPackSize();
1046 total_UnpackSize += item.Size;
1047
1048 if (item2.IsDir())
1049 { 1053 {
1054 CMyComPtr<ISequentialOutStream> outStream;
1055 RINOK(extractCallback->GetStream(index, &outStream, askMode))
1056
1057 total_PackSize += item2.GetPackSize();
1058 total_UnpackSize += item.Size;
1059
1060 if (item2.IsDir())
1061 {
1062 RINOK(extractCallback->PrepareOperation(askMode))
1063 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
1064 continue;
1065 }
1066 if (!testMode && !outStream)
1067 continue;
1068 outStreamSum->Init(item.IsCrcFormat());
1069 outStreamSum->SetStream(outStream);
1050 RINOK(extractCallback->PrepareOperation(askMode)) 1070 RINOK(extractCallback->PrepareOperation(askMode))
1051 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
1052 continue;
1053 } 1071 }
1054 if (!testMode && !outStream)
1055 continue;
1056 outStreamSumSpec->Init(item.IsCrcFormat());
1057 outStreamSumSpec->SetStream(outStream);
1058 outStream.Release();
1059
1060 RINOK(extractCallback->PrepareOperation(askMode))
1061 RINOK(InStream_SeekSet(_stream, item.GetDataPosition())) 1072 RINOK(InStream_SeekSet(_stream, item.GetDataPosition()))
1062 streamSpec->Init(item.Size); 1073 inStream->Init(item.Size);
1063 RINOK(copyCoder->Code(inStream, outStreamSum, NULL, NULL, progress)) 1074 RINOK(copyCoder.Interface()->Code(inStream, outStreamSum, NULL, NULL, lps))
1064 outStreamSumSpec->ReleaseStream(); 1075 outStreamSum->ReleaseStream();
1065 Int32 res = NExtract::NOperationResult::kDataError; 1076 Int32 res = NExtract::NOperationResult::kDataError;
1066 if (copyCoderSpec->TotalSize == item.Size) 1077 if (copyCoder->TotalSize == item.Size)
1067 { 1078 {
1068 res = NExtract::NOperationResult::kOK; 1079 res = NExtract::NOperationResult::kOK;
1069 if (item.IsCrcFormat() && item.ChkSum != outStreamSumSpec->GetCRC()) 1080 if (item.IsCrcFormat() && item.ChkSum != outStreamSum->GetChecksum())
1070 res = NExtract::NOperationResult::kCRCError; 1081 res = NExtract::NOperationResult::kCRCError;
1071 } 1082 }
1072 RINOK(extractCallback->SetOperationResult(res)) 1083 RINOK(extractCallback->SetOperationResult(res))
diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp
index 4bcb904..3901192 100644
--- a/CPP/7zip/Archive/DmgHandler.cpp
+++ b/CPP/7zip/Archive/DmgHandler.cpp
@@ -2,10 +2,13 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../../../C/Alloc.h"
5#include "../../../C/CpuArch.h" 6#include "../../../C/CpuArch.h"
6 7
8#include "../../Common/AutoPtr.h"
7#include "../../Common/ComTry.h" 9#include "../../Common/ComTry.h"
8#include "../../Common/IntToString.h" 10#include "../../Common/IntToString.h"
11#include "../../Common/MyBuffer2.h"
9#include "../../Common/MyXml.h" 12#include "../../Common/MyXml.h"
10#include "../../Common/UTFConvert.h" 13#include "../../Common/UTFConvert.h"
11 14
@@ -20,32 +23,67 @@
20#include "../Compress/BZip2Decoder.h" 23#include "../Compress/BZip2Decoder.h"
21#include "../Compress/CopyCoder.h" 24#include "../Compress/CopyCoder.h"
22#include "../Compress/LzfseDecoder.h" 25#include "../Compress/LzfseDecoder.h"
26#include "../Compress/XzDecoder.h"
23#include "../Compress/ZlibDecoder.h" 27#include "../Compress/ZlibDecoder.h"
24 28
25#include "Common/OutStreamWithCRC.h" 29#include "Common/OutStreamWithCRC.h"
26 30
27// #define DMG_SHOW_RAW 31// #define DMG_SHOW_RAW
28 32
29// #include <stdio.h> 33// #define SHOW_DEBUG_INFO
30#define PRF(x) // x 34
35/* for debug only: we can use block cache also for METHOD_COPY blocks.
36 It can reduce the number of Stream->Read() requests.
37 But it can increase memory usage.
38 Note: METHOD_COPY blocks are not fused usually.
39 But if METHOD_COPY blocks is fused in some dmg example,
40 block size can exceed k_Chunk_Size_MAX.
41 So we don't use cache for METHOD_COPY block, if (block_size > k_Chunk_Size_MAX)
42*/
43// for debug only:
44// #define Z7_DMG_USE_CACHE_FOR_COPY_BLOCKS
45
46#ifdef SHOW_DEBUG_INFO
47#include <stdio.h>
48#define PRF(x) x
49#else
50#define PRF(x)
51#endif
52
31 53
32#define Get16(p) GetBe16(p) 54#define Get16(p) GetBe16(p)
33#define Get32(p) GetBe32(p) 55#define Get32(p) GetBe32(p)
34#define Get64(p) GetBe64(p) 56#define Get64(p) GetBe64(p)
35 57
58#define Get32a(p) GetBe32a(p)
59#define Get64a(p) GetBe64a(p)
60
36Byte *Base64ToBin(Byte *dest, const char *src); 61Byte *Base64ToBin(Byte *dest, const char *src);
37 62
38namespace NArchive { 63namespace NArchive {
39namespace NDmg { 64namespace NDmg {
40 65
66// allocation limits for compressed blocks for GetStream() interface:
67static const unsigned k_NumChunks_MAX = 128;
68static const size_t k_Chunk_Size_MAX = (size_t)1 << 28;
69// 256 MB cache for 32-bit:
70// 4 GB cache for 64-bit:
71static const size_t k_Chunks_TotalSize_MAX = (size_t)1 << (sizeof(size_t) + 24);
41 72
42static const UInt32 METHOD_ZERO_0 = 0; 73// 2 GB limit for 32-bit:
74// 4 GB limit for 64-bit:
75// that limit can be increased for 64-bit mode, if there are such dmg files
76static const size_t k_XmlSize_MAX =
77 ((size_t)1 << (sizeof(size_t) / 4 + 30)) - 256;
78
79static const UInt32 METHOD_ZERO_0 = 0; // sparse
43static const UInt32 METHOD_COPY = 1; 80static const UInt32 METHOD_COPY = 1;
44static const UInt32 METHOD_ZERO_2 = 2; // without file CRC calculation 81static const UInt32 METHOD_ZERO_2 = 2; // sparse : without file CRC calculation
45static const UInt32 METHOD_ADC = 0x80000004; 82static const UInt32 METHOD_ADC = 0x80000004;
46static const UInt32 METHOD_ZLIB = 0x80000005; 83static const UInt32 METHOD_ZLIB = 0x80000005;
47static const UInt32 METHOD_BZIP2 = 0x80000006; 84static const UInt32 METHOD_BZIP2 = 0x80000006;
48static const UInt32 METHOD_LZFSE = 0x80000007; 85static const UInt32 METHOD_LZFSE = 0x80000007;
86static const UInt32 METHOD_XZ = 0x80000008;
49static const UInt32 METHOD_COMMENT = 0x7FFFFFFE; // is used to comment "+beg" and "+end" in extra field. 87static const UInt32 METHOD_COMMENT = 0x7FFFFFFE; // is used to comment "+beg" and "+end" in extra field.
50static const UInt32 METHOD_END = 0xFFFFFFFF; 88static const UInt32 METHOD_END = 0xFFFFFFFF;
51 89
@@ -54,20 +92,41 @@ struct CBlock
54{ 92{
55 UInt32 Type; 93 UInt32 Type;
56 UInt64 UnpPos; 94 UInt64 UnpPos;
57 UInt64 UnpSize; 95 // UInt64 UnpSize;
58 UInt64 PackPos; 96 UInt64 PackPos;
59 UInt64 PackSize; 97 UInt64 PackSize;
60 98
61 UInt64 GetNextPackOffset() const { return PackPos + PackSize; } 99 bool NeedCrc() const { return Type != METHOD_ZERO_2; }
62 UInt64 GetNextUnpPos() const { return UnpPos + UnpSize; } 100 bool IsZeroMethod() const
101 {
102 return (Type & ~(UInt32)METHOD_ZERO_2) == 0;
103 // return Type == METHOD_ZERO_0 || Type == METHOD_ZERO_2;
104 }
105
106 bool IsClusteredMethod() const
107 {
108 // most of dmg files have non-fused COPY_METHOD blocks.
109 // so we don't exclude COPY_METHOD blocks when we try to detect size of cluster.
110 return !IsZeroMethod(); // include COPY_METHOD blocks.
111 // Type > METHOD_ZERO_2; // for debug: exclude COPY_METHOD blocks.
112 }
63 113
64 bool IsZeroMethod() const { return Type == METHOD_ZERO_0 || Type == METHOD_ZERO_2; } 114 bool NeedAllocateBuffer() const
65 bool ThereAreDataInBlock() const { return Type != METHOD_COMMENT && Type != METHOD_END; } 115 {
116 return
117#ifdef Z7_DMG_USE_CACHE_FOR_COPY_BLOCKS
118 !IsZeroMethod();
119#else
120 Type > METHOD_ZERO_2;
121 // !IsZeroMethod() && Type != METHOD_COPY;
122#endif
123 }
124 // we don't store non-data blocks now
125 // bool ThereAreDataInBlock() const { return Type != METHOD_COMMENT && Type != METHOD_END; }
66}; 126};
67 127
68static const UInt32 kCheckSumType_CRC = 2; 128static const UInt32 kCheckSumType_CRC = 2;
69 129static const unsigned kChecksumSize_Max = 0x80;
70static const size_t kChecksumSize_Max = 0x80;
71 130
72struct CChecksum 131struct CChecksum
73{ 132{
@@ -78,6 +137,11 @@ struct CChecksum
78 bool IsCrc32() const { return Type == kCheckSumType_CRC && NumBits == 32; } 137 bool IsCrc32() const { return Type == kCheckSumType_CRC && NumBits == 32; }
79 UInt32 GetCrc32() const { return Get32(Data); } 138 UInt32 GetCrc32() const { return Get32(Data); }
80 void Parse(const Byte *p); 139 void Parse(const Byte *p);
140
141 void PrintType(AString &s) const;
142 void Print(AString &s) const;
143 void Print_with_Name(AString &s) const;
144 void AddToComment(AString &s, const char *name) const;
81}; 145};
82 146
83void CChecksum::Parse(const Byte *p) 147void CChecksum::Parse(const Byte *p)
@@ -87,16 +151,107 @@ void CChecksum::Parse(const Byte *p)
87 memcpy(Data, p + 8, kChecksumSize_Max); 151 memcpy(Data, p + 8, kChecksumSize_Max);
88} 152}
89 153
154
155void CChecksum::PrintType(AString &s) const
156{
157 if (NumBits == 0)
158 return;
159 if (IsCrc32())
160 s += "CRC";
161 else
162 {
163 s += "Checksum";
164 s.Add_UInt32(Type);
165 s.Add_Minus();
166 s.Add_UInt32(NumBits);
167 }
168}
169
170void CChecksum::Print(AString &s) const
171{
172 if (NumBits == 0)
173 return;
174 char temp[kChecksumSize_Max * 2 + 2];
175 /*
176 if (IsCrc32())
177 ConvertUInt32ToHex8Digits(GetCrc32(), temp);
178 else
179 */
180 {
181 UInt32 numBits = kChecksumSize_Max * 8;
182 if (numBits > NumBits)
183 numBits = NumBits;
184 const unsigned numBytes = (numBits + 7) >> 3;
185 if (numBytes <= 8)
186 ConvertDataToHex_Upper(temp, Data, numBytes);
187 else
188 ConvertDataToHex_Lower(temp, Data, numBytes);
189 }
190 s += temp;
191}
192
193void CChecksum::Print_with_Name(AString &s) const
194{
195 if (NumBits == 0)
196 return;
197 PrintType(s);
198 s += ": ";
199 Print(s);
200}
201
202static void AddToComment_Prop(AString &s, const char *name, const char *val)
203{
204 s += name;
205 s += ": ";
206 s += val;
207 s.Add_LF();
208}
209
210void CChecksum::AddToComment(AString &s, const char *name) const
211{
212 AString s2;
213 Print_with_Name(s2);
214 if (!s2.IsEmpty())
215 AddToComment_Prop(s, name, s2);
216}
217
218
90struct CFile 219struct CFile
91{ 220{
92 UInt64 Size; 221 UInt64 Size;
222 CRecordVector<CBlock> Blocks;
93 UInt64 PackSize; 223 UInt64 PackSize;
94 UInt64 StartPos; 224 UInt64 StartPackPos;
225 UInt64 BlockSize_MAX;
226 UInt64 StartUnpackSector; // unpack sector position of this file from all files
227 UInt64 NumUnpackSectors;
228 Int32 Descriptor;
229 bool IsCorrect;
230 bool FullFileChecksum;
95 AString Name; 231 AString Name;
96 CRecordVector<CBlock> Blocks; 232 // AString Id;
97 CChecksum Checksum; 233 CChecksum Checksum;
98 bool FullFileChecksum;
99 234
235 UInt64 GetUnpackSize_of_Block(unsigned blockIndex) const
236 {
237 return (blockIndex == Blocks.Size() - 1 ?
238 Size : Blocks[blockIndex + 1].UnpPos) - Blocks[blockIndex].UnpPos;
239 }
240
241 CFile():
242 Size(0),
243 PackSize(0),
244 StartPackPos(0),
245 BlockSize_MAX(0),
246 StartUnpackSector(0),
247 NumUnpackSectors(0),
248 Descriptor(0),
249 IsCorrect(false),
250 FullFileChecksum(false)
251 {
252 Checksum.Type = 0;
253 Checksum.NumBits = 0;
254 }
100 HRESULT Parse(const Byte *p, UInt32 size); 255 HRESULT Parse(const Byte *p, UInt32 size);
101}; 256};
102 257
@@ -109,87 +264,127 @@ struct CExtraFile
109#endif 264#endif
110 265
111 266
267static void AddToComment_UInt64(AString &s, UInt64 v, const char *name)
268{
269 s += name;
270 s += ": ";
271 s.Add_UInt64(v);
272 s.Add_LF();
273}
274
112struct CForkPair 275struct CForkPair
113{ 276{
114 UInt64 Offset; 277 UInt64 Offset;
115 UInt64 Len; 278 UInt64 Len;
116 279
280 // (p) is aligned for 8-bytes
117 void Parse(const Byte *p) 281 void Parse(const Byte *p)
118 { 282 {
119 Offset = Get64(p); 283 Offset = Get64a(p);
120 Len = Get64(p + 8); 284 Len = Get64a(p + 8);
285 }
286
287 bool GetEndPos(UInt64 &endPos)
288 {
289 endPos = Offset + Len;
290 return endPos >= Offset;
121 } 291 }
122 292
123 bool UpdateTop(UInt64 limit, UInt64 &top) 293 bool UpdateTop(UInt64 limit, UInt64 &top)
124 { 294 {
125 if (Offset > limit || Len > limit - Offset) 295 if (Offset > limit || Len > limit - Offset)
126 return false; 296 return false;
127 UInt64 top2 = Offset + Len; 297 const UInt64 top2 = Offset + Len;
128 if (top <= top2) 298 if (top <= top2)
129 top = top2; 299 top = top2;
130 return true; 300 return true;
131 } 301 }
302
303 void Print(AString &s, const char *name) const;
132}; 304};
133 305
306void CForkPair::Print(AString &s, const char *name) const
307{
308 if (Offset != 0 || Len != 0)
309 {
310 s += name; s.Add_Minus(); AddToComment_UInt64(s, Offset, "offset");
311 s += name; s.Add_Minus(); AddToComment_UInt64(s, Len, "length");
312 }
313}
314
134 315
135Z7_CLASS_IMP_CHandler_IInArchive_1( 316Z7_CLASS_IMP_CHandler_IInArchive_1(
136 IInArchiveGetStream 317 IInArchiveGetStream
137) 318)
138 CMyComPtr<IInStream> _inStream;
139 CObjectVector<CFile> _files;
140 bool _masterCrcError; 319 bool _masterCrcError;
141 bool _headersError; 320 bool _headersError;
321 bool _dataForkError;
322 bool _rsrcMode_wasUsed;
323
324 CMyComPtr<IInStream> _inStream;
325 CObjectVector<CFile> _files;
142 326
143 UInt32 _dataStartOffset; 327 // UInt32 _dataStartOffset;
144 UInt64 _startPos; 328 UInt64 _startPos;
145 UInt64 _phySize; 329 UInt64 _phySize;
146 330
147 AString _name; 331 AString _name;
148 332
149 #ifdef DMG_SHOW_RAW 333 CForkPair _dataForkPair;
334 CForkPair rsrcPair, xmlPair, blobPair;
335
336 // UInt64 _runningDataForkOffset;
337 // UInt32 _segmentNumber;
338 // UInt32 _segmentCount;
339 UInt64 _numSectors; // total unpacked number of sectors
340 Byte _segmentGUID[16];
341
342 CChecksum _dataForkChecksum;
343 CChecksum _masterChecksum;
344
345#ifdef DMG_SHOW_RAW
150 CObjectVector<CExtraFile> _extras; 346 CObjectVector<CExtraFile> _extras;
151 #endif 347#endif
152 348
153 HRESULT ReadData(IInStream *stream, const CForkPair &pair, CByteBuffer &buf); 349 HRESULT ReadData(IInStream *stream, const CForkPair &pair, CByteBuffer &buf);
154 bool ParseBlob(const CByteBuffer &data); 350 bool ParseBlob(const CByteBuffer &data);
155 HRESULT Open2(IInStream *stream); 351 HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openArchiveCallback);
156 HRESULT Extract(IInStream *stream); 352 HRESULT Extract(IInStream *stream);
157}; 353};
158 354
159// that limit can be increased, if there are such dmg files
160static const size_t kXmlSizeMax = 0xFFFF0000; // 4 GB - 64 KB;
161 355
162struct CMethods 356struct CMethods
163{ 357{
164 CRecordVector<UInt32> Types; 358 CRecordVector<UInt32> Types;
165 CRecordVector<UInt32> ChecksumTypes;
166 359
167 void Update(const CFile &file); 360 void Update(const CFile &file);
168 void GetString(AString &s) const; 361 void AddToString(AString &s) const;
169}; 362};
170 363
171void CMethods::Update(const CFile &file) 364void CMethods::Update(const CFile &file)
172{ 365{
173 ChecksumTypes.AddToUniqueSorted(file.Checksum.Type);
174 FOR_VECTOR (i, file.Blocks) 366 FOR_VECTOR (i, file.Blocks)
367 {
368 if (Types.Size() >= (1 << 8))
369 break;
175 Types.AddToUniqueSorted(file.Blocks[i].Type); 370 Types.AddToUniqueSorted(file.Blocks[i].Type);
371 }
176} 372}
177 373
178void CMethods::GetString(AString &res) const 374void CMethods::AddToString(AString &res) const
179{ 375{
180 res.Empty(); 376 FOR_VECTOR (i, Types)
181
182 unsigned i;
183
184 for (i = 0; i < Types.Size(); i++)
185 { 377 {
186 const UInt32 type = Types[i]; 378 const UInt32 type = Types[i];
379 /*
187 if (type == METHOD_COMMENT || type == METHOD_END) 380 if (type == METHOD_COMMENT || type == METHOD_END)
188 continue; 381 continue;
382 */
189 char buf[16]; 383 char buf[16];
190 const char *s; 384 const char *s;
191 switch (type) 385 switch (type)
192 { 386 {
387 // case METHOD_COMMENT: s = "Comment"; break;
193 case METHOD_ZERO_0: s = "Zero0"; break; 388 case METHOD_ZERO_0: s = "Zero0"; break;
194 case METHOD_ZERO_2: s = "Zero2"; break; 389 case METHOD_ZERO_2: s = "Zero2"; break;
195 case METHOD_COPY: s = "Copy"; break; 390 case METHOD_COPY: s = "Copy"; break;
@@ -197,25 +392,15 @@ void CMethods::GetString(AString &res) const
197 case METHOD_ZLIB: s = "ZLIB"; break; 392 case METHOD_ZLIB: s = "ZLIB"; break;
198 case METHOD_BZIP2: s = "BZip2"; break; 393 case METHOD_BZIP2: s = "BZip2"; break;
199 case METHOD_LZFSE: s = "LZFSE"; break; 394 case METHOD_LZFSE: s = "LZFSE"; break;
200 default: ConvertUInt32ToString(type, buf); s = buf; 395 case METHOD_XZ: s = "XZ"; break;
396 default: ConvertUInt32ToHex(type, buf); s = buf;
201 } 397 }
202 res.Add_OptSpaced(s); 398 res.Add_OptSpaced(s);
203 } 399 }
204
205 for (i = 0; i < ChecksumTypes.Size(); i++)
206 {
207 res.Add_Space_if_NotEmpty();
208 UInt32 type = ChecksumTypes[i];
209 switch (type)
210 {
211 case kCheckSumType_CRC: res += "CRC"; break;
212 default:
213 res += "Check";
214 res.Add_UInt32(type);
215 }
216 }
217} 400}
218 401
402
403
219struct CAppleName 404struct CAppleName
220{ 405{
221 bool IsFs; 406 bool IsFs;
@@ -229,6 +414,7 @@ static const CAppleName k_Names[] =
229 { true, "hfsx", "Apple_HFSX" }, 414 { true, "hfsx", "Apple_HFSX" },
230 { true, "ufs", "Apple_UFS" }, 415 { true, "ufs", "Apple_UFS" },
231 { true, "apfs", "Apple_APFS" }, 416 { true, "apfs", "Apple_APFS" },
417 { true, "iso", "Apple_ISO" },
232 418
233 // efi_sys partition is FAT32, but it's not main file. So we use (IsFs = false) 419 // efi_sys partition is FAT32, but it's not main file. So we use (IsFs = false)
234 { false, "efi_sys", "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" }, 420 { false, "efi_sys", "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" },
@@ -237,6 +423,13 @@ static const CAppleName k_Names[] =
237 { false, "ddm", "DDM" }, 423 { false, "ddm", "DDM" },
238 { false, NULL, "Apple_partition_map" }, 424 { false, NULL, "Apple_partition_map" },
239 { false, NULL, " GPT " }, 425 { false, NULL, " GPT " },
426 /* " GPT " is substring of full name entry in dmg that contains
427 some small metadata GPT entry. It's not real FS entry:
428 "Primary GPT Header",
429 "Primary GPT Table"
430 "Backup GPT Header",
431 "Backup GPT Table",
432 */
240 { false, NULL, "MBR" }, 433 { false, NULL, "MBR" },
241 { false, NULL, "Driver" }, 434 { false, NULL, "Driver" },
242 { false, NULL, "Patches" } 435 { false, NULL, "Patches" }
@@ -244,15 +437,54 @@ static const CAppleName k_Names[] =
244 437
245static const unsigned kNumAppleNames = Z7_ARRAY_SIZE(k_Names); 438static const unsigned kNumAppleNames = Z7_ARRAY_SIZE(k_Names);
246 439
440const char *Find_Apple_FS_Ext(const AString &name);
441const char *Find_Apple_FS_Ext(const AString &name)
442{
443 for (unsigned i = 0; i < kNumAppleNames; i++)
444 {
445 const CAppleName &a = k_Names[i];
446 if (a.Ext)
447 if (name == a.AppleName)
448 return a.Ext;
449 }
450 return NULL;
451}
452
453
454bool Is_Apple_FS_Or_Unknown(const AString &name);
455bool Is_Apple_FS_Or_Unknown(const AString &name)
456{
457 for (unsigned i = 0; i < kNumAppleNames; i++)
458 {
459 const CAppleName &a = k_Names[i];
460 // if (name.Find(a.AppleName) >= 0)
461 if (strstr(name, a.AppleName))
462 return a.IsFs;
463 }
464 return true;
465}
466
467
468
469// define it for debug only:
470// #define Z7_DMG_SINGLE_FILE_MODE
471
247static const Byte kProps[] = 472static const Byte kProps[] =
248{ 473{
249 kpidPath, 474 kpidPath,
250 kpidSize, 475 kpidSize,
251 kpidPackSize, 476 kpidPackSize,
252 kpidCRC,
253 kpidComment, 477 kpidComment,
254 kpidMethod 478 kpidMethod,
479 kpidNumBlocks,
480 kpidClusterSize,
481 kpidChecksum,
482 kpidCRC,
483 kpidId
255 // kpidOffset 484 // kpidOffset
485#ifdef Z7_DMG_SINGLE_FILE_MODE
486 , kpidPosition
487#endif
256}; 488};
257 489
258IMP_IInArchive_Props 490IMP_IInArchive_Props
@@ -261,9 +493,11 @@ static const Byte kArcProps[] =
261{ 493{
262 kpidMethod, 494 kpidMethod,
263 kpidNumBlocks, 495 kpidNumBlocks,
496 kpidClusterSize,
264 kpidComment 497 kpidComment
265}; 498};
266 499
500
267Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 501Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
268{ 502{
269 COM_TRY_BEGIN 503 COM_TRY_BEGIN
@@ -273,10 +507,33 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
273 case kpidMethod: 507 case kpidMethod:
274 { 508 {
275 CMethods m; 509 CMethods m;
276 FOR_VECTOR (i, _files) 510 CRecordVector<UInt32> ChecksumTypes;
277 m.Update(_files[i]); 511 {
512 FOR_VECTOR (i, _files)
513 {
514 const CFile &file = _files[i];
515 m.Update(file);
516 if (ChecksumTypes.Size() < (1 << 8))
517 ChecksumTypes.AddToUniqueSorted(file.Checksum.Type);
518 }
519 }
278 AString s; 520 AString s;
279 m.GetString(s); 521 m.AddToString(s);
522
523 FOR_VECTOR (i, ChecksumTypes)
524 {
525 const UInt32 type = ChecksumTypes[i];
526 switch (type)
527 {
528 case kCheckSumType_CRC:
529 s.Add_OptSpaced("CRC");
530 break;
531 default:
532 s.Add_OptSpaced("Checksum");
533 s.Add_UInt32(type);
534 }
535 }
536
280 if (!s.IsEmpty()) 537 if (!s.IsEmpty())
281 prop = s; 538 prop = s;
282 break; 539 break;
@@ -289,36 +546,34 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
289 prop = numBlocks; 546 prop = numBlocks;
290 break; 547 break;
291 } 548 }
549 case kpidClusterSize:
550 {
551 UInt64 blockSize_MAX = 0;
552 FOR_VECTOR (i, _files)
553 {
554 const UInt64 a = _files[i].BlockSize_MAX;
555 if (blockSize_MAX < a)
556 blockSize_MAX = a;
557 }
558 prop = blockSize_MAX;
559 break;
560 }
292 case kpidMainSubfile: 561 case kpidMainSubfile:
293 { 562 {
294 int mainIndex = -1; 563 int mainIndex = -1;
295 unsigned numFS = 0;
296 unsigned numUnknown = 0;
297 FOR_VECTOR (i, _files) 564 FOR_VECTOR (i, _files)
298 { 565 {
299 const AString &name = _files[i].Name; 566 if (Is_Apple_FS_Or_Unknown(_files[i].Name))
300 unsigned n;
301 for (n = 0; n < kNumAppleNames; n++)
302 { 567 {
303 const CAppleName &appleName = k_Names[n]; 568 if (mainIndex != -1)
304 // if (name.Find(appleName.AppleName) >= 0)
305 if (strstr(name, appleName.AppleName))
306 { 569 {
307 if (appleName.IsFs) 570 mainIndex = -1;
308 {
309 numFS++;
310 mainIndex = (int)i;
311 }
312 break; 571 break;
313 } 572 }
314 }
315 if (n == kNumAppleNames)
316 {
317 mainIndex = (int)i; 573 mainIndex = (int)i;
318 numUnknown++;
319 } 574 }
320 } 575 }
321 if (numFS + numUnknown == 1) 576 if (mainIndex != -1)
322 prop = (UInt32)(Int32)mainIndex; 577 prop = (UInt32)(Int32)mainIndex;
323 break; 578 break;
324 } 579 }
@@ -330,7 +585,8 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
330 case kpidWarningFlags: 585 case kpidWarningFlags:
331 { 586 {
332 UInt32 v = 0; 587 UInt32 v = 0;
333 if (_headersError) v |= kpv_ErrorFlags_HeadersError; 588 if (_headersError) v |= kpv_ErrorFlags_HeadersError;
589 if (_dataForkError) v |= kpv_ErrorFlags_CrcError;
334 if (v != 0) 590 if (v != 0)
335 prop = v; 591 prop = v;
336 break; 592 break;
@@ -340,15 +596,39 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
340 case kpidPhySize: prop = _phySize; break; 596 case kpidPhySize: prop = _phySize; break;
341 597
342 case kpidComment: 598 case kpidComment:
343 if (!_name.IsEmpty() && _name.Len() < 256) 599 {
344 prop = _name; 600 AString s;
345 break; 601 if (!_name.IsEmpty())
602 AddToComment_Prop(s, "Name", _name);
603 AddToComment_UInt64(s, _numSectors << 9, "unpack-size");
604 {
605 char temp[sizeof(_segmentGUID) * 2 + 2];
606 ConvertDataToHex_Lower(temp, _segmentGUID, sizeof(_segmentGUID));
607 AddToComment_Prop(s, "ID", temp);
608 }
609 _masterChecksum.AddToComment(s, "master-checksum");
610 _dataForkChecksum.AddToComment(s, "pack-checksum");
611 {
612 /*
613 if (_dataStartOffset != 0)
614 AddToComment_UInt64(s, _dataStartOffset, "payload-start-offset");
615 */
616 // if (_dataForkPair.Offset != 0)
617 _dataForkPair.Print(s, "pack");
618 rsrcPair.Print(s, "rsrc");
619 xmlPair.Print(s, "xml");
620 blobPair.Print(s, "blob");
621 }
622 if (_rsrcMode_wasUsed)
623 s += "RSRC_MODE\n";
624 if (!s.IsEmpty())
625 prop = s;
626 }
627 break;
346 628
347 case kpidName: 629 case kpidName:
348 if (!_name.IsEmpty() && _name.Len() < 256) 630 if (!_name.IsEmpty())
349 {
350 prop = _name + ".dmg"; 631 prop = _name + ".dmg";
351 }
352 break; 632 break;
353 } 633 }
354 prop.Detach(value); 634 prop.Detach(value);
@@ -358,39 +638,64 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
358 638
359IMP_IInArchive_ArcProps 639IMP_IInArchive_ArcProps
360 640
641
642
643static const UInt64 kSectorNumber_LIMIT = (UInt64)1 << (63 - 9);
644
361HRESULT CFile::Parse(const Byte *p, UInt32 size) 645HRESULT CFile::Parse(const Byte *p, UInt32 size)
362{ 646{
363 const UInt32 kHeadSize = 0xCC; 647 // CFile was initialized to default values: 0 in size variables and (IsCorrect == false)
648 const unsigned kHeadSize = 0xCC;
364 if (size < kHeadSize) 649 if (size < kHeadSize)
365 return S_FALSE; 650 return S_FALSE;
366 if (Get32(p) != 0x6D697368) // "mish" signature 651 if (Get32(p) != 0x6D697368) // "mish" signature
367 return S_FALSE; 652 return S_FALSE;
368 if (Get32(p + 4) != 1) // version 653 if (Get32(p + 4) != 1) // version
369 return S_FALSE; 654 return S_FALSE;
370 // UInt64 firstSectorNumber = Get64(p + 8); 655
371 UInt64 numSectors = Get64(p + 0x10); 656 StartUnpackSector = Get64(p + 8);
372 657 NumUnpackSectors = Get64(p + 0x10);
373 StartPos = Get64(p + 0x18); 658 StartPackPos = Get64(p + 0x18);
374 659
375 // UInt32 decompressedBufRequested = Get32(p + 0x20); // ??? 660#ifdef SHOW_DEBUG_INFO
376 // UInt32 blocksDescriptor = Get32(p + 0x24); // number starting from -1? 661 /* the number of sectors that must be allocated.
662 == 0x208 for 256KB clusters
663 == 0x808 for 1MB clusters
664 == 0x1001 for 1MB clusters in some example
665 */
666 const UInt32 decompressedBufRequested = Get32(p + 0x20);
667#endif
668
669 // Descriptor is file index. usually started from -1
670 // in one dmg it was started from 0
671 Descriptor = (Int32)Get32(p + 0x24);
377 // char Reserved1[24]; 672 // char Reserved1[24];
378 673
379 Checksum.Parse(p + 0x40); 674 Checksum.Parse(p + 0x40);
380 PRF(printf("\n\nChecksum Type = %2d", Checksum.Type)); 675 PRF(printf("\n" " Checksum Type = %2u"
381 676 "\n StartUnpackSector = %8x"
382 UInt32 numBlocks = Get32(p + 0xC8); 677 "\n NumUnpackSectors = %8x"
383 if (numBlocks > ((UInt32)1 << 28)) 678 "\n StartPos = %8x"
384 return S_FALSE; 679 "\n decompressedBufRequested=%8x"
385 680 "\n blocksDescriptor=%8x"
386 const UInt32 kRecordSize = 40; 681 , (unsigned)Checksum.Type
387 if (numBlocks * kRecordSize + kHeadSize != size) 682 , (unsigned)StartUnpackSector
683 , (unsigned)NumUnpackSectors
684 , (unsigned)StartPackPos
685 , (unsigned)decompressedBufRequested
686 , (unsigned)Descriptor
687 );)
688
689 const UInt32 numBlocks = Get32(p + 0xC8);
690 const unsigned kRecordSize = 40;
691 if ((UInt64)numBlocks * kRecordSize + kHeadSize != size)
388 return S_FALSE; 692 return S_FALSE;
389 693
390 PackSize = 0;
391 Size = 0;
392 Blocks.ClearAndReserve(numBlocks); 694 Blocks.ClearAndReserve(numBlocks);
393 FullFileChecksum = true; 695 FullFileChecksum = true;
696 /* IsCorrect = false; by default
697 So we return S_OK, if we can ignore some error in headers.
698 */
394 699
395 p += kHeadSize; 700 p += kHeadSize;
396 UInt32 i; 701 UInt32 i;
@@ -399,64 +704,104 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size)
399 { 704 {
400 CBlock b; 705 CBlock b;
401 b.Type = Get32(p); 706 b.Type = Get32(p);
402 b.UnpPos = Get64(p + 0x08) << 9; 707 {
403 b.UnpSize = Get64(p + 0x10) << 9; 708 const UInt64 a = Get64(p + 0x08);
709 if (a >= kSectorNumber_LIMIT)
710 return S_OK;
711 b.UnpPos = a << 9;
712 }
713 UInt64 unpSize;
714 {
715 const UInt64 a = Get64(p + 0x10);
716 if (a >= kSectorNumber_LIMIT)
717 return S_OK;
718 unpSize = a << 9;
719 }
720 const UInt64 newSize = b.UnpPos + unpSize;
721 if (newSize >= ((UInt64)1 << 63))
722 return S_OK;
723
404 b.PackPos = Get64(p + 0x18); 724 b.PackPos = Get64(p + 0x18);
405 b.PackSize = Get64(p + 0x20); 725 b.PackSize = Get64(p + 0x20);
406
407 // b.PackPos can be 0 for some types. So we don't check it 726 // b.PackPos can be 0 for some types. So we don't check it
408 if (!Blocks.IsEmpty()) 727 if (b.UnpPos != Size)
409 if (b.UnpPos != Blocks.Back().GetNextUnpPos()) 728 return S_OK;
410 return S_FALSE;
411 729
412 PRF(printf("\nType=%8x m[1]=%8x uPos=%8x uSize=%7x pPos=%8x pSize=%7x", 730 PRF(printf("\nType=%8x comment=%8x uPos=%8x uSize=%7x pPos=%8x pSize=%7x",
413 b.Type, Get32(p + 4), (UInt32)b.UnpPos, (UInt32)b.UnpSize, (UInt32)b.PackPos, (UInt32)b.PackSize)); 731 (unsigned)b.Type, Get32(p + 4), (unsigned)b.UnpPos, (unsigned)unpSize, (unsigned)b.PackPos, (unsigned)b.PackSize));
414 732
415 if (b.Type == METHOD_COMMENT) 733 if (b.Type == METHOD_COMMENT)
734 {
735 // some files contain 2 comment block records:
736 // record[0] : Type=METHOD_COMMENT, comment_field = "+beg"
737 // record[num-2] : Type=METHOD_COMMENT, comment_field = "+end"
738 // we skip these useless records.
416 continue; 739 continue;
740 }
417 if (b.Type == METHOD_END) 741 if (b.Type == METHOD_END)
418 break; 742 break;
419 PackSize += b.PackSize; 743
420 744 // we add only blocks that have non empty unpacked data:
421 if (b.UnpSize != 0) 745 if (unpSize != 0)
422 { 746 {
423 if (b.Type == METHOD_ZERO_2) 747 const UInt64 k_max_pos = (UInt64)1 << 63;
748 if (b.PackPos >= k_max_pos ||
749 b.PackSize >= k_max_pos - b.PackPos)
750 return S_OK;
751
752 /* we don't count non-ZERO blocks here, because
753 ZERO blocks in dmg files are not limited by some cluster size.
754 note: COPY blocks also sometimes are fused to larger blocks.
755 */
756 if (b.IsClusteredMethod())
757 if (BlockSize_MAX < unpSize)
758 BlockSize_MAX = unpSize;
759
760 PackSize += b.PackSize;
761 if (!b.NeedCrc())
424 FullFileChecksum = false; 762 FullFileChecksum = false;
425 Blocks.AddInReserved(b); 763 Blocks.AddInReserved(b);
764 Size = newSize;
426 } 765 }
427 } 766 }
428 767
768 PRF(printf("\n");)
769
429 if (i != numBlocks - 1) 770 if (i != numBlocks - 1)
430 return S_FALSE; 771 {
431 if (!Blocks.IsEmpty()) 772 // return S_FALSE;
432 Size = Blocks.Back().GetNextUnpPos(); 773 return S_OK;
433 if (Size != (numSectors << 9)) 774 }
434 return S_FALSE; 775
435 776 if ((Size >> 9) == NumUnpackSectors)
777 IsCorrect = true;
436 return S_OK; 778 return S_OK;
437} 779}
438 780
439static int FindKeyPair(const CXmlItem &item, const char *key, const char *nextTag) 781
782static const CXmlItem *FindKeyPair(const CXmlItem &item, const char *key, const char *nextTag)
440{ 783{
441 for (unsigned i = 0; i + 1 < item.SubItems.Size(); i++) 784 for (unsigned i = 0; i + 1 < item.SubItems.Size(); i++)
442 { 785 {
443 const CXmlItem &si = item.SubItems[i]; 786 const CXmlItem &si = item.SubItems[i];
444 if (si.IsTagged("key") && si.GetSubString() == key && item.SubItems[i + 1].IsTagged(nextTag)) 787 if (si.IsTagged("key") && si.GetSubString() == key)
445 return (int)(i + 1); 788 {
789 const CXmlItem *si_1 = &item.SubItems[i + 1];
790 if (si_1->IsTagged(nextTag))
791 return si_1;
792 }
446 } 793 }
447 return -1; 794 return NULL;
448} 795}
449 796
450static const AString *GetStringFromKeyPair(const CXmlItem &item, const char *key, const char *nextTag) 797static const AString *GetStringFromKeyPair(const CXmlItem &item, const char *key, const char *nextTag)
451{ 798{
452 int index = FindKeyPair(item, key, nextTag); 799 const CXmlItem *si_1 = FindKeyPair(item, key, nextTag);
453 if (index >= 0) 800 if (si_1)
454 return item.SubItems[index].GetSubStringPtr(); 801 return si_1->GetSubStringPtr();
455 return NULL; 802 return NULL;
456} 803}
457 804
458static const unsigned HEADER_SIZE = 0x200;
459
460static const Byte k_Signature[] = { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 }; 805static const Byte k_Signature[] = { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 };
461 806
462static inline bool IsKoly(const Byte *p) 807static inline bool IsKoly(const Byte *p)
@@ -485,144 +830,175 @@ HRESULT CHandler::ReadData(IInStream *stream, const CForkPair &pair, CByteBuffer
485} 830}
486 831
487 832
833
488bool CHandler::ParseBlob(const CByteBuffer &data) 834bool CHandler::ParseBlob(const CByteBuffer &data)
489{ 835{
490 if (data.Size() < 12) 836 const unsigned kHeaderSize = 3 * 4;
837 if (data.Size() < kHeaderSize)
491 return false; 838 return false;
492 const Byte *p = (const Byte *)data; 839 const Byte * const p = (const Byte *)data;
493 if (Get32(p) != 0xFADE0CC0) 840 if (Get32a(p) != 0xfade0cc0) // CSMAGIC_EMBEDDED_SIGNATURE
494 return true; 841 return true;
495 const UInt32 size = Get32(p + 4); 842 const UInt32 size = Get32a(p + 4);
496 if (size != data.Size()) 843 if (size != data.Size())
497 return false; 844 return false;
498 const UInt32 num = Get32(p + 8); 845 const UInt32 num = Get32a(p + 8);
499 if (num > (size - 12) / 8) 846 if (num > (size - kHeaderSize) / 8)
500 return false; 847 return false;
501 848
502 for (UInt32 i = 0; i < num; i++) 849 const UInt32 limit = num * 8 + kHeaderSize;
850 for (size_t i = kHeaderSize; i < limit; i += 8)
503 { 851 {
504 // UInt32 type = Get32(p + i * 8 + 12); 852 // type == 0 == CSSLOT_CODEDIRECTORY for CSMAGIC_CODEDIRECTORY item
505 UInt32 offset = Get32(p + i * 8 + 12 + 4); 853 // UInt32 type = Get32(p + i);
506 if (size - offset < 8) 854 const UInt32 offset = Get32a(p + i + 4);
855 if (offset < limit || offset > size - 8)
507 return false; 856 return false;
508 const Byte *p2 = (const Byte *)data + offset; 857 // offset is not aligned for 4 here !!!
858 const Byte * const p2 = p + offset;
509 const UInt32 magic = Get32(p2); 859 const UInt32 magic = Get32(p2);
510 const UInt32 len = Get32(p2 + 4); 860 const UInt32 len = Get32(p2 + 4);
511 if (size - offset < len || len < 8) 861 if (size - offset < len || len < 8)
512 return false; 862 return false;
513 863
514 #ifdef DMG_SHOW_RAW 864#ifdef DMG_SHOW_RAW
515 CExtraFile &extra = _extras.AddNew(); 865 CExtraFile &extra = _extras.AddNew();
516 extra.Name = "_blob_"; 866 extra.Name = "_blob_";
517 extra.Data.CopyFrom(p2, len); 867 extra.Data.CopyFrom(p2, len);
518 #endif 868#endif
519 869
520 if (magic == 0xFADE0C02) 870 if (magic == 0xfade0c02) // CSMAGIC_CODEDIRECTORY
521 { 871 {
522 #ifdef DMG_SHOW_RAW 872#ifdef DMG_SHOW_RAW
523 extra.Name += "codedir"; 873 extra.Name += "codedir";
524 #endif 874#endif
525 875
526 if (len < 11 * 4) 876 if (len < 11 * 4)
527 return false; 877 return false;
528 UInt32 idOffset = Get32(p2 + 0x14); 878 const UInt32 idOffset = Get32(p2 + 5 * 4);
529 if (idOffset >= len) 879 if (idOffset >= len)
530 return false; 880 return false;
531 UInt32 len2 = len - idOffset; 881 UInt32 len2 = len - idOffset;
532 if (len2 < (1 << 10)) 882 const UInt32 kNameLenMax = 1 << 8;
533 _name.SetFrom_CalcLen((const char *)(p2 + idOffset), len2); 883 if (len2 > kNameLenMax)
884 len2 = kNameLenMax;
885 _name.SetFrom_CalcLen((const char *)(p2 + idOffset), len2);
886 /*
887 // #define kSecCodeSignatureHashSHA1 1
888 // #define kSecCodeSignatureHashSHA256 2
889 const UInt32 hashOffset = Get32(p2 + 4 * 4);
890 const UInt32 nSpecialSlots = Get32(p2 + 6 * 4);
891 const UInt32 nCodeSlots = Get32(p2 + 7 * 4);
892 const unsigned hashSize = p2[36];
893 const unsigned hashType = p2[37];
894 // const unsigned unused = p2[38];
895 const unsigned pageSize = p2[39];
896 */
534 } 897 }
535 #ifdef DMG_SHOW_RAW 898#ifdef DMG_SHOW_RAW
536 else if (magic == 0xFADE0C01) 899 else if (magic == 0xfade0c01) extra.Name += "requirements";
537 extra.Name += "requirements"; 900 else if (magic == 0xfade0b01) extra.Name += "signed";
538 else if (magic == 0xFADE0B01)
539 extra.Name += "signed";
540 else 901 else
541 { 902 {
542 char temp[16]; 903 char temp[16];
543 ConvertUInt32ToHex8Digits(magic, temp); 904 ConvertUInt32ToHex8Digits(magic, temp);
544 extra.Name += temp; 905 extra.Name += temp;
545 } 906 }
546 #endif 907#endif
547 } 908 }
548 909
549 return true; 910 return true;
550} 911}
551 912
552 913
553HRESULT CHandler::Open2(IInStream *stream) 914
915
916HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openArchiveCallback)
554{ 917{
555 /* 918 /*
556 - usual dmg contains Koly Header at the end: 919 - usual dmg contains Koly Header at the end:
557 - rare case dmg contains Koly Header at the start. 920 - rare case old dmg contains Koly Header at the begin.
558 */ 921 */
559 922
560 _dataStartOffset = 0; 923 // _dataStartOffset = 0;
561 UInt64 fileSize; 924 UInt64 fileSize;
562 RINOK(InStream_GetPos_GetSize(stream, _startPos, fileSize)) 925 RINOK(InStream_GetPos_GetSize(stream, _startPos, fileSize))
563 926
564 Byte buf[HEADER_SIZE]; 927 const unsigned HEADER_SIZE = 0x200;
928 UInt64 buf[HEADER_SIZE / sizeof(UInt64)];
565 RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE)) 929 RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE))
566 930
567 UInt64 headerPos; 931 UInt64 headerPos;
568 bool startKolyMode = false; 932 bool front_Koly_Mode = false;
569 933
570 if (IsKoly(buf)) 934 /*
935 _dataForkChecksum.Offset == 0 for koly-at-the-end
936 _dataForkChecksum.Offset == 512 for koly-at-the-start
937 so we can use (_dataForkChecksum.Offset) to detect "koly-at-the-start" mode
938 */
939
940 if (IsKoly((const Byte *)(const void *)buf))
571 { 941 {
572 // it can be normal koly-at-the-end or koly-at-the-start 942 // it can be normal koly-at-the-end or koly-at-the-start
573 headerPos = _startPos; 943 headerPos = _startPos;
944 /*
574 if (_startPos <= (1 << 8)) 945 if (_startPos <= (1 << 8))
575 { 946 {
576 // we want to support startKolyMode, even if there is 947 // we want to support front_Koly_Mode, even if there is
577 // some data before dmg file, like 128 bytes MacBin header 948 // some data before dmg file, like 128 bytes MacBin header
578 _dataStartOffset = HEADER_SIZE; 949 _dataStartOffset = HEADER_SIZE;
579 startKolyMode = true; 950 front_Koly_Mode = true;
580 } 951 }
952 */
581 } 953 }
582 else 954 else
583 { 955 {
584 // we check only koly-at-the-end 956 /* we try to open in backward mode only for first attempt
957 when (_startPos == 0) */
958 if (_startPos != 0)
959 return S_FALSE;
585 headerPos = fileSize; 960 headerPos = fileSize;
586 if (headerPos < HEADER_SIZE) 961 if (headerPos < HEADER_SIZE)
587 return S_FALSE; 962 return S_FALSE;
588 headerPos -= HEADER_SIZE; 963 headerPos -= HEADER_SIZE;
589 RINOK(InStream_SeekSet(stream, headerPos)) 964 RINOK(InStream_SeekSet(stream, headerPos))
590 RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE)) 965 RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE))
591 if (!IsKoly(buf)) 966 if (!IsKoly((const Byte *)(const void *)buf))
592 return S_FALSE; 967 return S_FALSE;
593 } 968 }
594 969
595 // UInt32 flags = Get32(buf + 12); 970 // UInt32 flags = Get32a((const Byte *)(const void *)buf + 12);
596 // UInt64 runningDataForkOffset = Get64(buf + 0x10); 971 // _runningDataForkOffset = Get64a((const Byte *)(const void *)buf + 0x10);
597 972 _dataForkPair.Parse((const Byte *)(const void *)buf + 0x18);
598 CForkPair dataForkPair, rsrcPair, xmlPair, blobPair; 973 rsrcPair.Parse((const Byte *)(const void *)buf + 0x28);
599 974 // _segmentNumber = Get32a(buf + 0x38); // 0 or 1
600 dataForkPair.Parse(buf + 0x18); 975 // _segmentCount = Get32a(buf + 0x3C); // 0 (if not set) or 1
601 rsrcPair.Parse(buf + 0x28); 976 memcpy(_segmentGUID, (const Byte *)(const void *)buf + 0x40, 16);
602 xmlPair.Parse(buf + 0xD8); 977 _dataForkChecksum.Parse((const Byte *)(const void *)buf + 0x50);
603 blobPair.Parse(buf + 0x128); 978 xmlPair.Parse((const Byte *)(const void *)buf + 0xD8);
604 979 // Byte resereved[]
605 // UInt32 segmentNumber = Get32(buf + 0x38); 980 blobPair.Parse((const Byte *)(const void *)buf + 0x128);
606 // UInt32 segmentCount = Get32(buf + 0x3C); 981 _masterChecksum.Parse((const Byte *)(const void *)buf + 0x160);
607 // Byte segmentGUID[16]; 982 // UInt32 imageVariant = Get32a((const Byte *)(const void *)buf + 0x1E8); imageVariant = imageVariant;
608 // CChecksum dataForkChecksum; 983 _numSectors = Get64((const Byte *)(const void *)buf + 0x1EC); // it's not aligned for 8-bytes
609 // dataForkChecksum.Parse(buf + 0x50); 984 // Byte resereved[12];
610 985
986 if (_dataForkPair.Offset == HEADER_SIZE
987 && headerPos + HEADER_SIZE < fileSize)
988 front_Koly_Mode = true;
989
990 const UInt64 limit = front_Koly_Mode ? fileSize : headerPos;
611 UInt64 top = 0; 991 UInt64 top = 0;
612 UInt64 limit = startKolyMode ? fileSize : headerPos; 992 if (!_dataForkPair.UpdateTop(limit, top)) return S_FALSE;
613
614 if (!dataForkPair.UpdateTop(limit, top)) return S_FALSE;
615 if (!xmlPair.UpdateTop(limit, top)) return S_FALSE; 993 if (!xmlPair.UpdateTop(limit, top)) return S_FALSE;
616 if (!rsrcPair.UpdateTop(limit, top)) return S_FALSE; 994 if (!rsrcPair.UpdateTop(limit, top)) return S_FALSE;
617 995
618 /* Some old dmg files contain garbage data in blobPair field. 996 /* Some old dmg files contain garbage data in blobPair field.
619 So we need to ignore such garbage case; 997 So we need to ignore such garbage case;
620 And we still need to detect offset of start of archive for "parser" mode. */ 998 And we still need to detect offset of start of archive for "parser" mode. */
999 const bool useBlob = blobPair.UpdateTop(limit, top);
621 1000
622 bool useBlob = blobPair.UpdateTop(limit, top); 1001 if (front_Koly_Mode)
623
624
625 if (startKolyMode)
626 _phySize = top; 1002 _phySize = top;
627 else 1003 else
628 { 1004 {
@@ -637,71 +1013,78 @@ HRESULT CHandler::Open2(IInStream *stream)
637 - archive with offset. 1013 - archive with offset.
638 So we try to read XML with absolute offset to select from these two ways. 1014 So we try to read XML with absolute offset to select from these two ways.
639 */ 1015 */
640 CForkPair xmlPair2 = xmlPair; 1016 CForkPair xmlPair2 = xmlPair;
641 const char *sz = "<?xml version"; 1017 const char *sz = "<?xml version";
642 const unsigned len = (unsigned)strlen(sz); 1018 const unsigned len = (unsigned)strlen(sz);
643 if (xmlPair2.Len > len) 1019 if (xmlPair2.Len > len)
644 xmlPair2.Len = len; 1020 xmlPair2.Len = len;
645 CByteBuffer buf2; 1021 CByteBuffer buf2;
646 if (xmlPair2.Len < len 1022 if (xmlPair2.Len < len
647 || ReadData(stream, xmlPair2, buf2) != S_OK 1023 || ReadData(stream, xmlPair2, buf2) != S_OK
648 || memcmp(buf2, sz, len) != 0) 1024 || memcmp(buf2, sz, len) != 0)
649 { 1025 {
650 // if absolute offset is not OK, probably it's archive with offset 1026 // if absolute offset is not OK, probably it's archive with offset
651 _startPos = headerPos - top; 1027 _startPos = headerPos - top;
652 _phySize = top + HEADER_SIZE; 1028 _phySize = top + HEADER_SIZE;
653 } 1029 }
654 } 1030 }
655 } 1031 }
656 1032
657 // Byte reserved[0x78] 1033 if (useBlob
658 1034 && blobPair.Len != 0
659 if (useBlob && blobPair.Len != 0) 1035 && blobPair.Len <= (1u << 24)) // we don't want parsing of big blobs
660 { 1036 {
661 #ifdef DMG_SHOW_RAW 1037#ifdef DMG_SHOW_RAW
662 CExtraFile &extra = _extras.AddNew(); 1038 CExtraFile &extra = _extras.AddNew();
663 extra.Name = "_blob.bin"; 1039 extra.Name = "_blob.bin";
664 CByteBuffer &blobBuf = extra.Data; 1040 CByteBuffer &blobBuf = extra.Data;
665 #else 1041#else
666 CByteBuffer blobBuf; 1042 CByteBuffer blobBuf;
667 #endif 1043#endif
668 RINOK(ReadData(stream, blobPair, blobBuf)) 1044 RINOK(ReadData(stream, blobPair, blobBuf))
669 if (!ParseBlob(blobBuf)) 1045 if (!ParseBlob(blobBuf))
670 _headersError = true; 1046 _headersError = true;
671 } 1047 }
672 1048
673 1049
674 CChecksum masterChecksum; 1050 UInt64 openTotal = 0;
675 masterChecksum.Parse(buf + 0x160); 1051 UInt64 openCur = 0;
676 1052 if (_dataForkChecksum.IsCrc32())
677 // UInt32 imageVariant = Get32(buf + 0x1E8); 1053 openTotal = _dataForkPair.Len;
678 // UInt64 numSectors = Get64(buf + 0x1EC);
679 // Byte reserved[0x12]
680 1054
681 const UInt32 RSRC_HEAD_SIZE = 0x100; 1055 const UInt32 RSRC_HEAD_SIZE = 0x100;
682 1056
683 // We don't know the size of the field "offset" in rsrc. 1057 /* we have 2 ways to read files and blocks metadata:
684 // We suppose that it uses 24 bits. So we use Rsrc, only if the rsrcLen < (1 << 24). 1058 via Xml or via Rsrc.
685 bool useRsrc = (rsrcPair.Len > RSRC_HEAD_SIZE && rsrcPair.Len < ((UInt32)1 << 24)); 1059 But some images have no Rsrc fork.
686 // useRsrc = false; 1060 Is it possible that there is no Xml?
687 1061 Rsrc method will not work for big files. */
688 if (useRsrc) 1062 // v23.02: we use xml mode by default
1063 // if (rsrcPair.Len >= RSRC_HEAD_SIZE && rsrcPair.Len <= ((UInt32)1 << 24)) // for debug
1064 if (xmlPair.Len == 0)
689 { 1065 {
690 #ifdef DMG_SHOW_RAW 1066 // We don't know the size of the field "offset" in Rsrc.
1067 // We suppose that it uses 24 bits. So we use Rsrc, only if the rsrcPair.Len <= (1 << 24).
1068 const bool canUseRsrc = (rsrcPair.Len >= RSRC_HEAD_SIZE && rsrcPair.Len <= ((UInt32)1 << 24));
1069 if (!canUseRsrc)
1070 return S_FALSE;
1071
1072 _rsrcMode_wasUsed = true;
1073#ifdef DMG_SHOW_RAW
691 CExtraFile &extra = _extras.AddNew(); 1074 CExtraFile &extra = _extras.AddNew();
692 extra.Name = "rsrc.bin"; 1075 extra.Name = "rsrc.bin";
693 CByteBuffer &rsrcBuf = extra.Data; 1076 CByteBuffer &rsrcBuf = extra.Data;
694 #else 1077#else
695 CByteBuffer rsrcBuf; 1078 CByteBuffer rsrcBuf;
696 #endif 1079#endif
697 1080
698 RINOK(ReadData(stream, rsrcPair, rsrcBuf)) 1081 RINOK(ReadData(stream, rsrcPair, rsrcBuf))
699 1082
700 const Byte *p = rsrcBuf; 1083 const Byte *p = rsrcBuf;
701 UInt32 headSize = Get32(p + 0); 1084 const UInt32 headSize = Get32a(p + 0);
702 UInt32 footerOffset = Get32(p + 4); 1085 const UInt32 footerOffset = Get32a(p + 4);
703 UInt32 mainDataSize = Get32(p + 8); 1086 const UInt32 mainDataSize = Get32a(p + 8);
704 UInt32 footerSize = Get32(p + 12); 1087 const UInt32 footerSize = Get32a(p + 12);
705 if (headSize != RSRC_HEAD_SIZE 1088 if (headSize != RSRC_HEAD_SIZE
706 || footerOffset >= rsrcPair.Len 1089 || footerOffset >= rsrcPair.Len
707 || mainDataSize >= rsrcPair.Len 1090 || mainDataSize >= rsrcPair.Len
@@ -709,59 +1092,59 @@ HRESULT CHandler::Open2(IInStream *stream)
709 || footerOffset != headSize + mainDataSize) 1092 || footerOffset != headSize + mainDataSize)
710 return S_FALSE; 1093 return S_FALSE;
711 1094
712 const UInt32 footerEnd = footerOffset + footerSize;
713 if (footerEnd != rsrcPair.Len)
714 { 1095 {
715 // there is rare case dmg example, where there are 4 additional bytes 1096 const UInt32 footerEnd = footerOffset + footerSize;
716 UInt64 rem = rsrcPair.Len - footerOffset; 1097 if (footerEnd != rsrcPair.Len)
717 if (rem < footerSize 1098 {
1099 // there is rare case dmg example, where there are 4 additional bytes
1100 const UInt64 rem = rsrcPair.Len - footerOffset;
1101 if (rem < footerSize
718 || rem - footerSize != 4 1102 || rem - footerSize != 4
719 || Get32(p + footerEnd) != 0) 1103 || Get32(p + footerEnd) != 0)
720 return S_FALSE; 1104 return S_FALSE;
1105 }
721 } 1106 }
722 1107
723 if (footerSize < 16) 1108 if (footerSize < 0x1e)
724 return S_FALSE; 1109 return S_FALSE;
725 if (memcmp(p, p + footerOffset, 16) != 0) 1110 if (memcmp(p, p + footerOffset, 16) != 0)
726 return S_FALSE; 1111 return S_FALSE;
727 1112
728 p += footerOffset; 1113 p += footerOffset;
729 1114
730 if ((UInt32)Get16(p + 0x18) != 0x1C) 1115 if ((UInt32)Get16(p + 0x18) != 0x1c)
731 return S_FALSE; 1116 return S_FALSE;
732 const UInt32 namesOffset = Get16(p + 0x1A); 1117 const UInt32 namesOffset = Get16(p + 0x1a);
733 if (namesOffset > footerSize) 1118 if (namesOffset > footerSize)
734 return S_FALSE; 1119 return S_FALSE;
735 1120
736 UInt32 numItems = (UInt32)Get16(p + 0x1C) + 1; 1121 const UInt32 numItems = (UInt32)Get16(p + 0x1c) + 1;
737 if (numItems * 8 + 0x1E > namesOffset) 1122 if (numItems * 8 + 0x1e > namesOffset)
738 return S_FALSE; 1123 return S_FALSE;
739 1124
740 for (UInt32 i = 0; i < numItems; i++) 1125 for (UInt32 i = 0; i < numItems; i++)
741 { 1126 {
742 const Byte *p2 = p + 0x1E + i * 8; 1127 const Byte *p2 = p + 0x1e + (size_t)i * 8;
743
744 const UInt32 typeId = Get32(p2); 1128 const UInt32 typeId = Get32(p2);
745 1129 const UInt32 k_typeId_blkx = 0x626c6b78; // blkx
746 #ifndef DMG_SHOW_RAW 1130#ifndef DMG_SHOW_RAW
747 if (typeId != 0x626C6B78) // blkx 1131 if (typeId != k_typeId_blkx)
748 continue; 1132 continue;
749 #endif 1133#endif
750
751 const UInt32 numFiles = (UInt32)Get16(p2 + 4) + 1; 1134 const UInt32 numFiles = (UInt32)Get16(p2 + 4) + 1;
752 const UInt32 offs = Get16(p2 + 6); 1135 const UInt32 offs = Get16(p2 + 6);
753 if (0x1C + offs + 12 * numFiles > namesOffset) 1136 if (0x1c + offs + 12 * numFiles > namesOffset)
754 return S_FALSE; 1137 return S_FALSE;
755 1138
756 for (UInt32 k = 0; k < numFiles; k++) 1139 for (UInt32 k = 0; k < numFiles; k++)
757 { 1140 {
758 const Byte *p3 = p + 0x1C + offs + k * 12; 1141 const Byte *p3 = p + 0x1c + offs + k * 12;
759 // UInt32 id = Get16(p3); 1142 // UInt32 id = Get16(p3);
760 const UInt32 namePos = Get16(p3 + 2); 1143 const UInt32 namePos = Get16(p3 + 2);
761 // Byte attributes = p3[4]; // = 0x50 for blkx 1144 // Byte attributes = p3[4]; // = 0x50 for blkx #define (ATTRIBUTE_HDIUTIL)
762 // we don't know how many bits we can use. So we use 24 bits only 1145 // we don't know how many bits we can use. So we use 24 bits only
763 UInt32 blockOffset = Get32(p3 + 4); 1146 UInt32 blockOffset = Get32(p3 + 4);
764 blockOffset &= (((UInt32)1 << 24) - 1); 1147 blockOffset &= ((UInt32)1 << 24) - 1;
765 // UInt32 unknown2 = Get32(p3 + 8); // ??? 1148 // UInt32 unknown2 = Get32(p3 + 8); // ???
766 if (blockOffset + 4 >= mainDataSize) 1149 if (blockOffset + 4 >= mainDataSize)
767 return S_FALSE; 1150 return S_FALSE;
@@ -772,38 +1155,38 @@ HRESULT CHandler::Open2(IInStream *stream)
772 1155
773 AString name; 1156 AString name;
774 1157
775 if (namePos != 0xFFFF) 1158 if (namePos != 0xffff)
776 { 1159 {
777 UInt32 namesBlockSize = footerSize - namesOffset; 1160 const UInt32 namesBlockSize = footerSize - namesOffset;
778 if (namePos >= namesBlockSize) 1161 if (namePos >= namesBlockSize)
779 return S_FALSE; 1162 return S_FALSE;
780 const Byte *namePtr = p + namesOffset + namePos; 1163 const Byte *namePtr = p + namesOffset + namePos;
781 UInt32 nameLen = *namePtr; 1164 const UInt32 nameLen = *namePtr;
782 if (namesBlockSize - namePos <= nameLen) 1165 if (namesBlockSize - namePos <= nameLen)
783 return S_FALSE; 1166 return S_FALSE;
784 for (UInt32 r = 1; r <= nameLen; r++) 1167 for (UInt32 r = 1; r <= nameLen; r++)
785 { 1168 {
786 Byte c = namePtr[r]; 1169 const Byte c = namePtr[r];
787 if (c < 0x20 || c >= 0x80) 1170 if (c < 0x20 || c >= 0x80)
788 break; 1171 break;
789 name += (char)c; 1172 name += (char)c;
790 } 1173 }
791 } 1174 }
792 1175
793 if (typeId == 0x626C6B78) // blkx 1176 if (typeId == k_typeId_blkx)
794 { 1177 {
795 CFile &file = _files.AddNew(); 1178 CFile &file = _files.AddNew();
796 file.Name = name; 1179 file.Name = name;
797 RINOK(file.Parse(pBlock + 4, blockSize)) 1180 RINOK(file.Parse(pBlock + 4, blockSize))
1181 if (!file.IsCorrect)
1182 _headersError = true;
798 } 1183 }
799 1184
800 #ifdef DMG_SHOW_RAW 1185#ifdef DMG_SHOW_RAW
801 { 1186 {
802 AString name2; 1187 AString name2;
803
804 name2.Add_UInt32(i); 1188 name2.Add_UInt32(i);
805 name2 += '_'; 1189 name2 += '_';
806
807 { 1190 {
808 char temp[4 + 1] = { 0 }; 1191 char temp[4 + 1] = { 0 };
809 memcpy(temp, p2, 4); 1192 memcpy(temp, p2, 4);
@@ -812,69 +1195,80 @@ HRESULT CHandler::Open2(IInStream *stream)
812 name2.Trim(); 1195 name2.Trim();
813 name2 += '_'; 1196 name2 += '_';
814 name2.Add_UInt32(k); 1197 name2.Add_UInt32(k);
815
816 if (!name.IsEmpty()) 1198 if (!name.IsEmpty())
817 { 1199 {
818 name2 += '_'; 1200 name2 += '_';
819 name2 += name; 1201 name2 += name;
820 } 1202 }
821 1203 CExtraFile &extra2 = _extras.AddNew();
822 CExtraFile &extra = _extras.AddNew(); 1204 extra2.Name = name2;
823 extra.Name = name2; 1205 extra2.Data.CopyFrom(pBlock + 4, blockSize);
824 extra.Data.CopyFrom(pBlock + 4, blockSize);
825 } 1206 }
826 #endif 1207#endif
827 } 1208 }
828 } 1209 }
829 } 1210 }
830 else 1211 else
831 { 1212 {
832 if (xmlPair.Len >= kXmlSizeMax || xmlPair.Len == 0) 1213 if (xmlPair.Len > k_XmlSize_MAX)
833 return S_FALSE; 1214 return S_FALSE;
834 size_t size = (size_t)xmlPair.Len; 1215 // if (!canUseXml) return S_FALSE;
835 if (size != xmlPair.Len) 1216 const size_t size = (size_t)xmlPair.Len;
836 return S_FALSE; 1217 // if (size + 1 <= xmlPair.Len) return S_FALSE; // optional check
837
838 RINOK(InStream_SeekSet(stream, _startPos + xmlPair.Offset)) 1218 RINOK(InStream_SeekSet(stream, _startPos + xmlPair.Offset))
839
840 CXml xml; 1219 CXml xml;
841 { 1220 {
842 CObjArray<char> xmlStr(size + 1); 1221 openTotal += size;
843 RINOK(ReadStream_FALSE(stream, xmlStr, size)) 1222 if (openArchiveCallback)
1223 {
1224 RINOK(openArchiveCallback->SetTotal(NULL, &openTotal))
1225 }
1226 size_t pos = 0;
1227 CAlignedBuffer1 xmlStr(size + 1);
1228 for (;;)
1229 {
1230 const size_t k_OpenStep = 1 << 24;
1231 const size_t cur = MyMin(k_OpenStep, size - pos);
1232 RINOK(ReadStream_FALSE(stream, xmlStr + pos, cur))
1233 pos += cur;
1234 openCur += cur;
1235 if (pos == size)
1236 break;
1237 if (openArchiveCallback)
1238 {
1239 RINOK(openArchiveCallback->SetCompleted(NULL, &openCur))
1240 }
1241 }
844 xmlStr[size] = 0; 1242 xmlStr[size] = 0;
845 // if (strlen(xmlStr) != size) return S_FALSE; 1243 // if (strlen((const char *)(const void *)(const Byte *)xmlStr) != size) return S_FALSE;
846 if (!xml.Parse(xmlStr)) 1244 if (!xml.Parse((char *)(void *)(Byte *)xmlStr))
847 return S_FALSE; 1245 return S_FALSE;
848 1246
849 #ifdef DMG_SHOW_RAW 1247#ifdef DMG_SHOW_RAW
850 CExtraFile &extra = _extras.AddNew(); 1248 CExtraFile &extra = _extras.AddNew();
851 extra.Name = "a.xml"; 1249 extra.Name = "a.xml";
852 extra.Data.CopyFrom((const Byte *)(const char *)xmlStr, size); 1250 extra.Data.CopyFrom(xmlStr, size);
853 #endif 1251#endif
854 } 1252 }
855 1253
856 if (xml.Root.Name != "plist") 1254 if (xml.Root.Name != "plist")
857 return S_FALSE; 1255 return S_FALSE;
858 1256
859 int dictIndex = xml.Root.FindSubTag("dict"); 1257 const CXmlItem *dictItem = xml.Root.FindSubTag_GetPtr("dict");
860 if (dictIndex < 0) 1258 if (!dictItem)
861 return S_FALSE; 1259 return S_FALSE;
862 1260
863 const CXmlItem &dictItem = xml.Root.SubItems[dictIndex]; 1261 const CXmlItem *rfDictItem = FindKeyPair(*dictItem, "resource-fork", "dict");
864 int rfDictIndex = FindKeyPair(dictItem, "resource-fork", "dict"); 1262 if (!rfDictItem)
865 if (rfDictIndex < 0)
866 return S_FALSE; 1263 return S_FALSE;
867 1264
868 const CXmlItem &rfDictItem = dictItem.SubItems[rfDictIndex]; 1265 const CXmlItem *arrItem = FindKeyPair(*rfDictItem, "blkx", "array");
869 int arrIndex = FindKeyPair(rfDictItem, "blkx", "array"); 1266 if (!arrItem)
870 if (arrIndex < 0)
871 return S_FALSE; 1267 return S_FALSE;
872 1268
873 const CXmlItem &arrItem = rfDictItem.SubItems[arrIndex]; 1269 FOR_VECTOR (i, arrItem->SubItems)
874
875 FOR_VECTOR (i, arrItem.SubItems)
876 { 1270 {
877 const CXmlItem &item = arrItem.SubItems[i]; 1271 const CXmlItem &item = arrItem->SubItems[i];
878 if (!item.IsTagged("dict")) 1272 if (!item.IsTagged("dict"))
879 continue; 1273 continue;
880 1274
@@ -893,25 +1287,38 @@ HRESULT CHandler::Open2(IInStream *stream)
893 destLen = (unsigned)(endPtr - (const Byte *)rawBuf); 1287 destLen = (unsigned)(endPtr - (const Byte *)rawBuf);
894 } 1288 }
895 1289
896 #ifdef DMG_SHOW_RAW 1290#ifdef DMG_SHOW_RAW
897 CExtraFile &extra = _extras.AddNew(); 1291 CExtraFile &extra = _extras.AddNew();
898 extra.Name.Add_UInt32(_files.Size()); 1292 extra.Name.Add_UInt32(_files.Size());
899 extra.Data.CopyFrom(rawBuf, destLen); 1293 extra.Data.CopyFrom(rawBuf, destLen);
900 #endif 1294#endif
901 } 1295 }
902 CFile &file = _files.AddNew(); 1296 CFile &file = _files.AddNew();
903 { 1297 {
1298 /* xml code removes front space for such string:
1299 <string> (Apple_Free : 3)</string>
1300 maybe we shoud fix xml code and return full string with space.
1301 */
904 const AString *name = GetStringFromKeyPair(item, "Name", "string"); 1302 const AString *name = GetStringFromKeyPair(item, "Name", "string");
905 if (!name || name->IsEmpty()) 1303 if (!name || name->IsEmpty())
906 name = GetStringFromKeyPair(item, "CFName", "string"); 1304 name = GetStringFromKeyPair(item, "CFName", "string");
907 if (name) 1305 if (name)
908 file.Name = *name; 1306 file.Name = *name;
909 } 1307 }
1308 /*
1309 {
1310 const AString *s = GetStringFromKeyPair(item, "ID", "string");
1311 if (s)
1312 file.Id = *s;
1313 }
1314 */
910 RINOK(file.Parse(rawBuf, destLen)) 1315 RINOK(file.Parse(rawBuf, destLen))
1316 if (!file.IsCorrect)
1317 _headersError = true;
911 } 1318 }
912 } 1319 }
913 1320
914 if (masterChecksum.IsCrc32()) 1321 if (_masterChecksum.IsCrc32())
915 { 1322 {
916 UInt32 crc = CRC_INIT_VAL; 1323 UInt32 crc = CRC_INIT_VAL;
917 unsigned i; 1324 unsigned i;
@@ -920,54 +1327,127 @@ HRESULT CHandler::Open2(IInStream *stream)
920 const CChecksum &cs = _files[i].Checksum; 1327 const CChecksum &cs = _files[i].Checksum;
921 if ((cs.NumBits & 0x7) != 0) 1328 if ((cs.NumBits & 0x7) != 0)
922 break; 1329 break;
923 UInt32 len = cs.NumBits >> 3; 1330 const UInt32 len = cs.NumBits >> 3;
924 if (len > kChecksumSize_Max) 1331 if (len > kChecksumSize_Max)
925 break; 1332 break;
926 crc = CrcUpdate(crc, cs.Data, (size_t)len); 1333 crc = CrcUpdate(crc, cs.Data, (size_t)len);
927 } 1334 }
928 if (i == _files.Size()) 1335 if (i == _files.Size())
929 _masterCrcError = (CRC_GET_DIGEST(crc) != masterChecksum.GetCrc32()); 1336 _masterCrcError = (CRC_GET_DIGEST(crc) != _masterChecksum.GetCrc32());
1337 }
1338
1339 {
1340 UInt64 sec = 0;
1341 FOR_VECTOR (i, _files)
1342 {
1343 const CFile &file = _files[i];
1344 /*
1345 if (file.Descriptor != (Int32)i - 1)
1346 _headersError = true;
1347 */
1348 if (file.StartUnpackSector != sec)
1349 _headersError = true;
1350 if (file.NumUnpackSectors >= kSectorNumber_LIMIT)
1351 _headersError = true;
1352 sec += file.NumUnpackSectors;
1353 if (sec >= kSectorNumber_LIMIT)
1354 _headersError = true;
1355 }
1356 if (sec != _numSectors)
1357 _headersError = true;
1358 }
1359
1360 // data checksum calculation can be slow for big dmg file
1361 if (_dataForkChecksum.IsCrc32())
1362 {
1363 UInt64 endPos;
1364 if (!_dataForkPair.GetEndPos(endPos)
1365 || _dataForkPair.Offset >= ((UInt64)1 << 63))
1366 _headersError = true;
1367 else
1368 {
1369 const UInt64 seekPos = _startPos + _dataForkPair.Offset;
1370 if (seekPos > fileSize
1371 || endPos > fileSize - _startPos)
1372 {
1373 _headersError = true;
1374 // kpv_ErrorFlags_UnexpectedEnd
1375 }
1376 else
1377 {
1378 const size_t kBufSize = 1 << 15;
1379 CAlignedBuffer1 buf2(kBufSize);
1380 RINOK(InStream_SeekSet(stream, seekPos))
1381 if (openArchiveCallback)
1382 {
1383 RINOK(openArchiveCallback->SetTotal(NULL, &openTotal))
1384 }
1385 UInt32 crc = CRC_INIT_VAL;
1386 UInt64 pos = 0;
1387 for (;;)
1388 {
1389 const UInt64 rem = _dataForkPair.Len - pos;
1390 size_t cur = kBufSize;
1391 if (cur > rem)
1392 cur = (UInt32)rem;
1393 if (cur == 0)
1394 break;
1395 RINOK(ReadStream_FALSE(stream, buf2, cur))
1396 crc = CrcUpdate(crc, buf2, cur);
1397 pos += cur;
1398 openCur += cur;
1399 if ((pos & ((1 << 24) - 1)) == 0 && openArchiveCallback)
1400 {
1401 RINOK(openArchiveCallback->SetCompleted(NULL, &openCur))
1402 }
1403 }
1404 if (_dataForkChecksum.GetCrc32() != CRC_GET_DIGEST(crc))
1405 _dataForkError = true;
1406 }
1407 }
930 } 1408 }
931 1409
932 return S_OK; 1410 return S_OK;
933} 1411}
934 1412
1413
1414
935Z7_COM7F_IMF(CHandler::Open(IInStream *stream, 1415Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
936 const UInt64 * /* maxCheckStartPosition */, 1416 const UInt64 * /* maxCheckStartPosition */,
937 IArchiveOpenCallback * /* openArchiveCallback */)) 1417 IArchiveOpenCallback *openArchiveCallback))
938{ 1418{
939 COM_TRY_BEGIN 1419 COM_TRY_BEGIN
940 { 1420 Close();
941 Close(); 1421 RINOK(Open2(stream, openArchiveCallback))
942 if (Open2(stream) != S_OK) 1422 _inStream = stream;
943 return S_FALSE;
944 _inStream = stream;
945 }
946 return S_OK; 1423 return S_OK;
947 COM_TRY_END 1424 COM_TRY_END
948} 1425}
949 1426
950Z7_COM7F_IMF(CHandler::Close()) 1427Z7_COM7F_IMF(CHandler::Close())
951{ 1428{
952 _phySize = 0;
953 _inStream.Release();
954 _files.Clear();
955 _masterCrcError = false; 1429 _masterCrcError = false;
956 _headersError = false; 1430 _headersError = false;
1431 _dataForkError = false;
1432 _rsrcMode_wasUsed = false;
1433 _phySize = 0;
1434 _startPos = 0;
957 _name.Empty(); 1435 _name.Empty();
958 #ifdef DMG_SHOW_RAW 1436 _inStream.Release();
1437 _files.Clear();
1438#ifdef DMG_SHOW_RAW
959 _extras.Clear(); 1439 _extras.Clear();
960 #endif 1440#endif
961 return S_OK; 1441 return S_OK;
962} 1442}
963 1443
964Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) 1444Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
965{ 1445{
966 *numItems = _files.Size() 1446 *numItems = _files.Size()
967 #ifdef DMG_SHOW_RAW 1447#ifdef DMG_SHOW_RAW
968 + _extras.Size() 1448 + _extras.Size()
969 #endif 1449#endif
970 ; 1450 ;
971 return S_OK; 1451 return S_OK;
972} 1452}
973 1453
@@ -980,7 +1460,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
980 COM_TRY_BEGIN 1460 COM_TRY_BEGIN
981 NWindows::NCOM::CPropVariant prop; 1461 NWindows::NCOM::CPropVariant prop;
982 1462
983 #ifdef DMG_SHOW_RAW 1463#ifdef DMG_SHOW_RAW
984 if (index >= _files.Size()) 1464 if (index >= _files.Size())
985 { 1465 {
986 const CExtraFile &extra = _extras[index - _files.Size()]; 1466 const CExtraFile &extra = _extras[index - _files.Size()];
@@ -996,7 +1476,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
996 } 1476 }
997 } 1477 }
998 else 1478 else
999 #endif 1479#endif
1000 { 1480 {
1001 const CFile &item = _files[index]; 1481 const CFile &item = _files[index];
1002 switch (propID) 1482 switch (propID)
@@ -1009,21 +1489,44 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1009 prop = item.Checksum.GetCrc32(); 1489 prop = item.Checksum.GetCrc32();
1010 break; 1490 break;
1011 } 1491 }
1492 case kpidChecksum:
1493 {
1494 AString s;
1495 item.Checksum.Print(s);
1496 if (!s.IsEmpty())
1497 prop = s;
1498 break;
1499 }
1012 1500
1013 /* 1501 /*
1014 case kpidOffset: 1502 case kpidOffset:
1015 { 1503 {
1016 prop = item.StartPos; 1504 prop = item.StartPackPos;
1017 break; 1505 break;
1018 } 1506 }
1019 */ 1507 */
1020 1508
1509 case kpidNumBlocks:
1510 prop = (UInt32)item.Blocks.Size();
1511 break;
1512 case kpidClusterSize:
1513 prop = item.BlockSize_MAX;
1514 break;
1515
1021 case kpidMethod: 1516 case kpidMethod:
1022 { 1517 {
1518 AString s;
1519 if (!item.IsCorrect)
1520 s.Add_OptSpaced("CORRUPTED");
1023 CMethods m; 1521 CMethods m;
1024 m.Update(item); 1522 m.Update(item);
1025 AString s; 1523 m.AddToString(s);
1026 m.GetString(s); 1524 {
1525 AString s2;
1526 item.Checksum.PrintType(s2);
1527 if (!s2.IsEmpty())
1528 s.Add_OptSpaced(s2);
1529 }
1027 if (!s.IsEmpty()) 1530 if (!s.IsEmpty())
1028 prop = s; 1531 prop = s;
1029 break; 1532 break;
@@ -1031,6 +1534,9 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1031 1534
1032 case kpidPath: 1535 case kpidPath:
1033 { 1536 {
1537#ifdef Z7_DMG_SINGLE_FILE_MODE
1538 prop = "a.img";
1539#else
1034 UString name; 1540 UString name;
1035 name.Add_UInt32(index); 1541 name.Add_UInt32(index);
1036 unsigned num = 10; 1542 unsigned num = 10;
@@ -1059,18 +1565,9 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1059 subName.Trim(); 1565 subName.Trim();
1060 if (!subName.IsEmpty()) 1566 if (!subName.IsEmpty())
1061 { 1567 {
1062 for (unsigned n = 0; n < kNumAppleNames; n++) 1568 const char *ext = Find_Apple_FS_Ext(subName);
1063 { 1569 if (ext)
1064 const CAppleName &appleName = k_Names[n]; 1570 subName = ext;
1065 if (appleName.Ext)
1066 {
1067 if (subName == appleName.AppleName)
1068 {
1069 subName = appleName.Ext;
1070 break;
1071 }
1072 }
1073 }
1074 UString name2; 1571 UString name2;
1075 ConvertUTF8ToUnicode(subName, name2); 1572 ConvertUTF8ToUnicode(subName, name2);
1076 name.Add_Dot(); 1573 name.Add_Dot();
@@ -1085,6 +1582,8 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1085 name += name2; 1582 name += name2;
1086 } 1583 }
1087 prop = name; 1584 prop = name;
1585#endif
1586
1088 break; 1587 break;
1089 } 1588 }
1090 1589
@@ -1095,6 +1594,24 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1095 prop = name; 1594 prop = name;
1096 break; 1595 break;
1097 } 1596 }
1597 case kpidId:
1598 {
1599 prop.Set_Int32((Int32)item.Descriptor);
1600 /*
1601 if (!item.Id.IsEmpty())
1602 {
1603 UString s;
1604 ConvertUTF8ToUnicode(item.Id, s);
1605 prop = s;
1606 }
1607 */
1608 break;
1609 }
1610#ifdef Z7_DMG_SINGLE_FILE_MODE
1611 case kpidPosition:
1612 prop = item.StartUnpackSector << 9;
1613 break;
1614#endif
1098 } 1615 }
1099 } 1616 }
1100 prop.Detach(value); 1617 prop.Detach(value);
@@ -1103,21 +1620,11 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1103} 1620}
1104 1621
1105 1622
1106Z7_CLASS_IMP_NOQIB_1( 1623class CAdcDecoder
1107 CAdcDecoder 1624{
1108 , ICompressCoder
1109)
1110 CLzOutWindow m_OutWindowStream; 1625 CLzOutWindow m_OutWindowStream;
1111 CInBuffer m_InStream; 1626 CInBuffer m_InStream;
1112 1627
1113 /*
1114 void ReleaseStreams()
1115 {
1116 m_OutWindowStream.ReleaseStream();
1117 m_InStream.ReleaseStream();
1118 }
1119 */
1120
1121 class CCoderReleaser Z7_final 1628 class CCoderReleaser Z7_final
1122 { 1629 {
1123 CAdcDecoder *m_Coder; 1630 CAdcDecoder *m_Coder;
@@ -1128,22 +1635,28 @@ Z7_CLASS_IMP_NOQIB_1(
1128 { 1635 {
1129 if (NeedFlush) 1636 if (NeedFlush)
1130 m_Coder->m_OutWindowStream.Flush(); 1637 m_Coder->m_OutWindowStream.Flush();
1131 // m_Coder->ReleaseStreams();
1132 } 1638 }
1133 }; 1639 };
1134 friend class CCoderReleaser; 1640 friend class CCoderReleaser;
1135 1641
1136public: 1642public:
1137 HRESULT CodeReal(ISequentialInStream *inStream, 1643 HRESULT Code(ISequentialInStream * const inStream,
1138 ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, 1644 ISequentialOutStream *outStream,
1139 ICompressProgressInfo *progress); 1645 const UInt64 * const inSize,
1646 const UInt64 * const outSize,
1647 ICompressProgressInfo * const progress);
1140}; 1648};
1141 1649
1142HRESULT CAdcDecoder::CodeReal(ISequentialInStream *inStream, 1650
1143 ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, 1651HRESULT CAdcDecoder::Code(ISequentialInStream * const inStream,
1144 ICompressProgressInfo *progress) 1652 ISequentialOutStream *outStream,
1653 const UInt64 * const inSize,
1654 const UInt64 * const outSizePtr,
1655 ICompressProgressInfo * const progress)
1145{ 1656{
1146 if (!m_OutWindowStream.Create(1 << 18)) 1657 try {
1658
1659 if (!m_OutWindowStream.Create(1 << 18)) // at least (1 << 16) is required here
1147 return E_OUTOFMEMORY; 1660 return E_OUTOFMEMORY;
1148 if (!m_InStream.Create(1 << 18)) 1661 if (!m_InStream.Create(1 << 18))
1149 return E_OUTOFMEMORY; 1662 return E_OUTOFMEMORY;
@@ -1155,73 +1668,72 @@ HRESULT CAdcDecoder::CodeReal(ISequentialInStream *inStream,
1155 1668
1156 CCoderReleaser coderReleaser(this); 1669 CCoderReleaser coderReleaser(this);
1157 1670
1158 const UInt32 kStep = (1 << 20); 1671 const UInt32 kStep = 1 << 22;
1159 UInt64 nextLimit = kStep; 1672 UInt64 nextLimit = kStep;
1160 1673 const UInt64 outSize = *outSizePtr;
1161 UInt64 pos = 0; 1674 UInt64 pos = 0;
1162 while (pos < *outSize) 1675 /* match sequences and literal sequences do not cross 64KB range
1676 in some dmg archive examples. But is it so for any Adc stream? */
1677
1678 while (pos < outSize)
1163 { 1679 {
1164 if (pos > nextLimit && progress) 1680 if (pos >= nextLimit && progress)
1165 { 1681 {
1166 UInt64 packSize = m_InStream.GetProcessedSize();
1167 RINOK(progress->SetRatioInfo(&packSize, &pos))
1168 nextLimit += kStep; 1682 nextLimit += kStep;
1683 const UInt64 packSize = m_InStream.GetProcessedSize();
1684 RINOK(progress->SetRatioInfo(&packSize, &pos))
1169 } 1685 }
1170 Byte b; 1686 Byte b;
1171 if (!m_InStream.ReadByte(b)) 1687 if (!m_InStream.ReadByte(b))
1172 return S_FALSE; 1688 return S_FALSE;
1173 UInt64 rem = *outSize - pos; 1689 const UInt64 rem = outSize - pos;
1174 if (b & 0x80) 1690 if (b & 0x80)
1175 { 1691 {
1176 unsigned num = (b & 0x7F) + 1; 1692 unsigned num = (unsigned)b - 0x80 + 1;
1177 if (num > rem) 1693 if (num > rem)
1178 return S_FALSE; 1694 return S_FALSE;
1179 for (unsigned i = 0; i < num; i++) 1695 pos += num;
1696 do
1180 { 1697 {
1181 if (!m_InStream.ReadByte(b)) 1698 if (!m_InStream.ReadByte(b))
1182 return S_FALSE; 1699 return S_FALSE;
1183 m_OutWindowStream.PutByte(b); 1700 m_OutWindowStream.PutByte(b);
1184 } 1701 }
1185 pos += num; 1702 while (--num);
1186 continue; 1703 continue;
1187 } 1704 }
1188 Byte b1; 1705 Byte b1;
1189 if (!m_InStream.ReadByte(b1)) 1706 if (!m_InStream.ReadByte(b1))
1190 return S_FALSE; 1707 return S_FALSE;
1191 1708
1192 UInt32 len, distance; 1709 UInt32 len, dist;
1193 1710
1194 if (b & 0x40) 1711 if (b & 0x40)
1195 { 1712 {
1196 len = ((UInt32)b & 0x3F) + 4; 1713 len = (UInt32)b - 0x40 + 4;
1197 Byte b2; 1714 Byte b2;
1198 if (!m_InStream.ReadByte(b2)) 1715 if (!m_InStream.ReadByte(b2))
1199 return S_FALSE; 1716 return S_FALSE;
1200 distance = ((UInt32)b1 << 8) + b2; 1717 dist = ((UInt32)b1 << 8) + b2;
1201 } 1718 }
1202 else 1719 else
1203 { 1720 {
1204 b &= 0x3F;
1205 len = ((UInt32)b >> 2) + 3; 1721 len = ((UInt32)b >> 2) + 3;
1206 distance = (((UInt32)b & 3) << 8) + b1; 1722 dist = (((UInt32)b & 3) << 8) + b1;
1207 } 1723 }
1208 1724
1209 if (distance >= pos || len > rem) 1725 if (/* dist >= pos || */ len > rem)
1726 return S_FALSE;
1727 if (!m_OutWindowStream.CopyBlock(dist, len))
1210 return S_FALSE; 1728 return S_FALSE;
1211 m_OutWindowStream.CopyBlock(distance, len);
1212 pos += len; 1729 pos += len;
1213 } 1730 }
1214 if (*inSize != m_InStream.GetProcessedSize()) 1731 if (*inSize != m_InStream.GetProcessedSize())
1215 return S_FALSE; 1732 return S_FALSE;
1216 coderReleaser.NeedFlush = false; 1733 coderReleaser.NeedFlush = false;
1217 return m_OutWindowStream.Flush(); 1734 return m_OutWindowStream.Flush();
1218}
1219 1735
1220Z7_COM7F_IMF(CAdcDecoder::Code(ISequentialInStream *inStream, 1736 }
1221 ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
1222 ICompressProgressInfo *progress))
1223{
1224 try { return CodeReal(inStream, outStream, inSize, outSize, progress);}
1225 catch(const CInBufferException &e) { return e.ErrorCode; } 1737 catch(const CInBufferException &e) { return e.ErrorCode; }
1226 catch(const CLzOutWindowException &e) { return e.ErrorCode; } 1738 catch(const CLzOutWindowException &e) { return e.ErrorCode; }
1227 catch(...) { return S_FALSE; } 1739 catch(...) { return S_FALSE; }
@@ -1229,8 +1741,53 @@ Z7_COM7F_IMF(CAdcDecoder::Code(ISequentialInStream *inStream,
1229 1741
1230 1742
1231 1743
1744struct CDecoders
1745{
1746 CMyComPtr2<ICompressCoder, NCompress::NZlib::CDecoder> zlib;
1747 CMyComPtr2<ICompressCoder, NCompress::NBZip2::CDecoder> bzip2;
1748 CMyComPtr2<ICompressCoder, NCompress::NLzfse::CDecoder> lzfse;
1749 CMyUniquePtr<NCompress::NXz::CDecoder> xz;
1750 CMyUniquePtr<CAdcDecoder> adc;
1751
1752 HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
1753 const CBlock &block, const UInt64 *unpSize, ICompressProgressInfo *progress);
1754};
1232 1755
1233 1756HRESULT CDecoders::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
1757 const CBlock &block, const UInt64 *unpSize, ICompressProgressInfo *progress)
1758{
1759 HRESULT hres;
1760 UInt64 processed;
1761 switch (block.Type)
1762 {
1763 case METHOD_ADC:
1764 adc.Create_if_Empty();
1765 return adc->Code(inStream, outStream, &block.PackSize, unpSize, progress);
1766 case METHOD_LZFSE:
1767 lzfse.Create_if_Empty();
1768 return lzfse.Interface()->Code(inStream, outStream, &block.PackSize, unpSize, progress);
1769 case METHOD_ZLIB:
1770 zlib.Create_if_Empty();
1771 hres = zlib.Interface()->Code(inStream, outStream, NULL, unpSize, progress);
1772 processed = zlib->GetInputProcessedSize();
1773 break;
1774 case METHOD_BZIP2:
1775 bzip2.Create_if_Empty();
1776 hres = bzip2.Interface()->Code(inStream, outStream, NULL, unpSize, progress);
1777 processed = bzip2->GetInputProcessedSize();
1778 break;
1779 case METHOD_XZ:
1780 xz.Create_if_Empty();
1781 hres = xz->Decode(inStream, outStream, unpSize, true, progress);
1782 processed = xz->Stat.InSize;
1783 break;
1784 default:
1785 return E_NOTIMPL;
1786 }
1787 if (hres == S_OK && processed != block.PackSize)
1788 hres = S_FALSE;
1789 return hres;
1790}
1234 1791
1235 1792
1236Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, 1793Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
@@ -1239,7 +1796,11 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1239 COM_TRY_BEGIN 1796 COM_TRY_BEGIN
1240 const bool allFilesMode = (numItems == (UInt32)(Int32)-1); 1797 const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
1241 if (allFilesMode) 1798 if (allFilesMode)
1242 numItems = _files.Size(); 1799 numItems = _files.Size()
1800#ifdef DMG_SHOW_RAW
1801 + _extras.Size()
1802#endif
1803 ;
1243 if (numItems == 0) 1804 if (numItems == 0)
1244 return S_OK; 1805 return S_OK;
1245 UInt64 totalSize = 0; 1806 UInt64 totalSize = 0;
@@ -1247,55 +1808,46 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1247 1808
1248 for (i = 0; i < numItems; i++) 1809 for (i = 0; i < numItems; i++)
1249 { 1810 {
1250 UInt32 index = (allFilesMode ? i : indices[i]); 1811 const UInt32 index = allFilesMode ? i : indices[i];
1251 #ifdef DMG_SHOW_RAW 1812#ifdef DMG_SHOW_RAW
1252 if (index >= _files.Size()) 1813 if (index >= _files.Size())
1253 totalSize += _extras[index - _files.Size()].Data.Size(); 1814 totalSize += _extras[index - _files.Size()].Data.Size();
1254 else 1815 else
1255 #endif 1816#endif
1256 totalSize += _files[index].Size; 1817 totalSize += _files[index].Size;
1257 } 1818 }
1258 extractCallback->SetTotal(totalSize); 1819 RINOK(extractCallback->SetTotal(totalSize))
1259
1260 UInt64 currentPackTotal = 0;
1261 UInt64 currentUnpTotal = 0;
1262 UInt64 currentPackSize = 0;
1263 UInt64 currentUnpSize = 0;
1264 1820
1265 const UInt32 kZeroBufSize = (1 << 14); 1821 const size_t kZeroBufSize = 1 << 14;
1266 CByteBuffer zeroBuf(kZeroBufSize); 1822 CAlignedBuffer1 zeroBuf(kZeroBufSize);
1267 memset(zeroBuf, 0, kZeroBufSize); 1823 memset(zeroBuf, 0, kZeroBufSize);
1268 1824
1269 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 1825 CDecoders decoders;
1270 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 1826 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
1271 1827 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1272 NCompress::NBZip2::CDecoder *bzip2CoderSpec = new NCompress::NBZip2::CDecoder();
1273 CMyComPtr<ICompressCoder> bzip2Coder = bzip2CoderSpec;
1274
1275 NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder();
1276 CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec;
1277
1278 CAdcDecoder *adcCoderSpec = new CAdcDecoder();
1279 CMyComPtr<ICompressCoder> adcCoder = adcCoderSpec;
1280
1281 NCompress::NLzfse::CDecoder *lzfseCoderSpec = new NCompress::NLzfse::CDecoder();
1282 CMyComPtr<ICompressCoder> lzfseCoder = lzfseCoderSpec;
1283
1284 CLocalProgress *lps = new CLocalProgress;
1285 CMyComPtr<ICompressProgressInfo> progress = lps;
1286 lps->Init(extractCallback, false); 1828 lps->Init(extractCallback, false);
1829 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
1830 inStream->SetStream(_inStream);
1287 1831
1288 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 1832 UInt64 total_PackSize = 0;
1289 CMyComPtr<ISequentialInStream> inStream(streamSpec); 1833 UInt64 total_UnpackSize = 0;
1290 streamSpec->SetStream(_inStream); 1834 UInt64 cur_PackSize = 0;
1835 UInt64 cur_UnpackSize = 0;
1291 1836
1292 for (i = 0; i < numItems; i++, currentPackTotal += currentPackSize, currentUnpTotal += currentUnpSize) 1837 for (i = 0;; i++,
1838 total_PackSize += cur_PackSize,
1839 total_UnpackSize += cur_UnpackSize)
1293 { 1840 {
1294 lps->InSize = currentPackTotal; 1841 lps->InSize = total_PackSize;
1295 lps->OutSize = currentUnpTotal; 1842 lps->OutSize = total_UnpackSize;
1296 currentPackSize = 0; 1843 cur_PackSize = 0;
1297 currentUnpSize = 0; 1844 cur_UnpackSize = 0;
1298 RINOK(lps->SetCur()) 1845 RINOK(lps->SetCur())
1846 if (i >= numItems)
1847 return S_OK;
1848
1849 Int32 opRes = NExtract::NOperationResult::kOK;
1850 {
1299 CMyComPtr<ISequentialOutStream> realOutStream; 1851 CMyComPtr<ISequentialOutStream> realOutStream;
1300 const Int32 askMode = testMode ? 1852 const Int32 askMode = testMode ?
1301 NExtract::NAskMode::kTest : 1853 NExtract::NAskMode::kTest :
@@ -1307,227 +1859,209 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1307 continue; 1859 continue;
1308 RINOK(extractCallback->PrepareOperation(askMode)) 1860 RINOK(extractCallback->PrepareOperation(askMode))
1309 1861
1310 1862#ifdef DMG_SHOW_RAW
1311 COutStreamWithCRC *outCrcStreamSpec = new COutStreamWithCRC;
1312 CMyComPtr<ISequentialOutStream> outCrcStream = outCrcStreamSpec;
1313 outCrcStreamSpec->SetStream(realOutStream);
1314 bool needCrc = false;
1315 outCrcStreamSpec->Init(needCrc);
1316
1317 CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
1318 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
1319 outStreamSpec->SetStream(outCrcStream);
1320
1321 realOutStream.Release();
1322
1323 Int32 opRes = NExtract::NOperationResult::kOK;
1324 #ifdef DMG_SHOW_RAW
1325 if (index >= _files.Size()) 1863 if (index >= _files.Size())
1326 { 1864 {
1327 const CByteBuffer &buf = _extras[index - _files.Size()].Data; 1865 const CByteBuffer &buf = _extras[index - _files.Size()].Data;
1328 outStreamSpec->Init(buf.Size()); 1866 if (realOutStream)
1329 RINOK(WriteStream(outStream, buf, buf.Size())); 1867 RINOK(WriteStream(realOutStream, buf, buf.Size()))
1330 currentPackSize = currentUnpSize = buf.Size(); 1868 cur_PackSize = cur_UnpackSize = buf.Size();
1331 } 1869 }
1332 else 1870 else
1333 #endif 1871#endif
1334 { 1872 {
1335 const CFile &item = _files[index]; 1873 const CFile &item = _files[index];
1336 currentPackSize = item.PackSize; 1874 cur_PackSize = item.PackSize;
1337 currentUnpSize = item.Size; 1875 cur_UnpackSize = item.Size;
1338 1876
1339 needCrc = item.Checksum.IsCrc32(); 1877 if (!item.IsCorrect)
1340 1878 opRes = NExtract::NOperationResult::kHeadersError;
1341 UInt64 unpPos = 0; 1879 else
1342 UInt64 packPos = 0;
1343 { 1880 {
1344 FOR_VECTOR (j, item.Blocks) 1881 CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outCrcStream;
1882 outCrcStream->SetStream(realOutStream);
1883 // realOutStream.Release();
1884 const bool needCrc = item.Checksum.IsCrc32();
1885 outCrcStream->Init(needCrc);
1886
1887 CMyComPtr2_Create<ISequentialOutStream, CLimitedSequentialOutStream> outStream;
1888 outStream->SetStream(outCrcStream);
1889
1890 UInt64 unpPos = 0;
1891 UInt64 packPos = 0;
1892
1893 FOR_VECTOR (blockIndex, item.Blocks)
1345 { 1894 {
1346 lps->InSize = currentPackTotal + packPos; 1895 lps->InSize = total_PackSize + packPos;
1347 lps->OutSize = currentUnpTotal + unpPos; 1896 lps->OutSize = total_UnpackSize + unpPos;
1348 RINOK(lps->SetCur()) 1897 RINOK(lps->SetCur())
1349 1898
1350 const CBlock &block = item.Blocks[j]; 1899 const CBlock &block = item.Blocks[blockIndex];
1351 if (!block.ThereAreDataInBlock()) 1900 // if (!block.ThereAreDataInBlock()) continue;
1352 continue;
1353 1901
1354 packPos += block.PackSize; 1902 packPos += block.PackSize;
1355 if (block.UnpPos != unpPos) 1903 if (block.UnpPos != unpPos)
1356 { 1904 {
1357 opRes = NExtract::NOperationResult::kDataError; 1905 opRes = NExtract::NOperationResult::kHeadersError;
1358 break; 1906 break;
1359 } 1907 }
1360 1908
1361 RINOK(InStream_SeekSet(_inStream, _startPos + _dataStartOffset + item.StartPos + block.PackPos)) 1909 RINOK(InStream_SeekSet(_inStream, _startPos + _dataForkPair.Offset + item.StartPackPos + block.PackPos))
1362 streamSpec->Init(block.PackSize); 1910 inStream->Init(block.PackSize);
1363 bool realMethod = true;
1364 outStreamSpec->Init(block.UnpSize);
1365 HRESULT res = S_OK;
1366
1367 outCrcStreamSpec->EnableCalc(needCrc);
1368 1911
1369 switch (block.Type) 1912 const UInt64 unpSize = item.GetUnpackSize_of_Block(blockIndex);
1370 {
1371 case METHOD_ZERO_0:
1372 case METHOD_ZERO_2:
1373 realMethod = false;
1374 if (block.PackSize != 0)
1375 opRes = NExtract::NOperationResult::kUnsupportedMethod;
1376 outCrcStreamSpec->EnableCalc(block.Type == METHOD_ZERO_0);
1377 break;
1378 1913
1379 case METHOD_COPY: 1914 outStream->Init(unpSize);
1380 if (block.UnpSize != block.PackSize) 1915 HRESULT res = S_OK;
1381 {
1382 opRes = NExtract::NOperationResult::kUnsupportedMethod;
1383 break;
1384 }
1385 res = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
1386 break;
1387
1388 case METHOD_ADC:
1389 {
1390 res = adcCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, progress);
1391 break;
1392 }
1393
1394 case METHOD_ZLIB:
1395 {
1396 res = zlibCoder->Code(inStream, outStream, NULL, NULL, progress);
1397 if (res == S_OK)
1398 if (zlibCoderSpec->GetInputProcessedSize() != block.PackSize)
1399 opRes = NExtract::NOperationResult::kDataError;
1400 break;
1401 }
1402 1916
1403 case METHOD_BZIP2: 1917 outCrcStream->EnableCalc(needCrc && block.NeedCrc());
1404 {
1405 res = bzip2Coder->Code(inStream, outStream, NULL, NULL, progress);
1406 if (res == S_OK)
1407 if (bzip2CoderSpec->GetInputProcessedSize() != block.PackSize)
1408 opRes = NExtract::NOperationResult::kDataError;
1409 break;
1410 }
1411 1918
1412 case METHOD_LZFSE: 1919 if (block.IsZeroMethod())
1413 { 1920 {
1414 res = lzfseCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, progress); 1921 if (block.PackSize != 0)
1415 break;
1416 }
1417
1418 default:
1419 opRes = NExtract::NOperationResult::kUnsupportedMethod; 1922 opRes = NExtract::NOperationResult::kUnsupportedMethod;
1420 break;
1421 } 1923 }
1924 else if (block.Type == METHOD_COPY)
1925 {
1926 if (unpSize != block.PackSize)
1927 opRes = NExtract::NOperationResult::kUnsupportedMethod;
1928 else
1929 res = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);
1930 }
1931 else
1932 res = decoders.Code(inStream, outStream, block, &unpSize, lps);
1422 1933
1423 if (res != S_OK) 1934 if (res != S_OK)
1424 { 1935 {
1425 if (res != S_FALSE) 1936 if (res != S_FALSE)
1426 return res; 1937 {
1938 if (res != E_NOTIMPL)
1939 return res;
1940 opRes = NExtract::NOperationResult::kUnsupportedMethod;
1941 }
1427 if (opRes == NExtract::NOperationResult::kOK) 1942 if (opRes == NExtract::NOperationResult::kOK)
1428 opRes = NExtract::NOperationResult::kDataError; 1943 opRes = NExtract::NOperationResult::kDataError;
1429 } 1944 }
1430 1945
1431 unpPos += block.UnpSize; 1946 unpPos += unpSize;
1432 1947
1433 if (!outStreamSpec->IsFinishedOK()) 1948 if (!outStream->IsFinishedOK())
1434 { 1949 {
1435 if (realMethod && opRes == NExtract::NOperationResult::kOK) 1950 if (!block.IsZeroMethod() && opRes == NExtract::NOperationResult::kOK)
1436 opRes = NExtract::NOperationResult::kDataError; 1951 opRes = NExtract::NOperationResult::kDataError;
1437 1952
1438 while (outStreamSpec->GetRem() != 0) 1953 for (unsigned k = 0;;)
1439 { 1954 {
1440 UInt64 rem = outStreamSpec->GetRem(); 1955 const UInt64 rem = outStream->GetRem();
1441 UInt32 size = (UInt32)MyMin(rem, (UInt64)kZeroBufSize); 1956 if (rem == 0)
1957 break;
1958 size_t size = kZeroBufSize;
1959 if (size > rem)
1960 size = (size_t)rem;
1442 RINOK(WriteStream(outStream, zeroBuf, size)) 1961 RINOK(WriteStream(outStream, zeroBuf, size))
1962 k++;
1963 if ((k & 0xfff) == 0)
1964 {
1965 lps->OutSize = total_UnpackSize + unpPos - outStream->GetRem();
1966 RINOK(lps->SetCur())
1967 }
1443 } 1968 }
1444 } 1969 }
1445 } 1970 }
1446 } 1971 if (needCrc && opRes == NExtract::NOperationResult::kOK)
1447 1972 {
1448 if (needCrc && opRes == NExtract::NOperationResult::kOK) 1973 if (outCrcStream->GetCRC() != item.Checksum.GetCrc32())
1449 { 1974 opRes = NExtract::NOperationResult::kCRCError;
1450 if (outCrcStreamSpec->GetCRC() != item.Checksum.GetCrc32()) 1975 }
1451 opRes = NExtract::NOperationResult::kCRCError;
1452 } 1976 }
1453 } 1977 }
1454 outStream.Release(); 1978 }
1455 RINOK(extractCallback->SetOperationResult(opRes)) 1979 RINOK(extractCallback->SetOperationResult(opRes))
1456 } 1980 }
1457 1981
1458 return S_OK;
1459 COM_TRY_END 1982 COM_TRY_END
1460} 1983}
1461 1984
1985
1986
1987
1462struct CChunk 1988struct CChunk
1463{ 1989{
1464 int BlockIndex; 1990 int BlockIndex;
1465 UInt64 AccessMark; 1991 UInt64 AccessMark;
1466 CByteBuffer Buf; 1992 Byte *Buf;
1993 size_t BufSize;
1994
1995 void Free()
1996 {
1997 z7_AlignedFree(Buf);
1998 Buf = NULL;
1999 BufSize = 0;
2000 }
2001 void Alloc(size_t size)
2002 {
2003 Buf = (Byte *)z7_AlignedAlloc(size);
2004 }
1467}; 2005};
1468 2006
1469 2007
1470Z7_CLASS_IMP_COM_1( 2008Z7_CLASS_IMP_IInStream(
1471 CInStream 2009 CInStream
1472 , IInStream
1473) 2010)
1474 Z7_IFACE_COM7_IMP(ISequentialInStream) 2011 bool _errorMode;
1475
1476 UInt64 _virtPos; 2012 UInt64 _virtPos;
1477 int _latestChunk; 2013 int _latestChunk;
1478 int _latestBlock; 2014 int _latestBlock;
1479 UInt64 _accessMark; 2015 UInt64 _accessMark;
1480 CObjectVector<CChunk> _chunks; 2016 UInt64 _chunks_TotalSize;
1481 2017 CRecordVector<CChunk> _chunks;
1482 NCompress::NBZip2::CDecoder *bzip2CoderSpec;
1483 CMyComPtr<ICompressCoder> bzip2Coder;
1484
1485 NCompress::NZlib::CDecoder *zlibCoderSpec;
1486 CMyComPtr<ICompressCoder> zlibCoder;
1487
1488 CAdcDecoder *adcCoderSpec;
1489 CMyComPtr<ICompressCoder> adcCoder;
1490
1491 NCompress::NLzfse::CDecoder *lzfseCoderSpec;
1492 CMyComPtr<ICompressCoder> lzfseCoder;
1493
1494 CBufPtrSeqOutStream *outStreamSpec;
1495 CMyComPtr<ISequentialOutStream> outStream;
1496
1497 CLimitedSequentialInStream *limitedStreamSpec;
1498 CMyComPtr<ISequentialInStream> inStream;
1499 2018
1500public: 2019public:
1501 CMyComPtr<IInStream> Stream; 2020 CMyComPtr<IInStream> Stream;
1502 UInt64 Size;
1503 const CFile *File; 2021 const CFile *File;
2022 UInt64 Size;
2023private:
1504 UInt64 _startPos; 2024 UInt64 _startPos;
1505 2025
1506 HRESULT InitAndSeek(UInt64 startPos) 2026 ~CInStream();
2027 CMyComPtr2<ISequentialOutStream, CBufPtrSeqOutStream> outStream;
2028 CMyComPtr2<ISequentialInStream, CLimitedSequentialInStream> inStream;
2029 CDecoders decoders;
2030public:
2031
2032 // HRESULT
2033 void Init(UInt64 startPos)
1507 { 2034 {
2035 _errorMode = false;
1508 _startPos = startPos; 2036 _startPos = startPos;
1509 _virtPos = 0; 2037 _virtPos = 0;
1510 _latestChunk = -1; 2038 _latestChunk = -1;
1511 _latestBlock = -1; 2039 _latestBlock = -1;
1512 _accessMark = 0; 2040 _accessMark = 0;
2041 _chunks_TotalSize = 0;
1513 2042
1514 limitedStreamSpec = new CLimitedSequentialInStream; 2043 inStream.Create_if_Empty();
1515 inStream = limitedStreamSpec; 2044 inStream->SetStream(Stream);
1516 limitedStreamSpec->SetStream(Stream);
1517 2045
1518 outStreamSpec = new CBufPtrSeqOutStream; 2046 outStream.Create_if_Empty();
1519 outStream = outStreamSpec; 2047 // return S_OK;
1520 return S_OK;
1521 } 2048 }
1522}; 2049};
1523 2050
1524 2051
2052CInStream::~CInStream()
2053{
2054 unsigned i = _chunks.Size();
2055 while (i)
2056 _chunks[--i].Free();
2057}
2058
1525static unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos) 2059static unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos)
1526{ 2060{
1527 unsigned left = 0, right = blocks.Size(); 2061 unsigned left = 0, right = blocks.Size();
1528 for (;;) 2062 for (;;)
1529 { 2063 {
1530 unsigned mid = (left + right) / 2; 2064 const unsigned mid = (left + right) / 2;
1531 if (mid == left) 2065 if (mid == left)
1532 return left; 2066 return left;
1533 if (pos < blocks[mid].UnpPos) 2067 if (pos < blocks[mid].UnpPos)
@@ -1539,7 +2073,11 @@ static unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos)
1539 2073
1540Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) 2074Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
1541{ 2075{
1542 COM_TRY_BEGIN 2076 // COM_TRY_BEGIN
2077 try {
2078
2079 if (_errorMode)
2080 return E_OUTOFMEMORY;
1543 2081
1544 if (processedSize) 2082 if (processedSize)
1545 *processedSize = 0; 2083 *processedSize = 0;
@@ -1548,7 +2086,7 @@ Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
1548 if (_virtPos >= Size) 2086 if (_virtPos >= Size)
1549 return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL; 2087 return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL;
1550 { 2088 {
1551 UInt64 rem = Size - _virtPos; 2089 const UInt64 rem = Size - _virtPos;
1552 if (size > rem) 2090 if (size > rem)
1553 size = (UInt32)rem; 2091 size = (UInt32)rem;
1554 } 2092 }
@@ -1556,115 +2094,120 @@ Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
1556 if (_latestBlock >= 0) 2094 if (_latestBlock >= 0)
1557 { 2095 {
1558 const CBlock &block = File->Blocks[(unsigned)_latestBlock]; 2096 const CBlock &block = File->Blocks[(unsigned)_latestBlock];
1559 if (_virtPos < block.UnpPos || (_virtPos - block.UnpPos) >= block.UnpSize) 2097 if (_virtPos < block.UnpPos ||
2098 _virtPos - block.UnpPos >= File->GetUnpackSize_of_Block((unsigned)_latestBlock))
1560 _latestBlock = -1; 2099 _latestBlock = -1;
1561 } 2100 }
1562 2101
1563 if (_latestBlock < 0) 2102 if (_latestBlock < 0)
1564 { 2103 {
1565 _latestChunk = -1; 2104 _latestChunk = -1;
1566 unsigned blockIndex = FindBlock(File->Blocks, _virtPos); 2105 const unsigned blockIndex = FindBlock(File->Blocks, _virtPos);
1567 const CBlock &block = File->Blocks[blockIndex]; 2106 const CBlock &block = File->Blocks[blockIndex];
2107 const UInt64 unpSize = File->GetUnpackSize_of_Block(blockIndex);
1568 2108
1569 if (!block.IsZeroMethod() && block.Type != METHOD_COPY) 2109 if (block.NeedAllocateBuffer()
2110 && unpSize <= k_Chunk_Size_MAX)
1570 { 2111 {
1571 unsigned i; 2112 unsigned i = 0;
1572 for (i = 0; i < _chunks.Size(); i++) 2113 {
1573 if (_chunks[i].BlockIndex == (int)blockIndex) 2114 unsigned numChunks = _chunks.Size();
1574 break; 2115 if (numChunks)
1575 2116 {
2117 const CChunk *chunk = _chunks.ConstData();
2118 do
2119 {
2120 if (chunk->BlockIndex == (int)blockIndex)
2121 break;
2122 chunk++;
2123 }
2124 while (--numChunks);
2125 i = _chunks.Size() - numChunks;
2126 }
2127 }
1576 if (i != _chunks.Size()) 2128 if (i != _chunks.Size())
1577 _latestChunk = (int)i; 2129 _latestChunk = (int)i;
1578 else 2130 else
1579 { 2131 {
1580 const unsigned kNumChunksMax = 128;
1581 unsigned chunkIndex; 2132 unsigned chunkIndex;
1582 2133 for (;;)
1583 if (_chunks.Size() != kNumChunksMax)
1584 chunkIndex = _chunks.Add(CChunk());
1585 else
1586 { 2134 {
2135 if (_chunks.IsEmpty() ||
2136 (_chunks.Size() < k_NumChunks_MAX
2137 && _chunks_TotalSize + unpSize <= k_Chunks_TotalSize_MAX))
2138 {
2139 CChunk chunk;
2140 chunk.Buf = NULL;
2141 chunk.BufSize = 0;
2142 chunk.BlockIndex = -1;
2143 chunk.AccessMark = 0;
2144 chunkIndex = _chunks.Add(chunk);
2145 break;
2146 }
1587 chunkIndex = 0; 2147 chunkIndex = 0;
1588 for (i = 0; i < _chunks.Size(); i++) 2148 if (_chunks.Size() == 1)
1589 if (_chunks[i].AccessMark < _chunks[chunkIndex].AccessMark) 2149 break;
1590 chunkIndex = i; 2150 {
2151 const CChunk *chunks = _chunks.ConstData();
2152 UInt64 accessMark_min = chunks[chunkIndex].AccessMark;
2153 const unsigned numChunks = _chunks.Size();
2154 for (i = 1; i < numChunks; i++)
2155 {
2156 if (chunks[i].AccessMark < accessMark_min)
2157 {
2158 chunkIndex = i;
2159 accessMark_min = chunks[i].AccessMark;
2160 }
2161 }
2162 }
2163 {
2164 CChunk &chunk = _chunks[chunkIndex];
2165 const UInt64 newTotalSize = _chunks_TotalSize - chunk.BufSize;
2166 if (newTotalSize + unpSize <= k_Chunks_TotalSize_MAX)
2167 break;
2168 _chunks_TotalSize = newTotalSize;
2169 chunk.Free();
2170 }
2171 // we have called chunk.Free() before, because
2172 // _chunks.Delete() doesn't call chunk.Free().
2173 _chunks.Delete(chunkIndex);
2174 PRF(printf("\n++num_chunks=%u, _chunks_TotalSize = %u\n", (unsigned)_chunks.Size(), (unsigned)_chunks_TotalSize);)
1591 } 2175 }
1592 2176
1593 CChunk &chunk = _chunks[chunkIndex]; 2177 CChunk &chunk = _chunks[chunkIndex];
1594 chunk.BlockIndex = -1; 2178 chunk.BlockIndex = -1;
1595 chunk.AccessMark = 0; 2179 chunk.AccessMark = 0;
1596 2180
1597 if (chunk.Buf.Size() < block.UnpSize) 2181 if (chunk.BufSize < unpSize)
1598 { 2182 {
1599 chunk.Buf.Free(); 2183 _chunks_TotalSize -= chunk.BufSize;
1600 if (block.UnpSize > ((UInt32)1 << 31)) 2184 chunk.Free();
1601 return E_FAIL; 2185 // if (unpSize > k_Chunk_Size_MAX) return E_FAIL;
1602 chunk.Buf.Alloc((size_t)block.UnpSize); 2186 chunk.Alloc((size_t)unpSize);
2187 if (!chunk.Buf)
2188 return E_OUTOFMEMORY;
2189 chunk.BufSize = (size_t)unpSize;
2190 _chunks_TotalSize += chunk.BufSize;
1603 } 2191 }
1604 2192
1605 outStreamSpec->Init(chunk.Buf, (size_t)block.UnpSize); 2193 RINOK(InStream_SeekSet(Stream, _startPos + File->StartPackPos + block.PackPos))
1606
1607 RINOK(InStream_SeekSet(Stream, _startPos + File->StartPos + block.PackPos))
1608 2194
1609 limitedStreamSpec->Init(block.PackSize); 2195 inStream->Init(block.PackSize);
1610 HRESULT res = S_OK; 2196#ifdef Z7_DMG_USE_CACHE_FOR_COPY_BLOCKS
1611 2197 if (block.Type == METHOD_COPY)
1612 switch (block.Type)
1613 { 2198 {
1614 case METHOD_COPY: 2199 if (block.PackSize != unpSize)
1615 if (block.PackSize != block.UnpSize) 2200 return E_FAIL;
1616 return E_FAIL; 2201 RINOK(ReadStream_FAIL(inStream, chunk.Buf, (size_t)unpSize))
1617 res = ReadStream_FAIL(inStream, chunk.Buf, (size_t)block.UnpSize); 2202 }
1618 break; 2203 else
1619 2204#endif
1620 case METHOD_ADC: 2205 {
1621 if (!adcCoder) 2206 outStream->Init(chunk.Buf, (size_t)unpSize);
1622 { 2207 RINOK(decoders.Code(inStream, outStream, block, &unpSize, NULL))
1623 adcCoderSpec = new CAdcDecoder(); 2208 if (outStream->GetPos() != unpSize)
1624 adcCoder = adcCoderSpec;
1625 }
1626 res = adcCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, NULL);
1627 break;
1628
1629 case METHOD_ZLIB:
1630 if (!zlibCoder)
1631 {
1632 zlibCoderSpec = new NCompress::NZlib::CDecoder();
1633 zlibCoder = zlibCoderSpec;
1634 }
1635 res = zlibCoder->Code(inStream, outStream, NULL, NULL, NULL);
1636 if (res == S_OK && zlibCoderSpec->GetInputProcessedSize() != block.PackSize)
1637 res = S_FALSE;
1638 break;
1639
1640 case METHOD_BZIP2:
1641 if (!bzip2Coder)
1642 {
1643 bzip2CoderSpec = new NCompress::NBZip2::CDecoder();
1644 bzip2Coder = bzip2CoderSpec;
1645 }
1646 res = bzip2Coder->Code(inStream, outStream, NULL, NULL, NULL);
1647 if (res == S_OK && bzip2CoderSpec->GetInputProcessedSize() != block.PackSize)
1648 res = S_FALSE;
1649 break;
1650
1651 case METHOD_LZFSE:
1652 if (!lzfseCoder)
1653 {
1654 lzfseCoderSpec = new NCompress::NLzfse::CDecoder();
1655 lzfseCoder = lzfseCoderSpec;
1656 }
1657 res = lzfseCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, NULL);
1658 break;
1659
1660 default:
1661 return E_FAIL; 2209 return E_FAIL;
1662 } 2210 }
1663
1664 if (res != S_OK)
1665 return res;
1666 if (block.Type != METHOD_COPY && outStreamSpec->GetPos() != block.UnpSize)
1667 return E_FAIL;
1668 chunk.BlockIndex = (int)blockIndex; 2211 chunk.BlockIndex = (int)blockIndex;
1669 _latestChunk = (int)chunkIndex; 2212 _latestChunk = (int)chunkIndex;
1670 } 2213 }
@@ -1677,29 +2220,40 @@ Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
1677 2220
1678 const CBlock &block = File->Blocks[(unsigned)_latestBlock]; 2221 const CBlock &block = File->Blocks[(unsigned)_latestBlock];
1679 const UInt64 offset = _virtPos - block.UnpPos; 2222 const UInt64 offset = _virtPos - block.UnpPos;
1680 const UInt64 rem = block.UnpSize - offset; 2223 {
1681 if (size > rem) 2224 const UInt64 rem = File->GetUnpackSize_of_Block((unsigned)_latestBlock) - offset;
1682 size = (UInt32)rem; 2225 if (size > rem)
1683 2226 size = (UInt32)rem;
2227 if (size == 0) // it's unexpected case. but we check it.
2228 return S_OK;
2229 }
1684 HRESULT res = S_OK; 2230 HRESULT res = S_OK;
1685 2231
1686 if (block.Type == METHOD_COPY) 2232 if (block.IsZeroMethod())
2233 memset(data, 0, size);
2234 else if (_latestChunk >= 0)
2235 memcpy(data, _chunks[_latestChunk].Buf + (size_t)offset, size);
2236 else
1687 { 2237 {
1688 RINOK(InStream_SeekSet(Stream, _startPos + File->StartPos + block.PackPos + offset)) 2238 if (block.Type != METHOD_COPY)
2239 return E_FAIL;
2240 RINOK(InStream_SeekSet(Stream, _startPos + File->StartPackPos + block.PackPos + offset))
1689 res = Stream->Read(data, size, &size); 2241 res = Stream->Read(data, size, &size);
1690 } 2242 }
1691 else if (block.IsZeroMethod())
1692 memset(data, 0, size);
1693 else if (size != 0)
1694 memcpy(data, _chunks[_latestChunk].Buf + (size_t)offset, size);
1695 2243
1696 _virtPos += size; 2244 _virtPos += size;
1697 if (processedSize) 2245 if (processedSize)
1698 *processedSize = size; 2246 *processedSize = size;
1699
1700 return res; 2247 return res;
1701 COM_TRY_END 2248 // COM_TRY_END
2249 }
2250 catch(...)
2251 {
2252 _errorMode = true;
2253 return E_OUTOFMEMORY;
2254 }
1702} 2255}
2256
1703 2257
1704Z7_COM7F_IMF(CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) 2258Z7_COM7F_IMF(CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
1705{ 2259{
@@ -1722,29 +2276,39 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
1722{ 2276{
1723 COM_TRY_BEGIN 2277 COM_TRY_BEGIN
1724 2278
1725 #ifdef DMG_SHOW_RAW 2279#ifdef DMG_SHOW_RAW
1726 if (index >= (UInt32)_files.Size()) 2280 if (index >= _files.Size())
1727 return S_FALSE; 2281 return S_FALSE;
1728 #endif 2282#endif
1729 2283
1730 CInStream *spec = new CInStream; 2284 CMyComPtr2<ISequentialInStream, CInStream> spec;
1731 CMyComPtr<ISequentialInStream> specStream = spec; 2285 spec.Create_if_Empty();
1732 spec->File = &_files[index]; 2286 spec->File = &_files[index];
1733 const CFile &file = *spec->File; 2287 const CFile &file = *spec->File;
2288
2289 if (!file.IsCorrect)
2290 return S_FALSE;
1734 2291
1735 FOR_VECTOR (i, file.Blocks) 2292 FOR_VECTOR (i, file.Blocks)
1736 { 2293 {
1737 const CBlock &block = file.Blocks[i]; 2294 const CBlock &block = file.Blocks[i];
2295 if (!block.NeedAllocateBuffer())
2296 continue;
2297
1738 switch (block.Type) 2298 switch (block.Type)
1739 { 2299 {
1740 case METHOD_ZERO_0: 2300#ifdef Z7_DMG_USE_CACHE_FOR_COPY_BLOCKS
1741 case METHOD_ZERO_2:
1742 case METHOD_COPY: 2301 case METHOD_COPY:
2302 break;
2303#endif
1743 case METHOD_ADC: 2304 case METHOD_ADC:
1744 case METHOD_ZLIB: 2305 case METHOD_ZLIB:
1745 case METHOD_BZIP2: 2306 case METHOD_BZIP2:
1746 case METHOD_LZFSE: 2307 case METHOD_LZFSE:
1747 case METHOD_END: 2308 case METHOD_XZ:
2309 // case METHOD_END:
2310 if (file.GetUnpackSize_of_Block(i) > k_Chunk_Size_MAX)
2311 return S_FALSE;
1748 break; 2312 break;
1749 default: 2313 default:
1750 return S_FALSE; 2314 return S_FALSE;
@@ -1753,8 +2317,9 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
1753 2317
1754 spec->Stream = _inStream; 2318 spec->Stream = _inStream;
1755 spec->Size = spec->File->Size; 2319 spec->Size = spec->File->Size;
1756 RINOK(spec->InitAndSeek(_startPos + _dataStartOffset)) 2320 // RINOK(
1757 *stream = specStream.Detach(); 2321 spec->Init(_startPos + _dataForkPair.Offset);
2322 *stream = spec.Detach();
1758 return S_OK; 2323 return S_OK;
1759 2324
1760 COM_TRY_END 2325 COM_TRY_END
diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp
index 7e1facc..e31b4ae 100644
--- a/CPP/7zip/Archive/ElfHandler.cpp
+++ b/CPP/7zip/Archive/ElfHandler.cpp
@@ -155,6 +155,7 @@ bool CHeader::Parse(const Byte *p)
155// The program header table itself. 155// The program header table itself.
156 156
157#define PT_PHDR 6 157#define PT_PHDR 6
158#define PT_GNU_STACK 0x6474e551
158 159
159static const CUInt32PCharPair g_SegnmentTypes[] = 160static const CUInt32PCharPair g_SegnmentTypes[] =
160{ 161{
@@ -167,7 +168,7 @@ static const CUInt32PCharPair g_SegnmentTypes[] =
167 { 6, "Program header table" }, 168 { 6, "Program header table" },
168 { 7, "TLS" }, 169 { 7, "TLS" },
169 { 0x6474e550, "GNU_EH_FRAME" }, 170 { 0x6474e550, "GNU_EH_FRAME" },
170 { 0x6474e551, "GNU_STACK" }, 171 { PT_GNU_STACK, "GNU_STACK" },
171 { 0x6474e552, "GNU_RELRO" } 172 { 0x6474e552, "GNU_RELRO" }
172}; 173};
173 174
@@ -607,6 +608,7 @@ static const CUInt32PCharPair g_OS[] =
607 608
608#define k_Machine_MIPS 8 609#define k_Machine_MIPS 8
609#define k_Machine_ARM 40 610#define k_Machine_ARM 40
611#define k_Machine_RISCV 243
610 612
611/* 613/*
612#define EF_ARM_ABIMASK 0xFF000000 614#define EF_ARM_ABIMASK 0xFF000000
@@ -640,6 +642,15 @@ static const CUInt32PCharPair g_MIPS_Flags[] =
640 { 27, "MDMX" } 642 { 27, "MDMX" }
641}; 643};
642 644
645static const char * const g_RISCV_Flags[] =
646{
647 "RVC",
648 NULL,
649 NULL,
650 "RVE",
651 "TSO"
652};
653
643 654
644// #define ET_NONE 0 655// #define ET_NONE 0
645#define ET_REL 1 656#define ET_REL 1
@@ -670,6 +681,8 @@ Z7_CLASS_IMP_CHandler_IInArchive_1(
670 CHeader _header; 681 CHeader _header;
671 bool _headersError; 682 bool _headersError;
672 bool _allowTail; 683 bool _allowTail;
684 bool _stackFlags_Defined;
685 UInt32 _stackFlags;
673 686
674 void GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const; 687 void GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const;
675 HRESULT Open2(IInStream *stream); 688 HRESULT Open2(IInStream *stream);
@@ -706,6 +719,7 @@ static const Byte kArcProps[] =
706 kpidBigEndian, 719 kpidBigEndian,
707 kpidHostOS, 720 kpidHostOS,
708 kpidCharacts, 721 kpidCharacts,
722 kpidComment,
709 kpidHeadersSize 723 kpidHeadersSize
710}; 724};
711 725
@@ -782,6 +796,23 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
782 s.Add_Space(); 796 s.Add_Space();
783 s += FlagsToString(g_MIPS_Flags, Z7_ARRAY_SIZE(g_MIPS_Flags), flags); 797 s += FlagsToString(g_MIPS_Flags, Z7_ARRAY_SIZE(g_MIPS_Flags), flags);
784 } 798 }
799 else if (_header.Machine == k_Machine_RISCV)
800 {
801 s += "FLOAT_";
802 const UInt32 fl = (flags >> 1) & 3;
803 /*
804 static const char * const g_RISCV_Flags_Float[] =
805 { "SOFT", "SINGLE", "DOUBLE", "QUAD" };
806 s += g_RISCV_Flags_Float[fl];
807 */
808 if (fl)
809 s.Add_UInt32(16u << fl);
810 else
811 s += "SOFT";
812 s.Add_Space();
813 flags &= ~(UInt32)6;
814 s += FlagsToString(g_RISCV_Flags, Z7_ARRAY_SIZE(g_RISCV_Flags), flags);
815 }
785 else 816 else
786 { 817 {
787 char sz[16]; 818 char sz[16];
@@ -795,6 +826,14 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
795 826
796 case kpidHostOS: PAIR_TO_PROP(g_OS, _header.Os, prop); break; 827 case kpidHostOS: PAIR_TO_PROP(g_OS, _header.Os, prop); break;
797 case kpidCharacts: TYPE_TO_PROP(g_Types, _header.Type, prop); break; 828 case kpidCharacts: TYPE_TO_PROP(g_Types, _header.Type, prop); break;
829 case kpidComment:
830 if (_stackFlags_Defined)
831 {
832 AString s ("STACK: ");
833 s += FlagsToString(g_SegmentFlags, Z7_ARRAY_SIZE(g_SegmentFlags), _stackFlags);
834 prop = s;
835 }
836 break;
798 case kpidExtension: 837 case kpidExtension:
799 { 838 {
800 const char *s = NULL; 839 const char *s = NULL;
@@ -913,9 +952,13 @@ HRESULT CHandler::Open2(IInStream *stream)
913 CSegment seg; 952 CSegment seg;
914 seg.Parse(p, _header.Mode64, _header.Be); 953 seg.Parse(p, _header.Mode64, _header.Be);
915 seg.UpdateTotalSize(_totalSize); 954 seg.UpdateTotalSize(_totalSize);
916 if (addSegments) 955 if (seg.Type == PT_GNU_STACK && !_stackFlags_Defined)
917 if (seg.Type != PT_PHDR) 956 {
918 _segments.AddInReserved(seg); 957 _stackFlags = seg.Flags;
958 _stackFlags_Defined = true;
959 }
960 if (addSegments && seg.Type != PT_PHDR)
961 _segments.AddInReserved(seg);
919 } 962 }
920 } 963 }
921 964
@@ -1002,6 +1045,7 @@ Z7_COM7F_IMF(CHandler::Close())
1002{ 1045{
1003 _totalSize = 0; 1046 _totalSize = 0;
1004 _headersError = false; 1047 _headersError = false;
1048 _stackFlags_Defined = false;
1005 1049
1006 _inStream.Release(); 1050 _inStream.Release();
1007 _segments.Clear(); 1051 _segments.Clear();
@@ -1034,26 +1078,23 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1034 _segments[index].Size : 1078 _segments[index].Size :
1035 _sections[index - _segments.Size()].GetSize(); 1079 _sections[index - _segments.Size()].GetSize();
1036 } 1080 }
1037 extractCallback->SetTotal(totalSize); 1081 RINOK(extractCallback->SetTotal(totalSize))
1038 1082
1039 UInt64 currentTotalSize = 0; 1083 UInt64 currentTotalSize = 0;
1040 UInt64 currentItemSize; 1084 UInt64 currentItemSize;
1041 1085
1042 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 1086 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
1043 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 1087 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1044
1045 CLocalProgress *lps = new CLocalProgress;
1046 CMyComPtr<ICompressProgressInfo> progress = lps;
1047 lps->Init(extractCallback, false); 1088 lps->Init(extractCallback, false);
1089 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
1090 inStream->SetStream(_inStream);
1048 1091
1049 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 1092 for (i = 0;; i++, currentTotalSize += currentItemSize)
1050 CMyComPtr<ISequentialInStream> inStream(streamSpec);
1051 streamSpec->SetStream(_inStream);
1052
1053 for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
1054 { 1093 {
1055 lps->InSize = lps->OutSize = currentTotalSize; 1094 lps->InSize = lps->OutSize = currentTotalSize;
1056 RINOK(lps->SetCur()) 1095 RINOK(lps->SetCur())
1096 if (i >= numItems)
1097 break;
1057 const Int32 askMode = testMode ? 1098 const Int32 askMode = testMode ?
1058 NExtract::NAskMode::kTest : 1099 NExtract::NAskMode::kTest :
1059 NExtract::NAskMode::kExtract; 1100 NExtract::NAskMode::kExtract;
@@ -1071,18 +1112,17 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1071 currentItemSize = item.GetSize(); 1112 currentItemSize = item.GetSize();
1072 offset = item.Offset; 1113 offset = item.Offset;
1073 } 1114 }
1074 1115 {
1075 CMyComPtr<ISequentialOutStream> outStream; 1116 CMyComPtr<ISequentialOutStream> outStream;
1076 RINOK(extractCallback->GetStream(index, &outStream, askMode)) 1117 RINOK(extractCallback->GetStream(index, &outStream, askMode))
1077 if (!testMode && !outStream) 1118 if (!testMode && !outStream)
1078 continue; 1119 continue;
1079 1120 RINOK(extractCallback->PrepareOperation(askMode))
1080 RINOK(extractCallback->PrepareOperation(askMode)) 1121 RINOK(InStream_SeekSet(_inStream, offset))
1081 RINOK(InStream_SeekSet(_inStream, offset)) 1122 inStream->Init(currentItemSize);
1082 streamSpec->Init(currentItemSize); 1123 RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps))
1083 RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)) 1124 }
1084 outStream.Release(); 1125 RINOK(extractCallback->SetOperationResult(copyCoder->TotalSize == currentItemSize ?
1085 RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ?
1086 NExtract::NOperationResult::kOK: 1126 NExtract::NOperationResult::kOK:
1087 NExtract::NOperationResult::kDataError)) 1127 NExtract::NOperationResult::kDataError))
1088 } 1128 }
diff --git a/CPP/7zip/Archive/ExtHandler.cpp b/CPP/7zip/Archive/ExtHandler.cpp
index f309485..5af2a92 100644
--- a/CPP/7zip/Archive/ExtHandler.cpp
+++ b/CPP/7zip/Archive/ExtHandler.cpp
@@ -20,6 +20,7 @@
20#include "../../../C/CpuArch.h" 20#include "../../../C/CpuArch.h"
21 21
22#include "../../Common/ComTry.h" 22#include "../../Common/ComTry.h"
23#include "../../Common/IntToString.h"
23#include "../../Common/MyLinux.h" 24#include "../../Common/MyLinux.h"
24#include "../../Common/StringConvert.h" 25#include "../../Common/StringConvert.h"
25#include "../../Common/UTFConvert.h" 26#include "../../Common/UTFConvert.h"
@@ -240,15 +241,6 @@ static const char * const g_NodeFlags[] =
240}; 241};
241 242
242 243
243static inline char GetHex(unsigned t) { return (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); }
244
245static inline void PrintHex(unsigned v, char *s)
246{
247 s[0] = GetHex((v >> 4) & 0xF);
248 s[1] = GetHex(v & 0xF);
249}
250
251
252enum 244enum
253{ 245{
254 k_Type_UNKNOWN, 246 k_Type_UNKNOWN,
@@ -1860,12 +1852,10 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1860 1852
1861 case kpidId: 1853 case kpidId:
1862 { 1854 {
1863 if (!IsEmptyData(_h.Uuid, 16)) 1855 if (!IsEmptyData(_h.Uuid, sizeof(_h.Uuid)))
1864 { 1856 {
1865 char s[16 * 2 + 2]; 1857 char s[sizeof(_h.Uuid) * 2 + 2];
1866 for (unsigned i = 0; i < 16; i++) 1858 ConvertDataToHex_Lower(s, _h.Uuid, sizeof(_h.Uuid));
1867 PrintHex(_h.Uuid[i], s + i * 2);
1868 s[16 * 2] = 0;
1869 prop = s; 1859 prop = s;
1870 } 1860 }
1871 break; 1861 break;
@@ -2602,7 +2592,7 @@ HRESULT CHandler::GetStream_Node(unsigned nodeIndex, ISequentialInStream **strea
2602 2592
2603 CMyComPtr<IInStream> streamTemp; 2593 CMyComPtr<IInStream> streamTemp;
2604 2594
2605 UInt64 numBlocks64 = (node.FileSize + (UInt64)(((UInt32)1 << _h.BlockBits) - 1)) >> _h.BlockBits; 2595 const UInt64 numBlocks64 = (node.FileSize + (UInt64)(((UInt32)1 << _h.BlockBits) - 1)) >> _h.BlockBits;
2606 2596
2607 if (node.IsFlags_EXTENTS()) 2597 if (node.IsFlags_EXTENTS())
2608 { 2598 {
@@ -2729,27 +2719,25 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2729 totalSize += node.FileSize; 2719 totalSize += node.FileSize;
2730 } 2720 }
2731 2721
2732 extractCallback->SetTotal(totalSize); 2722 RINOK(extractCallback->SetTotal(totalSize))
2733 2723
2734 UInt64 totalPackSize; 2724 UInt64 totalPackSize;
2735 totalSize = totalPackSize = 0; 2725 totalSize = totalPackSize = 0;
2736 2726
2737 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 2727 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
2738 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
2739
2740 CLocalProgress *lps = new CLocalProgress;
2741 CMyComPtr<ICompressProgressInfo> progress = lps;
2742 lps->Init(extractCallback, false); 2728 lps->Init(extractCallback, false);
2729 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
2743 2730
2744 for (i = 0;; i++) 2731 for (i = 0;; i++)
2745 { 2732 {
2746 lps->InSize = totalPackSize; 2733 lps->InSize = totalPackSize;
2747 lps->OutSize = totalSize; 2734 lps->OutSize = totalSize;
2748 RINOK(lps->SetCur()) 2735 RINOK(lps->SetCur())
2749 2736 if (i >= numItems)
2750 if (i == numItems)
2751 break; 2737 break;
2752 2738
2739 int opRes;
2740 {
2753 CMyComPtr<ISequentialOutStream> outStream; 2741 CMyComPtr<ISequentialOutStream> outStream;
2754 const Int32 askMode = testMode ? 2742 const Int32 askMode = testMode ?
2755 NExtract::NAskMode::kTest : 2743 NExtract::NAskMode::kTest :
@@ -2786,7 +2774,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2786 continue; 2774 continue;
2787 RINOK(extractCallback->PrepareOperation(askMode)) 2775 RINOK(extractCallback->PrepareOperation(askMode))
2788 2776
2789 int res = NExtract::NOperationResult::kDataError; 2777 opRes = NExtract::NOperationResult::kDataError;
2790 { 2778 {
2791 CMyComPtr<ISequentialInStream> inSeqStream; 2779 CMyComPtr<ISequentialInStream> inSeqStream;
2792 HRESULT hres = GetStream(index, &inSeqStream); 2780 HRESULT hres = GetStream(index, &inSeqStream);
@@ -2794,21 +2782,21 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2794 { 2782 {
2795 if (hres == E_OUTOFMEMORY) 2783 if (hres == E_OUTOFMEMORY)
2796 return hres; 2784 return hres;
2797 res = NExtract::NOperationResult::kUnsupportedMethod; 2785 opRes = NExtract::NOperationResult::kUnsupportedMethod;
2798 } 2786 }
2799 else 2787 else
2800 { 2788 {
2801 RINOK(hres) 2789 RINOK(hres)
2802 { 2790 {
2803 hres = copyCoder->Code(inSeqStream, outStream, NULL, NULL, progress); 2791 hres = copyCoder.Interface()->Code(inSeqStream, outStream, NULL, NULL, lps);
2804 if (hres == S_OK) 2792 if (hres == S_OK)
2805 { 2793 {
2806 if (copyCoderSpec->TotalSize == unpackSize) 2794 if (copyCoder->TotalSize == unpackSize)
2807 res = NExtract::NOperationResult::kOK; 2795 opRes = NExtract::NOperationResult::kOK;
2808 } 2796 }
2809 else if (hres == E_NOTIMPL) 2797 else if (hres == E_NOTIMPL)
2810 { 2798 {
2811 res = NExtract::NOperationResult::kUnsupportedMethod; 2799 opRes = NExtract::NOperationResult::kUnsupportedMethod;
2812 } 2800 }
2813 else if (hres != S_FALSE) 2801 else if (hres != S_FALSE)
2814 { 2802 {
@@ -2817,7 +2805,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2817 } 2805 }
2818 } 2806 }
2819 } 2807 }
2820 RINOK(extractCallback->SetOperationResult(res)) 2808 }
2809 RINOK(extractCallback->SetOperationResult(opRes))
2821 } 2810 }
2822 2811
2823 return S_OK; 2812 return S_OK;
diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp
index 4a843a8..b31ee4f 100644
--- a/CPP/7zip/Archive/FatHandler.cpp
+++ b/CPP/7zip/Archive/FatHandler.cpp
@@ -26,6 +26,8 @@
26 26
27#define Get16(p) GetUi16(p) 27#define Get16(p) GetUi16(p)
28#define Get32(p) GetUi32(p) 28#define Get32(p) GetUi32(p)
29#define Get16a(p) GetUi16a(p)
30#define Get32a(p) GetUi32a(p)
29 31
30#define PRF(x) /* x */ 32#define PRF(x) /* x */
31 33
@@ -57,6 +59,7 @@ struct CHeader
57 UInt32 NumHiddenSectors; 59 UInt32 NumHiddenSectors;
58 60
59 bool VolFieldsDefined; 61 bool VolFieldsDefined;
62 bool HeadersWarning;
60 63
61 UInt32 VolId; 64 UInt32 VolId;
62 // Byte VolName[11]; 65 // Byte VolName[11];
@@ -125,6 +128,8 @@ bool CHeader::Parse(const Byte *p)
125 if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) 128 if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)
126 return false; 129 return false;
127 130
131 HeadersWarning = false;
132
128 int codeOffset = 0; 133 int codeOffset = 0;
129 switch (p[0]) 134 switch (p[0])
130 { 135 {
@@ -259,8 +264,22 @@ bool CHeader::Parse(const Byte *p)
259 } 264 }
260 265
261 FatSize = numClusters + 2; 266 FatSize = numClusters + 2;
262 if (FatSize > BadCluster || CalcFatSizeInSectors() > NumFatSectors) 267 if (FatSize > BadCluster)
263 return false; 268 return false;
269 if (CalcFatSizeInSectors() > NumFatSectors)
270 {
271 /* some third-party program can create such FAT image, where
272 size of FAT table (NumFatSectors from headers) is smaller than
273 required value that is calculated from calculated (FatSize) value.
274 Another FAT unpackers probably ignore that error.
275 v23.02: we also ignore that error, and
276 we recalculate (FatSize) value from (NumFatSectors).
277 New (FatSize) will be smaller than original "full" (FatSize) value.
278 So we will have some unused clusters at the end of archive.
279 */
280 FatSize = (UInt32)(((UInt64)NumFatSectors << (3 + SectorSizeLog)) / NumFatBits);
281 HeadersWarning = true;
282 }
264 return true; 283 return true;
265} 284}
266 285
@@ -410,7 +429,7 @@ HRESULT CDatabase::OpenProgressFat(bool changeTotal)
410 return S_OK; 429 return S_OK;
411 if (changeTotal) 430 if (changeTotal)
412 { 431 {
413 UInt64 numTotalBytes = (Header.CalcFatSizeInSectors() << Header.SectorSizeLog) + 432 const UInt64 numTotalBytes = (Header.CalcFatSizeInSectors() << Header.SectorSizeLog) +
414 ((UInt64)(Header.FatSize - NumFreeClusters) << Header.ClusterSizeLog); 433 ((UInt64)(Header.FatSize - NumFreeClusters) << Header.ClusterSizeLog);
415 RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes)) 434 RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes))
416 } 435 }
@@ -494,7 +513,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level)
494 return S_FALSE; 513 return S_FALSE;
495 PRF(printf("\nCluster = %4X", cluster)); 514 PRF(printf("\nCluster = %4X", cluster));
496 RINOK(SeekToCluster(cluster)) 515 RINOK(SeekToCluster(cluster))
497 UInt32 newCluster = Fat[cluster]; 516 const UInt32 newCluster = Fat[cluster];
498 if ((newCluster & kFatItemUsedByDirMask) != 0) 517 if ((newCluster & kFatItemUsedByDirMask) != 0)
499 return S_FALSE; 518 return S_FALSE;
500 Fat[cluster] |= kFatItemUsedByDirMask; 519 Fat[cluster] |= kFatItemUsedByDirMask;
@@ -650,15 +669,18 @@ HRESULT CDatabase::Open()
650 669
651 if (Header.IsFat32()) 670 if (Header.IsFat32())
652 { 671 {
653 SeekToSector(Header.FsInfoSector); 672 if (((UInt32)Header.FsInfoSector << Header.SectorSizeLog) + kHeaderSize <= fileSize
654 RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize)) 673 && SeekToSector(Header.FsInfoSector) == S_OK
655 if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA) 674 && ReadStream_FALSE(InStream, buf, kHeaderSize) == S_OK
656 return S_FALSE; 675 && 0xaa550000 == Get32(buf + 508)
657 if (Get32(buf) == 0x41615252 && Get32(buf + 484) == 0x61417272) 676 && 0x41615252 == Get32(buf)
677 && 0x61417272 == Get32(buf + 484))
658 { 678 {
659 NumFreeClusters = Get32(buf + 488); 679 NumFreeClusters = Get32(buf + 488);
660 numFreeClustersDefined = (NumFreeClusters <= Header.FatSize); 680 numFreeClustersDefined = (NumFreeClusters <= Header.FatSize);
661 } 681 }
682 else
683 Header.HeadersWarning = true;
662 } 684 }
663 } 685 }
664 686
@@ -675,30 +697,35 @@ HRESULT CDatabase::Open()
675 { 697 {
676 const UInt32 kBufSize = (1 << 15); 698 const UInt32 kBufSize = (1 << 15);
677 byteBuf.Alloc(kBufSize); 699 byteBuf.Alloc(kBufSize);
678 for (UInt32 i = 0; i < Header.FatSize;) 700 for (UInt32 i = 0;;)
679 { 701 {
680 UInt32 size = Header.FatSize - i; 702 UInt32 size = Header.FatSize - i;
703 if (size == 0)
704 break;
681 const UInt32 kBufSize32 = kBufSize / 4; 705 const UInt32 kBufSize32 = kBufSize / 4;
682 if (size > kBufSize32) 706 if (size > kBufSize32)
683 size = kBufSize32; 707 size = kBufSize32;
684 UInt32 readSize = Header.SizeToSectors(size * 4) << Header.SectorSizeLog; 708 const UInt32 readSize = Header.SizeToSectors(size * 4) << Header.SectorSizeLog;
685 RINOK(ReadStream_FALSE(InStream, byteBuf, readSize)) 709 RINOK(ReadStream_FALSE(InStream, byteBuf, readSize))
686 NumCurUsedBytes += readSize; 710 NumCurUsedBytes += readSize;
687 711
688 const UInt32 *src = (const UInt32 *)(const void *)(const Byte *)byteBuf; 712 const UInt32 *src = (const UInt32 *)(const void *)(const Byte *)byteBuf;
689 UInt32 *dest = Fat + i; 713 UInt32 *dest = Fat + i;
714 const UInt32 *srcLim = src + size;
690 if (numFreeClustersDefined) 715 if (numFreeClustersDefined)
691 for (UInt32 j = 0; j < size; j++) 716 do
692 dest[j] = Get32(src + j) & 0x0FFFFFFF; 717 *dest++ = Get32a(src) & 0x0FFFFFFF;
718 while (++src != srcLim);
693 else 719 else
694 { 720 {
695 UInt32 numFreeClusters = 0; 721 UInt32 numFreeClusters = 0;
696 for (UInt32 j = 0; j < size; j++) 722 do
697 { 723 {
698 UInt32 v = Get32(src + j) & 0x0FFFFFFF; 724 const UInt32 v = Get32a(src) & 0x0FFFFFFF;
725 *dest++ = v;
699 numFreeClusters += (UInt32)(v - 1) >> 31; 726 numFreeClusters += (UInt32)(v - 1) >> 31;
700 dest[j] = v;
701 } 727 }
728 while (++src != srcLim);
702 NumFreeClusters += numFreeClusters; 729 NumFreeClusters += numFreeClusters;
703 } 730 }
704 i += size; 731 i += size;
@@ -715,11 +742,11 @@ HRESULT CDatabase::Open()
715 byteBuf.Alloc(kBufSize); 742 byteBuf.Alloc(kBufSize);
716 Byte *p = byteBuf; 743 Byte *p = byteBuf;
717 RINOK(ReadStream_FALSE(InStream, p, kBufSize)) 744 RINOK(ReadStream_FALSE(InStream, p, kBufSize))
718 UInt32 fatSize = Header.FatSize; 745 const UInt32 fatSize = Header.FatSize;
719 UInt32 *fat = &Fat[0]; 746 UInt32 *fat = &Fat[0];
720 if (Header.NumFatBits == 16) 747 if (Header.NumFatBits == 16)
721 for (UInt32 j = 0; j < fatSize; j++) 748 for (UInt32 j = 0; j < fatSize; j++)
722 fat[j] = Get16(p + j * 2); 749 fat[j] = Get16a(p + j * 2);
723 else 750 else
724 for (UInt32 j = 0; j < fatSize; j++) 751 for (UInt32 j = 0; j < fatSize; j++)
725 fat[j] = (Get16(p + j * 3 / 2) >> ((j & 1) << 2)) & 0xFFF; 752 fat[j] = (Get16(p + j * 3 / 2) >> ((j & 1) << 2)) & 0xFFF;
@@ -773,7 +800,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
773 streamSpec->BlockSizeLog = Header.ClusterSizeLog; 800 streamSpec->BlockSizeLog = Header.ClusterSizeLog;
774 streamSpec->Size = item.Size; 801 streamSpec->Size = item.Size;
775 802
776 UInt32 numClusters = Header.GetNumClusters(item.Size); 803 const UInt32 numClusters = Header.GetNumClusters(item.Size);
777 streamSpec->Vector.ClearAndReserve(numClusters); 804 streamSpec->Vector.ClearAndReserve(numClusters);
778 UInt32 cluster = item.Cluster; 805 UInt32 cluster = item.Cluster;
779 UInt32 size = item.Size; 806 UInt32 size = item.Size;
@@ -785,7 +812,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
785 } 812 }
786 else 813 else
787 { 814 {
788 UInt32 clusterSize = Header.ClusterSize(); 815 const UInt32 clusterSize = Header.ClusterSize();
789 for (;; size -= clusterSize) 816 for (;; size -= clusterSize)
790 { 817 {
791 if (!Header.IsValidCluster(cluster)) 818 if (!Header.IsValidCluster(cluster))
@@ -907,6 +934,14 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
907 // case kpidVolName: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.VolName, prop); break; 934 // case kpidVolName: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.VolName, prop); break;
908 // case kpidFileSysType: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.FileSys, prop); break; 935 // case kpidFileSysType: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.FileSys, prop); break;
909 // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break; 936 // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break;
937 case kpidWarningFlags:
938 {
939 UInt32 v = 0;
940 if (Header.HeadersWarning) v |= kpv_ErrorFlags_HeadersError;
941 if (v != 0)
942 prop = v;
943 break;
944 }
910 } 945 }
911 prop.Detach(value); 946 prop.Detach(value);
912 return S_OK; 947 return S_OK;
diff --git a/CPP/7zip/Archive/GptHandler.cpp b/CPP/7zip/Archive/GptHandler.cpp
index 78c76cf..23a1db6 100644
--- a/CPP/7zip/Archive/GptHandler.cpp
+++ b/CPP/7zip/Archive/GptHandler.cpp
@@ -24,6 +24,10 @@ using namespace NWindows;
24 24
25namespace NArchive { 25namespace NArchive {
26 26
27namespace NMbr {
28const char *GetFileSystem(ISequentialInStream *stream, UInt64 partitionSize);
29}
30
27namespace NFat { 31namespace NFat {
28API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size); 32API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size);
29} 33}
@@ -34,8 +38,6 @@ static const unsigned k_SignatureSize = 12;
34static const Byte k_Signature[k_SignatureSize] = 38static const Byte k_Signature[k_SignatureSize] =
35 { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 }; 39 { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 };
36 40
37static const UInt32 kSectorSize = 512;
38
39static const CUInt32PCharPair g_PartitionFlags[] = 41static const CUInt32PCharPair g_PartitionFlags[] =
40{ 42{
41 { 0, "Sys" }, 43 { 0, "Sys" },
@@ -66,9 +68,9 @@ struct CPartition
66 return true; 68 return true;
67 } 69 }
68 70
69 UInt64 GetSize() const { return (LastLba - FirstLba + 1) * kSectorSize; } 71 UInt64 GetSize(unsigned sectorSizeLog) const { return (LastLba - FirstLba + 1) << sectorSizeLog; }
70 UInt64 GetPos() const { return FirstLba * kSectorSize; } 72 UInt64 GetPos(unsigned sectorSizeLog) const { return FirstLba << sectorSizeLog; }
71 UInt64 GetEnd() const { return (LastLba + 1) * kSectorSize; } 73 UInt64 GetEnd(unsigned sectorSizeLog) const { return (LastLba + 1) << sectorSizeLog; }
72 74
73 void Parse(const Byte *p) 75 void Parse(const Byte *p)
74 { 76 {
@@ -144,6 +146,7 @@ Z7_class_CHandler_final: public CHandlerCont
144 146
145 CRecordVector<CPartition> _items; 147 CRecordVector<CPartition> _items;
146 UInt64 _totalSize; 148 UInt64 _totalSize;
149 unsigned _sectorSizeLog;
147 Byte Guid[16]; 150 Byte Guid[16];
148 151
149 CByteBuffer _buffer; 152 CByteBuffer _buffer;
@@ -153,8 +156,8 @@ Z7_class_CHandler_final: public CHandlerCont
153 virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override 156 virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
154 { 157 {
155 const CPartition &item = _items[index]; 158 const CPartition &item = _items[index];
156 pos = item.GetPos(); 159 pos = item.GetPos(_sectorSizeLog);
157 size = item.GetSize(); 160 size = item.GetSize(_sectorSizeLog);
158 return NExtract::NOperationResult::kOK; 161 return NExtract::NOperationResult::kOK;
159 } 162 }
160}; 163};
@@ -162,22 +165,32 @@ Z7_class_CHandler_final: public CHandlerCont
162 165
163HRESULT CHandler::Open2(IInStream *stream) 166HRESULT CHandler::Open2(IInStream *stream)
164{ 167{
165 _buffer.Alloc(kSectorSize * 2); 168 const unsigned kBufSize = 2 << 12;
166 RINOK(ReadStream_FALSE(stream, _buffer, kSectorSize * 2)) 169 _buffer.Alloc(kBufSize);
167 170 RINOK(ReadStream_FALSE(stream, _buffer, kBufSize))
168 const Byte *buf = _buffer; 171 const Byte *buf = _buffer;
169 if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA) 172 if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
170 return S_FALSE; 173 return S_FALSE;
171 174 {
172 buf += kSectorSize; 175 for (unsigned sectorSizeLog = 9;; sectorSizeLog += 3)
173 if (memcmp(buf, k_Signature, k_SignatureSize) != 0) 176 {
174 return S_FALSE; 177 if (sectorSizeLog > 12)
178 return S_FALSE;
179 if (memcmp(buf + ((size_t)1 << sectorSizeLog), k_Signature, k_SignatureSize) == 0)
180 {
181 buf += ((size_t)1 << sectorSizeLog);
182 _sectorSizeLog = sectorSizeLog;
183 break;
184 }
185 }
186 }
187 const UInt32 kSectorSize = 1u << _sectorSizeLog;
175 { 188 {
176 // if (Get32(buf + 8) != 0x10000) return S_FALSE; // revision 189 // if (Get32(buf + 8) != 0x10000) return S_FALSE; // revision
177 UInt32 headerSize = Get32(buf + 12); // = 0x5C usually 190 const UInt32 headerSize = Get32(buf + 12); // = 0x5C usually
178 if (headerSize > kSectorSize) 191 if (headerSize > kSectorSize)
179 return S_FALSE; 192 return S_FALSE;
180 UInt32 crc = Get32(buf + 0x10); 193 const UInt32 crc = Get32(buf + 0x10);
181 SetUi32(_buffer + kSectorSize + 0x10, 0) 194 SetUi32(_buffer + kSectorSize + 0x10, 0)
182 if (CrcCalc(_buffer + kSectorSize, headerSize) != crc) 195 if (CrcCalc(_buffer + kSectorSize, headerSize) != crc)
183 return S_FALSE; 196 return S_FALSE;
@@ -191,18 +204,15 @@ HRESULT CHandler::Open2(IInStream *stream)
191 // UInt64 lastUsableLba = Get64(buf + 0x30); 204 // UInt64 lastUsableLba = Get64(buf + 0x30);
192 memcpy(Guid, buf + 0x38, 16); 205 memcpy(Guid, buf + 0x38, 16);
193 const UInt64 tableLba = Get64(buf + 0x48); 206 const UInt64 tableLba = Get64(buf + 0x48);
194 if (tableLba < 2) 207 if (tableLba < 2 || (tableLba >> (63 - _sectorSizeLog)) != 0)
195 return S_FALSE; 208 return S_FALSE;
196 const UInt32 numEntries = Get32(buf + 0x50); 209 const UInt32 numEntries = Get32(buf + 0x50);
210 if (numEntries > (1 << 16))
211 return S_FALSE;
197 const UInt32 entrySize = Get32(buf + 0x54); // = 128 usually 212 const UInt32 entrySize = Get32(buf + 0x54); // = 128 usually
198 const UInt32 entriesCrc = Get32(buf + 0x58); 213 if (entrySize < 128 || entrySize > (1 << 12))
199
200 if (entrySize < 128
201 || entrySize > (1 << 12)
202 || numEntries > (1 << 16)
203 || tableLba < 2
204 || tableLba >= ((UInt64)1 << (64 - 10)))
205 return S_FALSE; 214 return S_FALSE;
215 const UInt32 entriesCrc = Get32(buf + 0x58);
206 216
207 const UInt32 tableSize = entrySize * numEntries; 217 const UInt32 tableSize = entrySize * numEntries;
208 const UInt32 tableSizeAligned = (tableSize + kSectorSize - 1) & ~(kSectorSize - 1); 218 const UInt32 tableSizeAligned = (tableSize + kSectorSize - 1) & ~(kSectorSize - 1);
@@ -222,18 +232,24 @@ HRESULT CHandler::Open2(IInStream *stream)
222 item.Parse(_buffer + i * entrySize); 232 item.Parse(_buffer + i * entrySize);
223 if (item.IsUnused()) 233 if (item.IsUnused())
224 continue; 234 continue;
225 UInt64 endPos = item.GetEnd(); 235 if (item.LastLba < item.FirstLba)
236 return S_FALSE;
237 if ((item.LastLba >> (63 - _sectorSizeLog)) != 0)
238 return S_FALSE;
239 const UInt64 endPos = item.GetEnd(_sectorSizeLog);
226 if (_totalSize < endPos) 240 if (_totalSize < endPos)
227 _totalSize = endPos; 241 _totalSize = endPos;
228 _items.Add(item); 242 _items.Add(item);
229 } 243 }
230 244
245 _buffer.Free();
231 { 246 {
247 if ((backupLba >> (63 - _sectorSizeLog)) != 0)
248 return S_FALSE;
232 const UInt64 end = (backupLba + 1) * kSectorSize; 249 const UInt64 end = (backupLba + 1) * kSectorSize;
233 if (_totalSize < end) 250 if (_totalSize < end)
234 _totalSize = end; 251 _totalSize = end;
235 } 252 }
236
237 { 253 {
238 UInt64 fileEnd; 254 UInt64 fileEnd;
239 RINOK(InStream_GetSize_SeekToEnd(stream, fileEnd)) 255 RINOK(InStream_GetSize_SeekToEnd(stream, fileEnd))
@@ -258,27 +274,6 @@ HRESULT CHandler::Open2(IInStream *stream)
258} 274}
259 275
260 276
261
262static const unsigned k_Ntfs_Fat_HeaderSize = 512;
263
264static const Byte k_NtfsSignature[] = { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 };
265
266static bool IsNtfs(const Byte *p)
267{
268 if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)
269 return false;
270 if (memcmp(p + 3, k_NtfsSignature, Z7_ARRAY_SIZE(k_NtfsSignature)) != 0)
271 return false;
272 switch (p[0])
273 {
274 case 0xE9: /* codeOffset = 3 + (Int16)Get16(p + 1); */ break;
275 case 0xEB: if (p[2] != 0x90) return false; /* codeOffset = 2 + (int)(signed char)p[1]; */ break;
276 default: return false;
277 }
278 return true;
279}
280
281
282Z7_COM7F_IMF(CHandler::Open(IInStream *stream, 277Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
283 const UInt64 * /* maxCheckStartPosition */, 278 const UInt64 * /* maxCheckStartPosition */,
284 IArchiveOpenCallback * /* openArchiveCallback */)) 279 IArchiveOpenCallback * /* openArchiveCallback */))
@@ -307,20 +302,9 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
307 // ((IInArchiveGetStream *)this)-> 302 // ((IInArchiveGetStream *)this)->
308 GetStream(fileIndex, &inStream) == S_OK && inStream) 303 GetStream(fileIndex, &inStream) == S_OK && inStream)
309 { 304 {
310 Byte temp[k_Ntfs_Fat_HeaderSize]; 305 const char *fs = NMbr::GetFileSystem(inStream, item.GetSize(_sectorSizeLog));
311 if (ReadStream_FAIL(inStream, temp, k_Ntfs_Fat_HeaderSize) == S_OK) 306 if (fs)
312 { 307 item.Ext = fs;
313 if (IsNtfs(temp))
314 {
315 item.Ext = "ntfs";
316 continue;
317 }
318 if (NFat::IsArc_Fat(temp, k_Ntfs_Fat_HeaderSize) == k_IsArc_Res_YES)
319 {
320 item.Ext = "fat";
321 continue;
322 }
323 }
324 } 308 }
325 } 309 }
326 } 310 }
@@ -331,6 +315,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
331 315
332Z7_COM7F_IMF(CHandler::Close()) 316Z7_COM7F_IMF(CHandler::Close())
333{ 317{
318 _sectorSizeLog = 0;
334 _totalSize = 0; 319 _totalSize = 0;
335 memset(Guid, 0, sizeof(Guid)); 320 memset(Guid, 0, sizeof(Guid));
336 _items.Clear(); 321 _items.Clear();
@@ -350,6 +335,7 @@ static const Byte kProps[] =
350 335
351static const Byte kArcProps[] = 336static const Byte kArcProps[] =
352{ 337{
338 kpidSectorSize,
353 kpidId 339 kpidId
354}; 340};
355 341
@@ -369,6 +355,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
369 break; 355 break;
370 } 356 }
371 case kpidPhySize: prop = _totalSize; break; 357 case kpidPhySize: prop = _totalSize; break;
358 case kpidSectorSize: prop = (UInt32)((UInt32)1 << _sectorSizeLog); break;
372 case kpidId: 359 case kpidId:
373 { 360 {
374 char s[48]; 361 char s[48];
@@ -420,15 +407,22 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
420 } 407 }
421 { 408 {
422 s.Add_Dot(); 409 s.Add_Dot();
423 s += (item.Ext ? item.Ext : "img"); 410 if (item.Ext)
411 {
412 AString fs (item.Ext);
413 fs.MakeLower_Ascii();
414 s += fs;
415 }
416 else
417 s += "img";
424 } 418 }
425 prop = s; 419 prop = s;
426 break; 420 break;
427 } 421 }
428 422
429 case kpidSize: 423 case kpidSize:
430 case kpidPackSize: prop = item.GetSize(); break; 424 case kpidPackSize: prop = item.GetSize(_sectorSizeLog); break;
431 case kpidOffset: prop = item.GetPos(); break; 425 case kpidOffset: prop = item.GetPos(_sectorSizeLog); break;
432 426
433 case kpidFileSystem: 427 case kpidFileSystem:
434 { 428 {
@@ -462,10 +456,11 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
462 COM_TRY_END 456 COM_TRY_END
463} 457}
464 458
459// we suppport signature only for 512-bytes sector.
465REGISTER_ARC_I( 460REGISTER_ARC_I(
466 "GPT", "gpt mbr", NULL, 0xCB, 461 "GPT", "gpt mbr", NULL, 0xCB,
467 k_Signature, 462 k_Signature,
468 kSectorSize, 463 1 << 9,
469 0, 464 0,
470 NULL) 465 NULL)
471 466
diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp
index ad9a074..ca9d246 100644
--- a/CPP/7zip/Archive/GzHandler.cpp
+++ b/CPP/7zip/Archive/GzHandler.cpp
@@ -10,7 +10,6 @@
10#include "../../Common/Defs.h" 10#include "../../Common/Defs.h"
11#include "../../Common/StringConvert.h" 11#include "../../Common/StringConvert.h"
12 12
13#include "../../Windows/PropVariant.h"
14#include "../../Windows/PropVariantUtils.h" 13#include "../../Windows/PropVariantUtils.h"
15#include "../../Windows/TimeUtils.h" 14#include "../../Windows/TimeUtils.h"
16 15
@@ -206,13 +205,13 @@ static HRESULT ReadString(NDecoder::CCOMCoder *stream, AString &s, size_t limit
206 s.Empty(); 205 s.Empty();
207 for (size_t i = 0; i < limit; i++) 206 for (size_t i = 0; i < limit; i++)
208 { 207 {
209 Byte b = stream->ReadAlignedByte(); 208 const Byte b = stream->ReadAlignedByte();
210 if (stream->InputEofError()) 209 if (stream->InputEofError())
211 return S_FALSE; 210 return S_FALSE;
212 // crc = CRC_UPDATE_BYTE(crc, b); 211 // crc = CRC_UPDATE_BYTE(crc, b);
213 if (b == 0) 212 if (b == 0)
214 return S_OK; 213 return S_OK;
215 s += (char)b; 214 s.Add_Char((char)b);
216 } 215 }
217 return S_FALSE; 216 return S_FALSE;
218} 217}
@@ -229,7 +228,7 @@ static UInt32 Is_Deflate(const Byte *p, size_t size)
229 return k_IsArc_Res_NO; 228 return k_IsArc_Res_NO;
230 if (type == 0) 229 if (type == 0)
231 { 230 {
232 // Stored (uncompreessed data) 231 // Stored (uncompreessed data)
233 if ((b >> 3) != 0) 232 if ((b >> 3) != 0)
234 return k_IsArc_Res_NO; 233 return k_IsArc_Res_NO;
235 if (size < 4) 234 if (size < 4)
@@ -261,11 +260,11 @@ API_FUNC_static_IsArc IsArc_Gz(const Byte *p, size_t size)
261 p[2] != kSignature_2) 260 p[2] != kSignature_2)
262 return k_IsArc_Res_NO; 261 return k_IsArc_Res_NO;
263 262
264 Byte flags = p[3]; 263 const Byte flags = p[3];
265 if ((flags & NFlags::kReserved) != 0) 264 if ((flags & NFlags::kReserved) != 0)
266 return k_IsArc_Res_NO; 265 return k_IsArc_Res_NO;
267 266
268 Byte extraFlags = p[8]; 267 const Byte extraFlags = p[8];
269 // maybe that flag can have another values for some gz archives? 268 // maybe that flag can have another values for some gz archives?
270 if (extraFlags != 0 && 269 if (extraFlags != 0 &&
271 extraFlags != NExtraFlags::kMaximum && 270 extraFlags != NExtraFlags::kMaximum &&
@@ -288,7 +287,7 @@ API_FUNC_static_IsArc IsArc_Gz(const Byte *p, size_t size)
288 return k_IsArc_Res_NO; 287 return k_IsArc_Res_NO;
289 if (size < 4) 288 if (size < 4)
290 return k_IsArc_Res_NEED_MORE; 289 return k_IsArc_Res_NEED_MORE;
291 unsigned len = GetUi16(p + 2); 290 const unsigned len = GetUi16(p + 2);
292 size -= 4; 291 size -= 4;
293 xlen -= 4; 292 xlen -= 4;
294 p += 4; 293 p += 4;
@@ -469,24 +468,19 @@ Z7_CLASS_IMP_CHandler_IInArchive_3(
469 UInt64 _headerSize; // only start header (without footer) 468 UInt64 _headerSize; // only start header (without footer)
470 469
471 CMyComPtr<IInStream> _stream; 470 CMyComPtr<IInStream> _stream;
472 CMyComPtr<ICompressCoder> _decoder; 471 CMyComPtr2<ICompressCoder, NDecoder::CCOMCoder> _decoder;
473 NDecoder::CCOMCoder *_decoderSpec;
474 472
475 CSingleMethodProps _props; 473 CSingleMethodProps _props;
476 CHandlerTimeOptions _timeOptions; 474 CHandlerTimeOptions _timeOptions;
477 475
478public: 476public:
479 CHandler(): 477 CHandler():
480 _isArc(false), 478 _isArc(false)
481 _decoderSpec(NULL)
482 {} 479 {}
483 480
484 void CreateDecoder() 481 void CreateDecoder()
485 { 482 {
486 if (_decoder) 483 _decoder.Create_if_Empty();
487 return;
488 _decoderSpec = new NDecoder::CCOMCoder;
489 _decoder = _decoderSpec;
490 } 484 }
491}; 485};
492 486
@@ -538,6 +532,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
538 prop = s; 532 prop = s;
539 } 533 }
540 break; 534 break;
535 default: break;
541 } 536 }
542 prop.Detach(value); 537 prop.Detach(value);
543 return S_OK; 538 return S_OK;
@@ -587,6 +582,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
587 } 582 }
588 case kpidHostOS: TYPE_TO_PROP(kHostOSes, _item.HostOS, prop); break; 583 case kpidHostOS: TYPE_TO_PROP(kHostOSes, _item.HostOS, prop); break;
589 case kpidCRC: if (_stream) prop = _item.Crc; break; 584 case kpidCRC: if (_stream) prop = _item.Crc; break;
585 default: break;
590 } 586 }
591 prop.Detach(value); 587 prop.Detach(value);
592 return S_OK; 588 return S_OK;
@@ -640,12 +636,12 @@ Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))
640 { 636 {
641 Close(); 637 Close();
642 CreateDecoder(); 638 CreateDecoder();
643 _decoderSpec->SetInStream(stream); 639 _decoder->SetInStream(stream);
644 _decoderSpec->InitInStream(true); 640 _decoder->InitInStream(true);
645 RINOK(_item.ReadHeader(_decoderSpec)) 641 RINOK(_item.ReadHeader(_decoder.ClsPtr()))
646 if (_decoderSpec->InputEofError()) 642 if (_decoder->InputEofError())
647 return S_FALSE; 643 return S_FALSE;
648 _headerSize = _decoderSpec->GetInputProcessedSize(); 644 _headerSize = _decoder->GetInputProcessedSize();
649 _isArc = true; 645 _isArc = true;
650 return S_OK; 646 return S_OK;
651 } 647 }
@@ -669,7 +665,7 @@ Z7_COM7F_IMF(CHandler::Close())
669 665
670 _stream.Release(); 666 _stream.Release();
671 if (_decoder) 667 if (_decoder)
672 _decoderSpec->ReleaseInStream(); 668 _decoder->ReleaseInStream();
673 return S_OK; 669 return S_OK;
674} 670}
675 671
@@ -683,9 +679,11 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
683 return E_INVALIDARG; 679 return E_INVALIDARG;
684 680
685 if (_packSize_Defined) 681 if (_packSize_Defined)
686 extractCallback->SetTotal(_packSize); 682 RINOK(extractCallback->SetTotal(_packSize))
687 // UInt64 currentTotalPacked = 0; 683 // UInt64 currentTotalPacked = 0;
688 // RINOK(extractCallback->SetCompleted(&currentTotalPacked)); 684 // RINOK(extractCallback->SetCompleted(&currentTotalPacked));
685 Int32 retResult;
686 {
689 CMyComPtr<ISequentialOutStream> realOutStream; 687 CMyComPtr<ISequentialOutStream> realOutStream;
690 const Int32 askMode = testMode ? 688 const Int32 askMode = testMode ?
691 NExtract::NAskMode::kTest : 689 NExtract::NAskMode::kTest :
@@ -694,18 +692,16 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
694 if (!testMode && !realOutStream) 692 if (!testMode && !realOutStream)
695 return S_OK; 693 return S_OK;
696 694
697 extractCallback->PrepareOperation(askMode); 695 RINOK(extractCallback->PrepareOperation(askMode))
698 696
699 CreateDecoder(); 697 CreateDecoder();
700 698
701 COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; 699 CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;
702 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); 700 outStream->SetStream(realOutStream);
703 outStreamSpec->SetStream(realOutStream); 701 outStream->Init();
704 outStreamSpec->Init(); 702 // realOutStream.Release();
705 realOutStream.Release();
706 703
707 CLocalProgress *lps = new CLocalProgress; 704 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
708 CMyComPtr<ICompressProgressInfo> progress = lps;
709 lps->Init(extractCallback, true); 705 lps->Init(extractCallback, true);
710 706
711 bool needReadFirstItem = _needSeekToStart; 707 bool needReadFirstItem = _needSeekToStart;
@@ -715,7 +711,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
715 if (!_stream) 711 if (!_stream)
716 return E_FAIL; 712 return E_FAIL;
717 RINOK(InStream_SeekToBegin(_stream)) 713 RINOK(InStream_SeekToBegin(_stream))
718 _decoderSpec->InitInStream(true); 714 _decoder->InitInStream(true);
719 // printf("\nSeek"); 715 // printf("\nSeek");
720 } 716 }
721 else 717 else
@@ -723,7 +719,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
723 719
724 bool firstItem = true; 720 bool firstItem = true;
725 721
726 UInt64 packSize = _decoderSpec->GetInputProcessedSize(); 722 UInt64 packSize = _decoder->GetInputProcessedSize();
727 // printf("\npackSize = %d", (unsigned)packSize); 723 // printf("\npackSize = %d", (unsigned)packSize);
728 724
729 UInt64 unpackedSize = 0; 725 UInt64 unpackedSize = 0;
@@ -746,12 +742,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
746 742
747 if (!firstItem || needReadFirstItem) 743 if (!firstItem || needReadFirstItem)
748 { 744 {
749 result = item.ReadHeader(_decoderSpec); 745 result = item.ReadHeader(_decoder.ClsPtr());
750 746
751 if (result != S_OK && result != S_FALSE) 747 if (result != S_OK && result != S_FALSE)
752 return result; 748 return result;
753 749
754 if (_decoderSpec->InputEofError()) 750 if (_decoder->InputEofError())
755 result = S_FALSE; 751 result = S_FALSE;
756 752
757 if (result != S_OK && firstItem) 753 if (result != S_OK && firstItem)
@@ -760,7 +756,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
760 break; 756 break;
761 } 757 }
762 758
763 if (packSize == _decoderSpec->GetStreamSize()) 759 if (packSize == _decoder->GetStreamSize())
764 { 760 {
765 result = S_OK; 761 result = S_OK;
766 break; 762 break;
@@ -776,20 +772,20 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
776 numStreams++; 772 numStreams++;
777 firstItem = false; 773 firstItem = false;
778 774
779 UInt64 startOffset = outStreamSpec->GetSize(); 775 const UInt64 startOffset = outStream->GetSize();
780 outStreamSpec->InitCRC(); 776 outStream->InitCRC();
781 777
782 result = _decoderSpec->CodeResume(outStream, NULL, progress); 778 result = _decoder->CodeResume(outStream, NULL, lps);
783 779
784 packSize = _decoderSpec->GetInputProcessedSize(); 780 packSize = _decoder->GetInputProcessedSize();
785 unpackedSize = outStreamSpec->GetSize(); 781 unpackedSize = outStream->GetSize();
786 782
787 if (result != S_OK && result != S_FALSE) 783 if (result != S_OK && result != S_FALSE)
788 return result; 784 return result;
789 785
790 if (_decoderSpec->InputEofError()) 786 if (_decoder->InputEofError())
791 { 787 {
792 packSize = _decoderSpec->GetStreamSize(); 788 packSize = _decoder->GetStreamSize();
793 _needMoreInput = true; 789 _needMoreInput = true;
794 result = S_FALSE; 790 result = S_FALSE;
795 } 791 }
@@ -797,18 +793,18 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
797 if (result != S_OK) 793 if (result != S_OK)
798 break; 794 break;
799 795
800 _decoderSpec->AlignToByte(); 796 _decoder->AlignToByte();
801 797
802 result = item.ReadFooter1(_decoderSpec); 798 result = item.ReadFooter1(_decoder.ClsPtr());
803 799
804 packSize = _decoderSpec->GetInputProcessedSize(); 800 packSize = _decoder->GetInputProcessedSize();
805 801
806 if (result != S_OK && result != S_FALSE) 802 if (result != S_OK && result != S_FALSE)
807 return result; 803 return result;
808 804
809 if (result != S_OK) 805 if (result != S_OK)
810 { 806 {
811 if (_decoderSpec->InputEofError()) 807 if (_decoder->InputEofError())
812 { 808 {
813 _needMoreInput = true; 809 _needMoreInput = true;
814 result = S_FALSE; 810 result = S_FALSE;
@@ -816,7 +812,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
816 break; 812 break;
817 } 813 }
818 814
819 if (item.Crc != outStreamSpec->GetCRC() || 815 if (item.Crc != outStream->GetCRC() ||
820 item.Size32 != (UInt32)(unpackedSize - startOffset)) 816 item.Size32 != (UInt32)(unpackedSize - startOffset))
821 { 817 {
822 crcError = true; 818 crcError = true;
@@ -840,9 +836,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
840 _numStreams_Defined = true; 836 _numStreams_Defined = true;
841 } 837 }
842 838
843 outStream.Release(); 839 // outStream.Release();
844 840
845 Int32 retResult = NExtract::NOperationResult::kDataError; 841 retResult = NExtract::NOperationResult::kDataError;
846 842
847 if (!_isArc) 843 if (!_isArc)
848 retResult = NExtract::NOperationResult::kIsNotArc; 844 retResult = NExtract::NOperationResult::kIsNotArc;
@@ -858,10 +854,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
858 retResult = NExtract::NOperationResult::kOK; 854 retResult = NExtract::NOperationResult::kOK;
859 else 855 else
860 return result; 856 return result;
857 }
861 858
862 return extractCallback->SetOperationResult(retResult); 859 return extractCallback->SetOperationResult(retResult);
863
864
865 COM_TRY_END 860 COM_TRY_END
866} 861}
867 862
@@ -966,13 +961,11 @@ static HRESULT UpdateArchive(
966 RINOK(updateCallback->SetTotal(unpackSize)) 961 RINOK(updateCallback->SetTotal(unpackSize))
967 RINOK(updateCallback->SetCompleted(&complexity)) 962 RINOK(updateCallback->SetCompleted(&complexity))
968 963
969 CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC; 964 CMyComPtr2_Create<ISequentialInStream, CSequentialInStreamWithCRC> crcStream;
970 CMyComPtr<ISequentialInStream> crcStream(inStreamSpec); 965 crcStream->SetStream(fileInStream);
971 inStreamSpec->SetStream(fileInStream); 966 crcStream->Init();
972 inStreamSpec->Init();
973 967
974 CLocalProgress *lps = new CLocalProgress; 968 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
975 CMyComPtr<ICompressProgressInfo> progress = lps;
976 lps->Init(updateCallback, true); 969 lps->Init(updateCallback, true);
977 970
978 item.ExtraFlags = props.GetLevel() >= 7 ? 971 item.ExtraFlags = props.GetLevel() >= 7 ?
@@ -983,13 +976,13 @@ static HRESULT UpdateArchive(
983 976
984 RINOK(item.WriteHeader(outStream)) 977 RINOK(item.WriteHeader(outStream))
985 978
986 NEncoder::CCOMCoder *deflateEncoderSpec = new NEncoder::CCOMCoder; 979 CMyComPtr2_Create<ICompressCoder, NEncoder::CCOMCoder> deflateEncoder;
987 CMyComPtr<ICompressCoder> deflateEncoder = deflateEncoderSpec; 980
988 RINOK(props.SetCoderProps(deflateEncoderSpec, NULL)) 981 RINOK(props.SetCoderProps(deflateEncoder.ClsPtr(), NULL))
989 RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)) 982 RINOK(deflateEncoder.Interface()->Code(crcStream, outStream, NULL, NULL, lps))
990 983
991 item.Crc = inStreamSpec->GetCRC(); 984 item.Crc = crcStream->GetCRC();
992 unpackSizeReal = inStreamSpec->GetSize(); 985 unpackSizeReal = crcStream->GetSize();
993 item.Size32 = (UInt32)unpackSizeReal; 986 item.Size32 = (UInt32)unpackSizeReal;
994 RINOK(item.WriteFooter(outStream)) 987 RINOK(item.WriteFooter(outStream))
995 } 988 }
@@ -1124,8 +1117,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1124 if (!_stream) 1117 if (!_stream)
1125 return E_NOTIMPL; 1118 return E_NOTIMPL;
1126 1119
1127 CLocalProgress *lps = new CLocalProgress; 1120 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1128 CMyComPtr<ICompressProgressInfo> progress = lps;
1129 lps->Init(updateCallback, true); 1121 lps->Init(updateCallback, true);
1130 1122
1131 Z7_DECL_CMyComPtr_QI_FROM( 1123 Z7_DECL_CMyComPtr_QI_FROM(
@@ -1156,7 +1148,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1156 NULL); // unpacksize 1148 NULL); // unpacksize
1157 */ 1149 */
1158 1150
1159 return NCompress::CopyStream(_stream, outStream, progress); 1151 return NCompress::CopyStream(_stream, outStream, lps);
1160 1152
1161 COM_TRY_END 1153 COM_TRY_END
1162} 1154}
diff --git a/CPP/7zip/Archive/HandlerCont.cpp b/CPP/7zip/Archive/HandlerCont.cpp
index b4524a4..6a0eee2 100644
--- a/CPP/7zip/Archive/HandlerCont.cpp
+++ b/CPP/7zip/Archive/HandlerCont.cpp
@@ -37,26 +37,24 @@ Z7_COM7F_IMF(CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems,
37 GetItem_ExtractInfo(allFilesMode ? i : indices[i], pos, size); 37 GetItem_ExtractInfo(allFilesMode ? i : indices[i], pos, size);
38 totalSize += size; 38 totalSize += size;
39 } 39 }
40 extractCallback->SetTotal(totalSize); 40 RINOK(extractCallback->SetTotal(totalSize))
41 41
42 totalSize = 0; 42 totalSize = 0;
43 43
44 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 44 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
45 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
46
47 CLocalProgress *lps = new CLocalProgress;
48 CMyComPtr<ICompressProgressInfo> progress = lps;
49 lps->Init(extractCallback, false); 45 lps->Init(extractCallback, false);
50 46 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> streamSpec;
51 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
52 CMyComPtr<ISequentialInStream> inStream(streamSpec);
53 streamSpec->SetStream(_stream); 47 streamSpec->SetStream(_stream);
48 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
54 49
55 for (i = 0; i < numItems; i++) 50 for (i = 0;; i++)
56 { 51 {
57 lps->InSize = totalSize; 52 lps->InSize = totalSize;
58 lps->OutSize = totalSize; 53 lps->OutSize = totalSize;
59 RINOK(lps->SetCur()) 54 RINOK(lps->SetCur())
55 if (i >= numItems)
56 break;
57
60 CMyComPtr<ISequentialOutStream> outStream; 58 CMyComPtr<ISequentialOutStream> outStream;
61 const Int32 askMode = testMode ? 59 const Int32 askMode = testMode ?
62 NExtract::NAskMode::kTest : 60 NExtract::NAskMode::kTest :
@@ -78,13 +76,12 @@ Z7_COM7F_IMF(CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems,
78 RINOK(InStream_SeekSet(_stream, pos)) 76 RINOK(InStream_SeekSet(_stream, pos))
79 streamSpec->Init(size); 77 streamSpec->Init(size);
80 78
81 RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)) 79 RINOK(copyCoder.Interface()->Code(streamSpec, outStream, NULL, NULL, lps))
82 80
83 opRes = NExtract::NOperationResult::kDataError; 81 opRes = NExtract::NOperationResult::kDataError;
84 82 if (copyCoder->TotalSize == size)
85 if (copyCoderSpec->TotalSize == size)
86 opRes = NExtract::NOperationResult::kOK; 83 opRes = NExtract::NOperationResult::kOK;
87 else if (copyCoderSpec->TotalSize < size) 84 else if (copyCoder->TotalSize < size)
88 opRes = NExtract::NOperationResult::kUnexpectedEnd; 85 opRes = NExtract::NOperationResult::kUnexpectedEnd;
89 } 86 }
90 87
@@ -135,23 +132,28 @@ Z7_COM7F_IMF(CHandlerImg::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosit
135 return S_OK; 132 return S_OK;
136} 133}
137 134
138static const Byte k_GDP_Signature[] = { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T' }; 135static const Byte k_GDP_Signature[] =
136 { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 };
139// static const Byte k_Ext_Signature[] = { 0x53, 0xEF }; 137// static const Byte k_Ext_Signature[] = { 0x53, 0xEF };
140// static const unsigned k_Ext_Signature_offset = 0x438; 138// static const unsigned k_Ext_Signature_offset = 0x438;
141 139
142static const char *GetImgExt(ISequentialInStream *stream) 140static const char *GetImgExt(ISequentialInStream *stream)
143{ 141{
144 const size_t kHeaderSize = 1 << 11; 142 // const size_t kHeaderSize_for_Ext = (1 << 11); // for ext
143 const size_t kHeaderSize = 2 << 12; // for 4 KB sector GPT
145 Byte buf[kHeaderSize]; 144 Byte buf[kHeaderSize];
146 if (ReadStream_FAIL(stream, buf, kHeaderSize) == S_OK) 145 size_t processed = kHeaderSize;
146 if (ReadStream(stream, buf, &processed) == S_OK)
147 { 147 {
148 if (processed >= kHeaderSize)
148 if (buf[0x1FE] == 0x55 && buf[0x1FF] == 0xAA) 149 if (buf[0x1FE] == 0x55 && buf[0x1FF] == 0xAA)
149 { 150 {
150 if (memcmp(buf + 512, k_GDP_Signature, sizeof(k_GDP_Signature)) == 0) 151 for (unsigned k = (1 << 9); k <= (1u << 12); k <<= 3)
151 return "gpt"; 152 if (memcmp(buf + k, k_GDP_Signature, sizeof(k_GDP_Signature)) == 0)
153 return "gpt";
152 return "mbr"; 154 return "mbr";
153 } 155 }
154 if (NExt::IsArc_Ext(buf, kHeaderSize) == k_IsArc_Res_YES) 156 if (NExt::IsArc_Ext(buf, processed) == k_IsArc_Res_YES)
155 return "ext"; 157 return "ext";
156 } 158 }
157 return NULL; 159 return NULL;
@@ -280,13 +282,12 @@ Z7_COM7F_IMF(CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems,
280 progress = imgProgress; 282 progress = imgProgress;
281 } 283 }
282 284
283 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 285 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
284 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
285 286
286 hres = copyCoder->Code(inStream, outStream, NULL, &_size, progress); 287 hres = copyCoder.Interface()->Code(inStream, outStream, NULL, &_size, progress);
287 if (hres == S_OK) 288 if (hres == S_OK)
288 { 289 {
289 if (copyCoderSpec->TotalSize == _size) 290 if (copyCoder->TotalSize == _size)
290 opRes = NExtract::NOperationResult::kOK; 291 opRes = NExtract::NOperationResult::kOK;
291 292
292 if (_stream_unavailData) 293 if (_stream_unavailData)
@@ -295,7 +296,7 @@ Z7_COM7F_IMF(CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems,
295 opRes = NExtract::NOperationResult::kUnsupportedMethod; 296 opRes = NExtract::NOperationResult::kUnsupportedMethod;
296 else if (_stream_dataError) 297 else if (_stream_dataError)
297 opRes = NExtract::NOperationResult::kDataError; 298 opRes = NExtract::NOperationResult::kDataError;
298 else if (copyCoderSpec->TotalSize < _size) 299 else if (copyCoder->TotalSize < _size)
299 opRes = NExtract::NOperationResult::kUnexpectedEnd; 300 opRes = NExtract::NOperationResult::kUnexpectedEnd;
300 } 301 }
301 } 302 }
@@ -317,30 +318,4 @@ Z7_COM7F_IMF(CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems,
317 COM_TRY_END 318 COM_TRY_END
318} 319}
319 320
320
321HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
322{
323 areThereNonZeros = false;
324 numZeros = 0;
325 const size_t kBufSize = 1 << 11;
326 Byte buf[kBufSize];
327 for (;;)
328 {
329 UInt32 size = 0;
330 RINOK(stream->Read(buf, kBufSize, &size))
331 if (size == 0)
332 return S_OK;
333 for (UInt32 i = 0; i < size; i++)
334 if (buf[i] != 0)
335 {
336 areThereNonZeros = true;
337 numZeros += i;
338 return S_OK;
339 }
340 numZeros += size;
341 if (numZeros > maxSize)
342 return S_OK;
343 }
344}
345
346} 321}
diff --git a/CPP/7zip/Archive/HandlerCont.h b/CPP/7zip/Archive/HandlerCont.h
index 2dd0529..82e451a 100644
--- a/CPP/7zip/Archive/HandlerCont.h
+++ b/CPP/7zip/Archive/HandlerCont.h
@@ -68,9 +68,10 @@ class CHandlerImg:
68 public IInStream, 68 public IInStream,
69 public CMyUnknownImp 69 public CMyUnknownImp
70{ 70{
71 Z7_COM_UNKNOWN_IMP_3( 71 Z7_COM_UNKNOWN_IMP_4(
72 IInArchive, 72 IInArchive,
73 IInArchiveGetStream, 73 IInArchiveGetStream,
74 ISequentialInStream,
74 IInStream) 75 IInStream)
75 76
76 Z7_COM7F_IMP(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback)) 77 Z7_COM7F_IMP(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback))
@@ -80,18 +81,17 @@ class CHandlerImg:
80 // Z7_IFACEM_IInArchive_Img(Z7_COM7F_PUREO) 81 // Z7_IFACEM_IInArchive_Img(Z7_COM7F_PUREO)
81 82
82protected: 83protected:
84 bool _stream_unavailData;
85 bool _stream_unsupportedMethod;
86 bool _stream_dataError;
87 // bool _stream_UsePackSize;
88 // UInt64 _stream_PackSize;
83 UInt64 _virtPos; 89 UInt64 _virtPos;
84 UInt64 _posInArc; 90 UInt64 _posInArc;
85 UInt64 _size; 91 UInt64 _size;
86 CMyComPtr<IInStream> Stream; 92 CMyComPtr<IInStream> Stream;
87 const char *_imgExt; 93 const char *_imgExt;
88 94
89 bool _stream_unavailData;
90 bool _stream_unsupportedMethod;
91 bool _stream_dataError;
92 // bool _stream_UsePackSize;
93 // UInt64 _stream_PackSize;
94
95 void Reset_PosInArc() { _posInArc = (UInt64)0 - 1; } 95 void Reset_PosInArc() { _posInArc = (UInt64)0 - 1; }
96 void Reset_VirtPos() { _virtPos = (UInt64)0; } 96 void Reset_VirtPos() { _virtPos = (UInt64)0; }
97 97
diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp
index 696ecd7..4049fbc 100644
--- a/CPP/7zip/Archive/HfsHandler.cpp
+++ b/CPP/7zip/Archive/HfsHandler.cpp
@@ -1673,8 +1673,8 @@ Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
1673 return S_OK; 1673 return S_OK;
1674 } 1674 }
1675 #else 1675 #else
1676 UNUSED_VAR(index); 1676 UNUSED_VAR(index)
1677 UNUSED_VAR(propID); 1677 UNUSED_VAR(propID)
1678 #endif 1678 #endif
1679 return S_OK; 1679 return S_OK;
1680} 1680}
@@ -1786,14 +1786,14 @@ Z7_COM7F_IMF(CHandler::Close())
1786 1786
1787static const UInt32 kCompressionBlockSize = 1 << 16; 1787static const UInt32 kCompressionBlockSize = 1 << 16;
1788 1788
1789CDecoder::CDecoder() 1789CDecoder::CDecoder(bool IsAdlerOptional)
1790{ 1790{
1791 _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); 1791 /* Some new hfs files contain zlib resource fork without Adler checksum.
1792 _zlibDecoder = _zlibDecoderSpec; 1792 We do not know how we must detect case where there is Adler
1793 1793 checksum or there is no Adler checksum.
1794 _lzfseDecoderSpec = new NCompress::NLzfse::CDecoder(); 1794 */
1795 _lzfseDecoder = _lzfseDecoderSpec; 1795 _zlibDecoder->IsAdlerOptional = IsAdlerOptional;
1796 _lzfseDecoderSpec->LzvnMode = true; 1796 _lzfseDecoder->LzvnMode = true;
1797} 1797}
1798 1798
1799HRESULT CDecoder::ExtractResourceFork_ZLIB( 1799HRESULT CDecoder::ExtractResourceFork_ZLIB(
@@ -1862,8 +1862,7 @@ HRESULT CDecoder::ExtractResourceFork_ZLIB(
1862 if (prev != dataSize2) 1862 if (prev != dataSize2)
1863 return S_FALSE; 1863 return S_FALSE;
1864 1864
1865 CBufInStream *bufInStreamSpec = new CBufInStream; 1865 CMyComPtr2_Create<ISequentialInStream, CBufInStream> bufInStream;
1866 CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec;
1867 1866
1868 // bool padError = false; 1867 // bool padError = false;
1869 UInt64 outPos = 0; 1868 UInt64 outPos = 0;
@@ -1899,11 +1898,11 @@ HRESULT CDecoder::ExtractResourceFork_ZLIB(
1899 else 1898 else
1900 { 1899 {
1901 const UInt64 blockSize64 = blockSize; 1900 const UInt64 blockSize64 = blockSize;
1902 bufInStreamSpec->Init(buf, size); 1901 bufInStream->Init(buf, size);
1903 RINOK(_zlibDecoder->Code(bufInStream, outStream, NULL, &blockSize64, NULL)) 1902 RINOK(_zlibDecoder.Interface()->Code(bufInStream, outStream, NULL, &blockSize64, NULL))
1904 if (_zlibDecoderSpec->GetOutputProcessedSize() != blockSize) 1903 if (_zlibDecoder->GetOutputProcessedSize() != blockSize)
1905 return S_FALSE; 1904 return S_FALSE;
1906 const UInt64 inSize = _zlibDecoderSpec->GetInputProcessedSize(); 1905 const UInt64 inSize = _zlibDecoder->GetInputProcessedSize();
1907 if (inSize != size) 1906 if (inSize != size)
1908 { 1907 {
1909 if (inSize > size) 1908 if (inSize > size)
@@ -2005,8 +2004,7 @@ HRESULT CDecoder::ExtractResourceFork_LZFSE(
2005 const size_t kBufSize = kCompressionBlockSize; 2004 const size_t kBufSize = kCompressionBlockSize;
2006 _buf.Alloc(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header 2005 _buf.Alloc(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header
2007 2006
2008 CBufInStream *bufInStreamSpec = new CBufInStream; 2007 CMyComPtr2_Create<ISequentialInStream, CBufInStream> bufInStream;
2009 CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec;
2010 2008
2011 UInt64 outPos = 0; 2009 UInt64 outPos = 0;
2012 2010
@@ -2042,8 +2040,8 @@ HRESULT CDecoder::ExtractResourceFork_LZFSE(
2042 { 2040 {
2043 const UInt64 blockSize64 = blockSize; 2041 const UInt64 blockSize64 = blockSize;
2044 const UInt64 packSize64 = size; 2042 const UInt64 packSize64 = size;
2045 bufInStreamSpec->Init(buf, size); 2043 bufInStream->Init(buf, size);
2046 RINOK(_lzfseDecoder->Code(bufInStream, outStream, &packSize64, &blockSize64, NULL)) 2044 RINOK(_lzfseDecoder.Interface()->Code(bufInStream, outStream, &packSize64, &blockSize64, NULL))
2047 // in/out sizes were checked in Code() 2045 // in/out sizes were checked in Code()
2048 } 2046 }
2049 2047
@@ -2100,8 +2098,8 @@ HRESULT CDecoder::ExtractResourceFork_ZBM(
2100 const size_t kBufSize = kCompressionBlockSize; 2098 const size_t kBufSize = kCompressionBlockSize;
2101 _buf.Alloc(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header 2099 _buf.Alloc(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header
2102 2100
2103 CBufInStream *bufInStreamSpec = new CBufInStream; 2101 CBufInStream *bufInStream = new CBufInStream;
2104 CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec; 2102 CMyComPtr<ISequentialInStream> bufInStream = bufInStream;
2105 2103
2106 UInt64 outPos = 0; 2104 UInt64 outPos = 0;
2107 2105
@@ -2222,7 +2220,7 @@ HRESULT CDecoder::ExtractResourceFork_ZBM(
2222 2220
2223 // const UInt64 blockSize64 = blockSize; 2221 // const UInt64 blockSize64 = blockSize;
2224 // const UInt64 packSize64 = size; 2222 // const UInt64 packSize64 = size;
2225 // bufInStreamSpec->Init(buf, size); 2223 // bufInStream->Init(buf, size);
2226 // RINOK(_zbmDecoderSpec->Code(bufInStream, outStream, &packSize64, &blockSize64, NULL)); 2224 // RINOK(_zbmDecoderSpec->Code(bufInStream, outStream, &packSize64, &blockSize64, NULL));
2227 // in/out sizes were checked in Code() 2225 // in/out sizes were checked in Code()
2228 } 2226 }
@@ -2263,24 +2261,23 @@ HRESULT CDecoder::Extract(
2263 if (compressHeader.Method == kMethod_ZLIB_ATTR || 2261 if (compressHeader.Method == kMethod_ZLIB_ATTR ||
2264 compressHeader.Method == kMethod_LZVN_ATTR) 2262 compressHeader.Method == kMethod_LZVN_ATTR)
2265 { 2263 {
2266 CBufInStream *bufInStreamSpec = new CBufInStream; 2264 CMyComPtr2_Create<ISequentialInStream, CBufInStream> bufInStream;
2267 CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec;
2268 const size_t packSize = data->Size() - compressHeader.DataPos; 2265 const size_t packSize = data->Size() - compressHeader.DataPos;
2269 bufInStreamSpec->Init(*data + compressHeader.DataPos, packSize); 2266 bufInStream->Init(*data + compressHeader.DataPos, packSize);
2270 2267
2271 if (compressHeader.Method == kMethod_ZLIB_ATTR) 2268 if (compressHeader.Method == kMethod_ZLIB_ATTR)
2272 { 2269 {
2273 const HRESULT hres = _zlibDecoder->Code(bufInStream, realOutStream, 2270 const HRESULT hres = _zlibDecoder.Interface()->Code(bufInStream, realOutStream,
2274 NULL, &compressHeader.UnpackSize, NULL); 2271 NULL, &compressHeader.UnpackSize, NULL);
2275 if (hres == S_OK) 2272 if (hres == S_OK)
2276 if (_zlibDecoderSpec->GetOutputProcessedSize() == compressHeader.UnpackSize 2273 if (_zlibDecoder->GetOutputProcessedSize() == compressHeader.UnpackSize
2277 && _zlibDecoderSpec->GetInputProcessedSize() == packSize) 2274 && _zlibDecoder->GetInputProcessedSize() == packSize)
2278 opRes = NExtract::NOperationResult::kOK; 2275 opRes = NExtract::NOperationResult::kOK;
2279 return hres; 2276 return hres;
2280 } 2277 }
2281 { 2278 {
2282 const UInt64 packSize64 = packSize; 2279 const UInt64 packSize64 = packSize;
2283 const HRESULT hres = _lzfseDecoder->Code(bufInStream, realOutStream, 2280 const HRESULT hres = _lzfseDecoder.Interface()->Code(bufInStream, realOutStream,
2284 &packSize64, &compressHeader.UnpackSize, NULL); 2281 &packSize64, &compressHeader.UnpackSize, NULL);
2285 if (hres == S_OK) 2282 if (hres == S_OK)
2286 { 2283 {
@@ -2298,6 +2295,8 @@ HRESULT CDecoder::Extract(
2298 inStreamFork, realOutStream, 2295 inStreamFork, realOutStream,
2299 forkSize, compressHeader.UnpackSize, 2296 forkSize, compressHeader.UnpackSize,
2300 progressStart, extractCallback); 2297 progressStart, extractCallback);
2298 // for debug:
2299 // hres = NCompress::CopyStream(inStreamFork, realOutStream, NULL);
2301 } 2300 }
2302 else if (compressHeader.Method == NHfs::kMethod_LZVN_RSRC) 2301 else if (compressHeader.Method == NHfs::kMethod_LZVN_RSRC)
2303 { 2302 {
@@ -2350,18 +2349,21 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2350 const size_t kBufSize = kCompressionBlockSize; 2349 const size_t kBufSize = kCompressionBlockSize;
2351 CByteBuffer buf(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header 2350 CByteBuffer buf(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header
2352 2351
2353 CDecoder decoder; 2352 // there are hfs without adler in zlib.
2353 CDecoder decoder(true); // IsAdlerOptional
2354 2354
2355 for (i = 0;; i++, currentTotalSize += currentItemSize) 2355 for (i = 0;; i++, currentTotalSize += currentItemSize)
2356 { 2356 {
2357 RINOK(extractCallback->SetCompleted(&currentTotalSize)) 2357 RINOK(extractCallback->SetCompleted(&currentTotalSize))
2358 if (i == numItems) 2358 if (i >= numItems)
2359 break; 2359 break;
2360 const UInt32 index = allFilesMode ? i : indices[i]; 2360 const UInt32 index = allFilesMode ? i : indices[i];
2361 const CRef &ref = Refs[index]; 2361 const CRef &ref = Refs[index];
2362 const CItem &item = Items[ref.ItemIndex]; 2362 const CItem &item = Items[ref.ItemIndex];
2363 currentItemSize = Get_UnpackSize_of_Ref(ref); 2363 currentItemSize = Get_UnpackSize_of_Ref(ref);
2364 2364
2365 int opRes;
2366 {
2365 CMyComPtr<ISequentialOutStream> realOutStream; 2367 CMyComPtr<ISequentialOutStream> realOutStream;
2366 const Int32 askMode = testMode ? 2368 const Int32 askMode = testMode ?
2367 NExtract::NAskMode::kTest : 2369 NExtract::NAskMode::kTest :
@@ -2380,7 +2382,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2380 RINOK(extractCallback->PrepareOperation(askMode)) 2382 RINOK(extractCallback->PrepareOperation(askMode))
2381 2383
2382 UInt64 pos = 0; 2384 UInt64 pos = 0;
2383 int opRes = NExtract::NOperationResult::kDataError; 2385 opRes = NExtract::NOperationResult::kDataError;
2384 const CFork *fork = NULL; 2386 const CFork *fork = NULL;
2385 2387
2386 if (ref.AttrIndex >= 0) 2388 if (ref.AttrIndex >= 0)
@@ -2488,7 +2490,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2488 opRes = NExtract::NOperationResult::kDataError; 2490 opRes = NExtract::NOperationResult::kDataError;
2489 } 2491 }
2490 } 2492 }
2491 realOutStream.Release(); 2493 }
2492 RINOK(extractCallback->SetOperationResult(opRes)) 2494 RINOK(extractCallback->SetOperationResult(opRes))
2493 } 2495 }
2494 return S_OK; 2496 return S_OK;
@@ -2508,8 +2510,8 @@ HRESULT CHandler::GetForkStream(const CFork &fork, ISequentialInStream **stream)
2508 if (!fork.IsOk(Header.BlockSizeLog)) 2510 if (!fork.IsOk(Header.BlockSizeLog))
2509 return S_FALSE; 2511 return S_FALSE;
2510 2512
2511 CExtentsStream *extentStreamSpec = new CExtentsStream(); 2513 CMyComPtr2<ISequentialInStream, CExtentsStream> extentStream;
2512 CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec; 2514 extentStream.Create_if_Empty();
2513 2515
2514 UInt64 rem = fork.Size; 2516 UInt64 rem = fork.Size;
2515 UInt64 virt = 0; 2517 UInt64 virt = 0;
@@ -2531,7 +2533,7 @@ HRESULT CHandler::GetForkStream(const CFork &fork, ISequentialInStream **stream)
2531 se.Virt = virt; 2533 se.Virt = virt;
2532 virt += cur; 2534 virt += cur;
2533 rem -= cur; 2535 rem -= cur;
2534 extentStreamSpec->Extents.Add(se); 2536 extentStream->Extents.Add(se);
2535 } 2537 }
2536 2538
2537 if (rem != 0) 2539 if (rem != 0)
@@ -2540,9 +2542,9 @@ HRESULT CHandler::GetForkStream(const CFork &fork, ISequentialInStream **stream)
2540 CSeekExtent se; 2542 CSeekExtent se;
2541 se.Phy = 0; 2543 se.Phy = 0;
2542 se.Virt = virt; 2544 se.Virt = virt;
2543 extentStreamSpec->Extents.Add(se); 2545 extentStream->Extents.Add(se);
2544 extentStreamSpec->Stream = _stream; 2546 extentStream->Stream = _stream;
2545 extentStreamSpec->Init(); 2547 extentStream->Init();
2546 *stream = extentStream.Detach(); 2548 *stream = extentStream.Detach();
2547 return S_OK; 2549 return S_OK;
2548} 2550}
diff --git a/CPP/7zip/Archive/HfsHandler.h b/CPP/7zip/Archive/HfsHandler.h
index 0006e12..6d869c2 100644
--- a/CPP/7zip/Archive/HfsHandler.h
+++ b/CPP/7zip/Archive/HfsHandler.h
@@ -23,7 +23,7 @@ struct CCompressHeader
23 bool IsResource; 23 bool IsResource;
24 24
25 bool IsMethod_Compressed_Inline() const { return DataPos == k_decmpfs_HeaderSize; } 25 bool IsMethod_Compressed_Inline() const { return DataPos == k_decmpfs_HeaderSize; }
26 bool IsMethod_Uncompressed_Inline() const { return DataPos == k_decmpfs_HeaderSize + 1; } 26 bool IsMethod_Uncompressed_Inline() const { return DataPos == k_decmpfs_HeaderSize + 1; }
27 bool IsMethod_Resource() const { return IsResource; } 27 bool IsMethod_Resource() const { return IsResource; }
28 28
29 void Parse(const Byte *p, size_t size); 29 void Parse(const Byte *p, size_t size);
@@ -48,11 +48,8 @@ void MethodsMaskToProp(UInt32 methodsMask, NWindows::NCOM::CPropVariant &prop);
48 48
49class CDecoder 49class CDecoder
50{ 50{
51 NCompress::NZlib::CDecoder *_zlibDecoderSpec; 51 CMyComPtr2_Create<ICompressCoder, NCompress::NZlib::CDecoder> _zlibDecoder;
52 CMyComPtr<ICompressCoder> _zlibDecoder; 52 CMyComPtr2_Create<ICompressCoder, NCompress::NLzfse::CDecoder> _lzfseDecoder;
53
54 NCompress::NLzfse::CDecoder *_lzfseDecoderSpec;
55 CMyComPtr<ICompressCoder> _lzfseDecoder;
56 53
57 CByteBuffer _tableBuf; 54 CByteBuffer _tableBuf;
58 CByteBuffer _buf; 55 CByteBuffer _buf;
@@ -82,7 +79,7 @@ public:
82 UInt64 progressStart, IArchiveExtractCallback *extractCallback, 79 UInt64 progressStart, IArchiveExtractCallback *extractCallback,
83 int &opRes); 80 int &opRes);
84 81
85 CDecoder(); 82 CDecoder(bool IsAdlerOptional);
86}; 83};
87 84
88}} 85}}
diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h
index 3e68ac3..a817015 100644
--- a/CPP/7zip/Archive/IArchive.h
+++ b/CPP/7zip/Archive/IArchive.h
@@ -565,6 +565,56 @@ Z7_IFACE_CONSTR_ARCHIVE(IArchiveKeepModeForNextOpen, 0x04)
565Z7_IFACE_CONSTR_ARCHIVE(IArchiveAllowTail, 0x05) 565Z7_IFACE_CONSTR_ARCHIVE(IArchiveAllowTail, 0x05)
566 566
567 567
568namespace NRequestMemoryUseFlags
569{
570 const UInt32 k_AllowedSize_WasForced = 1 << 0; // (*allowedSize) was forced by -mmemx or -smemx
571 const UInt32 k_DefaultLimit_Exceeded = 1 << 1; // default limit of archive format was exceeded
572 const UInt32 k_MLimit_Exceeded = 1 << 2; // -mmemx value was exceeded
573 const UInt32 k_SLimit_Exceeded = 1 << 3; // -smemx value was exceeded
574
575 const UInt32 k_NoErrorMessage = 1 << 10; // do not show error message, and show only request
576 const UInt32 k_IsReport = 1 << 11; // only report is required, without user request
577
578 const UInt32 k_SkipArc_IsExpected = 1 << 12; // NRequestMemoryAnswerFlags::k_SkipArc flag answer is expected
579 const UInt32 k_Report_SkipArc = 1 << 13; // report about SkipArc operation
580
581 // const UInt32 k_SkipBigFile_IsExpected = 1 << 14; // NRequestMemoryAnswerFlags::k_SkipBigFiles flag answer is expected (unused)
582 // const UInt32 k_Report_SkipBigFile = 1 << 15; // report about SkipFile operation (unused)
583
584 // const UInt32 k_SkipBigFiles_IsExpected = 1 << 16; // NRequestMemoryAnswerFlags::k_SkipBigFiles flag answer is expected (unused)
585 // const UInt32 k_Report_SkipBigFiles = 1 << 17; // report that all big files will be skipped (unused)
586}
587
588namespace NRequestMemoryAnswerFlags
589{
590 const UInt32 k_Allow = 1 << 0; // allow further archive extraction
591 const UInt32 k_Stop = 1 << 1; // for exit (and return_code == E_ABORT is used)
592 const UInt32 k_SkipArc = 1 << 2; // skip current archive extraction
593 // const UInt32 k_SkipBigFile = 1 << 4; // skip extracting of files that exceed limit (unused)
594 // const UInt32 k_SkipBigFiles = 1 << 5; // skip extracting of files that exceed limit (unused)
595 const UInt32 k_Limit_Exceeded = 1 << 10; // limit was exceeded
596}
597
598/*
599 *allowedSize is in/out:
600 in : default allowed memory usage size or forced size, if it was changed by switch -mmemx.
601 out : value specified by user or unchanged value.
602
603 *answerFlags is in/out:
604 *answerFlags must be set by caller before calling for default action,
605
606 indexType : must be set with NEventIndexType::* constant
607 (indexType == kNoIndex), if request for whole archive.
608 index : must be set for some (indexType) types (if
609 fileIndex , if (indexType == NEventIndexType::kInArcIndex)
610 0, if if (indexType == kNoIndex)
611 path : NULL can be used for any indexType.
612*/
613#define Z7_IFACEM_IArchiveRequestMemoryUseCallback(x) \
614 x(RequestMemoryUse(UInt32 flags, UInt32 indexType, UInt32 index, const wchar_t *path, \
615 UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags))
616Z7_IFACE_CONSTR_ARCHIVE(IArchiveRequestMemoryUseCallback, 0x09)
617
568 618
569struct CStatProp 619struct CStatProp
570{ 620{
diff --git a/CPP/7zip/Archive/Icons/zst.ico b/CPP/7zip/Archive/Icons/zst.ico
new file mode 100644
index 0000000..e645e02
--- /dev/null
+++ b/CPP/7zip/Archive/Icons/zst.ico
Binary files differ
diff --git a/CPP/7zip/Archive/IhexHandler.cpp b/CPP/7zip/Archive/IhexHandler.cpp
index badb559..98ca0a3 100644
--- a/CPP/7zip/Archive/IhexHandler.cpp
+++ b/CPP/7zip/Archive/IhexHandler.cpp
@@ -7,14 +7,14 @@
7#include "../../Common/ComTry.h" 7#include "../../Common/ComTry.h"
8#include "../../Common/DynamicBuffer.h" 8#include "../../Common/DynamicBuffer.h"
9#include "../../Common/IntToString.h" 9#include "../../Common/IntToString.h"
10#include "../../Common/MyVector.h" 10#include "../../Common/StringToInt.h"
11 11
12#include "../../Windows/PropVariant.h" 12#include "../../Windows/PropVariant.h"
13 13
14#include "../Common/InBuffer.h"
14#include "../Common/ProgressUtils.h" 15#include "../Common/ProgressUtils.h"
15#include "../Common/RegisterArc.h" 16#include "../Common/RegisterArc.h"
16#include "../Common/StreamUtils.h" 17#include "../Common/StreamUtils.h"
17#include "../Common/InBuffer.h"
18 18
19namespace NArchive { 19namespace NArchive {
20namespace NIhex { 20namespace NIhex {
@@ -68,6 +68,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
68 if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; 68 if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
69 if (_dataError) v |= kpv_ErrorFlags_DataError; 69 if (_dataError) v |= kpv_ErrorFlags_DataError;
70 prop = v; 70 prop = v;
71 break;
71 } 72 }
72 } 73 }
73 prop.Detach(value); 74 prop.Detach(value);
@@ -99,19 +100,12 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
99 COM_TRY_END 100 COM_TRY_END
100} 101}
101 102
102static inline int HexToByte(unsigned c)
103{
104 if (c >= '0' && c <= '9') return (int)(c - '0');
105 if (c >= 'A' && c <= 'F') return (int)(c - 'A' + 10);
106 if (c >= 'a' && c <= 'f') return (int)(c - 'a' + 10);
107 return -1;
108}
109 103
110static int Parse(const Byte *p) 104static int Parse(const Byte *p)
111{ 105{
112 const int c1 = HexToByte(p[0]); if (c1 < 0) return -1; 106 unsigned v0 = p[0]; Z7_PARSE_HEX_DIGIT(v0, return -1;)
113 const int c2 = HexToByte(p[1]); if (c2 < 0) return -1; 107 unsigned v1 = p[1]; Z7_PARSE_HEX_DIGIT(v1, return -1;)
114 return (c1 << 4) | c2; 108 return (int)((v0 << 4) | v1);
115} 109}
116 110
117#define kType_Data 0 111#define kType_Data 0
@@ -123,7 +117,11 @@ static int Parse(const Byte *p)
123 117
124#define kType_MAX 5 118#define kType_MAX 5
125 119
126#define IS_LINE_DELIMITER(c) ((c) == 0 || (c) == 10 || (c) == 13) 120// we don't want to read files with big number of spaces between records
121// it's our limitation (out of specification):
122static const unsigned k_NumSpaces_LIMIT = 16 + 1;
123
124#define IS_LINE_DELIMITER(c) (/* (c) == 0 || */ (c) == 10 || (c) == 13)
127 125
128API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size) 126API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size)
129{ 127{
@@ -141,11 +139,11 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size)
141 if (size < 4 * 2) 139 if (size < 4 * 2)
142 return k_IsArc_Res_NEED_MORE; 140 return k_IsArc_Res_NEED_MORE;
143 141
144 int num = Parse(p); 142 const int num = Parse(p);
145 if (num < 0) 143 if (num < 0)
146 return k_IsArc_Res_NO; 144 return k_IsArc_Res_NO;
147 145
148 int type = Parse(p + 6); 146 const int type = Parse(p + 6);
149 if (type < 0 || type > kType_MAX) 147 if (type < 0 || type > kType_MAX)
150 return k_IsArc_Res_NO; 148 return k_IsArc_Res_NO;
151 149
@@ -162,7 +160,7 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size)
162 sum += (unsigned)v; 160 sum += (unsigned)v;
163 } 161 }
164 162
165 if ((sum & 0xFF) != 0) 163 if (sum & 0xFF)
166 return k_IsArc_Res_NO; 164 return k_IsArc_Res_NO;
167 165
168 if (type == kType_Data) 166 if (type == kType_Data)
@@ -199,17 +197,17 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size)
199 p += numChars; 197 p += numChars;
200 size -= numChars; 198 size -= numChars;
201 199
200 unsigned numSpaces = k_NumSpaces_LIMIT;
202 for (;;) 201 for (;;)
203 { 202 {
204 if (size == 0) 203 if (size == 0)
205 return k_IsArc_Res_NEED_MORE; 204 return k_IsArc_Res_NEED_MORE;
206 const Byte b = *p++; 205 const Byte b = *p++;
207 size--; 206 size--;
208 if (IS_LINE_DELIMITER(b))
209 continue;
210 if (b == ':') 207 if (b == ':')
211 break; 208 break;
212 return k_IsArc_Res_NO; 209 if (--numSpaces == 0 || !IS_LINE_DELIMITER(b))
210 return k_IsArc_Res_NO;
213 } 211 }
214 } 212 }
215 213
@@ -217,7 +215,7 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size)
217} 215}
218} 216}
219 217
220Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)) 218Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback))
221{ 219{
222 COM_TRY_BEGIN 220 COM_TRY_BEGIN
223 { 221 {
@@ -229,7 +227,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
229 { 227 {
230 size_t size = kStartSize; 228 size_t size = kStartSize;
231 RINOK(ReadStream(stream, temp, &size)) 229 RINOK(ReadStream(stream, temp, &size))
232 UInt32 isArcRes = IsArc_Ihex(temp, size); 230 const UInt32 isArcRes = IsArc_Ihex(temp, size);
233 if (isArcRes == k_IsArc_Res_NO) 231 if (isArcRes == k_IsArc_Res_NO)
234 return S_FALSE; 232 return S_FALSE;
235 if (isArcRes == k_IsArc_Res_NEED_MORE && size != kStartSize) 233 if (isArcRes == k_IsArc_Res_NEED_MORE && size != kStartSize)
@@ -243,7 +241,6 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
243 return E_OUTOFMEMORY; 241 return E_OUTOFMEMORY;
244 s.SetStream(stream); 242 s.SetStream(stream);
245 s.Init(); 243 s.Init();
246
247 { 244 {
248 Byte b; 245 Byte b;
249 if (!s.ReadByte(b)) 246 if (!s.ReadByte(b))
@@ -259,6 +256,8 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
259 } 256 }
260 257
261 UInt32 globalOffset = 0; 258 UInt32 globalOffset = 0;
259 const UInt32 k_progressStep = 1 << 24;
260 UInt64 progressNext = k_progressStep;
262 261
263 for (;;) 262 for (;;)
264 { 263 {
@@ -273,16 +272,14 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
273 _dataError = true; 272 _dataError = true;
274 return S_FALSE; 273 return S_FALSE;
275 } 274 }
276
277 { 275 {
278 size_t numPairs = ((unsigned)num + 4); 276 const size_t numPairs = (unsigned)num + 4;
279 size_t numBytes = numPairs * 2; 277 const size_t numBytes = numPairs * 2;
280 if (s.ReadBytes(temp, numBytes) != numBytes) 278 if (s.ReadBytes(temp, numBytes) != numBytes)
281 { 279 {
282 _needMoreInput = true; 280 _needMoreInput = true;
283 return S_FALSE; 281 return S_FALSE;
284 } 282 }
285
286 unsigned sum = (unsigned)num; 283 unsigned sum = (unsigned)num;
287 for (size_t i = 0; i < numPairs; i++) 284 for (size_t i = 0; i < numPairs; i++)
288 { 285 {
@@ -295,21 +292,21 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
295 temp[i] = (Byte)a; 292 temp[i] = (Byte)a;
296 sum += (unsigned)a; 293 sum += (unsigned)a;
297 } 294 }
298 if ((sum & 0xFF) != 0) 295 if (sum & 0xFF)
299 { 296 {
300 _dataError = true; 297 _dataError = true;
301 return S_FALSE; 298 return S_FALSE;
302 } 299 }
303 } 300 }
304 301
305 unsigned type = temp[2]; 302 const unsigned type = temp[2];
306 if (type > kType_MAX) 303 if (type > kType_MAX)
307 { 304 {
308 _dataError = true; 305 _dataError = true;
309 return S_FALSE; 306 return S_FALSE;
310 } 307 }
311 308
312 UInt32 a = GetBe16(temp); 309 const UInt32 a = GetBe16(temp);
313 310
314 if (type == kType_Data) 311 if (type == kType_Data)
315 { 312 {
@@ -322,7 +319,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
322 } 319 }
323 // if (num != 0) 320 // if (num != 0)
324 { 321 {
325 UInt32 offs = globalOffset + a; 322 const UInt32 offs = globalOffset + a;
326 CBlock *block = NULL; 323 CBlock *block = NULL;
327 if (!_blocks.IsEmpty()) 324 if (!_blocks.IsEmpty())
328 { 325 {
@@ -338,10 +335,21 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
338 block->Data.AddData(temp + 3, (unsigned)num); 335 block->Data.AddData(temp + 3, (unsigned)num);
339 } 336 }
340 } 337 }
341 else if (type == kType_Eof) 338 else
342 { 339 {
343 _phySize = s.GetProcessedSize(); 340 if (a != 0) // from description: the address field is typically 0.
344 { 341 {
342 _dataError = true;
343 return S_FALSE;
344 }
345 if (type == kType_Eof)
346 {
347 if (num != 0)
348 {
349 _dataError = true;
350 return S_FALSE;
351 }
352 _phySize = s.GetProcessedSize();
345 Byte b; 353 Byte b;
346 if (s.ReadByte(b)) 354 if (s.ReadByte(b))
347 { 355 {
@@ -357,16 +365,9 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
357 } 365 }
358 } 366 }
359 } 367 }
368 return S_OK;
360 } 369 }
361 return S_OK; 370
362 }
363 else
364 {
365 if (a != 0)
366 {
367 _dataError = true;
368 return S_FALSE;
369 }
370 if (type == kType_Seg || type == kType_High) 371 if (type == kType_Seg || type == kType_High)
371 { 372 {
372 if (num != 2) 373 if (num != 2)
@@ -374,8 +375,8 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
374 _dataError = true; 375 _dataError = true;
375 return S_FALSE; 376 return S_FALSE;
376 } 377 }
377 UInt32 d = GetBe16(temp + 3); 378 // here we use optimization trick for num shift calculation: (type == kType_Seg ? 4 : 16)
378 globalOffset = d << (type == kType_Seg ? 4 : 16); 379 globalOffset = (UInt32)GetBe16(temp + 3) << (1u << type);
379 } 380 }
380 else 381 else
381 { 382 {
@@ -387,6 +388,18 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
387 } 388 }
388 } 389 }
389 390
391 if (openCallback)
392 {
393 const UInt64 processed = s.GetProcessedSize();
394 if (processed >= progressNext)
395 {
396 progressNext = processed + k_progressStep;
397 const UInt64 numFiles = _blocks.Size();
398 RINOK(openCallback->SetCompleted(&numFiles, &processed))
399 }
400 }
401
402 unsigned numSpaces = k_NumSpaces_LIMIT;
390 for (;;) 403 for (;;)
391 { 404 {
392 Byte b; 405 Byte b;
@@ -395,12 +408,13 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
395 _needMoreInput = true; 408 _needMoreInput = true;
396 return S_FALSE; 409 return S_FALSE;
397 } 410 }
398 if (IS_LINE_DELIMITER(b))
399 continue;
400 if (b == ':') 411 if (b == ':')
401 break; 412 break;
402 _dataError = true; 413 if (--numSpaces == 0 || !IS_LINE_DELIMITER(b))
403 return S_FALSE; 414 {
415 _dataError = true;
416 return S_FALSE;
417 }
404 } 418 }
405 } 419 }
406 } 420 }
@@ -409,14 +423,13 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
409 COM_TRY_END 423 COM_TRY_END
410} 424}
411 425
426
412Z7_COM7F_IMF(CHandler::Close()) 427Z7_COM7F_IMF(CHandler::Close())
413{ 428{
414 _phySize = 0; 429 _phySize = 0;
415
416 _isArc = false; 430 _isArc = false;
417 _needMoreInput = false; 431 _needMoreInput = false;
418 _dataError = false; 432 _dataError = false;
419
420 _blocks.Clear(); 433 _blocks.Clear();
421 return S_OK; 434 return S_OK;
422} 435}
@@ -436,53 +449,40 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
436 UInt32 i; 449 UInt32 i;
437 for (i = 0; i < numItems; i++) 450 for (i = 0; i < numItems; i++)
438 totalSize += _blocks[allFilesMode ? i : indices[i]].Data.GetPos(); 451 totalSize += _blocks[allFilesMode ? i : indices[i]].Data.GetPos();
439 extractCallback->SetTotal(totalSize); 452 RINOK(extractCallback->SetTotal(totalSize))
440
441 UInt64 currentTotalSize = 0;
442 UInt64 currentItemSize;
443 453
444 CLocalProgress *lps = new CLocalProgress; 454 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
445 CMyComPtr<ICompressProgressInfo> progress = lps;
446 lps->Init(extractCallback, false); 455 lps->Init(extractCallback, false);
447 456
448 for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) 457 for (i = 0;; i++)
449 { 458 {
450 currentItemSize = 0; 459 lps->InSize = lps->OutSize;
451 lps->InSize = lps->OutSize = currentTotalSize;
452 RINOK(lps->SetCur()) 460 RINOK(lps->SetCur())
453 461 if (i >= numItems)
462 break;
454 const UInt32 index = allFilesMode ? i : indices[i]; 463 const UInt32 index = allFilesMode ? i : indices[i];
455 const CByteDynamicBuffer &data = _blocks[index].Data; 464 const CByteDynamicBuffer &data = _blocks[index].Data;
456 currentItemSize = data.GetPos(); 465 lps->OutSize += data.GetPos();
457
458 CMyComPtr<ISequentialOutStream> realOutStream;
459 const Int32 askMode = testMode ?
460 NExtract::NAskMode::kTest :
461 NExtract::NAskMode::kExtract;
462
463 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
464
465 if (!testMode && !realOutStream)
466 continue;
467
468 extractCallback->PrepareOperation(askMode);
469
470 if (realOutStream)
471 { 466 {
472 RINOK(WriteStream(realOutStream, (const Byte *)data, data.GetPos())) 467 CMyComPtr<ISequentialOutStream> realOutStream;
468 const Int32 askMode = testMode ?
469 NExtract::NAskMode::kTest :
470 NExtract::NAskMode::kExtract;
471 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
472 if (!testMode && !realOutStream)
473 continue;
474 RINOK(extractCallback->PrepareOperation(askMode))
475 if (realOutStream)
476 RINOK(WriteStream(realOutStream, (const Byte *)data, data.GetPos()))
473 } 477 }
474
475 realOutStream.Release();
476 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 478 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
477 } 479 }
478 480
479 lps->InSize = lps->OutSize = currentTotalSize; 481 return S_OK;
480 return lps->SetCur();
481
482 COM_TRY_END 482 COM_TRY_END
483} 483}
484 484
485// k_Signature: { ':', '1' } 485// k_Signature: { ':' }
486 486
487REGISTER_ARC_I_NO_SIG( 487REGISTER_ARC_I_NO_SIG(
488 "IHex", "ihex", NULL, 0xCD, 488 "IHex", "ihex", NULL, 0xCD,
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp
index 0c63c71..c085386 100644
--- a/CPP/7zip/Archive/Iso/IsoHandler.cpp
+++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp
@@ -85,13 +85,21 @@ static void AddString(AString &s, const char *name, const Byte *p, unsigned size
85 { 85 {
86 AString d; 86 AString d;
87 d.SetFrom((const char *)p, i); 87 d.SetFrom((const char *)p, i);
88 s += '\n';
89 s += name; 88 s += name;
90 s += ": "; 89 s += ": ";
91 s += d; 90 s += d;
91 s.Add_LF();
92 } 92 }
93} 93}
94 94
95static void AddProp_Size64(AString &s, const char *name, UInt64 size)
96{
97 s += name;
98 s += ": ";
99 s.Add_UInt64(size);
100 s.Add_LF();
101}
102
95#define ADD_STRING(n, v) AddString(s, n, vol. v, sizeof(vol. v)) 103#define ADD_STRING(n, v) AddString(s, n, vol. v, sizeof(vol. v))
96 104
97static void AddErrorMessage(AString &s, const char *message) 105static void AddErrorMessage(AString &s, const char *message)
@@ -122,6 +130,11 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
122 ADD_STRING("Copyright", CopyrightFileId); 130 ADD_STRING("Copyright", CopyrightFileId);
123 ADD_STRING("Abstract", AbstractFileId); 131 ADD_STRING("Abstract", AbstractFileId);
124 ADD_STRING("Bib", BibFileId); 132 ADD_STRING("Bib", BibFileId);
133 // ADD_STRING("EscapeSequence", EscapeSequence);
134 AddProp_Size64(s, "VolumeSpaceSize", vol.Get_VolumeSpaceSize_inBytes());
135 AddProp_Size64(s, "VolumeSetSize", vol.VolumeSetSize);
136 AddProp_Size64(s, "VolumeSequenceNumber", vol.VolumeSequenceNumber);
137
125 prop = s; 138 prop = s;
126 break; 139 break;
127 } 140 }
@@ -328,27 +341,26 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
328 else 341 else
329 totalSize += _archive.GetBootItemSize(index - _archive.Refs.Size()); 342 totalSize += _archive.GetBootItemSize(index - _archive.Refs.Size());
330 } 343 }
331 extractCallback->SetTotal(totalSize); 344 RINOK(extractCallback->SetTotal(totalSize))
332 345
333 UInt64 currentTotalSize = 0; 346 UInt64 currentTotalSize = 0;
334 UInt64 currentItemSize; 347 UInt64 currentItemSize;
335 348
336 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 349 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
337 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
338
339 CLocalProgress *lps = new CLocalProgress;
340 CMyComPtr<ICompressProgressInfo> progress = lps;
341 lps->Init(extractCallback, false); 350 lps->Init(extractCallback, false);
351 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
352 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
353 inStream->SetStream(_stream);
342 354
343 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 355 for (i = 0;; i++, currentTotalSize += currentItemSize)
344 CMyComPtr<ISequentialInStream> inStream(streamSpec);
345 streamSpec->SetStream(_stream);
346
347 for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
348 { 356 {
349 lps->InSize = lps->OutSize = currentTotalSize; 357 lps->InSize = lps->OutSize = currentTotalSize;
350 RINOK(lps->SetCur()) 358 RINOK(lps->SetCur())
359 if (i >= numItems)
360 break;
351 currentItemSize = 0; 361 currentItemSize = 0;
362 Int32 opRes = NExtract::NOperationResult::kOK;
363 {
352 CMyComPtr<ISequentialOutStream> realOutStream; 364 CMyComPtr<ISequentialOutStream> realOutStream;
353 const Int32 askMode = testMode ? 365 const Int32 askMode = testMode ?
354 NExtract::NAskMode::kTest : 366 NExtract::NAskMode::kTest :
@@ -385,7 +397,6 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
385 397
386 RINOK(extractCallback->PrepareOperation(askMode)) 398 RINOK(extractCallback->PrepareOperation(askMode))
387 399
388 bool isOK = true;
389 if (index < (UInt32)_archive.Refs.Size()) 400 if (index < (UInt32)_archive.Refs.Size())
390 { 401 {
391 const CRef &ref = _archive.Refs[index]; 402 const CRef &ref = _archive.Refs[index];
@@ -397,11 +408,11 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
397 continue; 408 continue;
398 lps->InSize = lps->OutSize = currentTotalSize + offset; 409 lps->InSize = lps->OutSize = currentTotalSize + offset;
399 RINOK(InStream_SeekSet(_stream, (UInt64)item2.ExtentLocation * kBlockSize)) 410 RINOK(InStream_SeekSet(_stream, (UInt64)item2.ExtentLocation * kBlockSize))
400 streamSpec->Init(item2.Size); 411 inStream->Init(item2.Size);
401 RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)) 412 RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
402 if (copyCoderSpec->TotalSize != item2.Size) 413 if (copyCoder->TotalSize != item2.Size)
403 { 414 {
404 isOK = false; 415 opRes = NExtract::NOperationResult::kDataError;
405 break; 416 break;
406 } 417 }
407 offset += item2.Size; 418 offset += item2.Size;
@@ -410,15 +421,14 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
410 else 421 else
411 { 422 {
412 RINOK(InStream_SeekSet(_stream, (UInt64)blockIndex * kBlockSize)) 423 RINOK(InStream_SeekSet(_stream, (UInt64)blockIndex * kBlockSize))
413 streamSpec->Init(currentItemSize); 424 inStream->Init(currentItemSize);
414 RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)) 425 RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
415 if (copyCoderSpec->TotalSize != currentItemSize) 426 if (copyCoder->TotalSize != currentItemSize)
416 isOK = false; 427 opRes = NExtract::NOperationResult::kDataError;
417 } 428 }
418 realOutStream.Release(); 429 // realOutStream.Release();
419 RINOK(extractCallback->SetOperationResult(isOK ? 430 }
420 NExtract::NOperationResult::kOK: 431 RINOK(extractCallback->SetOperationResult(opRes))
421 NExtract::NOperationResult::kDataError))
422 } 432 }
423 return S_OK; 433 return S_OK;
424 COM_TRY_END 434 COM_TRY_END
diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp
index 1d3a42f..0054abf 100644
--- a/CPP/7zip/Archive/Iso/IsoIn.cpp
+++ b/CPP/7zip/Archive/Iso/IsoIn.cpp
@@ -287,11 +287,17 @@ void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d)
287 ReadDateTime(d.MTime); 287 ReadDateTime(d.MTime);
288 ReadDateTime(d.ExpirationTime); 288 ReadDateTime(d.ExpirationTime);
289 ReadDateTime(d.EffectiveTime); 289 ReadDateTime(d.EffectiveTime);
290 d.FileStructureVersion = ReadByte(); // = 1 290 const Byte fileStructureVersion = ReadByte();
291 SkipZeros(1); 291 // d.FileStructureVersion = fileStructureVersion;
292 if (fileStructureVersion != 1 && // ECMA-119
293 fileStructureVersion != 2) // some ISO files have fileStructureVersion == 2.
294 {
295 // v24.05: we ignore that field, because we don't know what exact values are allowed there
296 // throw CHeaderErrorException();
297 }
298 SkipZeros(1); // (Reserved for future standardization)
292 ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse)); 299 ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse));
293 300 // Most ISO contain zeros in the following field (reserved for future standardization).
294 // Most ISO contains zeros in the following field (reserved for future standardization).
295 // But some ISO programs write some data to that area. 301 // But some ISO programs write some data to that area.
296 // So we disable check for zeros. 302 // So we disable check for zeros.
297 Skip(653); // SkipZeros(653); 303 Skip(653); // SkipZeros(653);
@@ -595,7 +601,16 @@ HRESULT CInArchive::Open2()
595 const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex]; 601 const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex];
596 if (vd.LogicalBlockSize != kBlockSize) 602 if (vd.LogicalBlockSize != kBlockSize)
597 return S_FALSE; 603 return S_FALSE;
598 604
605 {
606 FOR_VECTOR (i, VolDescs)
607 {
608 const CVolumeDescriptor &vd2 = VolDescs[i];
609 UpdatePhySize(0, vd2.Get_VolumeSpaceSize_inBytes());
610 }
611 }
612
613
599 IsArc = true; 614 IsArc = true;
600 615
601 (CDirRecord &)_rootDir = vd.RootDirRecord; 616 (CDirRecord &)_rootDir = vd.RootDirRecord;
@@ -615,6 +630,21 @@ HRESULT CInArchive::Open2()
615 } 630 }
616 } 631 }
617 } 632 }
633
634 {
635 // find boot item for expand:
636 // UEFI Specification : 13.3.2.1. ISO-9660 and El Torito
637 _expand_BootEntries_index = -1;
638 FOR_VECTOR (i, BootEntries)
639 {
640 const CBootInitialEntry &be = BootEntries[i];
641 if (be.SectorCount <= 1 && be.BootMediaType == NBootMediaType::kNoEmulation)
642 if (_expand_BootEntries_index == -1
643 || be.LoadRBA >= BootEntries[_expand_BootEntries_index].LoadRBA)
644 _expand_BootEntries_index = (int)i;
645 }
646 }
647
618 { 648 {
619 FOR_VECTOR (i, BootEntries) 649 FOR_VECTOR (i, BootEntries)
620 { 650 {
@@ -670,6 +700,8 @@ void CInArchive::Clear()
670 BootEntries.Clear(); 700 BootEntries.Clear();
671 SuspSkipSize = 0; 701 SuspSkipSize = 0;
672 IsSusp = false; 702 IsSusp = false;
703
704 _expand_BootEntries_index = -1;
673} 705}
674 706
675 707
@@ -684,7 +716,17 @@ UInt64 CInArchive::GetBootItemSize(unsigned index) const
684 if (startPos < _fileSize) 716 if (startPos < _fileSize)
685 { 717 {
686 const UInt64 rem = _fileSize - startPos; 718 const UInt64 rem = _fileSize - startPos;
687 if (rem < size) 719 /*
720 UEFI modification to ISO specification:
721 because SectorCount is 16-bit, size is limited by (32 MB).
722 UEFI Specification :
723 13.3.2.1. ISO-9660 and El Torito
724 If the value of Sector Count is set to 0 or 1,
725 EFI will assume the system partition consumes the space
726 from the beginning of the "no emulation" image to the end of the CD-ROM.
727 */
728 //
729 if ((int)index == _expand_BootEntries_index || rem < size)
688 size = rem; 730 size = rem;
689 } 731 }
690 return size; 732 return size;
diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h
index f3e4751..e7d1fee 100644
--- a/CPP/7zip/Archive/Iso/IsoIn.h
+++ b/CPP/7zip/Archive/Iso/IsoIn.h
@@ -214,17 +214,19 @@ struct CVolumeDescriptor
214 CDateTime MTime; 214 CDateTime MTime;
215 CDateTime ExpirationTime; 215 CDateTime ExpirationTime;
216 CDateTime EffectiveTime; 216 CDateTime EffectiveTime;
217 Byte FileStructureVersion; // = 1; 217 // Byte FileStructureVersion; // = 1;
218 Byte ApplicationUse[512]; 218 Byte ApplicationUse[512];
219 219
220 bool IsJoliet() const 220 bool IsJoliet() const
221 { 221 {
222 if ((VolFlags & 1) != 0) 222 if ((VolFlags & 1) != 0)
223 return false; 223 return false;
224 Byte b = EscapeSequence[2]; 224 const Byte b = EscapeSequence[2];
225 return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F && 225 return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F &&
226 (b == 0x40 || b == 0x43 || b == 0x45)); 226 (b == 0x40 || b == 0x43 || b == 0x45));
227 } 227 }
228
229 UInt64 Get_VolumeSpaceSize_inBytes() const { return (UInt64)VolumeSpaceSize * LogicalBlockSize; }
228}; 230};
229 231
230struct CRef 232struct CRef
@@ -293,6 +295,8 @@ public:
293 bool IsSusp; 295 bool IsSusp;
294 unsigned SuspSkipSize; 296 unsigned SuspSkipSize;
295 297
298 int _expand_BootEntries_index;
299
296 CRecordVector<UInt32> UniqStartLocations; 300 CRecordVector<UInt32> UniqStartLocations;
297 301
298 void UpdatePhySize(const UInt32 blockIndex, const UInt64 size) 302 void UpdatePhySize(const UInt32 blockIndex, const UInt64 size)
diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h
index 9556805..65829d0 100644
--- a/CPP/7zip/Archive/Iso/IsoItem.h
+++ b/CPP/7zip/Archive/Iso/IsoItem.h
@@ -179,7 +179,7 @@ struct CDirRecord
179 179
180 if (flags & (1 << 1)) link += "./"; 180 if (flags & (1 << 1)) link += "./";
181 else if (flags & (1 << 2)) link += "../"; 181 else if (flags & (1 << 2)) link += "../";
182 else if (flags & (1 << 3)) link += '/'; 182 else if (flags & (1 << 3)) link.Add_Slash();
183 else 183 else
184 needSlash = true; 184 needSlash = true;
185 185
@@ -201,7 +201,7 @@ struct CDirRecord
201 break; 201 break;
202 202
203 if (needSlash) 203 if (needSlash)
204 link += '/'; 204 link.Add_Slash();
205 } 205 }
206 206
207 return true; 207 return true;
diff --git a/CPP/7zip/Archive/LvmHandler.cpp b/CPP/7zip/Archive/LvmHandler.cpp
new file mode 100644
index 0000000..d144b2a
--- /dev/null
+++ b/CPP/7zip/Archive/LvmHandler.cpp
@@ -0,0 +1,1107 @@
1// LvmHandler.cpp
2
3#include "StdAfx.h"
4
5#include "../../../C/7zCrc.h"
6#include "../../../C/CpuArch.h"
7
8#include "../../Common/ComTry.h"
9#include "../../Common/MyBuffer.h"
10#include "../../Common/StringToInt.h"
11
12#include "../../Windows/PropVariantUtils.h"
13#include "../../Windows/TimeUtils.h"
14
15#include "../Common/RegisterArc.h"
16#include "../Common/StreamUtils.h"
17
18#include "HandlerCont.h"
19
20#define Get32(p) GetUi32(p)
21#define Get64(p) GetUi64(p)
22
23#define LE_32(offs, dest) dest = Get32(p + (offs))
24#define LE_64(offs, dest) dest = Get64(p + (offs))
25
26using namespace NWindows;
27
28namespace NArchive {
29namespace NLvm {
30
31#define SIGNATURE { 'L', 'A', 'B', 'E', 'L', 'O', 'N', 'E' }
32
33static const unsigned k_SignatureSize = 8;
34static const Byte k_Signature[k_SignatureSize] = SIGNATURE;
35
36static const unsigned k_Signature2Size = 8;
37static const Byte k_Signature2[k_Signature2Size] =
38 { 'L', 'V', 'M', '2', ' ', '0', '0', '1' };
39
40static const Byte FMTT_MAGIC[16] =
41 { ' ', 'L', 'V', 'M', '2', ' ', 'x', '[', '5', 'A', '%', 'r', '0', 'N', '*', '>' };
42
43static const UInt32 kSectorSize = 512;
44
45
46struct CPropVal
47{
48 bool IsNumber;
49 AString String;
50 UInt64 Number;
51
52 CPropVal(): IsNumber(false), Number(0) {}
53};
54
55
56struct CConfigProp
57{
58 AString Name;
59
60 bool IsVector;
61 CPropVal Val;
62 CObjectVector<CPropVal> Vector;
63
64 CConfigProp(): IsVector(false) {}
65};
66
67
68class CConfigItem
69{
70public:
71 AString Name;
72 CObjectVector<CConfigProp> Props;
73 CObjectVector<CConfigItem> Items;
74
75 const char *ParseItem(const char *s, int numAllowedLevels);
76
77 int FindProp(const char *name) const throw();
78 bool GetPropVal_Number(const char *name, UInt64 &val) const throw();
79 bool GetPropVal_String(const char *name, AString &val) const;
80
81 int FindSubItem(const char *tag) const throw();
82};
83
84struct CConfig
85{
86 CConfigItem Root;
87
88 bool Parse(const char *s);
89};
90
91
92static bool IsSpaceChar(char c)
93{
94 return (c == ' ' || c == '\t' || c == 0x0D || c == 0x0A);
95}
96
97static const char *SkipSpaces(const char * s)
98{
99 for (;; s++)
100 {
101 const char c = *s;
102 if (c == 0)
103 return s;
104 if (!IsSpaceChar(c))
105 {
106 if (c != '#')
107 return s;
108 s++;
109 for (;;)
110 {
111 const char c2 = *s;
112 if (c2 == 0)
113 return s;
114 if (c2 == '\n')
115 break;
116 s++;
117 }
118 }
119 }
120}
121
122#define SKIP_SPACES(s) s = SkipSpaces(s);
123
124int CConfigItem::FindProp(const char *name) const throw()
125{
126 FOR_VECTOR (i, Props)
127 if (Props[i].Name == name)
128 return (int)i;
129 return -1;
130}
131
132bool CConfigItem::GetPropVal_Number(const char *name, UInt64 &val) const throw()
133{
134 val = 0;
135 int index = FindProp(name);
136 if (index < 0)
137 return false;
138 const CConfigProp &prop = Props[index];
139 if (prop.IsVector)
140 return false;
141 if (!prop.Val.IsNumber)
142 return false;
143 val = prop.Val.Number;
144 return true;
145}
146
147bool CConfigItem::GetPropVal_String(const char *name, AString &val) const
148{
149 val.Empty();
150 int index = FindProp(name);
151 if (index < 0)
152 return false;
153 const CConfigProp &prop = Props[index];
154 if (prop.IsVector)
155 return false;
156 if (prop.Val.IsNumber)
157 return false;
158 val = prop.Val.String;
159 return true;
160}
161
162int CConfigItem::FindSubItem(const char *tag) const throw()
163{
164 FOR_VECTOR (i, Items)
165 if (Items[i].Name == tag)
166 return (int)i;
167 return -1;
168}
169
170static const char *FillProp(const char *s, CPropVal &val)
171{
172 SKIP_SPACES(s)
173 const char c = *s;
174 if (c == 0)
175 return NULL;
176
177 if (c == '\"')
178 {
179 s++;
180 val.IsNumber = false;
181 val.String.Empty();
182
183 for (;;)
184 {
185 const char c2 = *s;
186 if (c2 == 0)
187 return NULL;
188 s++;
189 if (c2 == '\"')
190 break;
191 val.String += c2;
192 }
193 }
194 else
195 {
196 const char *end;
197 val.IsNumber = true;
198 val.Number = ConvertStringToUInt64(s, &end);
199 if (s == end)
200 return NULL;
201 s = end;
202 }
203
204 SKIP_SPACES(s)
205 return s;
206}
207
208
209const char *CConfigItem::ParseItem(const char *s, int numAllowedLevels)
210{
211 if (numAllowedLevels < 0)
212 return NULL;
213
214 for (;;)
215 {
216 SKIP_SPACES(s)
217 const char *beg = s;
218
219 for (;; s++)
220 {
221 char c = *s;
222 if (c == 0 || c == '}')
223 {
224 if (s != beg)
225 return NULL;
226 return s;
227 }
228 if (IsSpaceChar(c) || c == '=' || c == '{')
229 break;
230 }
231
232 if (s == beg)
233 return NULL;
234
235 AString name;
236 name.SetFrom(beg, (unsigned)(s - beg));
237
238 SKIP_SPACES(s)
239
240 if (*s == 0 || *s == '}')
241 return NULL;
242
243 if (*s == '{')
244 {
245 s++;
246 CConfigItem &item = Items.AddNew();
247 item.Name = name;
248 s = item.ParseItem(s, numAllowedLevels - 1);
249 if (!s)
250 return NULL;
251 if (*s != '}')
252 return NULL;
253 s++;
254 continue;
255 }
256
257 if (*s != '=')
258 continue;
259
260 s++;
261 SKIP_SPACES(s)
262 if (*s == 0)
263 return NULL;
264 CConfigProp &prop = Props.AddNew();
265
266 prop.Name = name;
267
268 if (*s == '[')
269 {
270 s++;
271 prop.IsVector = true;
272
273 for (;;)
274 {
275 SKIP_SPACES(s)
276 char c = *s;
277 if (c == 0)
278 return NULL;
279 if (c == ']')
280 {
281 s++;
282 break;
283 }
284
285 CPropVal val;
286
287 s = FillProp(s, val);
288 if (!s)
289 return NULL;
290 prop.Vector.Add(val);
291 SKIP_SPACES(s)
292
293 if (*s == ',')
294 {
295 s++;
296 continue;
297 }
298 if (*s != ']')
299 return NULL;
300 s++;
301 break;
302 }
303 }
304 else
305 {
306 prop.IsVector = false;
307 s = FillProp(s, prop.Val);
308 if (!s)
309 return NULL;
310 }
311 }
312}
313
314
315bool CConfig::Parse(const char *s)
316{
317 s = Root.ParseItem(s, 10);
318 if (!s)
319 return false;
320 SKIP_SPACES(s)
321 return *s == 0;
322}
323
324
325/*
326static const CUInt32PCharPair g_PartitionFlags[] =
327{
328 { 0, "Sys" },
329 { 1, "Ignore" },
330 { 2, "Legacy" },
331 { 60, "Win-Read-only" },
332 { 62, "Win-Hidden" },
333 { 63, "Win-Not-Automount" }
334};
335*/
336
337/*
338static inline char GetHex(unsigned t) { return (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); }
339
340static void PrintHex(unsigned v, char *s)
341{
342 s[0] = GetHex((v >> 4) & 0xF);
343 s[1] = GetHex(v & 0xF);
344}
345
346static void ConvertUInt16ToHex4Digits(UInt32 val, char *s) throw()
347{
348 PrintHex(val >> 8, s);
349 PrintHex(val & 0xFF, s + 2);
350}
351
352static void GuidToString(const Byte *g, char *s)
353{
354 ConvertUInt32ToHex8Digits(Get32(g ), s); s += 8; *s++ = '-';
355 ConvertUInt16ToHex4Digits(Get16(g + 4), s); s += 4; *s++ = '-';
356 ConvertUInt16ToHex4Digits(Get16(g + 6), s); s += 4; *s++ = '-';
357 for (unsigned i = 0; i < 8; i++)
358 {
359 if (i == 2)
360 *s++ = '-';
361 PrintHex(g[8 + i], s);
362 s += 2;
363 }
364 *s = 0;
365}
366
367*/
368
369struct CPhyVol
370{
371 AString Name;
372
373 // AString id;
374 // AString device; // "/dev/sda2"
375 // AString status; // ["ALLOCATABLE"]
376 // AString flags; // []
377 // UInt64 dev_size; // in sectors
378 UInt64 pe_start; // in sectors
379 UInt64 pe_count; // in extents
380
381 bool Parse(const CConfigItem &ci)
382 {
383 Name = ci.Name;
384 // ci.GetPropVal_String("id", id);
385 // ci.GetPropVal_String("device", device);
386 bool res = true;
387 // if (!ci.GetPropVal_Number("dev_size", dev_size)) res = false;
388 if (!ci.GetPropVal_Number("pe_start", pe_start)) res = false;
389 if (!ci.GetPropVal_Number("pe_count", pe_count)) res = false;
390 return res;
391 }
392};
393
394struct CStripe
395{
396 AString Name; // "pv0";
397 UInt64 ExtentOffset; // ????
398};
399
400struct CSegment
401{
402 UInt64 start_extent;
403 UInt64 extent_count;
404 AString type;
405 CObjectVector<CStripe> stripes;
406
407 bool IsPosSizeOk() const
408 {
409 return
410 (start_extent < ((UInt64)1 << 63)) &&
411 (extent_count < ((UInt64)1 << 63));
412 }
413
414 UInt64 GetEndExtent() const { return start_extent + extent_count; }
415
416 bool Parse(const CConfigItem &si)
417 {
418 UInt64 stripe_count;
419
420 if (!si.GetPropVal_Number("start_extent", start_extent)) return false;
421 if (!si.GetPropVal_Number("extent_count", extent_count)) return false;
422 if (!si.GetPropVal_Number("stripe_count", stripe_count)) return false;
423 if (!si.GetPropVal_String("type", type)) return false;
424
425 //if (stripe_count != 1) return false;
426
427 const int spi = si.FindProp("stripes");
428 if (spi < 0)
429 return false;
430
431 const CConfigProp &prop = si.Props[spi];
432 if (!prop.IsVector)
433 return false;
434
435 if (stripe_count > (1 << 20))
436 return false;
437
438 const unsigned numStripes = (unsigned)stripe_count;
439 if (prop.Vector.Size() != numStripes * 2)
440 return false;
441
442 for (unsigned i = 0; i < numStripes; i++)
443 {
444 const CPropVal &v0 = prop.Vector[i * 2];
445 const CPropVal &v1 = prop.Vector[i * 2 + 1];
446 if (v0.IsNumber || !v1.IsNumber)
447 return false;
448 CStripe stripe;
449 stripe.Name = v0.String;
450 stripe.ExtentOffset = v1.Number;
451 stripes.Add(stripe);
452 }
453
454 return true;
455 }
456};
457
458
459struct CLogVol
460{
461 bool IsSupported;
462
463 AString Name;
464
465 AString id;
466 AString status; // ["READ", "WRITE", "VISIBLE"]
467 AString flags; // []
468
469 // UInt64 Pos;
470 // UInt64 Size;
471
472 // UInt64 GetSize() const { return Size; }
473 // UInt64 GetPos() const { return Pos; }
474
475 CObjectVector<CSegment> Segments;
476
477 CLogVol(): /* Pos(0), Size(0), */ IsSupported(false) {}
478
479 bool Parse(const CConfigItem &ci)
480 {
481 Name = ci.Name;
482
483 UInt64 segment_count;
484 if (!ci.GetPropVal_Number("segment_count", segment_count))
485 return false;
486
487 if (ci.Items.Size() != segment_count)
488 return false;
489
490 FOR_VECTOR (segIndex, ci.Items)
491 {
492 const CConfigItem &si = ci.Items[segIndex];
493 {
494 AString t ("segment");
495 t.Add_UInt32(segIndex + 1);
496 if (si.Name != t)
497 return false;
498 }
499
500 CSegment segment;
501
502 if (!segment.Parse(si))
503 return false;
504
505 // item.Size += (segment.extent_count * _extentSize) << 9;
506
507 Segments.Add(segment);
508 }
509
510 IsSupported = true;
511 return true;
512 }
513
514 bool GetNumExtents(UInt64 &numExtents) const
515 {
516 numExtents = 0;
517 if (Segments.IsEmpty())
518 return true;
519 unsigned i;
520 for (i = 1; i < Segments.Size(); i++)
521 if (!Segments[i].IsPosSizeOk())
522 return false;
523 for (i = 1; i < Segments.Size(); i++)
524 if (Segments[i - 1].GetEndExtent() != Segments[i].start_extent)
525 return false;
526 numExtents = Segments.Back().GetEndExtent();
527 return true;
528 }
529};
530
531
532struct CItem
533{
534 int LogVol;
535 int PhyVol;
536 UInt64 Pos;
537 UInt64 Size;
538 AString Name;
539 bool IsSupported;
540
541 CItem(): LogVol(-1), PhyVol(-1), Pos(0), Size(0), IsSupported(false) {}
542};
543
544
545struct CVolGroup
546{
547 CObjectVector<CLogVol> _logVols;
548 CObjectVector<CPhyVol> _phyVols;
549 AString _id;
550 int _extentSizeBits;
551
552 /*
553 UInt64 secno; // 3
554 AString status; // ["RESIZEABLE", "READ", "WRITE"]
555 AString flags; // []
556 UInt64 max_lv; // 0
557 UInt64 max_pv; // 0
558 UInt64 metadata_copies; // 0
559 */
560
561 void Clear()
562 {
563 _logVols.Clear();
564 _phyVols.Clear();
565 _id.Empty();
566 _extentSizeBits = -1;
567 }
568};
569
570
571Z7_class_CHandler_final: public CHandlerCont, public CVolGroup
572{
573 Z7_IFACE_COM7_IMP(IInArchive_Cont)
574
575 CObjectVector<CItem> _items;
576
577 UInt64 _cTime;
578
579 bool _isArc;
580
581 UInt64 _phySize;
582 CByteBuffer _buffer;
583
584 UInt64 _cfgPos;
585 UInt64 _cfgSize;
586
587 HRESULT Open2(IInStream *stream);
588
589 virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
590 {
591 if (index >= _items.Size())
592 {
593 pos = _cfgPos;
594 size = _cfgSize;
595 return NExtract::NOperationResult::kOK;
596 }
597 const CItem &item = _items[index];
598 if (!item.IsSupported)
599 return NExtract::NOperationResult::kUnsupportedMethod;
600 pos = item.Pos;
601 size = item.Size;
602 return NExtract::NOperationResult::kOK;
603 }
604};
605
606static const UInt32 LVM_CRC_INIT_VAL = 0xf597a6cf;
607
608static UInt32 Z7_FASTCALL LvmCrcCalc(const void *data, size_t size)
609{
610 return CrcUpdate(LVM_CRC_INIT_VAL, data, size);
611}
612
613struct CRawLocn
614{
615 UInt64 Offset; /* Offset in bytes to start sector */
616 UInt64 Size; /* Bytes */
617 UInt32 Checksum;
618 UInt32 Flags;
619
620 bool IsEmpty() const { return Offset == 0 && Size == 0; }
621
622 void Parse(const Byte *p)
623 {
624 LE_64(0x00, Offset);
625 LE_64(0x08, Size);
626 LE_32(0x10, Checksum);
627 LE_32(0x14, Flags);
628 }
629};
630
631// #define MDA_HEADER_SIZE 512
632
633struct mda_header
634{
635 UInt64 Start; /* Absolute start byte of mda_header */
636 UInt64 Size; /* Size of metadata area */
637
638 CRecordVector<CRawLocn> raw_locns;
639
640 bool Parse(const Byte *p, size_t size)
641 {
642 if (memcmp(p + 4, FMTT_MAGIC, 16) != 0)
643 return false;
644 UInt32 version;
645 LE_32(0x14, version);
646 if (version != 1)
647 return false;
648 LE_64(0x18, Start);
649 LE_64(0x20, Size);
650
651 unsigned pos = 0x28;
652
653 for (;;)
654 {
655 if (pos + 0x18 > size)
656 return false;
657 CRawLocn locn;
658 locn.Parse(p + pos);
659 if (locn.IsEmpty())
660 break;
661 pos += 0x18;
662 raw_locns.Add(locn);
663 }
664
665 return true;
666 }
667};
668
669
670static int inline GetLog(UInt64 num)
671{
672 for (unsigned i = 0; i < 64; i++)
673 if (((UInt64)1 << i) == num)
674 return (int)i;
675 return -1;
676}
677
678#define ID_LEN 32
679
680HRESULT CHandler::Open2(IInStream *stream)
681{
682 _buffer.Alloc(kSectorSize * 2);
683 RINOK(ReadStream_FALSE(stream, _buffer, kSectorSize * 2))
684
685 const Byte *buf = _buffer;
686
687 buf += kSectorSize;
688
689 // label_header
690
691 if (memcmp(buf, k_Signature, k_SignatureSize) != 0)
692 return S_FALSE;
693 const UInt64 sectorNumber = Get64(buf + 8);
694 if (sectorNumber != 1)
695 return S_FALSE;
696 if (Get32(buf + 16) != LvmCrcCalc(buf + 20, kSectorSize - 20))
697 return S_FALSE;
698
699 const UInt32 offsetToCont = Get32(buf + 20);
700 if (memcmp(buf + 24, k_Signature2, k_Signature2Size) != 0)
701 return S_FALSE;
702
703 if (offsetToCont != 32)
704 return S_FALSE;
705
706 // pv_header
707
708 size_t pos = offsetToCont;
709 const Byte *p = buf;
710
711 /*
712 {
713 Byte id[ID_LEN];
714 memcpy(id, p + pos, ID_LEN);
715 }
716 */
717
718 pos += ID_LEN;
719 const UInt64 device_size_xl = Get64(p + pos);
720 pos += 8;
721
722 _phySize = device_size_xl;
723 _isArc = true;
724
725 for (;;)
726 {
727 if (pos > kSectorSize - 16)
728 return S_FALSE;
729 // disk_locn (data areas)
730 UInt64 offset = Get64(p + pos);
731 UInt64 size = Get64(p + pos + 8);
732 pos += 16;
733 if (offset == 0 && size == 0)
734 break;
735 }
736
737 CConfig cfg;
738 // bool isFinded = false;
739
740 // for (;;)
741 {
742 if (pos > kSectorSize - 16)
743 return S_FALSE;
744 // disk_locn (metadata area headers)
745 UInt64 offset = Get64(p + pos);
746 UInt64 size = Get64(p + pos + 8);
747 pos += 16;
748 if (offset == 0 && size == 0)
749 {
750 // break;
751 return S_FALSE;
752 }
753
754 CByteBuffer meta;
755 const size_t sizeT = (size_t)size;
756 if (sizeT != size)
757 return S_FALSE;
758 meta.Alloc(sizeT);
759 RINOK(InStream_SeekSet(stream, offset))
760 RINOK(ReadStream_FALSE(stream, meta, sizeT))
761 if (Get32(meta) != LvmCrcCalc(meta + 4, kSectorSize - 4))
762 return S_FALSE;
763 mda_header mh;
764 if (!mh.Parse(meta, kSectorSize))
765 return S_FALSE;
766
767 if (mh.raw_locns.Size() != 1)
768 return S_FALSE;
769 unsigned g = 0;
770 // for (unsigned g = 0; g < mh.raw_locns.Size(); g++)
771 {
772 const CRawLocn &locn = mh.raw_locns[g];
773
774 CByteBuffer vgBuf;
775 if (locn.Size > ((UInt32)1 << 24))
776 return S_FALSE;
777
778 const size_t vgSize = (size_t)locn.Size;
779 if (vgSize == 0)
780 return S_FALSE;
781
782 vgBuf.Alloc(vgSize);
783
784 _cfgPos = offset + locn.Offset;
785 _cfgSize = vgSize;
786 RINOK(InStream_SeekSet(stream, _cfgPos))
787 RINOK(ReadStream_FALSE(stream, vgBuf, vgSize))
788 if (locn.Checksum != LvmCrcCalc(vgBuf, vgSize))
789 return S_FALSE;
790
791 {
792 AString s;
793 s.SetFrom_CalcLen((const char *)(const Byte *)vgBuf, (unsigned)vgSize);
794 _cfgSize = s.Len();
795 if (!cfg.Parse(s))
796 return S_FALSE;
797 // isFinded = true;
798 // break;
799 }
800 }
801
802 // if (isFinded) break;
803 }
804
805 // if (!isFinded) return S_FALSE;
806
807 if (cfg.Root.Items.Size() != 1)
808 return S_FALSE;
809 const CConfigItem &volGroup = cfg.Root.Items[0];
810 if (volGroup.Name != "VolGroup00")
811 return S_FALSE;
812
813 volGroup.GetPropVal_String("id", _id);
814
815 if (!cfg.Root.GetPropVal_Number("creation_time", _cTime))
816 _cTime = 0;
817
818 UInt64 extentSize;
819 if (!volGroup.GetPropVal_Number("extent_size", extentSize))
820 return S_FALSE;
821
822 _extentSizeBits = GetLog(extentSize);
823 if (_extentSizeBits < 0 || _extentSizeBits > (62 - 9))
824 return S_FALSE;
825
826
827 {
828 int pvsIndex = volGroup.FindSubItem("physical_volumes");
829 if (pvsIndex < 0)
830 return S_FALSE;
831
832 const CConfigItem &phyVols = volGroup.Items[pvsIndex];
833
834 FOR_VECTOR (i, phyVols.Items)
835 {
836 const CConfigItem &ci = phyVols.Items[i];
837 CPhyVol pv;
838 if (!pv.Parse(ci))
839 return S_FALSE;
840 _phyVols.Add(pv);
841 }
842 }
843
844 {
845 int lvIndex = volGroup.FindSubItem("logical_volumes");
846 if (lvIndex < 0)
847 return S_FALSE;
848
849 const CConfigItem &logVolumes = volGroup.Items[lvIndex];
850
851 FOR_VECTOR (i, logVolumes.Items)
852 {
853 const CConfigItem &ci = logVolumes.Items[i];
854 CLogVol &lv = _logVols.AddNew();
855 lv.Parse(ci) ; // check error
856 }
857 }
858
859 {
860 FOR_VECTOR (i, _logVols)
861 {
862 CLogVol &lv = _logVols[i];
863
864 CItem item;
865
866 item.LogVol = (int)i;
867 item.Pos = 0;
868 item.Size = 0;
869 item.Name = lv.Name;
870
871 if (lv.IsSupported)
872 {
873 UInt64 numExtents;
874 lv.IsSupported = lv.GetNumExtents(numExtents);
875
876 if (lv.IsSupported)
877 {
878 lv.IsSupported = false;
879 item.Size = numExtents << (_extentSizeBits + 9);
880
881 if (lv.Segments.Size() == 1)
882 {
883 const CSegment &segment = lv.Segments[0];
884 if (segment.stripes.Size() == 1)
885 {
886 const CStripe &stripe = segment.stripes[0];
887 FOR_VECTOR (pvIndex, _phyVols)
888 {
889 const CPhyVol &pv = _phyVols[pvIndex];
890 if (pv.Name == stripe.Name)
891 {
892 item.Pos = (pv.pe_start + (stripe.ExtentOffset << _extentSizeBits)) << 9;
893 lv.IsSupported = true;
894 item.IsSupported = true;
895 break;
896 }
897 }
898 }
899 }
900 }
901 }
902
903 _items.Add(item);
904 }
905 }
906
907 {
908 FOR_VECTOR (i, _phyVols)
909 {
910 const CPhyVol &pv = _phyVols[i];
911
912 if (pv.pe_start > (UInt64)1 << (62 - 9))
913 return S_FALSE;
914 if (pv.pe_count > (UInt64)1 << (62 - 9 - _extentSizeBits))
915 return S_FALSE;
916
917 CItem item;
918
919 item.PhyVol = (int)i;
920 item.Pos = pv.pe_start << 9;
921 item.Size = pv.pe_count << (_extentSizeBits + 9);
922 item.Name = pv.Name;
923 item.IsSupported = true;
924
925 _items.Add(item);
926 }
927 }
928
929 return S_OK;
930}
931
932
933Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
934 const UInt64 * /* maxCheckStartPosition */,
935 IArchiveOpenCallback * /* openArchiveCallback */))
936{
937 COM_TRY_BEGIN
938 Close();
939 RINOK(Open2(stream))
940 _stream = stream;
941 return S_OK;
942 COM_TRY_END
943}
944
945
946Z7_COM7F_IMF(CHandler::Close())
947{
948 CVolGroup::Clear();
949
950 _cfgPos = 0;
951 _cfgSize = 0;
952 _cTime = 0;
953 _phySize = 0;
954 _isArc = false;
955 _items.Clear();
956
957 _stream.Release();
958 return S_OK;
959}
960
961
962static const Byte kProps[] =
963{
964 kpidPath,
965 kpidSize,
966 kpidFileSystem,
967 kpidCharacts,
968 kpidOffset,
969 kpidId
970};
971
972static const Byte kArcProps[] =
973{
974 kpidId,
975 kpidCTime,
976 kpidClusterSize
977};
978
979IMP_IInArchive_Props
980IMP_IInArchive_ArcProps
981
982Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
983{
984 COM_TRY_BEGIN
985 NCOM::CPropVariant prop;
986
987 switch (propID)
988 {
989 case kpidMainSubfile:
990 {
991 /*
992 if (_items.Size() == 1)
993 prop = (UInt32)0;
994 */
995 break;
996 }
997 case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
998 case kpidId:
999 {
1000 prop = _id;
1001 break;
1002 }
1003 case kpidClusterSize:
1004 {
1005 if (_extentSizeBits >= 0)
1006 prop = ((UInt64)1 << (_extentSizeBits + 9));
1007 break;
1008 }
1009 case kpidCTime:
1010 {
1011 if (_cTime != 0)
1012 {
1013 FILETIME ft;
1014 NTime::UnixTime64_To_FileTime((Int64)_cTime, ft);
1015 prop = ft;
1016 }
1017 break;
1018 }
1019 case kpidErrorFlags:
1020 {
1021 UInt32 v = 0;
1022 if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
1023 // if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
1024 // if (_headerError) v |= kpv_ErrorFlags_HeadersError;
1025 if (v == 0 && !_stream)
1026 v |= kpv_ErrorFlags_UnsupportedMethod;
1027 if (v != 0)
1028 prop = v;
1029 break;
1030 }
1031 }
1032
1033 prop.Detach(value);
1034 return S_OK;
1035 COM_TRY_END
1036}
1037
1038
1039Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
1040{
1041 *numItems = _items.Size() + (_cfgSize == 0 ? 0 : 1);
1042 return S_OK;
1043}
1044
1045
1046Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
1047{
1048 COM_TRY_BEGIN
1049 NCOM::CPropVariant prop;
1050
1051 const CItem &item = _items[index];
1052
1053 // const CLogVol &item = _items[index];
1054
1055 if (index >= _items.Size())
1056 {
1057 switch (propID)
1058 {
1059 case kpidPath:
1060 {
1061 prop = "meta.txt";
1062 break;
1063 }
1064
1065 case kpidSize:
1066 case kpidPackSize: prop = _cfgSize; break;
1067 }
1068 }
1069 else
1070 {
1071 switch (propID)
1072 {
1073 case kpidPath:
1074 {
1075 AString s = item.Name;
1076 s += ".img";
1077 prop = s;
1078 break;
1079 }
1080
1081 case kpidSize:
1082 case kpidPackSize: prop = item.Size; break;
1083 case kpidOffset: prop = item.Pos; break;
1084
1085 case kpidId:
1086 {
1087 // prop = item.id;
1088 break;
1089 }
1090
1091 // case kpidCharacts: FLAGS64_TO_PROP(g_PartitionFlags, item.Flags, prop); break;
1092 }
1093 }
1094
1095 prop.Detach(value);
1096 return S_OK;
1097 COM_TRY_END
1098}
1099
1100REGISTER_ARC_I(
1101 "LVM", "lvm", NULL, 0xBF,
1102 k_Signature,
1103 kSectorSize,
1104 0,
1105 NULL)
1106
1107}}
diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp
index 9239afd..adfe59d 100644
--- a/CPP/7zip/Archive/LzhHandler.cpp
+++ b/CPP/7zip/Archive/LzhHandler.cpp
@@ -4,6 +4,7 @@
4 4
5#include "../../../C/CpuArch.h" 5#include "../../../C/CpuArch.h"
6 6
7#include "../../Common/AutoPtr.h"
7#include "../../Common/ComTry.h" 8#include "../../Common/ComTry.h"
8#include "../../Common/MyBuffer.h" 9#include "../../Common/MyBuffer.h"
9#include "../../Common/StringConvert.h" 10#include "../../Common/StringConvert.h"
@@ -37,6 +38,7 @@ using namespace NTime;
37 38
38static const UInt16 kCrc16Poly = 0xA001; 39static const UInt16 kCrc16Poly = 0xA001;
39 40
41MY_ALIGN(64)
40static UInt16 g_LzhCrc16Table[256]; 42static UInt16 g_LzhCrc16Table[256];
41 43
42#define CRC16_UPDATE_BYTE(crc, b) (g_LzhCrc16Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) 44#define CRC16_UPDATE_BYTE(crc, b) (g_LzhCrc16Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
@@ -219,7 +221,7 @@ struct CItem
219 AString s (GetDirName()); 221 AString s (GetDirName());
220 const char kDirSeparator = '\\'; 222 const char kDirSeparator = '\\';
221 // check kDirSeparator in Linux 223 // check kDirSeparator in Linux
222 s.Replace((char)(unsigned char)0xFF, kDirSeparator); 224 s.Replace((char)(Byte)0xFF, kDirSeparator);
223 if (!s.IsEmpty() && s.Back() != kDirSeparator) 225 if (!s.IsEmpty() && s.Back() != kDirSeparator)
224 s += kDirSeparator; 226 s += kDirSeparator;
225 s += GetFileName(); 227 s += GetFileName();
@@ -552,8 +554,8 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
552 } 554 }
553 if (_items.Size() % 100 == 0) 555 if (_items.Size() % 100 == 0)
554 { 556 {
555 UInt64 numFiles = _items.Size(); 557 const UInt64 numFiles = _items.Size();
556 UInt64 numBytes = item.DataPosition; 558 const UInt64 numBytes = item.DataPosition;
557 RINOK(callback->SetCompleted(&numFiles, &numBytes)) 559 RINOK(callback->SetCompleted(&numFiles, &numBytes))
558 } 560 }
559 } 561 }
@@ -600,91 +602,76 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
600 } 602 }
601 RINOK(extractCallback->SetTotal(totalUnPacked)) 603 RINOK(extractCallback->SetTotal(totalUnPacked))
602 604
603 UInt64 currentItemUnPacked, currentItemPacked; 605 UInt32 cur_Unpacked, cur_Packed;
604
605 NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = NULL;
606 CMyComPtr<ICompressCoder> lzhDecoder;
607 // CMyComPtr<ICompressCoder> lzh1Decoder;
608 // CMyComPtr<ICompressCoder> arj2Decoder;
609
610 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
611 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
612 606
613 CLocalProgress *lps = new CLocalProgress; 607 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
614 CMyComPtr<ICompressProgressInfo> progress = lps;
615 lps->Init(extractCallback, false); 608 lps->Init(extractCallback, false);
616 609 CMyUniquePtr<NCompress::NLzh::NDecoder::CCoder> lzhDecoder;
617 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 610 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
618 CMyComPtr<ISequentialInStream> inStream(streamSpec); 611 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
619 streamSpec->SetStream(_stream); 612 inStream->SetStream(_stream);
620 613
621 for (i = 0;; i++, 614 for (i = 0;; i++,
622 lps->OutSize += currentItemUnPacked, 615 lps->OutSize += cur_Unpacked,
623 lps->InSize += currentItemPacked) 616 lps->InSize += cur_Packed)
624 { 617 {
625 currentItemUnPacked = 0; 618 cur_Unpacked = 0;
626 currentItemPacked = 0; 619 cur_Packed = 0;
627
628 RINOK(lps->SetCur()) 620 RINOK(lps->SetCur())
629
630 if (i >= numItems) 621 if (i >= numItems)
631 break; 622 break;
632 623
633 CMyComPtr<ISequentialOutStream> realOutStream; 624 Int32 opRes;
634 const Int32 askMode = testMode ?
635 NExtract::NAskMode::kTest :
636 NExtract::NAskMode::kExtract;
637 const UInt32 index = allFilesMode ? i : indices[i];
638 const CItemEx &item = _items[index];
639 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
640
641 if (item.IsDir())
642 { 625 {
643 // if (!testMode) 626 CMyComPtr<ISequentialOutStream> realOutStream;
627 const Int32 askMode = testMode ?
628 NExtract::NAskMode::kTest :
629 NExtract::NAskMode::kExtract;
630 const UInt32 index = allFilesMode ? i : indices[i];
631 const CItemEx &item = _items[index];
632 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
633
634 if (item.IsDir())
644 { 635 {
645 RINOK(extractCallback->PrepareOperation(askMode)) 636 // if (!testMode)
646 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 637 {
638 RINOK(extractCallback->PrepareOperation(askMode))
639 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
640 }
641 continue;
647 } 642 }
648 continue; 643
649 } 644 if (!testMode && !realOutStream)
650 645 continue;
651 if (!testMode && !realOutStream) 646
652 continue; 647 RINOK(extractCallback->PrepareOperation(askMode))
653 648 cur_Unpacked = item.Size;
654 RINOK(extractCallback->PrepareOperation(askMode)) 649 cur_Packed = item.PackSize;
655 currentItemUnPacked = item.Size;
656 currentItemPacked = item.PackSize;
657 650
658 { 651 CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;
659 COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; 652 outStream->Init(realOutStream);
660 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
661 outStreamSpec->Init(realOutStream);
662 realOutStream.Release(); 653 realOutStream.Release();
663 654
664 RINOK(InStream_SeekSet(_stream, item.DataPosition)) 655 RINOK(InStream_SeekSet(_stream, item.DataPosition))
665 656
666 streamSpec->Init(item.PackSize); 657 inStream->Init(item.PackSize);
667 658
668 HRESULT res = S_OK; 659 HRESULT res = S_OK;
669 Int32 opRes = NExtract::NOperationResult::kOK; 660 opRes = NExtract::NOperationResult::kOK;
670 661
671 if (item.IsCopyMethod()) 662 if (item.IsCopyMethod())
672 { 663 {
673 res = copyCoder->Code(inStream, outStream, NULL, NULL, progress); 664 res = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);
674 if (res == S_OK && copyCoderSpec->TotalSize != item.PackSize) 665 if (res == S_OK && copyCoder->TotalSize != item.PackSize)
675 res = S_FALSE; 666 res = S_FALSE;
676 } 667 }
677 else if (item.IsLh4GroupMethod()) 668 else if (item.IsLh4GroupMethod())
678 { 669 {
679 if (!lzhDecoder) 670 lzhDecoder.Create_if_Empty();
680 { 671 // lzhDecoder->FinishMode = true;
681 lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder; 672 lzhDecoder->SetDictSize((UInt32)1 << item.GetNumDictBits());
682 lzhDecoder = lzhDecoderSpec; 673 res = lzhDecoder->Code(inStream, outStream, cur_Unpacked, lps);
683 } 674 if (res == S_OK && lzhDecoder->GetInputProcessedSize() != item.PackSize)
684 lzhDecoderSpec->FinishMode = true;
685 lzhDecoderSpec->SetDictSize(1 << item.GetNumDictBits());
686 res = lzhDecoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress);
687 if (res == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize)
688 res = S_FALSE; 675 res = S_FALSE;
689 } 676 }
690 /* 677 /*
@@ -696,7 +683,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
696 lzh1Decoder = lzh1DecoderSpec; 683 lzh1Decoder = lzh1DecoderSpec;
697 } 684 }
698 lzh1DecoderSpec->SetDictionary(item.GetNumDictBits()); 685 lzh1DecoderSpec->SetDictionary(item.GetNumDictBits());
699 res = lzh1Decoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress); 686 res = lzh1Decoder->Code(inStream, outStream, NULL, &cur_Unpacked, progress);
700 } 687 }
701 */ 688 */
702 else 689 else
@@ -709,13 +696,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
709 else 696 else
710 { 697 {
711 RINOK(res) 698 RINOK(res)
712 if (outStreamSpec->GetCRC() != item.CRC) 699 if (outStream->GetCRC() != item.CRC)
713 opRes = NExtract::NOperationResult::kCRCError; 700 opRes = NExtract::NOperationResult::kCRCError;
714 } 701 }
715 } 702 }
716 outStream.Release();
717 RINOK(extractCallback->SetOperationResult(opRes))
718 } 703 }
704 RINOK(extractCallback->SetOperationResult(opRes))
719 } 705 }
720 return S_OK; 706 return S_OK;
721 COM_TRY_END 707 COM_TRY_END
diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp
index 11cb76e..7cbabf4 100644
--- a/CPP/7zip/Archive/LzmaHandler.cpp
+++ b/CPP/7zip/Archive/LzmaHandler.cpp
@@ -80,31 +80,26 @@ class CDecoder Z7_final
80{ 80{
81 CMyComPtr<ISequentialOutStream> _bcjStream; 81 CMyComPtr<ISequentialOutStream> _bcjStream;
82 CFilterCoder *_filterCoder; 82 CFilterCoder *_filterCoder;
83 CMyComPtr<ICompressCoder> _lzmaDecoder;
84public: 83public:
85 NCompress::NLzma::CDecoder *_lzmaDecoderSpec; 84 CMyComPtr2<ICompressCoder, NCompress::NLzma::CDecoder> _lzmaDecoder;
86 85
87 ~CDecoder(); 86 ~CDecoder();
88 HRESULT Create(bool filtered, ISequentialInStream *inStream); 87 HRESULT Create(bool filtered, ISequentialInStream *inStream);
89 88
90 HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress); 89 HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
91 90
92 UInt64 GetInputProcessedSize() const { return _lzmaDecoderSpec->GetInputProcessedSize(); } 91 UInt64 GetInputProcessedSize() const { return _lzmaDecoder->GetInputProcessedSize(); }
93 92
94 void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoderSpec->ReleaseInStream(); } 93 void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoder->ReleaseInStream(); }
95 94
96 HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize) 95 HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize)
97 { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); } 96 { return _lzmaDecoder->ReadFromInputStream(data, size, processedSize); }
98}; 97};
99 98
100HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream) 99HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream)
101{ 100{
102 if (!_lzmaDecoder) 101 _lzmaDecoder.Create_if_Empty();
103 { 102 _lzmaDecoder->FinishStream = true;
104 _lzmaDecoderSpec = new NCompress::NLzma::CDecoder;
105 _lzmaDecoderSpec->FinishStream = true;
106 _lzmaDecoder = _lzmaDecoderSpec;
107 }
108 103
109 if (filteredMode) 104 if (filteredMode)
110 { 105 {
@@ -117,7 +112,7 @@ HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream)
117 } 112 }
118 } 113 }
119 114
120 return _lzmaDecoderSpec->SetInStream(inStream); 115 return _lzmaDecoder->SetInStream(inStream);
121} 116}
122 117
123CDecoder::~CDecoder() 118CDecoder::~CDecoder()
@@ -131,7 +126,7 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
131 if (header.FilterID > 1) 126 if (header.FilterID > 1)
132 return E_NOTIMPL; 127 return E_NOTIMPL;
133 128
134 RINOK(_lzmaDecoderSpec->SetDecoderProperties2(header.LzmaProps, 5)) 129 RINOK(_lzmaDecoder->SetDecoderProperties2(header.LzmaProps, 5))
135 130
136 bool filteredMode = (header.FilterID == 1); 131 bool filteredMode = (header.FilterID == 1);
137 132
@@ -143,7 +138,7 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
143 } 138 }
144 139
145 const UInt64 *Size = header.HasSize() ? &header.Size : NULL; 140 const UInt64 *Size = header.HasSize() ? &header.Size : NULL;
146 HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress); 141 HRESULT res = _lzmaDecoder->CodeResume(outStream, Size, progress);
147 142
148 if (filteredMode) 143 if (filteredMode)
149 { 144 {
@@ -160,7 +155,7 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
160 RINOK(res) 155 RINOK(res)
161 156
162 if (header.HasSize()) 157 if (header.HasSize())
163 if (_lzmaDecoderSpec->GetOutputProcessedSize() != header.Size) 158 if (_lzmaDecoder->GetOutputProcessedSize() != header.Size)
164 return S_FALSE; 159 return S_FALSE;
165 160
166 return S_OK; 161 return S_OK;
@@ -170,11 +165,7 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
170Z7_CLASS_IMP_CHandler_IInArchive_1( 165Z7_CLASS_IMP_CHandler_IInArchive_1(
171 IArchiveOpenSeq 166 IArchiveOpenSeq
172) 167)
173 CHeader _header;
174 bool _lzma86; 168 bool _lzma86;
175 CMyComPtr<IInStream> _stream;
176 CMyComPtr<ISequentialInStream> _seqStream;
177
178 bool _isArc; 169 bool _isArc;
179 bool _needSeekToStart; 170 bool _needSeekToStart;
180 bool _dataAfterEnd; 171 bool _dataAfterEnd;
@@ -186,6 +177,10 @@ Z7_CLASS_IMP_CHandler_IInArchive_1(
186 bool _unpackSize_Defined; 177 bool _unpackSize_Defined;
187 bool _numStreams_Defined; 178 bool _numStreams_Defined;
188 179
180 CHeader _header;
181 CMyComPtr<IInStream> _stream;
182 CMyComPtr<ISequentialInStream> _seqStream;
183
189 UInt64 _packSize; 184 UInt64 _packSize;
190 UInt64 _unpackSize; 185 UInt64 _unpackSize;
191 UInt64 _numStreams; 186 UInt64 _numStreams;
@@ -220,6 +215,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
220 prop = v; 215 prop = v;
221 break; 216 break;
222 } 217 }
218 default: break;
223 } 219 }
224 prop.Detach(value); 220 prop.Detach(value);
225 return S_OK; 221 return S_OK;
@@ -288,6 +284,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
288 case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break; 284 case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break;
289 case kpidPackSize: if (_packSize_Defined) prop = _packSize; break; 285 case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;
290 case kpidMethod: GetMethod(prop); break; 286 case kpidMethod: GetMethod(prop); break;
287 default: break;
291 } 288 }
292 prop.Detach(value); 289 prop.Detach(value);
293 return S_OK; 290 return S_OK;
@@ -366,7 +363,6 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal
366 ) 363 )
367 return S_FALSE; 364 return S_FALSE;
368 365
369 CDecoder state;
370 const UInt32 outLimit = 1 << 11; 366 const UInt32 outLimit = 1 << 11;
371 Byte outBuf[outLimit]; 367 Byte outBuf[outLimit];
372 368
@@ -452,9 +448,10 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
452 return E_INVALIDARG; 448 return E_INVALIDARG;
453 449
454 if (_packSize_Defined) 450 if (_packSize_Defined)
455 extractCallback->SetTotal(_packSize); 451 RINOK(extractCallback->SetTotal(_packSize))
456 452
457 453 Int32 opResult;
454 {
458 CMyComPtr<ISequentialOutStream> realOutStream; 455 CMyComPtr<ISequentialOutStream> realOutStream;
459 const Int32 askMode = testMode ? 456 const Int32 askMode = testMode ?
460 NExtract::NAskMode::kTest : 457 NExtract::NAskMode::kTest :
@@ -463,16 +460,14 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
463 if (!testMode && !realOutStream) 460 if (!testMode && !realOutStream)
464 return S_OK; 461 return S_OK;
465 462
466 extractCallback->PrepareOperation(askMode); 463 RINOK(extractCallback->PrepareOperation(askMode))
467 464
468 CDummyOutStream *outStreamSpec = new CDummyOutStream; 465 CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;
469 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); 466 outStream->SetStream(realOutStream);
470 outStreamSpec->SetStream(realOutStream); 467 outStream->Init();
471 outStreamSpec->Init();
472 realOutStream.Release(); 468 realOutStream.Release();
473 469
474 CLocalProgress *lps = new CLocalProgress; 470 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
475 CMyComPtr<ICompressProgressInfo> progress = lps;
476 lps->Init(extractCallback, true); 471 lps->Init(extractCallback, true);
477 472
478 if (_needSeekToStart) 473 if (_needSeekToStart)
@@ -485,8 +480,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
485 _needSeekToStart = true; 480 _needSeekToStart = true;
486 481
487 CDecoder decoder; 482 CDecoder decoder;
488 HRESULT result = decoder.Create(_lzma86, _seqStream); 483 RINOK(decoder.Create(_lzma86, _seqStream))
489 RINOK(result)
490 484
491 bool firstItem = true; 485 bool firstItem = true;
492 486
@@ -496,6 +490,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
496 490
497 bool dataAfterEnd = false; 491 bool dataAfterEnd = false;
498 492
493 HRESULT hres = S_OK;
494
499 for (;;) 495 for (;;)
500 { 496 {
501 lps->InSize = packSize; 497 lps->InSize = packSize;
@@ -523,32 +519,32 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
523 numStreams++; 519 numStreams++;
524 firstItem = false; 520 firstItem = false;
525 521
526 result = decoder.Code(st, outStream, progress); 522 hres = decoder.Code(st, outStream, lps);
527 523
528 packSize = decoder.GetInputProcessedSize(); 524 packSize = decoder.GetInputProcessedSize();
529 unpackSize = outStreamSpec->GetSize(); 525 unpackSize = outStream->GetSize();
530 526
531 if (result == E_NOTIMPL) 527 if (hres == E_NOTIMPL)
532 { 528 {
533 _unsupported = true; 529 _unsupported = true;
534 result = S_FALSE; 530 hres = S_FALSE;
535 break; 531 break;
536 } 532 }
537 if (result == S_FALSE) 533 if (hres == S_FALSE)
538 break; 534 break;
539 RINOK(result) 535 RINOK(hres)
540 } 536 }
541 537
542 if (firstItem) 538 if (firstItem)
543 { 539 {
544 _isArc = false; 540 _isArc = false;
545 result = S_FALSE; 541 hres = S_FALSE;
546 } 542 }
547 else if (result == S_OK || result == S_FALSE) 543 else if (hres == S_OK || hres == S_FALSE)
548 { 544 {
549 if (dataAfterEnd) 545 if (dataAfterEnd)
550 _dataAfterEnd = true; 546 _dataAfterEnd = true;
551 else if (decoder._lzmaDecoderSpec->NeedsMoreInput()) 547 else if (decoder._lzmaDecoder->NeedsMoreInput())
552 _needMoreInput = true; 548 _needMoreInput = true;
553 549
554 _packSize = packSize; 550 _packSize = packSize;
@@ -560,7 +556,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
560 _numStreams_Defined = true; 556 _numStreams_Defined = true;
561 } 557 }
562 558
563 Int32 opResult = NExtract::NOperationResult::kOK; 559 opResult = NExtract::NOperationResult::kOK;
564 560
565 if (!_isArc) 561 if (!_isArc)
566 opResult = NExtract::NOperationResult::kIsNotArc; 562 opResult = NExtract::NOperationResult::kIsNotArc;
@@ -570,14 +566,15 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
570 opResult = NExtract::NOperationResult::kUnsupportedMethod; 566 opResult = NExtract::NOperationResult::kUnsupportedMethod;
571 else if (_dataAfterEnd) 567 else if (_dataAfterEnd)
572 opResult = NExtract::NOperationResult::kDataAfterEnd; 568 opResult = NExtract::NOperationResult::kDataAfterEnd;
573 else if (result == S_FALSE) 569 else if (hres == S_FALSE)
574 opResult = NExtract::NOperationResult::kDataError; 570 opResult = NExtract::NOperationResult::kDataError;
575 else if (result == S_OK) 571 else if (hres == S_OK)
576 opResult = NExtract::NOperationResult::kOK; 572 opResult = NExtract::NOperationResult::kOK;
577 else 573 else
578 return result; 574 return hres;
579 575
580 outStream.Release(); 576 // outStream.Release();
577 }
581 return extractCallback->SetOperationResult(opResult); 578 return extractCallback->SetOperationResult(opResult);
582 579
583 COM_TRY_END 580 COM_TRY_END
diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp
index 0d3611b..82d34fd 100644
--- a/CPP/7zip/Archive/MbrHandler.cpp
+++ b/CPP/7zip/Archive/MbrHandler.cpp
@@ -30,6 +30,11 @@
30using namespace NWindows; 30using namespace NWindows;
31 31
32namespace NArchive { 32namespace NArchive {
33
34namespace NFat {
35API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size);
36}
37
33namespace NMbr { 38namespace NMbr {
34 39
35struct CChs 40struct CChs
@@ -89,8 +94,8 @@ struct CPartition
89 bool IsExtended() const { return Type == 5 || Type == 0xF; } 94 bool IsExtended() const { return Type == 5 || Type == 0xF; }
90 UInt32 GetLimit() const { return Lba + NumBlocks; } 95 UInt32 GetLimit() const { return Lba + NumBlocks; }
91 // bool IsActive() const { return Status == 0x80; } 96 // bool IsActive() const { return Status == 0x80; }
92 UInt64 GetPos() const { return (UInt64)Lba * 512; } 97 UInt64 GetPos(unsigned sectorSizeLog) const { return (UInt64)Lba << sectorSizeLog; }
93 UInt64 GetSize() const { return (UInt64)NumBlocks * 512; } 98 UInt64 GetSize(unsigned sectorSizeLog) const { return (UInt64)NumBlocks << sectorSizeLog; }
94 99
95 bool CheckLbaLimits() const { return (UInt32)0xFFFFFFFF - Lba >= NumBlocks; } 100 bool CheckLbaLimits() const { return (UInt32)0xFFFFFFFF - Lba >= NumBlocks; }
96 bool Parse(const Byte *p) 101 bool Parse(const Byte *p)
@@ -202,10 +207,13 @@ Z7_class_CHandler_final: public CHandlerCont
202 UInt64 _totalSize; 207 UInt64 _totalSize;
203 CByteBuffer _buffer; 208 CByteBuffer _buffer;
204 209
210 UInt32 _signature;
211 unsigned _sectorSizeLog;
212
205 virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override Z7_final 213 virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override Z7_final
206 { 214 {
207 const CItem &item = _items[index]; 215 const CItem &item = _items[index];
208 pos = item.Part.GetPos(); 216 pos = item.Part.GetPos(_sectorSizeLog);
209 size = item.Size; 217 size = item.Size;
210 return NExtract::NOperationResult::kOK; 218 return NExtract::NOperationResult::kOK;
211 } 219 }
@@ -213,6 +221,18 @@ Z7_class_CHandler_final: public CHandlerCont
213 HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level); 221 HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level);
214}; 222};
215 223
224/*
225static bool IsEmptyBuffer(const Byte *data, size_t size)
226{
227 for (unsigned i = 0; i < size; i++)
228 if (data[i] != 0)
229 return false;
230 return true;
231}
232*/
233
234const char *GetFileSystem(ISequentialInStream *stream, UInt64 partitionSize);
235
216HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level) 236HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level)
217{ 237{
218 if (level >= 128 || _items.Size() >= 128) 238 if (level >= 128 || _items.Size() >= 128)
@@ -221,24 +241,65 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsi
221 const unsigned kNumHeaderParts = 4; 241 const unsigned kNumHeaderParts = 4;
222 CPartition parts[kNumHeaderParts]; 242 CPartition parts[kNumHeaderParts];
223 243
244 if (level == 0)
245 _sectorSizeLog = 9;
246 const UInt32 kSectorSize = (UInt32)1 << _sectorSizeLog;
247 UInt32 bufSize = kSectorSize;
248 if (level == 0 && _totalSize >= (1 << 12))
249 bufSize = (1 << 12);
250 _buffer.Alloc(bufSize);
224 { 251 {
225 const UInt32 kSectorSize = 512;
226 _buffer.Alloc(kSectorSize);
227 Byte *buf = _buffer; 252 Byte *buf = _buffer;
228 UInt64 newPos = (UInt64)lba << 9; 253 const UInt64 newPos = (UInt64)lba << _sectorSizeLog;
229 if (newPos + 512 > _totalSize) 254 if (newPos + bufSize > _totalSize)
230 return S_FALSE; 255 return S_FALSE;
231 RINOK(InStream_SeekSet(stream, newPos)) 256 RINOK(InStream_SeekSet(stream, newPos))
232 RINOK(ReadStream_FALSE(stream, buf, kSectorSize)) 257 RINOK(ReadStream_FALSE(stream, buf, bufSize))
233
234 if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA) 258 if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
235 return S_FALSE; 259 return S_FALSE;
236 260 if (level == 0)
261 _signature = GetUi32(buf + 0x1B8);
237 for (unsigned i = 0; i < kNumHeaderParts; i++) 262 for (unsigned i = 0; i < kNumHeaderParts; i++)
238 if (!parts[i].Parse(buf + 0x1BE + 16 * i)) 263 if (!parts[i].Parse(buf + 0x1BE + 16 * i))
239 return S_FALSE; 264 return S_FALSE;
240 } 265 }
241 266
267 // 23.02: now we try to detect 4kn format (4 KB sectors case)
268 if (level == 0)
269 // if (_totalSize >= (1 << 28)) // we don't expect small images with 4 KB sectors
270 if (bufSize >= (1 << 12))
271 {
272 UInt32 lastLim = 0;
273 UInt32 firstLba = 0;
274 UInt32 numBlocks = 0; // in first partition
275 for (unsigned i = 0; i < kNumHeaderParts; i++)
276 {
277 const CPartition &part = parts[i];
278 if (part.IsEmpty())
279 continue;
280 if (firstLba == 0 && part.NumBlocks != 0)
281 {
282 firstLba = part.Lba;
283 numBlocks = part.NumBlocks;
284 }
285 const UInt32 newLim = part.GetLimit();
286 if (newLim < lastLim)
287 return S_FALSE;
288 lastLim = newLim;
289 }
290 if (lastLim != 0)
291 {
292 const UInt64 lim12 = (UInt64)lastLim << 12;
293 if (lim12 <= _totalSize
294 // && _totalSize - lim12 < (1 << 28) // we can try to exclude false positive cases
295 )
296 // if (IsEmptyBuffer(&_buffer[(1 << 9)], (1 << 12) - (1 << 9)))
297 if (InStream_SeekSet(stream, (UInt64)firstLba << 12) == S_OK)
298 if (GetFileSystem(stream, (UInt64)numBlocks << 12))
299 _sectorSizeLog = 12;
300 }
301 }
302
242 PRF(printf("\n# %8X", lba)); 303 PRF(printf("\n# %8X", lba));
243 304
244 UInt32 limLba = lba + 1; 305 UInt32 limLba = lba + 1;
@@ -265,7 +326,7 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsi
265 newLba = baseLba + part.Lba; 326 newLba = baseLba + part.Lba;
266 if (newLba < limLba) 327 if (newLba < limLba)
267 return S_FALSE; 328 return S_FALSE;
268 HRESULT res = ReadTables(stream, level < 1 ? newLba : baseLba, newLba, level + 1); 329 const HRESULT res = ReadTables(stream, level < 1 ? newLba : baseLba, newLba, level + 1);
269 if (res != S_FALSE && res != S_OK) 330 if (res != S_FALSE && res != S_OK)
270 return res; 331 return res;
271 } 332 }
@@ -287,8 +348,8 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsi
287 else 348 else
288 { 349 {
289 const CItem &back = _items.Back(); 350 const CItem &back = _items.Back();
290 UInt32 backLimit = back.Part.GetLimit(); 351 const UInt32 backLimit = back.Part.GetLimit();
291 UInt32 partLimit = part.GetLimit(); 352 const UInt32 partLimit = part.GetLimit();
292 if (backLimit < partLimit) 353 if (backLimit < partLimit)
293 { 354 {
294 n.IsReal = false; 355 n.IsReal = false;
@@ -302,7 +363,7 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsi
302 if (n.Part.GetLimit() < limLba) 363 if (n.Part.GetLimit() < limLba)
303 return S_FALSE; 364 return S_FALSE;
304 limLba = n.Part.GetLimit(); 365 limLba = n.Part.GetLimit();
305 n.Size = n.Part.GetSize(); 366 n.Size = n.Part.GetSize(_sectorSizeLog);
306 _items.Add(n); 367 _items.Add(n);
307 } 368 }
308 } 369 }
@@ -310,27 +371,30 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsi
310} 371}
311 372
312 373
374static const Byte k_Ntfs_Signature[] = { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 };
375
313static bool Is_Ntfs(const Byte *p) 376static bool Is_Ntfs(const Byte *p)
314{ 377{
315 if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) 378 if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)
316 return false; 379 return false;
317 // int codeOffset = 0;
318 switch (p[0]) 380 switch (p[0])
319 { 381 {
320 case 0xE9: /* codeOffset = 3 + (Int16)Get16(p + 1); */ break; 382 case 0xE9: /* codeOffset = 3 + (Int16)Get16(p + 1); */ break;
321 case 0xEB: if (p[2] != 0x90) return false; /* codeOffset = 2 + (int)(signed char)p[1]; */ break; 383 case 0xEB: if (p[2] != 0x90) return false; /* codeOffset = 2 + (int)(signed char)p[1]; */ break;
322 default: return false; 384 default: return false;
323 } 385 }
324 return memcmp(p + 3, "NTFS ", 8) == 0; 386 return memcmp(p + 3, k_Ntfs_Signature, Z7_ARRAY_SIZE(k_Ntfs_Signature)) == 0;
325} 387}
326 388
389static const Byte k_ExFat_Signature[] = { 'E', 'X', 'F', 'A', 'T', ' ', ' ', ' ' };
390
327static bool Is_ExFat(const Byte *p) 391static bool Is_ExFat(const Byte *p)
328{ 392{
329 if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA) 393 if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)
330 return false; 394 return false;
331 if (p[0] != 0xEB || p[1] != 0x76 || p[2] != 0x90) 395 if (p[0] != 0xEB || p[1] != 0x76 || p[2] != 0x90)
332 return false; 396 return false;
333 return memcmp(p + 3, "EXFAT ", 8) == 0; 397 return memcmp(p + 3, k_ExFat_Signature, Z7_ARRAY_SIZE(k_ExFat_Signature)) == 0;
334} 398}
335 399
336static bool AllAreZeros(const Byte *p, size_t size) 400static bool AllAreZeros(const Byte *p, size_t size)
@@ -350,8 +414,7 @@ static bool Is_Udf(const Byte *p)
350} 414}
351 415
352 416
353static const char *GetFileSystem( 417const char *GetFileSystem(ISequentialInStream *stream, UInt64 partitionSize)
354 ISequentialInStream *stream, UInt64 partitionSize)
355{ 418{
356 const size_t kHeaderSize = 1 << 9; 419 const size_t kHeaderSize = 1 << 9;
357 if (partitionSize >= kHeaderSize) 420 if (partitionSize >= kHeaderSize)
@@ -364,6 +427,8 @@ static const char *GetFileSystem(
364 return "NTFS"; 427 return "NTFS";
365 if (Is_ExFat(buf)) 428 if (Is_ExFat(buf))
366 return "exFAT"; 429 return "exFAT";
430 if (NFat::IsArc_Fat(buf, kHeaderSize))
431 return "FAT";
367 const size_t kHeaderSize2 = k_Udf_StartPos + (1 << 9); 432 const size_t kHeaderSize2 = k_Udf_StartPos + (1 << 9);
368 if (partitionSize >= kHeaderSize2) 433 if (partitionSize >= kHeaderSize2)
369 { 434 {
@@ -392,15 +457,17 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
392 RINOK(ReadTables(stream, 0, 0, 0)) 457 RINOK(ReadTables(stream, 0, 0, 0))
393 if (_items.IsEmpty()) 458 if (_items.IsEmpty())
394 return S_FALSE; 459 return S_FALSE;
395 UInt32 lbaLimit = _items.Back().Part.GetLimit();
396 UInt64 lim = (UInt64)lbaLimit << 9;
397 if (lim < _totalSize)
398 { 460 {
399 CItem n; 461 const UInt32 lbaLimit = _items.Back().Part.GetLimit();
400 n.Part.Lba = lbaLimit; 462 const UInt64 lim = (UInt64)lbaLimit << _sectorSizeLog;
401 n.Size = _totalSize - lim; 463 if (lim < _totalSize)
402 n.IsReal = false; 464 {
403 _items.Add(n); 465 CItem n;
466 n.Part.Lba = lbaLimit;
467 n.Size = _totalSize - lim;
468 n.IsReal = false;
469 _items.Add(n);
470 }
404 } 471 }
405 472
406 FOR_VECTOR (i, _items) 473 FOR_VECTOR (i, _items)
@@ -408,7 +475,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
408 CItem &item = _items[i]; 475 CItem &item = _items[i];
409 if (item.Part.Type != kType_Windows_NTFS) 476 if (item.Part.Type != kType_Windows_NTFS)
410 continue; 477 continue;
411 if (InStream_SeekSet(stream, item.Part.GetPos()) != S_OK) 478 if (InStream_SeekSet(stream, item.Part.GetPos(_sectorSizeLog)) != S_OK)
412 continue; 479 continue;
413 item.FileSystem = GetFileSystem(stream, item.Size); 480 item.FileSystem = GetFileSystem(stream, item.Size);
414 item.WasParsed = true; 481 item.WasParsed = true;
@@ -447,8 +514,15 @@ static const CStatProp kProps[] =
447 { "End CHS", kpidEndChs, VT_BSTR} 514 { "End CHS", kpidEndChs, VT_BSTR}
448}; 515};
449 516
517static const Byte kArcProps[] =
518{
519 kpidSectorSize,
520 kpidId
521};
522
450IMP_IInArchive_Props_WITH_NAME 523IMP_IInArchive_Props_WITH_NAME
451IMP_IInArchive_ArcProps_NO_Table 524IMP_IInArchive_ArcProps
525
452 526
453Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 527Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
454{ 528{
@@ -473,6 +547,8 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
473 break; 547 break;
474 } 548 }
475 case kpidPhySize: prop = _totalSize; break; 549 case kpidPhySize: prop = _totalSize; break;
550 case kpidSectorSize: prop = (UInt32)((UInt32)1 << _sectorSizeLog); break;
551 case kpidId: prop = _signature; break;
476 } 552 }
477 prop.Detach(value); 553 prop.Detach(value);
478 return S_OK; 554 return S_OK;
@@ -544,7 +620,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
544 break; 620 break;
545 case kpidSize: 621 case kpidSize:
546 case kpidPackSize: prop = item.Size; break; 622 case kpidPackSize: prop = item.Size; break;
547 case kpidOffset: prop = part.GetPos(); break; 623 case kpidOffset: prop = part.GetPos(_sectorSizeLog); break;
548 case kpidPrimary: if (item.IsReal) prop = item.IsPrim; break; 624 case kpidPrimary: if (item.IsReal) prop = item.IsPrim; break;
549 case kpidBegChs: if (item.IsReal) part.BeginChs.ToString(prop); break; 625 case kpidBegChs: if (item.IsReal) part.BeginChs.ToString(prop); break;
550 case kpidEndChs: if (item.IsReal) part.EndChs.ToString(prop); break; 626 case kpidEndChs: if (item.IsReal) part.EndChs.ToString(prop); break;
diff --git a/CPP/7zip/Archive/MslzHandler.cpp b/CPP/7zip/Archive/MslzHandler.cpp
index 04549f8..daf58bd 100644
--- a/CPP/7zip/Archive/MslzHandler.cpp
+++ b/CPP/7zip/Archive/MslzHandler.cpp
@@ -75,6 +75,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
75 if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; 75 if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
76 if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; 76 if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
77 prop = v; 77 prop = v;
78 break;
78 } 79 }
79 } 80 }
80 prop.Detach(value); 81 prop.Detach(value);
@@ -152,7 +153,7 @@ void CHandler::ParseName(Byte replaceByte, IArchiveOpenCallback *callback)
152 } 153 }
153 154
154 if (replaceByte >= 0x20 && replaceByte < 0x80) 155 if (replaceByte >= 0x20 && replaceByte < 0x80)
155 _name += (char)replaceByte; 156 _name.Add_Char((char)replaceByte);
156} 157}
157 158
158Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, 159Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */,
@@ -292,8 +293,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
292 if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) 293 if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
293 return E_INVALIDARG; 294 return E_INVALIDARG;
294 295
295 // extractCallback->SetTotal(_unpackSize); 296 // RINOK(extractCallback->SetTotal(_unpackSize))
296 297 Int32 opRes;
298 {
297 CMyComPtr<ISequentialOutStream> realOutStream; 299 CMyComPtr<ISequentialOutStream> realOutStream;
298 const Int32 askMode = testMode ? 300 const Int32 askMode = testMode ?
299 NExtract::NAskMode::kTest : 301 NExtract::NAskMode::kTest :
@@ -302,16 +304,14 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
302 if (!testMode && !realOutStream) 304 if (!testMode && !realOutStream)
303 return S_OK; 305 return S_OK;
304 306
305 extractCallback->PrepareOperation(askMode); 307 RINOK(extractCallback->PrepareOperation(askMode))
306 308
307 CDummyOutStream *outStreamSpec = new CDummyOutStream; 309 CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;
308 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); 310 outStream->SetStream(realOutStream);
309 outStreamSpec->SetStream(realOutStream); 311 outStream->Init();
310 outStreamSpec->Init(); 312 // realOutStream.Release();
311 realOutStream.Release();
312 313
313 CLocalProgress *lps = new CLocalProgress; 314 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
314 CMyComPtr<ICompressProgressInfo> progress = lps;
315 lps->Init(extractCallback, false); 315 lps->Init(extractCallback, false);
316 316
317 if (_needSeekToStart) 317 if (_needSeekToStart)
@@ -323,7 +323,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
323 else 323 else
324 _needSeekToStart = true; 324 _needSeekToStart = true;
325 325
326 Int32 opRes = NExtract::NOperationResult::kDataError; 326 opRes = NExtract::NOperationResult::kDataError;
327 327
328 bool isArc = false; 328 bool isArc = false;
329 bool needMoreInput = false; 329 bool needMoreInput = false;
@@ -344,7 +344,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
344 unpackSize = GetUi32(buffer + 10); 344 unpackSize = GetUi32(buffer + 10);
345 if (unpackSize <= kUnpackSizeMax) 345 if (unpackSize <= kUnpackSizeMax)
346 { 346 {
347 HRESULT result = MslzDec(s, outStream, unpackSize, needMoreInput, progress); 347 const HRESULT result = MslzDec(s, outStream, unpackSize, needMoreInput, lps);
348 if (result == S_OK) 348 if (result == S_OK)
349 opRes = NExtract::NOperationResult::kOK; 349 opRes = NExtract::NOperationResult::kOK;
350 else if (result != S_FALSE) 350 else if (result != S_FALSE)
@@ -374,8 +374,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
374 opRes = NExtract::NOperationResult::kUnexpectedEnd; 374 opRes = NExtract::NOperationResult::kUnexpectedEnd;
375 else if (_dataAfterEnd) 375 else if (_dataAfterEnd)
376 opRes = NExtract::NOperationResult::kDataAfterEnd; 376 opRes = NExtract::NOperationResult::kDataAfterEnd;
377 377 }
378 outStream.Release();
379 return extractCallback->SetOperationResult(opRes); 378 return extractCallback->SetOperationResult(opRes);
380 COM_TRY_END 379 COM_TRY_END
381} 380}
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
index 7a512b7..7ce2e8e 100644
--- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
@@ -73,7 +73,7 @@ static void AddDictProp(AString &s, UInt32 val)
73 if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } 73 if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
74 else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } 74 else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
75 s.Add_UInt32(val); 75 s.Add_UInt32(val);
76 s += c; 76 s.Add_Char(c);
77} 77}
78 78
79static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict) 79static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict)
@@ -87,7 +87,7 @@ static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict)
87 s += ((unsigned)method < Z7_ARRAY_SIZE(kMethods)) ? kMethods[(unsigned)method] : kUnknownMethod; 87 s += ((unsigned)method < Z7_ARRAY_SIZE(kMethods)) ? kMethods[(unsigned)method] : kUnknownMethod;
88 if (method == NMethodType::kLZMA) 88 if (method == NMethodType::kLZMA)
89 { 89 {
90 s += ':'; 90 s.Add_Colon();
91 AddDictProp(s, dict); 91 AddDictProp(s, dict);
92 } 92 }
93 return s; 93 return s;
@@ -105,7 +105,7 @@ AString CHandler::GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt3
105 s += (method < Z7_ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod; 105 s += (method < Z7_ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
106 if (method == NMethodType::kLZMA) 106 if (method == NMethodType::kLZMA)
107 { 107 {
108 s += ':'; 108 s.Add_Colon();
109 s += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary); 109 s += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary);
110 } 110 }
111 return s; 111 return s;
@@ -427,8 +427,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
427 427
428 extractCallback->SetTotal(totalSize + solidPosMax); 428 extractCallback->SetTotal(totalSize + solidPosMax);
429 429
430 CLocalProgress *lps = new CLocalProgress; 430 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
431 CMyComPtr<ICompressProgressInfo> progress = lps;
432 lps->Init(extractCallback, !_archive.IsSolid); 431 lps->Init(extractCallback, !_archive.IsSolid);
433 432
434 if (_archive.IsSolid) 433 if (_archive.IsSolid)
@@ -559,7 +558,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
559 } 558 }
560 else 559 else
561 { 560 {
562 HRESULT res = _archive.Decoder.SetToPos(pos, progress); 561 HRESULT res = _archive.Decoder.SetToPos(pos, lps);
563 if (res != S_OK) 562 if (res != S_OK)
564 { 563 {
565 if (res != S_FALSE) 564 if (res != S_FALSE)
@@ -620,7 +619,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
620 writeToTemp1 ? &tempBuf : NULL, 619 writeToTemp1 ? &tempBuf : NULL,
621 is_PatchedUninstaller, item.PatchSize, 620 is_PatchedUninstaller, item.PatchSize,
622 is_PatchedUninstaller ? NULL : (ISequentialOutStream *)realOutStream, 621 is_PatchedUninstaller ? NULL : (ISequentialOutStream *)realOutStream,
623 progress, 622 lps,
624 curPacked, curUnpacked32); 623 curPacked, curUnpacked32);
625 curUnpacked = curUnpacked32; 624 curUnpacked = curUnpacked32;
626 if (_archive.IsSolid) 625 if (_archive.IsSolid)
@@ -665,7 +664,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
665 writeToTemp ? &tempBuf2 : NULL, 664 writeToTemp ? &tempBuf2 : NULL,
666 false, 0, 665 false, 0,
667 realOutStream, 666 realOutStream,
668 progress, 667 lps,
669 curPacked2, curUnpacked2); 668 curPacked2, curUnpacked2);
670 curPacked += curPacked2; 669 curPacked += curPacked2;
671 if (!_archive.IsSolid) 670 if (!_archive.IsSolid)
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp
index 05ebfd0..c9e2c01 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp
@@ -979,7 +979,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
979 break; 979 break;
980 if (c < 0x80) 980 if (c < 0x80)
981 { 981 {
982 Raw_UString += (char)c; 982 Raw_UString.Add_Char((char)c);
983 continue; 983 continue;
984 } 984 }
985 985
@@ -2623,7 +2623,7 @@ void CInArchive::DetectNsisType(const CBlockHeader &bh, const Byte *p)
2623 2623
2624 for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p2 += kCmdSize) 2624 for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p2 += kCmdSize)
2625 { 2625 {
2626 UInt32 cmd = Get32(p2); // we use original (not converted) command 2626 const UInt32 cmd = Get32(p2); // we use original (not converted) command
2627 2627
2628 if (cmd < EW_WRITEUNINSTALLER || 2628 if (cmd < EW_WRITEUNINSTALLER ||
2629 cmd > EW_WRITEUNINSTALLER + numInsertMax) 2629 cmd > EW_WRITEUNINSTALLER + numInsertMax)
@@ -2639,7 +2639,7 @@ void CInArchive::DetectNsisType(const CBlockHeader &bh, const Byte *p)
2639 params[3] <= 1) 2639 params[3] <= 1)
2640 continue; 2640 continue;
2641 2641
2642 UInt32 altParam = params[3]; 2642 const UInt32 altParam = params[3];
2643 if (!IsGoodString(params[0]) || 2643 if (!IsGoodString(params[0]) ||
2644 !IsGoodString(altParam)) 2644 !IsGoodString(altParam))
2645 continue; 2645 continue;
@@ -2649,8 +2649,8 @@ void CInArchive::DetectNsisType(const CBlockHeader &bh, const Byte *p)
2649 continue; 2649 continue;
2650 if (AreTwoParamStringsEqual(altParam + additional, params[0])) 2650 if (AreTwoParamStringsEqual(altParam + additional, params[0]))
2651 { 2651 {
2652 unsigned numInserts = cmd - EW_WRITEUNINSTALLER; 2652 const unsigned numInserts = cmd - EW_WRITEUNINSTALLER;
2653 mask |= (1 << numInserts); 2653 mask |= ((unsigned)1 << numInserts);
2654 } 2654 }
2655 } 2655 }
2656 2656
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h
index bb8de62..1f8c967 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.h
+++ b/CPP/7zip/Archive/Nsis/NsisIn.h
@@ -416,7 +416,7 @@ public:
416 s = MultiByteToUnicodeString(APrefixes[item.Prefix]); 416 s = MultiByteToUnicodeString(APrefixes[item.Prefix]);
417 if (s.Len() > 0) 417 if (s.Len() > 0)
418 if (s.Back() != L'\\') 418 if (s.Back() != L'\\')
419 s += '\\'; 419 s.Add_Char('\\');
420 } 420 }
421 421
422 if (IsUnicode) 422 if (IsUnicode)
diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp
index c13e0ca..d55521d 100644
--- a/CPP/7zip/Archive/NtfsHandler.cpp
+++ b/CPP/7zip/Archive/NtfsHandler.cpp
@@ -71,14 +71,15 @@ struct CHeader
71{ 71{
72 unsigned SectorSizeLog; 72 unsigned SectorSizeLog;
73 unsigned ClusterSizeLog; 73 unsigned ClusterSizeLog;
74 unsigned MftRecordSizeLog;
74 // Byte MediaType; 75 // Byte MediaType;
75 UInt32 NumHiddenSectors; 76 // UInt32 NumHiddenSectors;
76 UInt64 NumSectors; 77 UInt64 NumSectors;
77 UInt64 NumClusters; 78 UInt64 NumClusters;
78 UInt64 MftCluster; 79 UInt64 MftCluster;
79 UInt64 SerialNumber; 80 UInt64 SerialNumber;
80 UInt16 SectorsPerTrack; 81 // UInt16 SectorsPerTrack;
81 UInt16 NumHeads; 82 // UInt16 NumHeads;
82 83
83 UInt64 GetPhySize_Clusters() const { return NumClusters << ClusterSizeLog; } 84 UInt64 GetPhySize_Clusters() const { return NumClusters << ClusterSizeLog; }
84 UInt64 GetPhySize_Max() const { return (NumSectors + 1) << SectorSizeLog; } 85 UInt64 GetPhySize_Max() const { return (NumSectors + 1) << SectorSizeLog; }
@@ -111,30 +112,42 @@ bool CHeader::Parse(const Byte *p)
111 if (memcmp(p + 3, "NTFS ", 8) != 0) 112 if (memcmp(p + 3, "NTFS ", 8) != 0)
112 return false; 113 return false;
113 { 114 {
114 int t = GetLog(Get16(p + 11)); 115 {
115 if (t < 9 || t > 12) 116 const int t = GetLog(Get16(p + 11));
116 return false; 117 if (t < 9 || t > 12)
117 SectorSizeLog = (unsigned)t; 118 return false;
118 t = GetLog(p[13]); 119 SectorSizeLog = (unsigned)t;
119 if (t < 0) 120 }
120 return false; 121 {
121 sectorsPerClusterLog = (unsigned)t; 122 const unsigned v = p[13];
122 ClusterSizeLog = SectorSizeLog + sectorsPerClusterLog; 123 if (v <= 0x80)
123 if (ClusterSizeLog > 30) 124 {
124 return false; 125 const int t = GetLog(v);
126 if (t < 0)
127 return false;
128 sectorsPerClusterLog = (unsigned)t;
129 }
130 else
131 sectorsPerClusterLog = 0x100 - v;
132 ClusterSizeLog = SectorSizeLog + sectorsPerClusterLog;
133 if (ClusterSizeLog > 30)
134 return false;
135 }
125 } 136 }
126 137
127 for (int i = 14; i < 21; i++) 138 for (int i = 14; i < 21; i++)
128 if (p[i] != 0) 139 if (p[i] != 0)
129 return false; 140 return false;
130 141
142 // F8 : a hard disk
143 // F0 : high-density 3.5-inch floppy disk
131 if (p[21] != 0xF8) // MediaType = Fixed_Disk 144 if (p[21] != 0xF8) // MediaType = Fixed_Disk
132 return false; 145 return false;
133 if (Get16(p + 22) != 0) // NumFatSectors 146 if (Get16(p + 22) != 0) // NumFatSectors
134 return false; 147 return false;
135 G16(p + 24, SectorsPerTrack); // 63 usually 148 // G16(p + 24, SectorsPerTrack); // 63 usually
136 G16(p + 26, NumHeads); // 255 149 // G16(p + 26, NumHeads); // 255
137 G32(p + 28, NumHiddenSectors); // 63 (XP) / 2048 (Vista and win7) / (0 on media that are not partitioned ?) 150 // G32(p + 28, NumHiddenSectors); // 63 (XP) / 2048 (Vista and win7) / (0 on media that are not partitioned ?)
138 if (Get32(p + 32) != 0) // NumSectors32 151 if (Get32(p + 32) != 0) // NumSectors32
139 return false; 152 return false;
140 153
@@ -156,14 +169,47 @@ bool CHeader::Parse(const Byte *p)
156 169
157 NumClusters = NumSectors >> sectorsPerClusterLog; 170 NumClusters = NumSectors >> sectorsPerClusterLog;
158 171
159 G64(p + 0x30, MftCluster); 172 G64(p + 0x30, MftCluster); // $MFT.
160 // G64(p + 0x38, Mft2Cluster); 173 // G64(p + 0x38, Mft2Cluster);
161 G64(p + 0x48, SerialNumber); 174 G64(p + 0x48, SerialNumber); // $MFTMirr
162 UInt32 numClustersInMftRec; 175
163 UInt32 numClustersInIndexBlock; 176 /*
164 G32(p + 0x40, numClustersInMftRec); // -10 means 2 ^10 = 1024 bytes. 177 numClusters_per_MftRecord:
165 G32(p + 0x44, numClustersInIndexBlock); 178 numClusters_per_IndexBlock:
166 return (numClustersInMftRec < 256 && numClustersInIndexBlock < 256); 179 only low byte from 4 bytes is used. Another 3 high bytes are zeros.
180 If the number is positive (number < 0x80),
181 then it represents the number of clusters.
182 If the number is negative (number >= 0x80),
183 then the size of the file record is 2 raised to the absolute value of this number.
184 example: (0xF6 == -10) means 2^10 = 1024 bytes.
185 */
186 {
187 UInt32 numClusters_per_MftRecord;
188 G32(p + 0x40, numClusters_per_MftRecord);
189 if (numClusters_per_MftRecord >= 0x100 || numClusters_per_MftRecord == 0)
190 return false;
191 if (numClusters_per_MftRecord < 0x80)
192 {
193 const int t = GetLog(numClusters_per_MftRecord);
194 if (t < 0)
195 return false;
196 MftRecordSizeLog = (unsigned)t + ClusterSizeLog;
197 }
198 else
199 MftRecordSizeLog = 0x100 - numClusters_per_MftRecord;
200 // what exact MFT record sizes are possible and supported by Windows?
201 // do we need to change this limit here?
202 const unsigned k_MftRecordSizeLog_MAX = 12;
203 if (MftRecordSizeLog > k_MftRecordSizeLog_MAX)
204 return false;
205 if (MftRecordSizeLog < SectorSizeLog)
206 return false;
207 }
208 {
209 UInt32 numClusters_per_IndexBlock;
210 G32(p + 0x44, numClusters_per_IndexBlock);
211 return (numClusters_per_IndexBlock < 0x100);
212 }
167} 213}
168 214
169struct CMftRef 215struct CMftRef
@@ -242,7 +288,7 @@ struct CFileNameAttr
242 {} 288 {}
243}; 289};
244 290
245static void GetString(const Byte *p, unsigned len, UString2 &res) 291static void GetString(const Byte *p, const unsigned len, UString2 &res)
246{ 292{
247 if (len == 0 && res.IsEmpty()) 293 if (len == 0 && res.IsEmpty())
248 return; 294 return;
@@ -250,7 +296,7 @@ static void GetString(const Byte *p, unsigned len, UString2 &res)
250 unsigned i; 296 unsigned i;
251 for (i = 0; i < len; i++) 297 for (i = 0; i < len; i++)
252 { 298 {
253 wchar_t c = Get16(p + i * 2); 299 const wchar_t c = Get16(p + i * 2);
254 if (c == 0) 300 if (c == 0)
255 break; 301 break;
256 s[i] = c; 302 s[i] = c;
@@ -273,8 +319,8 @@ bool CFileNameAttr::Parse(const Byte *p, unsigned size)
273 G32(p + 0x38, Attrib); 319 G32(p + 0x38, Attrib);
274 // G16(p + 0x3C, PackedEaSize); 320 // G16(p + 0x3C, PackedEaSize);
275 NameType = p[0x41]; 321 NameType = p[0x41];
276 unsigned len = p[0x40]; 322 const unsigned len = p[0x40];
277 if (0x42 + len > size) 323 if (0x42 + len * 2 > size)
278 return false; 324 return false;
279 if (len != 0) 325 if (len != 0)
280 GetString(p + 0x42, len, Name); 326 GetString(p + 0x42, len, Name);
@@ -537,11 +583,11 @@ bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax,
537 583
538 while (size > 0) 584 while (size > 0)
539 { 585 {
540 Byte b = *p++; 586 const unsigned b = *p++;
541 size--; 587 size--;
542 if (b == 0) 588 if (b == 0)
543 break; 589 break;
544 UInt32 num = b & 0xF; 590 unsigned num = b & 0xF;
545 if (num == 0 || num > 8 || num > size) 591 if (num == 0 || num > 8 || num > size)
546 return false; 592 return false;
547 593
@@ -561,7 +607,7 @@ bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax,
561 e.Virt = vcn; 607 e.Virt = vcn;
562 vcn += vSize; 608 vcn += vSize;
563 609
564 num = (b >> 4) & 0xF; 610 num = b >> 4;
565 if (num > 8 || num > size) 611 if (num > 8 || num > size)
566 return false; 612 return false;
567 613
@@ -614,12 +660,9 @@ static const UInt64 kEmptyTag = (UInt64)(Int64)-1;
614static const unsigned kNumCacheChunksLog = 1; 660static const unsigned kNumCacheChunksLog = 1;
615static const size_t kNumCacheChunks = (size_t)1 << kNumCacheChunksLog; 661static const size_t kNumCacheChunks = (size_t)1 << kNumCacheChunksLog;
616 662
617Z7_CLASS_IMP_COM_1( 663Z7_CLASS_IMP_IInStream(
618 CInStream 664 CInStream
619 , IInStream
620) 665)
621 Z7_IFACE_COM7_IMP(ISequentialInStream)
622
623 UInt64 _virtPos; 666 UInt64 _virtPos;
624 UInt64 _physPos; 667 UInt64 _physPos;
625 UInt64 _curRem; 668 UInt64 _curRem;
@@ -1279,12 +1322,12 @@ bool CMftRec::Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 r
1279 G16(p + 0x10, SeqNumber); 1322 G16(p + 0x10, SeqNumber);
1280 // G16(p + 0x12, LinkCount); 1323 // G16(p + 0x12, LinkCount);
1281 // PRF(printf(" L=%d", LinkCount)); 1324 // PRF(printf(" L=%d", LinkCount));
1282 UInt32 attrOffs = Get16(p + 0x14); 1325 const UInt32 attrOffs = Get16(p + 0x14);
1283 G16(p + 0x16, Flags); 1326 G16(p + 0x16, Flags);
1284 PRF(printf(" F=%4X", Flags)); 1327 PRF(printf(" F=%4X", Flags));
1285 1328
1286 UInt32 bytesInUse = Get32(p + 0x18); 1329 const UInt32 bytesInUse = Get32(p + 0x18);
1287 UInt32 bytesAlloc = Get32(p + 0x1C); 1330 const UInt32 bytesAlloc = Get32(p + 0x1C);
1288 G64(p + 0x20, BaseMftRef.Val); 1331 G64(p + 0x20, BaseMftRef.Val);
1289 if (BaseMftRef.Val != 0) 1332 if (BaseMftRef.Val != 0)
1290 { 1333 {
@@ -1405,7 +1448,6 @@ struct CDatabase
1405 CObjectVector<CMftRec> Recs; 1448 CObjectVector<CMftRec> Recs;
1406 CMyComPtr<IInStream> InStream; 1449 CMyComPtr<IInStream> InStream;
1407 CHeader Header; 1450 CHeader Header;
1408 unsigned RecSizeLog;
1409 UInt64 PhySize; 1451 UInt64 PhySize;
1410 1452
1411 IArchiveOpenCallback *OpenCallback; 1453 IArchiveOpenCallback *OpenCallback;
@@ -1417,6 +1459,9 @@ struct CDatabase
1417 CByteBuffer SecurData; 1459 CByteBuffer SecurData;
1418 CRecordVector<size_t> SecurOffsets; 1460 CRecordVector<size_t> SecurOffsets;
1419 1461
1462 // bool _headerWarning;
1463 bool ThereAreAltStreams;
1464
1420 bool _showSystemFiles; 1465 bool _showSystemFiles;
1421 bool _showDeletedFiles; 1466 bool _showDeletedFiles;
1422 CObjectVector<UString2> VirtFolderNames; 1467 CObjectVector<UString2> VirtFolderNames;
@@ -1426,10 +1471,6 @@ struct CDatabase
1426 int _lostFolderIndex_Normal; 1471 int _lostFolderIndex_Normal;
1427 int _lostFolderIndex_Deleted; 1472 int _lostFolderIndex_Deleted;
1428 1473
1429 // bool _headerWarning;
1430
1431 bool ThereAreAltStreams;
1432
1433 void InitProps() 1474 void InitProps()
1434 { 1475 {
1435 _showSystemFiles = true; 1476 _showSystemFiles = true;
@@ -1449,7 +1490,7 @@ struct CDatabase
1449 1490
1450 HRESULT SeekToCluster(UInt64 cluster); 1491 HRESULT SeekToCluster(UInt64 cluster);
1451 1492
1452 int FindDirItemForMtfRec(UInt64 recIndex) const 1493 int Find_DirItem_For_MftRec(UInt64 recIndex) const
1453 { 1494 {
1454 if (recIndex >= Recs.Size()) 1495 if (recIndex >= Recs.Size())
1455 return -1; 1496 return -1;
@@ -1773,26 +1814,22 @@ HRESULT CDatabase::Open()
1773 1814
1774 SeekToCluster(Header.MftCluster); 1815 SeekToCluster(Header.MftCluster);
1775 1816
1776 CMftRec mftRec; 1817 // we use ByteBuf for records reading.
1777 UInt32 numSectorsInRec; 1818 // so the size of ByteBuf must be >= mftRecordSize
1778 1819 const size_t recSize = (size_t)1 << Header.MftRecordSizeLog;
1820 const size_t kBufSize = MyMax((size_t)(1 << 15), recSize);
1821 ByteBuf.Alloc(kBufSize);
1822 RINOK(ReadStream_FALSE(InStream, ByteBuf, recSize))
1823 {
1824 const UInt32 allocSize = Get32(ByteBuf + 0x1C);
1825 if (allocSize != recSize)
1826 return S_FALSE;
1827 }
1828 // MftRecordSizeLog >= SectorSizeLog
1829 const UInt32 numSectorsInRec = 1u << (Header.MftRecordSizeLog - Header.SectorSizeLog);
1779 CMyComPtr<IInStream> mftStream; 1830 CMyComPtr<IInStream> mftStream;
1831 CMftRec mftRec;
1780 { 1832 {
1781 UInt32 blockSize = 1 << 12;
1782 ByteBuf.Alloc(blockSize);
1783 RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize))
1784
1785 {
1786 const UInt32 allocSize = Get32(ByteBuf + 0x1C);
1787 const int t = GetLog(allocSize);
1788 if (t < (int)Header.SectorSizeLog)
1789 return S_FALSE;
1790 RecSizeLog = (unsigned)t;
1791 if (RecSizeLog > 15)
1792 return S_FALSE;
1793 }
1794
1795 numSectorsInRec = 1 << (RecSizeLog - Header.SectorSizeLog);
1796 if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, 0, NULL)) 1833 if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, 0, NULL))
1797 return S_FALSE; 1834 return S_FALSE;
1798 if (!mftRec.Is_Magic_FILE()) 1835 if (!mftRec.Is_Magic_FILE())
@@ -1807,25 +1844,18 @@ HRESULT CDatabase::Open()
1807 1844
1808 // CObjectVector<CAttr> SecurityAttrs; 1845 // CObjectVector<CAttr> SecurityAttrs;
1809 1846
1810 UInt64 mftSize = mftRec.DataAttrs[0].Size; 1847 const UInt64 mftSize = mftRec.DataAttrs[0].Size;
1811 if ((mftSize >> 4) > Header.GetPhySize_Clusters()) 1848 if ((mftSize >> 4) > Header.GetPhySize_Clusters())
1812 return S_FALSE; 1849 return S_FALSE;
1813 1850
1814 const size_t kBufSize = (1 << 15);
1815 const size_t recSize = ((size_t)1 << RecSizeLog);
1816 if (kBufSize < recSize)
1817 return S_FALSE;
1818
1819 { 1851 {
1820 const UInt64 numFiles = mftSize >> RecSizeLog; 1852 const UInt64 numFiles = mftSize >> Header.MftRecordSizeLog;
1821 if (numFiles > (1 << 30)) 1853 if (numFiles > (1 << 30))
1822 return S_FALSE; 1854 return S_FALSE;
1823 if (OpenCallback) 1855 if (OpenCallback)
1824 { 1856 {
1825 RINOK(OpenCallback->SetTotal(&numFiles, &mftSize)) 1857 RINOK(OpenCallback->SetTotal(&numFiles, &mftSize))
1826 } 1858 }
1827
1828 ByteBuf.Alloc(kBufSize);
1829 Recs.ClearAndReserve((unsigned)numFiles); 1859 Recs.ClearAndReserve((unsigned)numFiles);
1830 } 1860 }
1831 1861
@@ -2119,7 +2149,7 @@ HRESULT CDatabase::Open()
2119 item.ParentFolder = -1; 2149 item.ParentFolder = -1;
2120 else 2150 else
2121 { 2151 {
2122 int index = FindDirItemForMtfRec(refIndex); 2152 int index = Find_DirItem_For_MftRec(refIndex);
2123 if (index < 0 || 2153 if (index < 0 ||
2124 Recs[Items[index].RecIndex].SeqNumber != parentDirRef.GetNumber()) 2154 Recs[Items[index].RecIndex].SeqNumber != parentDirRef.GetNumber())
2125 { 2155 {
@@ -2372,7 +2402,7 @@ static const CStatProp kArcProps[] =
2372 { NULL, kpidFileSystem, VT_BSTR}, 2402 { NULL, kpidFileSystem, VT_BSTR},
2373 { NULL, kpidClusterSize, VT_UI4}, 2403 { NULL, kpidClusterSize, VT_UI4},
2374 { NULL, kpidSectorSize, VT_UI4}, 2404 { NULL, kpidSectorSize, VT_UI4},
2375 { "Record Size", kpidRecordSize, VT_UI4}, 2405 { "MFT Record Size", kpidRecordSize, VT_UI4},
2376 { NULL, kpidHeadersSize, VT_UI8}, 2406 { NULL, kpidHeadersSize, VT_UI8},
2377 { NULL, kpidCTime, VT_FILETIME}, 2407 { NULL, kpidCTime, VT_FILETIME},
2378 { NULL, kpidId, VT_UI8}, 2408 { NULL, kpidId, VT_UI8},
@@ -2474,7 +2504,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
2474 break; 2504 break;
2475 } 2505 }
2476 case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break; 2506 case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break;
2477 case kpidRecordSize: prop = (UInt32)1 << RecSizeLog; break; 2507 case kpidRecordSize: prop = (UInt32)1 << Header.MftRecordSizeLog; break;
2478 case kpidId: prop = Header.SerialNumber; break; 2508 case kpidId: prop = Header.SerialNumber; break;
2479 2509
2480 case kpidIsTree: prop = true; break; 2510 case kpidIsTree: prop = true; break;
@@ -2745,21 +2775,19 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2745 UInt32 clusterSize = Header.ClusterSize(); 2775 UInt32 clusterSize = Header.ClusterSize();
2746 CByteBuffer buf(clusterSize); 2776 CByteBuffer buf(clusterSize);
2747 2777
2748 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 2778 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
2749 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
2750
2751 CLocalProgress *lps = new CLocalProgress;
2752 CMyComPtr<ICompressProgressInfo> progress = lps;
2753 lps->Init(extractCallback, false); 2779 lps->Init(extractCallback, false);
2780 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
2781 CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;
2754 2782
2755 CDummyOutStream *outStreamSpec = new CDummyOutStream; 2783 for (i = 0;; i++)
2756 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
2757
2758 for (i = 0; i < numItems; i++)
2759 { 2784 {
2760 lps->InSize = totalPackSize; 2785 lps->InSize = totalPackSize;
2761 lps->OutSize = totalSize; 2786 lps->OutSize = totalSize;
2762 RINOK(lps->SetCur()) 2787 RINOK(lps->SetCur())
2788 if (i >= numItems)
2789 break;
2790
2763 CMyComPtr<ISequentialOutStream> realOutStream; 2791 CMyComPtr<ISequentialOutStream> realOutStream;
2764 const Int32 askMode = testMode ? 2792 const Int32 askMode = testMode ?
2765 NExtract::NAskMode::kTest : 2793 NExtract::NAskMode::kTest :
@@ -2780,9 +2808,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2780 continue; 2808 continue;
2781 RINOK(extractCallback->PrepareOperation(askMode)) 2809 RINOK(extractCallback->PrepareOperation(askMode))
2782 2810
2783 outStreamSpec->SetStream(realOutStream); 2811 outStream->SetStream(realOutStream);
2784 realOutStream.Release(); 2812 realOutStream.Release();
2785 outStreamSpec->Init(); 2813 outStream->Init();
2786 2814
2787 const CMftRec &rec = Recs[item.RecIndex]; 2815 const CMftRec &rec = Recs[item.RecIndex];
2788 2816
@@ -2797,7 +2825,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2797 RINOK(hres) 2825 RINOK(hres)
2798 if (inStream) 2826 if (inStream)
2799 { 2827 {
2800 hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); 2828 hres = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);
2801 if (hres != S_OK && hres != S_FALSE) 2829 if (hres != S_OK && hres != S_FALSE)
2802 { 2830 {
2803 RINOK(hres) 2831 RINOK(hres)
@@ -2813,7 +2841,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2813 totalPackSize += data.GetPackSize(); 2841 totalPackSize += data.GetPackSize();
2814 totalSize += data.GetSize(); 2842 totalSize += data.GetSize();
2815 } 2843 }
2816 outStreamSpec->ReleaseStream(); 2844 outStream->ReleaseStream();
2817 RINOK(extractCallback->SetOperationResult(res)) 2845 RINOK(extractCallback->SetOperationResult(res))
2818 } 2846 }
2819 return S_OK; 2847 return S_OK;
@@ -2843,6 +2871,12 @@ Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
2843 { 2871 {
2844 RINOK(PROPVARIANT_to_bool(prop, _showSystemFiles)) 2872 RINOK(PROPVARIANT_to_bool(prop, _showSystemFiles))
2845 } 2873 }
2874 else if (IsString1PrefixedByString2_NoCase_Ascii(name, "mt"))
2875 {
2876 }
2877 else if (IsString1PrefixedByString2_NoCase_Ascii(name, "memuse"))
2878 {
2879 }
2846 else 2880 else
2847 return E_INVALIDARG; 2881 return E_INVALIDARG;
2848 } 2882 }
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp
index 9851ed3..0cab820 100644
--- a/CPP/7zip/Archive/PeHandler.cpp
+++ b/CPP/7zip/Archive/PeHandler.cpp
@@ -516,8 +516,15 @@ static const CUInt32PCharPair g_MachinePairs[] =
516 { 0x0520, "TriCore" }, 516 { 0x0520, "TriCore" },
517 { 0x0CEF, "CEF" }, 517 { 0x0CEF, "CEF" },
518 { 0x0EBC, "EFI" }, 518 { 0x0EBC, "EFI" },
519 { 0x5032, "RISCV32" },
520 { 0x5064, "RISCV64" },
521// { 0x5128, "RISCV128" },
522 { 0x6232, "LOONGARCH32" },
523 { 0x6264, "LOONGARCH64" },
519 { 0x8664, "x64" }, 524 { 0x8664, "x64" },
520 { 0x9041, "M32R" }, 525 { 0x9041, "M32R" },
526 { 0xA641, "ARM64EC" },
527 { 0xA64e, "ARM64X" },
521 { 0xAA64, "ARM64" }, 528 { 0xAA64, "ARM64" },
522 { 0xC0EE, "CEE" } 529 { 0xC0EE, "CEE" }
523}; 530};
diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp
index e5c2f9b..5f9e1c3 100644
--- a/CPP/7zip/Archive/PpmdHandler.cpp
+++ b/CPP/7zip/Archive/PpmdHandler.cpp
@@ -74,7 +74,7 @@ HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize)
74 return S_FALSE; 74 return S_FALSE;
75 Attrib = GetUi32(h + 4); 75 Attrib = GetUi32(h + 4);
76 Time = GetUi32(h + 12); 76 Time = GetUi32(h + 12);
77 unsigned info = GetUi16(h + 8); 77 const unsigned info = GetUi16(h + 8);
78 Order = (info & 0xF) + 1; 78 Order = (info & 0xF) + 1;
79 MemInMB = ((info >> 4) & 0xFF) + 1; 79 MemInMB = ((info >> 4) & 0xFF) + 1;
80 Ver = info >> 12; 80 Ver = info >> 12;
@@ -90,7 +90,7 @@ HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize)
90 if (nameLen > (1 << 9)) 90 if (nameLen > (1 << 9))
91 return S_FALSE; 91 return S_FALSE;
92 char *name = Name.GetBuf(nameLen); 92 char *name = Name.GetBuf(nameLen);
93 HRESULT res = ReadStream_FALSE(s, name, nameLen); 93 const HRESULT res = ReadStream_FALSE(s, name, nameLen);
94 Name.ReleaseBuf_CalcLen(nameLen); 94 Name.ReleaseBuf_CalcLen(nameLen);
95 headerSize = kHeaderSize + nameLen; 95 headerSize = kHeaderSize + nameLen;
96 return res; 96 return res;
@@ -128,12 +128,12 @@ IMP_IInArchive_ArcProps
128void CHandler::GetVersion(NCOM::CPropVariant &prop) 128void CHandler::GetVersion(NCOM::CPropVariant &prop)
129{ 129{
130 AString s ("PPMd"); 130 AString s ("PPMd");
131 s += (char)('A' + _item.Ver); 131 s.Add_Char((char)('A' + _item.Ver));
132 s += ":o"; 132 s += ":o";
133 s.Add_UInt32(_item.Order); 133 s.Add_UInt32(_item.Order);
134 s += ":mem"; 134 s += ":mem";
135 s.Add_UInt32(_item.MemInMB); 135 s.Add_UInt32(_item.MemInMB);
136 s += 'm'; 136 s.Add_Char('m');
137 if (_item.Ver >= kNewHeaderVer && _item.Restor != 0) 137 if (_item.Ver >= kNewHeaderVer && _item.Restor != 0)
138 { 138 {
139 s += ":r"; 139 s += ":r";
@@ -287,6 +287,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
287 // extractCallback->SetTotal(_packSize); 287 // extractCallback->SetTotal(_packSize);
288 UInt64 currentTotalPacked = 0; 288 UInt64 currentTotalPacked = 0;
289 RINOK(extractCallback->SetCompleted(&currentTotalPacked)) 289 RINOK(extractCallback->SetCompleted(&currentTotalPacked))
290 Int32 opRes;
291{
290 CMyComPtr<ISequentialOutStream> realOutStream; 292 CMyComPtr<ISequentialOutStream> realOutStream;
291 const Int32 askMode = testMode ? 293 const Int32 askMode = testMode ?
292 NExtract::NAskMode::kTest : 294 NExtract::NAskMode::kTest :
@@ -295,7 +297,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
295 if (!testMode && !realOutStream) 297 if (!testMode && !realOutStream)
296 return S_OK; 298 return S_OK;
297 299
298 extractCallback->PrepareOperation(askMode); 300 RINOK(extractCallback->PrepareOperation(askMode))
299 301
300 CByteInBufWrap inBuf; 302 CByteInBufWrap inBuf;
301 if (!inBuf.Alloc(1 << 20)) 303 if (!inBuf.Alloc(1 << 20))
@@ -306,15 +308,14 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
306 if (!outBuf.Alloc()) 308 if (!outBuf.Alloc())
307 return E_OUTOFMEMORY; 309 return E_OUTOFMEMORY;
308 310
309 CLocalProgress *lps = new CLocalProgress; 311 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
310 CMyComPtr<ICompressProgressInfo> progress = lps;
311 lps->Init(extractCallback, true); 312 lps->Init(extractCallback, true);
312 313
313 CPpmdCpp ppmd(_item.Ver); 314 CPpmdCpp ppmd(_item.Ver);
314 if (!ppmd.Alloc(_item.MemInMB)) 315 if (!ppmd.Alloc(_item.MemInMB))
315 return E_OUTOFMEMORY; 316 return E_OUTOFMEMORY;
316 317
317 Int32 opRes = NExtract::NOperationResult::kUnsupportedMethod; 318 opRes = NExtract::NOperationResult::kUnsupportedMethod;
318 319
319 if (_item.IsSupported()) 320 if (_item.IsSupported())
320 { 321 {
@@ -380,8 +381,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
380 381
381 RINOK(inBuf.Res) 382 RINOK(inBuf.Res)
382 } 383 }
383 384}
384 realOutStream.Release();
385 return extractCallback->SetOperationResult(opRes); 385 return extractCallback->SetOperationResult(opRes);
386} 386}
387 387
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
index 87d11e7..b786f3e 100644
--- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp
+++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
@@ -17,6 +17,7 @@
17 17
18#include "../../Common/FilterCoder.h" 18#include "../../Common/FilterCoder.h"
19#include "../../Common/LimitedStreams.h" 19#include "../../Common/LimitedStreams.h"
20#include "../../Common/MethodProps.h"
20#include "../../Common/ProgressUtils.h" 21#include "../../Common/ProgressUtils.h"
21#include "../../Common/RegisterArc.h" 22#include "../../Common/RegisterArc.h"
22#include "../../Common/StreamObjects.h" 23#include "../../Common/StreamObjects.h"
@@ -28,12 +29,13 @@
28 29
29#include "../../Crypto/Rar5Aes.h" 30#include "../../Crypto/Rar5Aes.h"
30 31
31#include "../Common/FindSignature.h" 32#include "../../Archive/Common/FindSignature.h"
32#include "../Common/ItemNameUtils.h" 33#include "../../Archive/Common/ItemNameUtils.h"
34#include "../../Archive/Common/HandlerOut.h"
33 35
34#include "../HandlerCont.h" 36#include "../../Archive/HandlerCont.h"
35 37
36#include "RarVol.h" 38#include "../../Archive/Rar/RarVol.h"
37#include "Rar5Handler.h" 39#include "Rar5Handler.h"
38 40
39using namespace NWindows; 41using namespace NWindows;
@@ -48,7 +50,9 @@ static const unsigned kMarkerSize = 8;
48static const Byte kMarker[kMarkerSize] = 50static const Byte kMarker[kMarkerSize] =
49 { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0 }; 51 { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0 };
50 52
51static const size_t kCommentSize_Max = (size_t)1 << 16; 53// Comment length is limited to 256 KB in rar-encoder.
54// So we use same limitation
55static const size_t kCommentSize_Max = (size_t)1 << 18;
52 56
53 57
54static const char * const kHostOS[] = 58static const char * const kHostOS[] =
@@ -104,34 +108,53 @@ static const char * const g_LinkTypes[] =
104static const char g_ExtraTimeFlags[] = { 'u', 'M', 'C', 'A', 'n' }; 108static const char g_ExtraTimeFlags[] = { 'u', 'M', 'C', 'A', 'n' };
105 109
106 110
107static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val) 111static
112Z7_NO_INLINE
113unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val_ptr)
108{ 114{
109 *val = 0; 115 if (maxSize > 10)
110 116 maxSize = 10;
111 for (unsigned i = 0; i < maxSize && i < 10;) 117 UInt64 val = 0;
118 unsigned i;
119 for (i = 0; i < maxSize;)
112 { 120 {
113 Byte b = p[i]; 121 const unsigned b = p[i];
114 *val |= (UInt64)(b & 0x7F) << (7 * i); 122 val |= (UInt64)(b & 0x7F) << (7 * i);
115 i++; 123 i++;
116 if ((b & 0x80) == 0) 124 if ((b & 0x80) == 0)
125 {
126 *val_ptr = val;
117 return i; 127 return i;
128 }
118 } 129 }
119 return 0; 130 *val_ptr = 0;
131#if 1
132 return 0; // 7zip-unrar : strict check of error
133#else
134 return i; // original-unrar : ignore error
135#endif
136}
137
138
139#define PARSE_VAR_INT(p, size, dest) \
140{ const unsigned num_ = ReadVarInt(p, size, &dest); \
141 if (num_ == 0) return false; \
142 p += num_; \
143 size -= num_; \
120} 144}
121 145
122 146
123bool CLinkInfo::Parse(const Byte *p, unsigned size) 147bool CLinkInfo::Parse(const Byte *p, unsigned size)
124{ 148{
125 const Byte *pStart = p; 149 const Byte *pStart = p;
126 unsigned num;
127 UInt64 len; 150 UInt64 len;
128 num = ReadVarInt(p, size, &Type); if (num == 0) { return false; } p += num; size -= num; 151 PARSE_VAR_INT(p, size, Type)
129 num = ReadVarInt(p, size, &Flags); if (num == 0) { return false; } p += num; size -= num; 152 PARSE_VAR_INT(p, size, Flags)
130 num = ReadVarInt(p, size, &len); if (num == 0) { return false; } p += num; size -= num; 153 PARSE_VAR_INT(p, size, len)
131 if (size != len) 154 if (size != len)
132 return false; 155 return false;
133 NameLen = (unsigned)len; 156 NameLen = (unsigned)len;
134 NameOffset = (unsigned)(p - pStart); 157 NameOffset = (unsigned)(size_t)(p - pStart);
135 return true; 158 return true;
136} 159}
137 160
@@ -174,7 +197,7 @@ int CItem::FindExtra(unsigned extraID, unsigned &recordDataSize) const
174 197
175 { 198 {
176 UInt64 size; 199 UInt64 size;
177 unsigned num = ReadVarInt(Extra + offset, rem, &size); 200 const unsigned num = ReadVarInt(Extra + offset, rem, &size);
178 if (num == 0) 201 if (num == 0)
179 return -1; 202 return -1;
180 offset += num; 203 offset += num;
@@ -185,7 +208,7 @@ int CItem::FindExtra(unsigned extraID, unsigned &recordDataSize) const
185 } 208 }
186 { 209 {
187 UInt64 id; 210 UInt64 id;
188 unsigned num = ReadVarInt(Extra + offset, rem, &id); 211 const unsigned num = ReadVarInt(Extra + offset, rem, &id);
189 if (num == 0) 212 if (num == 0)
190 return -1; 213 return -1;
191 offset += num; 214 offset += num;
@@ -257,17 +280,17 @@ void CItem::PrintInfo(AString &s) const
257 { 280 {
258 const Byte *p = Extra + offset; 281 const Byte *p = Extra + offset;
259 UInt64 flags; 282 UInt64 flags;
260 unsigned num = ReadVarInt(p, rem, &flags); 283 const unsigned num = ReadVarInt(p, rem, &flags);
261 if (num != 0) 284 if (num != 0)
262 { 285 {
263 s += ':'; 286 s.Add_Colon();
264 for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExtraTimeFlags); i++) 287 for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExtraTimeFlags); i++)
265 if ((flags & ((UInt64)1 << i)) != 0) 288 if ((flags & ((UInt64)1 << i)) != 0)
266 s += g_ExtraTimeFlags[i]; 289 s.Add_Char(g_ExtraTimeFlags[i]);
267 flags &= ~(((UInt64)1 << Z7_ARRAY_SIZE(g_ExtraTimeFlags)) - 1); 290 flags &= ~(((UInt64)1 << Z7_ARRAY_SIZE(g_ExtraTimeFlags)) - 1);
268 if (flags != 0) 291 if (flags != 0)
269 { 292 {
270 s += '_'; 293 s.Add_Char('_');
271 AddHex64(s, flags); 294 AddHex64(s, flags);
272 } 295 }
273 } 296 }
@@ -277,20 +300,20 @@ void CItem::PrintInfo(AString &s) const
277 CLinkInfo linkInfo; 300 CLinkInfo linkInfo;
278 if (linkInfo.Parse(Extra + offset, (unsigned)rem)) 301 if (linkInfo.Parse(Extra + offset, (unsigned)rem))
279 { 302 {
280 s += ':'; 303 s.Add_Colon();
281 PrintType(s, g_LinkTypes, Z7_ARRAY_SIZE(g_LinkTypes), linkInfo.Type); 304 PrintType(s, g_LinkTypes, Z7_ARRAY_SIZE(g_LinkTypes), linkInfo.Type);
282 UInt64 flags = linkInfo.Flags; 305 UInt64 flags = linkInfo.Flags;
283 if (flags != 0) 306 if (flags != 0)
284 { 307 {
285 s += ':'; 308 s.Add_Colon();
286 if (flags & NLinkFlags::kTargetIsDir) 309 if (flags & NLinkFlags::kTargetIsDir)
287 { 310 {
288 s += 'D'; 311 s.Add_Char('D');
289 flags &= ~((UInt64)NLinkFlags::kTargetIsDir); 312 flags &= ~((UInt64)NLinkFlags::kTargetIsDir);
290 } 313 }
291 if (flags != 0) 314 if (flags != 0)
292 { 315 {
293 s += '_'; 316 s.Add_Char('_');
294 AddHex64(s, flags); 317 AddHex64(s, flags);
295 } 318 }
296 } 319 }
@@ -310,19 +333,12 @@ bool CCryptoInfo::Parse(const Byte *p, size_t size)
310 Algo = 0; 333 Algo = 0;
311 Flags = 0; 334 Flags = 0;
312 Cnt = 0; 335 Cnt = 0;
313 336 PARSE_VAR_INT(p, size, Algo)
314 unsigned num = ReadVarInt(p, size, &Algo); 337 PARSE_VAR_INT(p, size, Flags)
315 if (num == 0) { return false; } p += num; size -= num;
316
317 num = ReadVarInt(p, size, &Flags);
318 if (num == 0) { return false; } p += num; size -= num;
319
320 if (size > 0) 338 if (size > 0)
321 Cnt = p[0]; 339 Cnt = p[0];
322
323 if (size != 1 + 16 + 16 + (unsigned)(IsThereCheck() ? 12 : 0)) 340 if (size != 1 + 16 + 16 + (unsigned)(IsThereCheck() ? 12 : 0))
324 return false; 341 return false;
325
326 return true; 342 return true;
327} 343}
328 344
@@ -330,18 +346,14 @@ bool CCryptoInfo::Parse(const Byte *p, size_t size)
330bool CItem::FindExtra_Version(UInt64 &version) const 346bool CItem::FindExtra_Version(UInt64 &version) const
331{ 347{
332 unsigned size; 348 unsigned size;
333 int offset = FindExtra(NExtraID::kVersion, size); 349 const int offset = FindExtra(NExtraID::kVersion, size);
334 if (offset < 0) 350 if (offset < 0)
335 return false; 351 return false;
336 const Byte *p = Extra + (unsigned)offset; 352 const Byte *p = Extra + (unsigned)offset;
337 353
338 UInt64 flags; 354 UInt64 flags;
339 unsigned num = ReadVarInt(p, size, &flags); 355 PARSE_VAR_INT(p, size, flags)
340 if (num == 0) { return false; } p += num; size -= num; 356 PARSE_VAR_INT(p, size, version)
341
342 num = ReadVarInt(p, size, &version);
343 if (num == 0) { return false; } p += num; size -= num;
344
345 return size == 0; 357 return size == 0;
346} 358}
347 359
@@ -407,7 +419,7 @@ bool CItem::GetAltStreamName(AString &name) const
407{ 419{
408 name.Empty(); 420 name.Empty();
409 unsigned size; 421 unsigned size;
410 int offset = FindExtra(NExtraID::kSubdata, size); 422 const int offset = FindExtra(NExtraID::kSubdata, size);
411 if (offset < 0) 423 if (offset < 0)
412 return false; 424 return false;
413 name.SetFrom_CalcLen((const char *)(Extra + (unsigned)offset), size); 425 name.SetFrom_CalcLen((const char *)(Extra + (unsigned)offset), size);
@@ -420,8 +432,13 @@ class CHash
420 bool _calcCRC; 432 bool _calcCRC;
421 UInt32 _crc; 433 UInt32 _crc;
422 int _blakeOffset; 434 int _blakeOffset;
423 CBlake2sp _blake; 435 CAlignedBuffer1 _buf;
436 // CBlake2sp _blake;
437 CBlake2sp *BlakeObj() { return (CBlake2sp *)(void *)(Byte *)_buf; }
424public: 438public:
439 CHash():
440 _buf(sizeof(CBlake2sp))
441 {}
425 442
426 void Init_NoCalc() 443 void Init_NoCalc()
427 { 444 {
@@ -434,17 +451,16 @@ public:
434 void Update(const void *data, size_t size); 451 void Update(const void *data, size_t size);
435 UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } 452 UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
436 453
437 bool Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoderSpec); 454 bool Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoder);
438}; 455};
439 456
440void CHash::Init(const CItem &item) 457void CHash::Init(const CItem &item)
441{ 458{
442 _crc = CRC_INIT_VAL; 459 _crc = CRC_INIT_VAL;
443 _calcCRC = item.Has_CRC(); 460 _calcCRC = item.Has_CRC();
444
445 _blakeOffset = item.FindExtra_Blake(); 461 _blakeOffset = item.FindExtra_Blake();
446 if (_blakeOffset >= 0) 462 if (_blakeOffset >= 0)
447 Blake2sp_Init(&_blake); 463 Blake2sp_Init(BlakeObj());
448} 464}
449 465
450void CHash::Update(const void *data, size_t size) 466void CHash::Update(const void *data, size_t size)
@@ -452,30 +468,28 @@ void CHash::Update(const void *data, size_t size)
452 if (_calcCRC) 468 if (_calcCRC)
453 _crc = CrcUpdate(_crc, data, size); 469 _crc = CrcUpdate(_crc, data, size);
454 if (_blakeOffset >= 0) 470 if (_blakeOffset >= 0)
455 Blake2sp_Update(&_blake, (const Byte *)data, size); 471 Blake2sp_Update(BlakeObj(), (const Byte *)data, size);
456} 472}
457 473
458bool CHash::Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoderSpec) 474bool CHash::Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoder)
459{ 475{
460 if (_calcCRC) 476 if (_calcCRC)
461 { 477 {
462 UInt32 crc = GetCRC(); 478 UInt32 crc = GetCRC();
463 if (cryptoDecoderSpec) 479 if (cryptoDecoder)
464 crc = cryptoDecoderSpec->Hmac_Convert_Crc32(crc); 480 crc = cryptoDecoder->Hmac_Convert_Crc32(crc);
465 if (crc != item.CRC) 481 if (crc != item.CRC)
466 return false; 482 return false;
467 } 483 }
468
469 if (_blakeOffset >= 0) 484 if (_blakeOffset >= 0)
470 { 485 {
471 Byte digest[BLAKE2S_DIGEST_SIZE]; 486 UInt32 digest[Z7_BLAKE2S_DIGEST_SIZE / sizeof(UInt32)];
472 Blake2sp_Final(&_blake, digest); 487 Blake2sp_Final(BlakeObj(), (Byte *)(void *)digest);
473 if (cryptoDecoderSpec) 488 if (cryptoDecoder)
474 cryptoDecoderSpec->Hmac_Convert_32Bytes(digest); 489 cryptoDecoder->Hmac_Convert_32Bytes((Byte *)(void *)digest);
475 if (memcmp(digest, &item.Extra[(unsigned)_blakeOffset], BLAKE2S_DIGEST_SIZE) != 0) 490 if (memcmp(digest, item.Extra + (unsigned)_blakeOffset, Z7_BLAKE2S_DIGEST_SIZE) != 0)
476 return false; 491 return false;
477 } 492 }
478
479 return true; 493 return true;
480} 494}
481 495
@@ -484,10 +498,10 @@ Z7_CLASS_IMP_NOQIB_1(
484 COutStreamWithHash 498 COutStreamWithHash
485 , ISequentialOutStream 499 , ISequentialOutStream
486) 500)
501 bool _size_Defined;
487 ISequentialOutStream *_stream; 502 ISequentialOutStream *_stream;
488 UInt64 _pos; 503 UInt64 _pos;
489 UInt64 _size; 504 UInt64 _size;
490 bool _size_Defined;
491 Byte *_destBuf; 505 Byte *_destBuf;
492public: 506public:
493 CHash _hash; 507 CHash _hash;
@@ -495,7 +509,7 @@ public:
495 COutStreamWithHash(): _destBuf(NULL) {} 509 COutStreamWithHash(): _destBuf(NULL) {}
496 510
497 void SetStream(ISequentialOutStream *stream) { _stream = stream; } 511 void SetStream(ISequentialOutStream *stream) { _stream = stream; }
498 void Init(const CItem &item, Byte *destBuf) 512 void Init(const CItem &item, Byte *destBuf, bool needChecksumCheck)
499 { 513 {
500 _size_Defined = false; 514 _size_Defined = false;
501 _size = 0; 515 _size = 0;
@@ -507,7 +521,10 @@ public:
507 _destBuf = destBuf; 521 _destBuf = destBuf;
508 } 522 }
509 _pos = 0; 523 _pos = 0;
510 _hash.Init(item); 524 if (needChecksumCheck)
525 _hash.Init(item);
526 else
527 _hash.Init_NoCalc();
511 } 528 }
512 UInt64 GetPos() const { return _pos; } 529 UInt64 GetPos() const { return _pos; }
513}; 530};
@@ -518,7 +535,7 @@ Z7_COM7F_IMF(COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *pr
518 HRESULT result = S_OK; 535 HRESULT result = S_OK;
519 if (_size_Defined) 536 if (_size_Defined)
520 { 537 {
521 UInt64 rem = _size - _pos; 538 const UInt64 rem = _size - _pos;
522 if (size > rem) 539 if (size > rem)
523 size = (UInt32)rem; 540 size = (UInt32)rem;
524 } 541 }
@@ -544,8 +561,7 @@ class CInArchive
544 size_t _bufPos; 561 size_t _bufPos;
545 ISequentialInStream *_stream; 562 ISequentialInStream *_stream;
546 563
547 NCrypto::NRar5::CDecoder *m_CryptoDecoderSpec; 564 CMyComPtr2<ICompressFilter, NCrypto::NRar5::CDecoder> m_CryptoDecoder;
548 CMyComPtr<ICompressFilter> m_CryptoDecoder;
549 565
550 Z7_CLASS_NO_COPY(CInArchive) 566 Z7_CLASS_NO_COPY(CInArchive)
551 567
@@ -561,6 +577,10 @@ public:
561 UInt64 StreamStartPosition; 577 UInt64 StreamStartPosition;
562 UInt64 Position; 578 UInt64 Position;
563 579
580 size_t Get_Buf_RemainSize() const { return _bufSize - _bufPos; }
581 bool Is_Buf_Finished() const { return _bufPos == _bufSize; }
582 const Byte *Get_Buf_Data() const { return _buf + _bufPos; }
583 void Move_BufPos(size_t num) { _bufPos += num; }
564 bool ReadVar(UInt64 &val); 584 bool ReadVar(UInt64 &val);
565 585
566 struct CHeader 586 struct CHeader
@@ -585,7 +605,7 @@ public:
585}; 605};
586 606
587 607
588static HRESULT MySetPassword(ICryptoGetTextPassword *getTextPassword, NCrypto::NRar5::CDecoder *cryptoDecoderSpec) 608static HRESULT MySetPassword(ICryptoGetTextPassword *getTextPassword, NCrypto::NRar5::CDecoder *cryptoDecoder)
589{ 609{
590 CMyComBSTR_Wipe password; 610 CMyComBSTR_Wipe password;
591 RINOK(getTextPassword->CryptoGetTextPassword(&password)) 611 RINOK(getTextPassword->CryptoGetTextPassword(&password))
@@ -596,15 +616,15 @@ static HRESULT MySetPassword(ICryptoGetTextPassword *getTextPassword, NCrypto::N
596 if (unicode.Len() > kPasswordLen_MAX) 616 if (unicode.Len() > kPasswordLen_MAX)
597 unicode.DeleteFrom(kPasswordLen_MAX); 617 unicode.DeleteFrom(kPasswordLen_MAX);
598 ConvertUnicodeToUTF8(unicode, utf8); 618 ConvertUnicodeToUTF8(unicode, utf8);
599 cryptoDecoderSpec->SetPassword((const Byte *)(const char *)utf8, utf8.Len()); 619 cryptoDecoder->SetPassword((const Byte *)(const char *)utf8, utf8.Len());
600 return S_OK; 620 return S_OK;
601} 621}
602 622
603 623
604bool CInArchive::ReadVar(UInt64 &val) 624bool CInArchive::ReadVar(UInt64 &val)
605{ 625{
606 unsigned offset = ReadVarInt(_buf + _bufPos, _bufSize - _bufPos, &val); 626 const unsigned offset = ReadVarInt(Get_Buf_Data(), Get_Buf_RemainSize(), &val);
607 _bufPos += offset; 627 Move_BufPos(offset);
608 return (offset != 0); 628 return (offset != 0);
609} 629}
610 630
@@ -627,61 +647,63 @@ HRESULT CInArchive::ReadBlockHeader(CHeader &h)
627 h.ExtraSize = 0; 647 h.ExtraSize = 0;
628 h.DataSize = 0; 648 h.DataSize = 0;
629 649
630 const unsigned kStartSize = 4 + 3; 650 Byte buf[AES_BLOCK_SIZE];
631 const unsigned kBufSize = AES_BLOCK_SIZE + AES_BLOCK_SIZE; // must be >= kStartSize;
632 Byte buf[kBufSize];
633 unsigned filled; 651 unsigned filled;
634 652
635 if (m_CryptoMode) 653 if (m_CryptoMode)
636 { 654 {
637 RINOK(ReadStream_Check(buf, kBufSize)) 655 _buf.AllocAtLeast(1 << 12); // at least (AES_BLOCK_SIZE * 2)
638 memcpy(m_CryptoDecoderSpec->_iv, buf, AES_BLOCK_SIZE);
639 RINOK(m_CryptoDecoderSpec->Init())
640
641 _buf.AllocAtLeast(1 << 12);
642 if (!(Byte *)_buf) 656 if (!(Byte *)_buf)
643 return E_OUTOFMEMORY; 657 return E_OUTOFMEMORY;
644 658 RINOK(ReadStream_Check(_buf, AES_BLOCK_SIZE * 2))
645 memcpy(_buf, buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE); 659 memcpy(m_CryptoDecoder->_iv, _buf, AES_BLOCK_SIZE);
646 if (m_CryptoDecoder->Filter(_buf, AES_BLOCK_SIZE) != AES_BLOCK_SIZE) 660 RINOK(m_CryptoDecoder->Init())
661 if (m_CryptoDecoder->Filter(_buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE) != AES_BLOCK_SIZE)
647 return E_FAIL; 662 return E_FAIL;
648 memcpy(buf, _buf, AES_BLOCK_SIZE); 663 memcpy(buf, _buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE);
649 filled = AES_BLOCK_SIZE; 664 filled = AES_BLOCK_SIZE;
650 } 665 }
651 else 666 else
652 { 667 {
668 const unsigned kStartSize = 4 + 3;
653 RINOK(ReadStream_Check(buf, kStartSize)) 669 RINOK(ReadStream_Check(buf, kStartSize))
654 filled = kStartSize; 670 filled = kStartSize;
655 } 671 }
656 672
657 UInt64 val;
658 unsigned offset = ReadVarInt(buf + 4, 3, &val);
659 if (offset == 0)
660 return S_FALSE;
661 { 673 {
674 UInt64 val;
675 unsigned offset = ReadVarInt(buf + 4, 3, &val);
676 if (offset == 0)
677 return S_FALSE;
662 size_t size = (size_t)val; 678 size_t size = (size_t)val;
663 _bufPos = (4 + offset);
664 _bufSize = _bufPos + size;
665 if (size < 2) 679 if (size < 2)
666 return S_FALSE; 680 return S_FALSE;
667 } 681 offset += 4;
668 682 _bufPos = offset;
669 size_t allocSize = _bufSize; 683 size += offset;
670 if (m_CryptoMode) 684 _bufSize = size;
671 allocSize = (allocSize + AES_BLOCK_SIZE - 1) & ~(size_t)(AES_BLOCK_SIZE - 1); 685 if (m_CryptoMode)
672 _buf.AllocAtLeast(allocSize); 686 size = (size + AES_BLOCK_SIZE - 1) & ~(size_t)(AES_BLOCK_SIZE - 1);
673 if (!(Byte *)_buf) 687 _buf.AllocAtLeast(size);
674 return E_OUTOFMEMORY; 688 if (!(Byte *)_buf)
675 689 return E_OUTOFMEMORY;
676 memcpy(_buf, buf, filled); 690 memcpy(_buf, buf, filled);
677 691 const size_t rem = size - filled;
678 size_t rem = allocSize - filled; 692 AddToSeekValue(size + (m_CryptoMode ? AES_BLOCK_SIZE : 0));
679 AddToSeekValue(allocSize + (m_CryptoMode ? AES_BLOCK_SIZE : 0)); 693 RINOK(ReadStream_Check(_buf + filled, rem))
680 RINOK(ReadStream_Check(_buf + filled, rem)) 694 if (m_CryptoMode)
681 if (m_CryptoMode) 695 {
682 { 696 if (m_CryptoDecoder->Filter(_buf + filled, (UInt32)rem) != rem)
683 if (m_CryptoDecoder->Filter(_buf + filled, (UInt32)rem) != rem) 697 return E_FAIL;
684 return E_FAIL; 698#if 1
699 // optional 7zip-unrar check : remainder must contain zeros.
700 const size_t pad = size - _bufSize;
701 const Byte *p = _buf + _bufSize;
702 for (size_t i = 0; i < pad; i++)
703 if (p[i])
704 return S_FALSE;
705#endif
706 }
685 } 707 }
686 708
687 if (CrcCalc(_buf + 4, _bufSize - 4) != Get32(buf)) 709 if (CrcCalc(_buf + 4, _bufSize - 4) != Get32(buf))
@@ -695,7 +717,7 @@ HRESULT CInArchive::ReadBlockHeader(CHeader &h)
695 UInt64 extraSize; 717 UInt64 extraSize;
696 if (!ReadVar(extraSize)) 718 if (!ReadVar(extraSize))
697 return S_FALSE; 719 return S_FALSE;
698 if (extraSize > _bufSize) 720 if (extraSize >= (1u << 21))
699 return S_FALSE; 721 return S_FALSE;
700 h.ExtraSize = (size_t)extraSize; 722 h.ExtraSize = (size_t)extraSize;
701 } 723 }
@@ -706,85 +728,117 @@ HRESULT CInArchive::ReadBlockHeader(CHeader &h)
706 return S_FALSE; 728 return S_FALSE;
707 } 729 }
708 730
731 if (h.ExtraSize > Get_Buf_RemainSize())
732 return S_FALSE;
709 return S_OK; 733 return S_OK;
710} 734}
711 735
712 736
713/* 737bool CInArcInfo::CLocator::Parse(const Byte *p, size_t size)
714int CInArcInfo::FindExtra(unsigned extraID, unsigned &recordDataSize) const
715{ 738{
716 recordDataSize = 0; 739 Flags = 0;
717 size_t offset = 0; 740 QuickOpen = 0;
741 Recovery = 0;
718 742
719 for (;;) 743 PARSE_VAR_INT(p, size, Flags)
744
745 if (Is_QuickOpen())
720 { 746 {
721 size_t rem = Extra.Size() - offset; 747 PARSE_VAR_INT(p, size, QuickOpen)
722 if (rem == 0) 748 }
723 return -1; 749 if (Is_Recovery())
724 750 {
751 PARSE_VAR_INT(p, size, Recovery)
752 }
753#if 0
754 // another records are possible in future rar formats.
755 if (size != 0)
756 return false;
757#endif
758 return true;
759}
760
761
762bool CInArcInfo::CMetadata::Parse(const Byte *p, size_t size)
763{
764 PARSE_VAR_INT(p, size, Flags)
765 if (Flags & NMetadataFlags::kArcName)
766 {
767 UInt64 nameLen;
768 PARSE_VAR_INT(p, size, nameLen)
769 if (nameLen > size)
770 return false;
771 ArcName.SetFrom_CalcLen((const char *)(const void *)p, (unsigned)nameLen);
772 p += (size_t)nameLen;
773 size -= (size_t)nameLen;
774 }
775 if (Flags & NMetadataFlags::kCTime)
776 {
777 if ((Flags & NMetadataFlags::kUnixTime) &&
778 (Flags & NMetadataFlags::kNanoSec) == 0)
725 { 779 {
726 UInt64 size; 780 if (size < 4)
727 unsigned num = ReadVarInt(Extra + offset, rem, &size); 781 return false;
728 if (num == 0) 782 CTime = GetUi32(p);
729 return -1; 783 p += 4;
730 offset += num; 784 size -= 4;
731 rem -= num;
732 if (size > rem)
733 return -1;
734 rem = (size_t)size;
735 } 785 }
786 else
736 { 787 {
737 UInt64 id; 788 if (size < 8)
738 unsigned num = ReadVarInt(Extra + offset, rem, &id); 789 return false;
739 if (num == 0) 790 CTime = GetUi64(p);
740 return -1; 791 p += 8;
741 offset += num; 792 size -= 8;
742 rem -= num;
743
744 if (id == extraID)
745 {
746 recordDataSize = (unsigned)rem;
747 return (int)offset;
748 }
749
750 offset += rem;
751 } 793 }
752 } 794 }
795#if 0
796 // another records are possible in future rar formats.
797 if (size != 0)
798 return false;
799#endif
800 return true;
753} 801}
754 802
755 803
756bool CInArcInfo::FindExtra_Locator(CLocator &locator) const 804bool CInArcInfo::ParseExtra(const Byte *p, size_t size)
757{ 805{
758 locator.Flags = 0; 806 for (;;)
759 locator.QuickOpen = 0;
760 locator.Recovery = 0;
761
762 unsigned size;
763 int offset = FindExtra(kArcExtraRecordType_Locator, size);
764 if (offset < 0)
765 return false;
766 const Byte *p = Extra + (unsigned)offset;
767
768 unsigned num;
769
770 num = ReadVarInt(p, size, &locator.Flags);
771 if (num == 0) return false; p += num; size -= num;
772
773 if (locator.Is_QuickOpen())
774 {
775 num = ReadVarInt(p, size, &locator.QuickOpen);
776 if (num == 0) return false; p += num; size -= num;
777 }
778
779 if (locator.Is_Recovery())
780 { 807 {
781 num = ReadVarInt(p, size, &locator.Recovery); 808 if (size == 0)
782 if (num == 0) return false; p += num; size -= num; 809 return true;
810 UInt64 recSize64, id;
811 PARSE_VAR_INT(p, size, recSize64)
812 if (recSize64 > size)
813 return false;
814 size_t recSize = (size_t)recSize64;
815 size -= recSize;
816 // READ_VAR_INT(p, recSize, recSize)
817 {
818 const unsigned num = ReadVarInt(p, recSize, &id);
819 if (num == 0)
820 return false;
821 p += num;
822 recSize -= num;
823 }
824 if (id == kArcExtraRecordType_Metadata)
825 {
826 Metadata_Defined = true;
827 if (!Metadata.Parse(p, recSize))
828 Metadata_Error = true;
829 }
830 else if (id == kArcExtraRecordType_Locator)
831 {
832 Locator_Defined = true;
833 if (!Locator.Parse(p, recSize))
834 Locator_Error = true;
835 }
836 else
837 UnknownExtraRecord = true;
838 p += recSize;
783 } 839 }
784
785 return true;
786} 840}
787*/ 841
788 842
789 843
790HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword, 844HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword,
@@ -830,26 +884,16 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit,
830 IsArc = true; 884 IsArc = true;
831 if (!getTextPassword) 885 if (!getTextPassword)
832 return E_NOTIMPL; 886 return E_NOTIMPL;
833
834 m_CryptoMode = true; 887 m_CryptoMode = true;
835 888 m_CryptoDecoder.Create_if_Empty();
836 if (!m_CryptoDecoder) 889 RINOK(m_CryptoDecoder->SetDecoderProps(
837 { 890 Get_Buf_Data(), (unsigned)Get_Buf_RemainSize(), false, false))
838 m_CryptoDecoderSpec = new NCrypto::NRar5::CDecoder; 891 RINOK(MySetPassword(getTextPassword, m_CryptoDecoder.ClsPtr()))
839 m_CryptoDecoder = m_CryptoDecoderSpec; 892 if (!m_CryptoDecoder->CalcKey_and_CheckPassword())
840 }
841
842 RINOK(m_CryptoDecoderSpec->SetDecoderProps(
843 _buf + _bufPos, (unsigned)(_bufSize - _bufPos), false, false))
844
845 RINOK(MySetPassword(getTextPassword, m_CryptoDecoderSpec))
846
847 if (!m_CryptoDecoderSpec->CalcKey_and_CheckPassword())
848 { 893 {
849 WrongPassword = True; 894 WrongPassword = True;
850 return S_FALSE; 895 return S_FALSE;
851 } 896 }
852
853 RINOK(ReadBlockHeader(h)) 897 RINOK(ReadBlockHeader(h))
854 } 898 }
855 899
@@ -866,42 +910,29 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit,
866 if (!ReadVar(info.VolNumber)) 910 if (!ReadVar(info.VolNumber))
867 return S_FALSE; 911 return S_FALSE;
868 912
869 if (h.ExtraSize != 0) 913 if (h.ExtraSize != Get_Buf_RemainSize())
914 return S_FALSE;
915 if (h.ExtraSize)
870 { 916 {
871 if (_bufSize - _bufPos < h.ExtraSize) 917 if (!info.ParseExtra(Get_Buf_Data(), h.ExtraSize))
872 return S_FALSE; 918 info.Extra_Error = true;
873 /*
874 info.Extra.Alloc(h.ExtraSize);
875 memcpy(info.Extra, _buf + _bufPos, h.ExtraSize);
876 */
877 _bufPos += h.ExtraSize;
878
879 /*
880 CInArcInfo::CLocator locator;
881 if (info.FindExtra_Locator(locator))
882 locator.Flags = locator.Flags;
883 */
884 } 919 }
885
886 if (_bufPos != _bufSize)
887 return S_FALSE;
888
889 return S_OK; 920 return S_OK;
890} 921}
891 922
892 923
893bool CInArchive::ReadFileHeader(const CHeader &header, CItem &item) 924bool CInArchive::ReadFileHeader(const CHeader &header, CItem &item)
894{ 925{
895 item.UnixMTime = 0;
896 item.CRC = 0;
897 item.Flags = 0;
898
899 item.CommonFlags = (UInt32)header.Flags; 926 item.CommonFlags = (UInt32)header.Flags;
900 item.PackSize = header.DataSize; 927 item.PackSize = header.DataSize;
928 item.UnixMTime = 0;
929 item.CRC = 0;
901 930
902 UInt64 flags64; 931 {
903 if (!ReadVar(flags64)) return false; 932 UInt64 flags64;
904 item.Flags = (UInt32)flags64; 933 if (!ReadVar(flags64)) return false;
934 item.Flags = (UInt32)flags64;
935 }
905 936
906 if (!ReadVar(item.Size)) return false; 937 if (!ReadVar(item.Size)) return false;
907 938
@@ -910,23 +941,20 @@ bool CInArchive::ReadFileHeader(const CHeader &header, CItem &item)
910 if (!ReadVar(attrib)) return false; 941 if (!ReadVar(attrib)) return false;
911 item.Attrib = (UInt32)attrib; 942 item.Attrib = (UInt32)attrib;
912 } 943 }
913
914 if (item.Has_UnixMTime()) 944 if (item.Has_UnixMTime())
915 { 945 {
916 if (_bufSize - _bufPos < 4) 946 if (Get_Buf_RemainSize() < 4)
917 return false; 947 return false;
918 item.UnixMTime = Get32(_buf + _bufPos); 948 item.UnixMTime = Get32(Get_Buf_Data());
919 _bufPos += 4; 949 Move_BufPos(4);
920 } 950 }
921
922 if (item.Has_CRC()) 951 if (item.Has_CRC())
923 { 952 {
924 if (_bufSize - _bufPos < 4) 953 if (Get_Buf_RemainSize() < 4)
925 return false; 954 return false;
926 item.CRC = Get32(_buf + _bufPos); 955 item.CRC = Get32(Get_Buf_Data());
927 _bufPos += 4; 956 Move_BufPos(4);
928 } 957 }
929
930 { 958 {
931 UInt64 method; 959 UInt64 method;
932 if (!ReadVar(method)) return false; 960 if (!ReadVar(method)) return false;
@@ -938,25 +966,24 @@ bool CInArchive::ReadFileHeader(const CHeader &header, CItem &item)
938 { 966 {
939 UInt64 len; 967 UInt64 len;
940 if (!ReadVar(len)) return false; 968 if (!ReadVar(len)) return false;
941 if (len > _bufSize - _bufPos) 969 if (len > Get_Buf_RemainSize())
942 return false; 970 return false;
943 item.Name.SetFrom_CalcLen((const char *)(_buf + _bufPos), (unsigned)len); 971 item.Name.SetFrom_CalcLen((const char *)Get_Buf_Data(), (unsigned)len);
944 _bufPos += (unsigned)len; 972 Move_BufPos((size_t)len);
945 } 973 }
946 974
947 item.Extra.Free(); 975 item.Extra.Free();
948 size_t extraSize = header.ExtraSize; 976 const size_t extraSize = header.ExtraSize;
949 if (extraSize != 0) 977 if (extraSize != 0)
950 { 978 {
951 if (_bufSize - _bufPos < extraSize) 979 if (Get_Buf_RemainSize() < extraSize)
952 return false; 980 return false;
953 item.Extra.Alloc(extraSize); 981 item.Extra.Alloc(extraSize);
954 memcpy(item.Extra, _buf + _bufPos, extraSize); 982 memcpy(item.Extra, Get_Buf_Data(), extraSize);
955 _bufPos += extraSize; 983 Move_BufPos(extraSize);
956 } 984 }
957
958 985
959 return (_bufPos == _bufSize); 986 return Is_Buf_Finished();
960} 987}
961 988
962 989
@@ -975,77 +1002,59 @@ struct CLinkFile
975 1002
976struct CUnpacker 1003struct CUnpacker
977{ 1004{
978 NCompress::CCopyCoder *copyCoderSpec; 1005 CMyComPtr2<ICompressCoder, NCompress::CCopyCoder> copyCoder;
979 CMyComPtr<ICompressCoder> copyCoder;
980
981 CMyComPtr<ICompressCoder> LzCoders[2]; 1006 CMyComPtr<ICompressCoder> LzCoders[2];
982 bool SolidAllowed; 1007 bool SolidAllowed;
983 1008 bool NeedCrc;
984 CFilterCoder *filterStreamSpec; 1009 CFilterCoder *filterStreamSpec;
985 CMyComPtr<ISequentialInStream> filterStream; 1010 CMyComPtr<ISequentialInStream> filterStream;
986 1011 CMyComPtr2<ICompressFilter, NCrypto::NRar5::CDecoder> cryptoDecoder;
987 NCrypto::NRar5::CDecoder *cryptoDecoderSpec;
988 CMyComPtr<ICompressFilter> cryptoDecoder;
989
990 CMyComPtr<ICryptoGetTextPassword> getTextPassword; 1012 CMyComPtr<ICryptoGetTextPassword> getTextPassword;
991 1013 CMyComPtr2<ISequentialOutStream, COutStreamWithHash> outStream;
992 COutStreamWithHash *outStreamSpec;
993 CMyComPtr<ISequentialOutStream> outStream;
994 1014
995 CByteBuffer _tempBuf; 1015 CByteBuffer _tempBuf;
996
997 CLinkFile *linkFile; 1016 CLinkFile *linkFile;
998 1017
999 CUnpacker(): linkFile(NULL) { SolidAllowed = false; } 1018 CUnpacker(): linkFile(NULL) { SolidAllowed = false; NeedCrc = true; }
1000 1019
1001 HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool isSolid, bool &wrongPassword); 1020 HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS
1021 const CItem &item, bool isSolid, bool &wrongPassword);
1002 1022
1003 HRESULT Code(const CItem &item, const CItem &lastItem, UInt64 packSize, 1023 HRESULT Code(const CItem &item, const CItem &lastItem, UInt64 packSize,
1004 ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress, 1024 ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress,
1005 bool &isCrcOK); 1025 bool &isCrcOK);
1006 1026
1007 HRESULT DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, UInt64 packSize, ISequentialInStream *inStream, CByteBuffer &buffer); 1027 HRESULT DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS
1028 const CItem &item, UInt64 packSize, ISequentialInStream *inStream, CByteBuffer &buffer);
1008}; 1029};
1009 1030
1010 1031
1011static const unsigned kLzMethodMax = 5; 1032static const unsigned kLzMethodMax = 5;
1012 1033
1013HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool isSolid, bool &wrongPassword) 1034HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS
1035 const CItem &item, bool isSolid, bool &wrongPassword)
1014{ 1036{
1015 wrongPassword = false; 1037 wrongPassword = false;
1016 1038
1017 if (item.GetAlgoVersion() != 0) 1039 if (item.Get_AlgoVersion_RawBits() > 1)
1018 return E_NOTIMPL; 1040 return E_NOTIMPL;
1019 1041
1020 if (!outStream) 1042 outStream.Create_if_Empty();
1021 {
1022 outStreamSpec = new COutStreamWithHash;
1023 outStream = outStreamSpec;
1024 }
1025 1043
1026 unsigned method = item.GetMethod(); 1044 const unsigned method = item.Get_Method();
1027 1045
1028 if (method == 0) 1046 if (method == 0)
1029 { 1047 copyCoder.Create_if_Empty();
1030 if (!copyCoder)
1031 {
1032 copyCoderSpec = new NCompress::CCopyCoder;
1033 copyCoder = copyCoderSpec;
1034 }
1035 }
1036 else 1048 else
1037 { 1049 {
1038 if (method > kLzMethodMax) 1050 if (method > kLzMethodMax)
1039 return E_NOTIMPL; 1051 return E_NOTIMPL;
1040
1041 /* 1052 /*
1042 if (item.IsSplitBefore()) 1053 if (item.IsSplitBefore())
1043 return S_FALSE; 1054 return S_FALSE;
1044 */ 1055 */
1045 1056 const unsigned lzIndex = item.IsService() ? 1 : 0;
1046 int lzIndex = item.IsService() ? 1 : 0;
1047 CMyComPtr<ICompressCoder> &lzCoder = LzCoders[lzIndex]; 1057 CMyComPtr<ICompressCoder> &lzCoder = LzCoders[lzIndex];
1048
1049 if (!lzCoder) 1058 if (!lzCoder)
1050 { 1059 {
1051 const UInt32 methodID = 0x40305; 1060 const UInt32 methodID = 0x40305;
@@ -1057,12 +1066,19 @@ HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool
1057 CMyComPtr<ICompressSetDecoderProperties2> csdp; 1066 CMyComPtr<ICompressSetDecoderProperties2> csdp;
1058 RINOK(lzCoder.QueryInterface(IID_ICompressSetDecoderProperties2, &csdp)) 1067 RINOK(lzCoder.QueryInterface(IID_ICompressSetDecoderProperties2, &csdp))
1059 1068
1060 Byte props[2] = { (Byte)(item.GetDictSize()), (Byte)(isSolid ? 1 : 0) }; 1069 const unsigned ver = item.Get_AlgoVersion_HuffRev();
1070 if (ver > 1)
1071 return E_NOTIMPL;
1072 const Byte props[2] =
1073 {
1074 (Byte)item.Get_DictSize_Main(),
1075 (Byte)((item.Get_DictSize_Frac() << 3) + (ver << 1) + (isSolid ? 1 : 0))
1076 };
1061 RINOK(csdp->SetDecoderProperties2(props, 2)) 1077 RINOK(csdp->SetDecoderProperties2(props, 2))
1062 } 1078 }
1063 1079
1064 unsigned cryptoSize = 0; 1080 unsigned cryptoSize = 0;
1065 int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize); 1081 const int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize);
1066 1082
1067 if (cryptoOffset >= 0) 1083 if (cryptoOffset >= 0)
1068 { 1084 {
@@ -1072,13 +1088,9 @@ HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool
1072 filterStream = filterStreamSpec; 1088 filterStream = filterStreamSpec;
1073 } 1089 }
1074 1090
1075 if (!cryptoDecoder) 1091 cryptoDecoder.Create_if_Empty();
1076 {
1077 cryptoDecoderSpec = new NCrypto::NRar5::CDecoder;
1078 cryptoDecoder = cryptoDecoderSpec;
1079 }
1080 1092
1081 RINOK(cryptoDecoderSpec->SetDecoderProps(item.Extra + (unsigned)cryptoOffset, cryptoSize, true, item.IsService())) 1093 RINOK(cryptoDecoder->SetDecoderProps(item.Extra + (unsigned)cryptoOffset, cryptoSize, true, item.IsService()))
1082 1094
1083 if (!getTextPassword) 1095 if (!getTextPassword)
1084 { 1096 {
@@ -1086,9 +1098,9 @@ HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool
1086 return E_NOTIMPL; 1098 return E_NOTIMPL;
1087 } 1099 }
1088 1100
1089 RINOK(MySetPassword(getTextPassword, cryptoDecoderSpec)) 1101 RINOK(MySetPassword(getTextPassword, cryptoDecoder.ClsPtr()))
1090 1102
1091 if (!cryptoDecoderSpec->CalcKey_and_CheckPassword()) 1103 if (!cryptoDecoder->CalcKey_and_CheckPassword())
1092 wrongPassword = True; 1104 wrongPassword = True;
1093 } 1105 }
1094 1106
@@ -1102,15 +1114,15 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz
1102{ 1114{
1103 isCrcOK = true; 1115 isCrcOK = true;
1104 1116
1105 unsigned method = item.GetMethod(); 1117 const unsigned method = item.Get_Method();
1106 if (method > kLzMethodMax) 1118 if (method > kLzMethodMax)
1107 return E_NOTIMPL; 1119 return E_NOTIMPL;
1108 1120
1109 bool needBuf = (linkFile && linkFile->NumLinks != 0); 1121 const bool needBuf = (linkFile && linkFile->NumLinks != 0);
1110 1122
1111 if (needBuf && !lastItem.Is_UnknownSize()) 1123 if (needBuf && !lastItem.Is_UnknownSize())
1112 { 1124 {
1113 size_t dataSize = (size_t)lastItem.Size; 1125 const size_t dataSize = (size_t)lastItem.Size;
1114 if (dataSize != lastItem.Size) 1126 if (dataSize != lastItem.Size)
1115 return E_NOTIMPL; 1127 return E_NOTIMPL;
1116 linkFile->Data.Alloc(dataSize); 1128 linkFile->Data.Alloc(dataSize);
@@ -1130,10 +1142,12 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz
1130 else 1142 else
1131 inStream = volsInStream; 1143 inStream = volsInStream;
1132 1144
1133 ICompressCoder *commonCoder = (method == 0) ? copyCoder : LzCoders[item.IsService() ? 1 : 0]; 1145 ICompressCoder *commonCoder = (method == 0) ?
1146 copyCoder.Interface() :
1147 LzCoders[item.IsService() ? 1 : 0].Interface();
1134 1148
1135 outStreamSpec->SetStream(realOutStream); 1149 outStream->SetStream(realOutStream);
1136 outStreamSpec->Init(lastItem, (needBuf ? (Byte *)linkFile->Data : NULL)); 1150 outStream->Init(lastItem, (needBuf ? (Byte *)linkFile->Data : NULL), NeedCrc);
1137 1151
1138 HRESULT res = S_OK; 1152 HRESULT res = S_OK;
1139 if (packSize != 0 || lastItem.Is_UnknownSize() || lastItem.Size != 0) 1153 if (packSize != 0 || lastItem.Is_UnknownSize() || lastItem.Size != 0)
@@ -1151,25 +1165,24 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz
1151 if (isCryptoMode) 1165 if (isCryptoMode)
1152 filterStreamSpec->ReleaseInStream(); 1166 filterStreamSpec->ReleaseInStream();
1153 1167
1154 UInt64 processedSize = outStreamSpec->GetPos(); 1168 const UInt64 processedSize = outStream->GetPos();
1155 if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size) 1169 if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size)
1156 res = S_FALSE; 1170 res = S_FALSE;
1157 1171
1158 // if (res == S_OK) 1172 // if (res == S_OK)
1159 { 1173 {
1160 unsigned cryptoSize = 0; 1174 unsigned cryptoSize = 0;
1161 int cryptoOffset = lastItem.FindExtra(NExtraID::kCrypto, cryptoSize); 1175 const int cryptoOffset = lastItem.FindExtra(NExtraID::kCrypto, cryptoSize);
1162 NCrypto::NRar5::CDecoder *crypto = NULL; 1176 NCrypto::NRar5::CDecoder *crypto = NULL;
1163
1164 if (cryptoOffset >= 0) 1177 if (cryptoOffset >= 0)
1165 { 1178 {
1166 CCryptoInfo cryptoInfo; 1179 CCryptoInfo cryptoInfo;
1167 if (cryptoInfo.Parse(lastItem.Extra + (unsigned)cryptoOffset, cryptoSize)) 1180 if (cryptoInfo.Parse(lastItem.Extra + (unsigned)cryptoOffset, cryptoSize))
1168 if (cryptoInfo.UseMAC()) 1181 if (cryptoInfo.UseMAC())
1169 crypto = cryptoDecoderSpec; 1182 crypto = cryptoDecoder.ClsPtr();
1170 } 1183 }
1171 1184 if (NeedCrc)
1172 isCrcOK = outStreamSpec->_hash.Check(lastItem, crypto); 1185 isCrcOK = outStream->_hash.Check(lastItem, crypto);
1173 } 1186 }
1174 1187
1175 if (linkFile) 1188 if (linkFile)
@@ -1186,12 +1199,14 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz
1186} 1199}
1187 1200
1188 1201
1189HRESULT CUnpacker::DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, UInt64 packSize, ISequentialInStream *inStream, CByteBuffer &buffer) 1202HRESULT CUnpacker::DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS
1203 const CItem &item, UInt64 packSize,
1204 ISequentialInStream *inStream,
1205 CByteBuffer &buffer)
1190{ 1206{
1191 CBufPtrSeqOutStream *outSpec = new CBufPtrSeqOutStream; 1207 CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> out;
1192 CMyComPtr<ISequentialOutStream> out = outSpec;
1193 _tempBuf.AllocAtLeast((size_t)item.Size); 1208 _tempBuf.AllocAtLeast((size_t)item.Size);
1194 outSpec->Init(_tempBuf, (size_t)item.Size); 1209 out->Init(_tempBuf, (size_t)item.Size);
1195 1210
1196 bool wrongPassword; 1211 bool wrongPassword;
1197 1212
@@ -1205,16 +1220,15 @@ HRESULT CUnpacker::DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item,
1205 if (wrongPassword) 1220 if (wrongPassword)
1206 return S_FALSE; 1221 return S_FALSE;
1207 1222
1208 CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream; 1223 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> limitedStream;
1209 CMyComPtr<ISequentialInStream> limitedStream(limitedStreamSpec); 1224 limitedStream->SetStream(inStream);
1210 limitedStreamSpec->SetStream(inStream); 1225 limitedStream->Init(packSize);
1211 limitedStreamSpec->Init(packSize);
1212 1226
1213 bool crcOK = true; 1227 bool crcOK = true;
1214 res = Code(item, item, packSize, limitedStream, out, NULL, crcOK); 1228 res = Code(item, item, packSize, limitedStream, out, NULL, crcOK);
1215 if (res == S_OK) 1229 if (res == S_OK)
1216 { 1230 {
1217 if (!crcOK || outSpec->GetPos() != item.Size) 1231 if (!crcOK || out->GetPos() != item.Size)
1218 res = S_FALSE; 1232 res = S_FALSE;
1219 else 1233 else
1220 buffer.CopyFrom(_tempBuf, (size_t)item.Size); 1234 buffer.CopyFrom(_tempBuf, (size_t)item.Size);
@@ -1241,7 +1255,9 @@ struct CTempBuf
1241 1255
1242 HRESULT Decode(DECL_EXTERNAL_CODECS_LOC_VARS 1256 HRESULT Decode(DECL_EXTERNAL_CODECS_LOC_VARS
1243 const CItem &item, 1257 const CItem &item,
1244 ISequentialInStream *inStream, CUnpacker &unpacker, CByteBuffer &destBuf); 1258 ISequentialInStream *inStream,
1259 CUnpacker &unpacker,
1260 CByteBuffer &destBuf);
1245}; 1261};
1246 1262
1247 1263
@@ -1294,9 +1310,8 @@ HRESULT CTempBuf::Decode(DECL_EXTERNAL_CODECS_LOC_VARS
1294 } 1310 }
1295 else 1311 else
1296 { 1312 {
1297 CBufInStream *bufInStreamSpec = new CBufInStream; 1313 CMyComPtr2_Create<ISequentialInStream, CBufInStream> bufInStream;
1298 CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec; 1314 bufInStream->Init(_buf, _offset);
1299 bufInStreamSpec->Init(_buf, _offset);
1300 RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS 1315 RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS
1301 item, _offset, bufInStream, destBuf)) 1316 item, _offset, bufInStream, destBuf))
1302 } 1317 }
@@ -1318,6 +1333,7 @@ static const Byte kProps[] =
1318 kpidCTime, 1333 kpidCTime,
1319 kpidATime, 1334 kpidATime,
1320 kpidAttrib, 1335 kpidAttrib,
1336 // kpidPosixAttrib, // for debug
1321 1337
1322 kpidIsAltStream, 1338 kpidIsAltStream,
1323 kpidEncrypted, 1339 kpidEncrypted,
@@ -1340,12 +1356,15 @@ static const Byte kArcProps[] =
1340{ 1356{
1341 kpidTotalPhySize, 1357 kpidTotalPhySize,
1342 kpidCharacts, 1358 kpidCharacts,
1359 kpidEncrypted,
1343 kpidSolid, 1360 kpidSolid,
1344 kpidNumBlocks, 1361 kpidNumBlocks,
1345 kpidEncrypted, 1362 kpidMethod,
1346 kpidIsVolume, 1363 kpidIsVolume,
1347 kpidVolumeIndex, 1364 kpidVolumeIndex,
1348 kpidNumVolumes, 1365 kpidNumVolumes,
1366 kpidName,
1367 kpidCTime,
1349 kpidComment 1368 kpidComment
1350}; 1369};
1351 1370
@@ -1368,6 +1387,17 @@ UInt64 CHandler::GetPackSize(unsigned refIndex) const
1368 } 1387 }
1369} 1388}
1370 1389
1390static char *PrintDictSize(char *s, UInt64 w)
1391{
1392 char c = 'K'; w >>= 10;
1393 if ((w & ((1 << 10) - 1)) == 0) { c = 'M'; w >>= 10;
1394 if ((w & ((1 << 10) - 1)) == 0) { c = 'G'; w >>= 10; }}
1395 s = ConvertUInt64ToString(w, s);
1396 *s++ = c;
1397 *s = 0;
1398 return s;
1399}
1400
1371 1401
1372Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 1402Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1373{ 1403{
@@ -1385,10 +1415,69 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1385 case kpidSolid: if (arcInfo) prop = arcInfo->IsSolid(); break; 1415 case kpidSolid: if (arcInfo) prop = arcInfo->IsSolid(); break;
1386 case kpidCharacts: 1416 case kpidCharacts:
1387 { 1417 {
1388 if (!_arcs.IsEmpty()) 1418 AString s;
1419 if (arcInfo)
1389 { 1420 {
1390 FLAGS_TO_PROP(k_ArcFlags, (UInt32)arcInfo->Flags, prop); 1421 s = FlagsToString(k_ArcFlags, Z7_ARRAY_SIZE(k_ArcFlags), (UInt32)arcInfo->Flags);
1422 if (arcInfo->Extra_Error)
1423 s.Add_OptSpaced("Extra-ERROR");
1424 if (arcInfo->UnsupportedFeature)
1425 s.Add_OptSpaced("unsupported-feature");
1426 if (arcInfo->Metadata_Defined)
1427 {
1428 s.Add_OptSpaced("Metadata");
1429 if (arcInfo->Metadata_Error)
1430 s += "-ERROR";
1431 else
1432 {
1433 if (arcInfo->Metadata.Flags & NMetadataFlags::kArcName)
1434 s.Add_OptSpaced("arc-name");
1435 if (arcInfo->Metadata.Flags & NMetadataFlags::kCTime)
1436 {
1437 s.Add_OptSpaced("ctime-");
1438 s +=
1439 (arcInfo->Metadata.Flags & NMetadataFlags::kUnixTime) ?
1440 (arcInfo->Metadata.Flags & NMetadataFlags::kNanoSec) ?
1441 "1ns" : "1s" : "win";
1442 }
1443 }
1444 }
1445 if (arcInfo->Locator_Defined)
1446 {
1447 s.Add_OptSpaced("Locator");
1448 if (arcInfo->Locator_Error)
1449 s += "-ERROR";
1450 else
1451 {
1452 if (arcInfo->Locator.Is_QuickOpen())
1453 {
1454 s.Add_OptSpaced("QuickOpen:");
1455 s.Add_UInt64(arcInfo->Locator.QuickOpen);
1456 }
1457 if (arcInfo->Locator.Is_Recovery())
1458 {
1459 s += "Recovery:";
1460 s.Add_UInt64(arcInfo->Locator.Recovery);
1461 }
1462 }
1463 }
1464 if (arcInfo->UnknownExtraRecord)
1465 s.Add_OptSpaced("Unknown-Extra-Record");
1466
1391 } 1467 }
1468 if (_comment_WasUsedInArc)
1469 {
1470 s.Add_OptSpaced("Comment");
1471 // s.Add_UInt32((UInt32)_comment.Size());
1472 }
1473 //
1474 if (_acls.Size() != 0)
1475 {
1476 s.Add_OptSpaced("ACL");
1477 // s.Add_UInt32(_acls.Size());
1478 }
1479 if (!s.IsEmpty())
1480 prop = s;
1392 break; 1481 break;
1393 } 1482 }
1394 case kpidEncrypted: if (arcInfo) prop = arcInfo->IsEncrypted; break; // it's for encrypted names. 1483 case kpidEncrypted: if (arcInfo) prop = arcInfo->IsEncrypted; break; // it's for encrypted names.
@@ -1415,13 +1504,55 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1415 break; 1504 break;
1416 } 1505 }
1417 1506
1507 case kpidName:
1508 if (arcInfo)
1509 if (!arcInfo->Metadata_Error
1510 && !arcInfo->Metadata.ArcName.IsEmpty())
1511 {
1512 UString s;
1513 if (ConvertUTF8ToUnicode(arcInfo->Metadata.ArcName, s))
1514 prop = s;
1515 }
1516 break;
1517
1518 case kpidCTime:
1519 if (arcInfo)
1520 if (!arcInfo->Metadata_Error
1521 && (arcInfo->Metadata.Flags & NMetadataFlags::kCTime))
1522 {
1523 const UInt64 ct = arcInfo->Metadata.CTime;
1524 if (arcInfo->Metadata.Flags & NMetadataFlags::kUnixTime)
1525 {
1526 if (arcInfo->Metadata.Flags & NMetadataFlags::kNanoSec)
1527 {
1528 const UInt64 sec = ct / 1000000000;
1529 const UInt64 ns = ct % 1000000000;
1530 UInt64 wt = NTime::UnixTime64_To_FileTime64((Int64)sec);
1531 wt += ns / 100;
1532 const unsigned ns100 = (unsigned)(ns % 100);
1533 FILETIME ft;
1534 ft.dwLowDateTime = (DWORD)(UInt32)wt;
1535 ft.dwHighDateTime = (DWORD)(UInt32)(wt >> 32);
1536 prop.SetAsTimeFrom_FT_Prec_Ns100(ft, k_PropVar_TimePrec_1ns, ns100);
1537 }
1538 else
1539 {
1540 const UInt64 wt = NTime::UnixTime64_To_FileTime64((Int64)ct);
1541 prop.SetAsTimeFrom_Ft64_Prec(wt, k_PropVar_TimePrec_Unix);
1542 }
1543 }
1544 else
1545 prop.SetAsTimeFrom_Ft64_Prec(ct, k_PropVar_TimePrec_100ns);
1546 }
1547 break;
1548
1418 case kpidComment: 1549 case kpidComment:
1419 { 1550 {
1420 // if (!_arcs.IsEmpty()) 1551 // if (!_arcs.IsEmpty())
1421 { 1552 {
1422 // const CArc &arc = _arcs[0]; 1553 // const CArc &arc = _arcs[0];
1423 const CByteBuffer &cmt = _comment; 1554 const CByteBuffer &cmt = _comment;
1424 if (cmt.Size() != 0 && cmt.Size() < (1 << 16)) 1555 if (cmt.Size() != 0 /* && cmt.Size() < (1 << 16) */)
1425 { 1556 {
1426 AString s; 1557 AString s;
1427 s.SetFrom_CalcLen((const char *)(const Byte *)cmt, (unsigned)cmt.Size()); 1558 s.SetFrom_CalcLen((const char *)(const Byte *)cmt, (unsigned)cmt.Size());
@@ -1435,11 +1566,48 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1435 1566
1436 case kpidNumBlocks: 1567 case kpidNumBlocks:
1437 { 1568 {
1438 UInt32 numBlocks = 0; 1569 prop = (UInt32)_numBlocks;
1439 FOR_VECTOR (i, _refs) 1570 break;
1440 if (!_items[_refs[i].Item].IsSolid()) 1571 }
1441 numBlocks++; 1572
1442 prop = (UInt32)numBlocks; 1573 case kpidMethod:
1574 {
1575 AString s;
1576
1577 UInt64 algo = _algo_Mask;
1578 for (unsigned v = 0; algo != 0; v++, algo >>= 1)
1579 {
1580 if ((algo & 1) == 0)
1581 continue;
1582 s.Add_OptSpaced("v");
1583 s.Add_UInt32(v + 6);
1584 if (v < Z7_ARRAY_SIZE(_methodMasks))
1585 {
1586 const UInt64 dict = _dictMaxSizes[v];
1587 if (dict)
1588 {
1589 char temp[24];
1590 temp[0] = ':';
1591 PrintDictSize(temp + 1, dict);
1592 s += temp;
1593 }
1594 unsigned method = _methodMasks[v];
1595 for (unsigned m = 0; method; m++, method >>= 1)
1596 {
1597 if ((method & 1) == 0)
1598 continue;
1599 s += ":m";
1600 s.Add_UInt32(m);
1601 }
1602 }
1603 }
1604 if (_rar5comapt_mask & 2)
1605 {
1606 s += ":c";
1607 if (_rar5comapt_mask & 1)
1608 s.Add_Char('n');
1609 }
1610 prop = s;
1443 break; 1611 break;
1444 } 1612 }
1445 1613
@@ -1459,6 +1627,10 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1459 UInt32 v = _errorFlags; 1627 UInt32 v = _errorFlags;
1460 if (!_isArc) 1628 if (!_isArc)
1461 v |= kpv_ErrorFlags_IsNotArc; 1629 v |= kpv_ErrorFlags_IsNotArc;
1630 if (_error_in_ACL)
1631 v |= kpv_ErrorFlags_HeadersError;
1632 if (_split_Error)
1633 v |= kpv_ErrorFlags_HeadersError;
1462 prop = v; 1634 prop = v;
1463 break; 1635 break;
1464 } 1636 }
@@ -1480,7 +1652,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1480 AString s ("part"); 1652 AString s ("part");
1481 UInt32 v = (UInt32)arcInfo->GetVolIndex() + 1; 1653 UInt32 v = (UInt32)arcInfo->GetVolIndex() + 1;
1482 if (v < 10) 1654 if (v < 10)
1483 s += '0'; 1655 s.Add_Char('0');
1484 s.Add_UInt32(v); 1656 s.Add_UInt32(v);
1485 s += ".rar"; 1657 s += ".rar";
1486 prop = s; 1658 prop = s;
@@ -1500,7 +1672,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1500 1672
1501Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) 1673Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
1502{ 1674{
1503 *numItems = _refs.Size(); 1675 *numItems = (UInt32)_refs.Size();
1504 return S_OK; 1676 return S_OK;
1505} 1677}
1506 1678
@@ -1571,13 +1743,21 @@ Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
1571 1743
1572 if (propID == kpidChecksum) 1744 if (propID == kpidChecksum)
1573 { 1745 {
1574 int hashRecOffset = item.FindExtra_Blake(); 1746 const int hashRecOffset = item.FindExtra_Blake();
1575 if (hashRecOffset >= 0) 1747 if (hashRecOffset >= 0)
1576 { 1748 {
1577 *dataSize = BLAKE2S_DIGEST_SIZE; 1749 *dataSize = Z7_BLAKE2S_DIGEST_SIZE;
1578 *propType = NPropDataType::kRaw; 1750 *propType = NPropDataType::kRaw;
1579 *data = &item.Extra[hashRecOffset]; 1751 *data = item.Extra + (unsigned)hashRecOffset;
1580 } 1752 }
1753 /*
1754 else if (item.Has_CRC() && item.IsEncrypted())
1755 {
1756 *dataSize = 4;
1757 *propType = NPropDataType::kRaw;
1758 *data = &item->CRC; // we must show same value for big/little endian here
1759 }
1760 */
1581 return S_OK; 1761 return S_OK;
1582 } 1762 }
1583 1763
@@ -1594,6 +1774,7 @@ static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CProp
1594 1774
1595 const Byte *p = item.Extra + (unsigned)offset; 1775 const Byte *p = item.Extra + (unsigned)offset;
1596 UInt64 flags; 1776 UInt64 flags;
1777 // PARSE_VAR_INT(p, size, flags)
1597 { 1778 {
1598 const unsigned num = ReadVarInt(p, size, &flags); 1779 const unsigned num = ReadVarInt(p, size, &flags);
1599 if (num == 0) 1780 if (num == 0)
@@ -1684,7 +1865,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1684 AString name; 1865 AString name;
1685 item.GetAltStreamName(name); 1866 item.GetAltStreamName(name);
1686 if (name[0] != ':') 1867 if (name[0] != ':')
1687 s += ':'; 1868 s.Add_Colon();
1688 s += name; 1869 s += name;
1689 ConvertUTF8ToUnicode(s, unicodeName); 1870 ConvertUTF8ToUnicode(s, unicodeName);
1690 } 1871 }
@@ -1714,7 +1895,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1714 1895
1715 case kpidIsDir: prop = item.IsDir(); break; 1896 case kpidIsDir: prop = item.IsDir(); break;
1716 case kpidSize: if (!lastItem.Is_UnknownSize()) prop = lastItem.Size; break; 1897 case kpidSize: if (!lastItem.Is_UnknownSize()) prop = lastItem.Size; break;
1717 case kpidPackSize: prop = GetPackSize(index); break; 1898 case kpidPackSize: prop = GetPackSize((unsigned)index); break;
1718 1899
1719 case kpidMTime: 1900 case kpidMTime:
1720 { 1901 {
@@ -1757,6 +1938,11 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1757 case kpidCopyLink: item.Link_to_Prop(NLinkType::kFileCopy, prop); break; 1938 case kpidCopyLink: item.Link_to_Prop(NLinkType::kFileCopy, prop); break;
1758 1939
1759 case kpidAttrib: prop = item.GetWinAttrib(); break; 1940 case kpidAttrib: prop = item.GetWinAttrib(); break;
1941 case kpidPosixAttrib:
1942 if (item.HostOS == kHost_Unix)
1943 prop = (UInt32)item.Attrib;
1944 break;
1945
1760 case kpidEncrypted: prop = item.IsEncrypted(); break; 1946 case kpidEncrypted: prop = item.IsEncrypted(); break;
1761 case kpidSolid: prop = item.IsSolid(); break; 1947 case kpidSolid: prop = item.IsSolid(); break;
1762 1948
@@ -1777,7 +1963,9 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1777 case kpidCRC: 1963 case kpidCRC:
1778 { 1964 {
1779 const CItem *item2 = (lastItem.IsSplitAfter() ? &item : &lastItem); 1965 const CItem *item2 = (lastItem.IsSplitAfter() ? &item : &lastItem);
1780 if (item2->Has_CRC()) 1966 // we don't want to show crc for encrypted file here,
1967 // because crc is also encrrypted.
1968 if (item2->Has_CRC() && !item2->IsEncrypted())
1781 prop = item2->CRC; 1969 prop = item2->CRC;
1782 break; 1970 break;
1783 } 1971 }
@@ -1785,56 +1973,61 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1785 case kpidMethod: 1973 case kpidMethod:
1786 { 1974 {
1787 char temp[128]; 1975 char temp[128];
1788 unsigned algo = item.GetAlgoVersion(); 1976 const unsigned algo = item.Get_AlgoVersion_RawBits();
1789 char *s = temp; 1977 char *s = temp;
1790 if (algo != 0) 1978 // if (algo != 0)
1791 { 1979 {
1792 ConvertUInt32ToString(algo, s); 1980 *s++ = 'v';
1793 s += MyStringLen(s); 1981 s = ConvertUInt32ToString((UInt32)algo + 6, s);
1982 if (item.Is_Rar5_Compat())
1983 *s++ = 'c';
1794 *s++ = ':'; 1984 *s++ = ':';
1795 } 1985 }
1796 unsigned m = item.GetMethod();
1797 { 1986 {
1798 s[0] = 'm'; 1987 const unsigned m = item.Get_Method();
1799 s[1] = (char)(m + '0'); 1988 *s++ = 'm';
1800 s[2] = 0; 1989 *s++ = (char)(m + '0');
1801 if (!item.IsDir()) 1990 if (!item.IsDir())
1802 { 1991 {
1803 s[2] = ':'; 1992 *s++ = ':';
1804 ConvertUInt32ToString(item.GetDictSize() + 17, s + 3); 1993 const unsigned dictMain = item.Get_DictSize_Main();
1994 const unsigned frac = item.Get_DictSize_Frac();
1995 /*
1996 if (frac == 0 && algo == 0)
1997 s = ConvertUInt32ToString(dictMain + 17, s);
1998 else
1999 */
2000 s = PrintDictSize(s, (UInt64)(32 + frac) << (12 + dictMain));
2001 if (item.Is_Rar5_Compat())
2002 {
2003 *s++ = ':';
2004 *s++ = 'c';
2005 }
1805 } 2006 }
1806 } 2007 }
1807
1808 unsigned cryptoSize = 0; 2008 unsigned cryptoSize = 0;
1809 int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize); 2009 const int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize);
1810 if (cryptoOffset >= 0) 2010 if (cryptoOffset >= 0)
1811 { 2011 {
1812 s = temp + strlen(temp);
1813 *s++ = ' '; 2012 *s++ = ' ';
1814
1815 CCryptoInfo cryptoInfo; 2013 CCryptoInfo cryptoInfo;
1816 2014 const bool isOK = cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize);
1817 bool isOK = cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize);
1818
1819 if (cryptoInfo.Algo == 0) 2015 if (cryptoInfo.Algo == 0)
1820 s = MyStpCpy(s, "AES"); 2016 s = MyStpCpy(s, "AES");
1821 else 2017 else
1822 { 2018 {
1823 s = MyStpCpy(s, "Crypto_"); 2019 s = MyStpCpy(s, "Crypto_");
1824 ConvertUInt64ToString(cryptoInfo.Algo, s); 2020 s = ConvertUInt64ToString(cryptoInfo.Algo, s);
1825 s += strlen(s);
1826 } 2021 }
1827
1828 if (isOK) 2022 if (isOK)
1829 { 2023 {
1830 *s++ = ':'; 2024 *s++ = ':';
1831 ConvertUInt32ToString(cryptoInfo.Cnt, s); 2025 s = ConvertUInt32ToString(cryptoInfo.Cnt, s);
1832 s += strlen(s);
1833 *s++ = ':'; 2026 *s++ = ':';
1834 ConvertUInt64ToString(cryptoInfo.Flags, s); 2027 s = ConvertUInt64ToString(cryptoInfo.Flags, s);
1835 } 2028 }
1836 } 2029 }
1837 2030 *s = 0;
1838 prop = temp; 2031 prop = temp;
1839 break; 2032 break;
1840 } 2033 }
@@ -1844,20 +2037,14 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1844 AString s; 2037 AString s;
1845 2038
1846 if (item.ACL >= 0) 2039 if (item.ACL >= 0)
1847 {
1848 s.Add_OptSpaced("ACL"); 2040 s.Add_OptSpaced("ACL");
1849 }
1850
1851 UInt32 flags = item.Flags;
1852 // flags &= ~(6); // we don't need compression related bits here.
1853 2041
2042 const UInt32 flags = item.Flags;
1854 if (flags != 0) 2043 if (flags != 0)
1855 { 2044 {
1856 AString s2 = FlagsToString(k_FileFlags, Z7_ARRAY_SIZE(k_FileFlags), flags); 2045 const AString s2 = FlagsToString(k_FileFlags, Z7_ARRAY_SIZE(k_FileFlags), flags);
1857 if (!s2.IsEmpty()) 2046 if (!s2.IsEmpty())
1858 {
1859 s.Add_OptSpaced(s2); 2047 s.Add_OptSpaced(s2);
1860 }
1861 } 2048 }
1862 2049
1863 item.PrintInfo(s); 2050 item.PrintInfo(s);
@@ -1895,7 +2082,7 @@ static int CompareItemsPaths(const CHandler &handler, unsigned p1, unsigned p2,
1895 { 2082 {
1896 if (!item2.Version_Defined) 2083 if (!item2.Version_Defined)
1897 return -1; 2084 return -1;
1898 int res = MyCompare(item1.Version, item2.Version); 2085 const int res = MyCompare(item1.Version, item2.Version);
1899 if (res != 0) 2086 if (res != 0)
1900 return res; 2087 return res;
1901 } 2088 }
@@ -1909,7 +2096,7 @@ static int CompareItemsPaths(const CHandler &handler, unsigned p1, unsigned p2,
1909 2096
1910static int CompareItemsPaths2(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1) 2097static int CompareItemsPaths2(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1)
1911{ 2098{
1912 int res = CompareItemsPaths(handler, p1, p2, name1); 2099 const int res = CompareItemsPaths(handler, p1, p2, name1);
1913 if (res != 0) 2100 if (res != 0)
1914 return res; 2101 return res;
1915 return MyCompare(p1, p2); 2102 return MyCompare(p1, p2);
@@ -1958,15 +2145,34 @@ static int FindLink(const CHandler &handler, const CUIntVector &sorted,
1958void CHandler::FillLinks() 2145void CHandler::FillLinks()
1959{ 2146{
1960 unsigned i; 2147 unsigned i;
1961 2148
2149 bool need_FillLinks = false;
2150
1962 for (i = 0; i < _refs.Size(); i++) 2151 for (i = 0; i < _refs.Size(); i++)
1963 { 2152 {
1964 const CItem &item = _items[_refs[i].Item]; 2153 const CItem &item = _items[_refs[i].Item];
1965 if (!item.IsDir() && !item.IsService() && item.NeedUse_as_CopyLink()) 2154 if (!item.IsDir()
1966 break; 2155 && !item.IsService()
2156 && item.NeedUse_as_CopyLink())
2157 need_FillLinks = true;
2158
2159 if (!item.IsSolid())
2160 _numBlocks++;
2161
2162 const unsigned algo = item.Get_AlgoVersion_RawBits();
2163 _algo_Mask |= (UInt64)1 << algo;
2164 _rar5comapt_mask |= 1u << item.Get_Rar5_CompatBit();
2165 if (!item.IsDir() && algo < Z7_ARRAY_SIZE(_methodMasks))
2166 {
2167 _methodMasks[algo] |= 1u << (item.Get_Method());
2168 UInt64 d = 32 + item.Get_DictSize_Frac();
2169 d <<= (12 + item.Get_DictSize_Main());
2170 if (_dictMaxSizes[algo] < d)
2171 _dictMaxSizes[algo] = d;
2172 }
1967 } 2173 }
1968 2174
1969 if (i == _refs.Size()) 2175 if (!need_FillLinks)
1970 return; 2176 return;
1971 2177
1972 CUIntVector sorted; 2178 CUIntVector sorted;
@@ -1994,7 +2200,7 @@ void CHandler::FillLinks()
1994 if (!item.FindExtra_Link(linkInfo) || linkInfo.Type != NLinkType::kFileCopy) 2200 if (!item.FindExtra_Link(linkInfo) || linkInfo.Type != NLinkType::kFileCopy)
1995 continue; 2201 continue;
1996 link.SetFrom_CalcLen((const char *)(item.Extra + linkInfo.NameOffset), linkInfo.NameLen); 2202 link.SetFrom_CalcLen((const char *)(item.Extra + linkInfo.NameOffset), linkInfo.NameLen);
1997 int linkIndex = FindLink(*this, sorted, link, i); 2203 const int linkIndex = FindLink(*this, sorted, link, i);
1998 if (linkIndex < 0) 2204 if (linkIndex < 0)
1999 continue; 2205 continue;
2000 if ((unsigned)linkIndex >= i) 2206 if ((unsigned)linkIndex >= i)
@@ -2018,30 +2224,24 @@ HRESULT CHandler::Open2(IInStream *stream,
2018 IArchiveOpenCallback *openCallback) 2224 IArchiveOpenCallback *openCallback)
2019{ 2225{
2020 CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; 2226 CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
2021 CMyComPtr<ICryptoGetTextPassword> getTextPassword; 2227 // CMyComPtr<ICryptoGetTextPassword> getTextPassword;
2022
2023 NRar::CVolumeName seqName; 2228 NRar::CVolumeName seqName;
2024 2229 CTempBuf tempBuf;
2025 UInt64 totalBytes = 0; 2230 CUnpacker unpacker;
2026 UInt64 curBytes = 0;
2027 2231
2028 if (openCallback) 2232 if (openCallback)
2029 { 2233 {
2030 openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); 2234 openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
2031 openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); 2235 openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&unpacker.getTextPassword);
2032 } 2236 }
2237 // unpacker.getTextPassword = getTextPassword;
2033 2238
2034 CTempBuf tempBuf; 2239 CInArchive arch;
2035
2036 CUnpacker unpacker;
2037 unpacker.getTextPassword = getTextPassword;
2038
2039 int prevSplitFile = -1; 2240 int prevSplitFile = -1;
2040 int prevMainFile = -1; 2241 int prevMainFile = -1;
2041 2242 UInt64 totalBytes = 0;
2243 UInt64 curBytes = 0;
2042 bool nextVol_is_Required = false; 2244 bool nextVol_is_Required = false;
2043
2044 CInArchive arch;
2045 2245
2046 for (;;) 2246 for (;;)
2047 { 2247 {
@@ -2053,7 +2253,6 @@ HRESULT CHandler::Open2(IInStream *stream,
2053 { 2253 {
2054 if (!openVolumeCallback) 2254 if (!openVolumeCallback)
2055 break; 2255 break;
2056
2057 if (_arcs.Size() == 1) 2256 if (_arcs.Size() == 1)
2058 { 2257 {
2059 UString baseName; 2258 UString baseName;
@@ -2067,14 +2266,10 @@ HRESULT CHandler::Open2(IInStream *stream,
2067 if (!seqName.InitName(baseName)) 2266 if (!seqName.InitName(baseName))
2068 break; 2267 break;
2069 } 2268 }
2070
2071 const UString volName = seqName.GetNextName(); 2269 const UString volName = seqName.GetNextName();
2072 2270 const HRESULT result = openVolumeCallback->GetStream(volName, &inStream);
2073 HRESULT result = openVolumeCallback->GetStream(volName, &inStream);
2074
2075 if (result != S_OK && result != S_FALSE) 2271 if (result != S_OK && result != S_FALSE)
2076 return result; 2272 return result;
2077
2078 if (!inStream || result != S_OK) 2273 if (!inStream || result != S_OK)
2079 { 2274 {
2080 if (nextVol_is_Required) 2275 if (nextVol_is_Required)
@@ -2092,29 +2287,26 @@ HRESULT CHandler::Open2(IInStream *stream,
2092 RINOK(openCallback->SetTotal(NULL, &totalBytes)) 2287 RINOK(openCallback->SetTotal(NULL, &totalBytes))
2093 } 2288 }
2094 2289
2095 CInArcInfo arcInfoOpen; 2290 CInArcInfo arcInfo_Open;
2096 { 2291 {
2097 HRESULT res = arch.Open(inStream, maxCheckStartPosition, getTextPassword, arcInfoOpen); 2292 const HRESULT res = arch.Open(inStream, maxCheckStartPosition, unpacker.getTextPassword, arcInfo_Open);
2098 if (arch.IsArc && arch.UnexpectedEnd) 2293 if (arch.IsArc && arch.UnexpectedEnd)
2099 _errorFlags |= kpv_ErrorFlags_UnexpectedEnd; 2294 _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
2100 if (_arcs.IsEmpty())
2101 {
2102 _isArc = arch.IsArc;
2103 }
2104
2105 if (res != S_OK)
2106 {
2107 if (res != S_FALSE)
2108 return res;
2109 if (_arcs.IsEmpty()) 2295 if (_arcs.IsEmpty())
2110 return res; 2296 _isArc = arch.IsArc;
2111 break; 2297 if (res != S_OK)
2112 } 2298 {
2299 if (res != S_FALSE)
2300 return res;
2301 if (_arcs.IsEmpty())
2302 return res;
2303 break;
2304 }
2113 } 2305 }
2114 2306
2115 CArc &arc = _arcs.AddNew(); 2307 CArc &arc = _arcs.AddNew();
2116 CInArcInfo &arcInfo = arc.Info; 2308 CInArcInfo &arcInfo = arc.Info;
2117 arcInfo = arcInfoOpen; 2309 arcInfo = arcInfo_Open;
2118 arc.Stream = inStream; 2310 arc.Stream = inStream;
2119 2311
2120 CItem item; 2312 CItem item;
@@ -2124,18 +2316,16 @@ HRESULT CHandler::Open2(IInStream *stream,
2124 item.Clear(); 2316 item.Clear();
2125 2317
2126 arcInfo.EndPos = arch.Position; 2318 arcInfo.EndPos = arch.Position;
2127
2128 if (arch.Position > endPos) 2319 if (arch.Position > endPos)
2129 { 2320 {
2130 _errorFlags |= kpv_ErrorFlags_UnexpectedEnd; 2321 _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
2131 break; 2322 break;
2132 } 2323 }
2133
2134 RINOK(InStream_SeekSet(inStream, arch.Position)) 2324 RINOK(InStream_SeekSet(inStream, arch.Position))
2135 2325
2136 { 2326 {
2137 CInArchive::CHeader h; 2327 CInArchive::CHeader h;
2138 HRESULT res = arch.ReadBlockHeader(h); 2328 const HRESULT res = arch.ReadBlockHeader(h);
2139 if (res != S_OK) 2329 if (res != S_OK)
2140 { 2330 {
2141 if (res != S_FALSE) 2331 if (res != S_FALSE)
@@ -2144,9 +2334,9 @@ HRESULT CHandler::Open2(IInStream *stream,
2144 { 2334 {
2145 _errorFlags |= kpv_ErrorFlags_UnexpectedEnd; 2335 _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
2146 if (arcInfo.EndPos < arch.Position) 2336 if (arcInfo.EndPos < arch.Position)
2147 arcInfo.EndPos = arch.Position; 2337 arcInfo.EndPos = arch.Position;
2148 if (arcInfo.EndPos < endPos) 2338 if (arcInfo.EndPos < endPos)
2149 arcInfo.EndPos = endPos; 2339 arcInfo.EndPos = endPos;
2150 } 2340 }
2151 else 2341 else
2152 _errorFlags |= kpv_ErrorFlags_HeadersError; 2342 _errorFlags |= kpv_ErrorFlags_HeadersError;
@@ -2159,6 +2349,8 @@ HRESULT CHandler::Open2(IInStream *stream,
2159 arcInfo.EndOfArchive_was_Read = true; 2349 arcInfo.EndOfArchive_was_Read = true;
2160 if (!arch.ReadVar(arcInfo.EndFlags)) 2350 if (!arch.ReadVar(arcInfo.EndFlags))
2161 _errorFlags |= kpv_ErrorFlags_HeadersError; 2351 _errorFlags |= kpv_ErrorFlags_HeadersError;
2352 if (!arch.Is_Buf_Finished() || h.ExtraSize || h.DataSize)
2353 arcInfo.UnsupportedFeature = true;
2162 if (arcInfo.IsVolume()) 2354 if (arcInfo.IsVolume())
2163 { 2355 {
2164 // for multivolume archives RAR can add ZERO bytes at the end for alignment. 2356 // for multivolume archives RAR can add ZERO bytes at the end for alignment.
@@ -2182,14 +2374,11 @@ HRESULT CHandler::Open2(IInStream *stream,
2182 } 2374 }
2183 2375
2184 item.RecordType = (Byte)h.Type; 2376 item.RecordType = (Byte)h.Type;
2185
2186 if (!arch.ReadFileHeader(h, item)) 2377 if (!arch.ReadFileHeader(h, item))
2187 { 2378 {
2188 _errorFlags |= kpv_ErrorFlags_HeadersError; 2379 _errorFlags |= kpv_ErrorFlags_HeadersError;
2189 break; 2380 break;
2190 } 2381 }
2191
2192 // item.MainPartSize = (UInt32)(Position - item.Position);
2193 item.DataPos = arch.Position; 2382 item.DataPos = arch.Position;
2194 } 2383 }
2195 2384
@@ -2201,7 +2390,7 @@ HRESULT CHandler::Open2(IInStream *stream,
2201 isOk_packSize = false; 2390 isOk_packSize = false;
2202 _errorFlags |= kpv_ErrorFlags_HeadersError; 2391 _errorFlags |= kpv_ErrorFlags_HeadersError;
2203 if (arcInfo.EndPos < endPos) 2392 if (arcInfo.EndPos < endPos)
2204 arcInfo.EndPos = endPos; 2393 arcInfo.EndPos = endPos;
2205 } 2394 }
2206 else 2395 else
2207 { 2396 {
@@ -2211,29 +2400,32 @@ HRESULT CHandler::Open2(IInStream *stream,
2211 } 2400 }
2212 2401
2213 bool needAdd = true; 2402 bool needAdd = true;
2214 2403
2404 if (!_comment_WasUsedInArc
2405 && _comment.Size() == 0
2406 && item.Is_CMT())
2215 { 2407 {
2216 if (_comment.Size() == 0 2408 _comment_WasUsedInArc = true;
2217 && item.Is_CMT() 2409 if ( item.PackSize <= kCommentSize_Max
2218 && item.PackSize < kCommentSize_Max
2219 && item.PackSize == item.Size 2410 && item.PackSize == item.Size
2220 && item.PackSize != 0 2411 && item.PackSize != 0
2221 && item.GetMethod() == 0 2412 && item.Get_Method() == 0
2222 && !item.IsSplit()) 2413 && !item.IsSplit())
2223 { 2414 {
2224 RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_VARS item, item.PackSize, inStream, _comment)) 2415 RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_VARS item, item.PackSize, inStream, _comment))
2225 needAdd = false; 2416 needAdd = false;
2417 // item.RecordType = (Byte)NHeaderType::kFile; // for debug
2226 } 2418 }
2227 } 2419 }
2420
2421 CRefItem ref;
2422 ref.Item = _items.Size();
2423 ref.Last = ref.Item;
2424 ref.Parent = -1;
2425 ref.Link = -1;
2228 2426
2229 if (needAdd) 2427 if (needAdd)
2230 { 2428 {
2231 CRefItem ref;
2232 ref.Item = _items.Size();
2233 ref.Last = ref.Item;
2234 ref.Parent = -1;
2235 ref.Link = -1;
2236
2237 if (item.IsService()) 2429 if (item.IsService())
2238 { 2430 {
2239 if (item.Is_STM()) 2431 if (item.Is_STM())
@@ -2244,8 +2436,16 @@ HRESULT CHandler::Open2(IInStream *stream,
2244 else 2436 else
2245 { 2437 {
2246 needAdd = false; 2438 needAdd = false;
2247 if (item.Is_ACL() && (!item.IsEncrypted() || arch.m_CryptoMode)) 2439 if (item.Is_ACL())
2248 { 2440 {
2441 _acl_Used = true;
2442 if (item.IsEncrypted() && !arch.m_CryptoMode)
2443 _error_in_ACL = true;
2444 else if (item.IsSolid()
2445 || prevMainFile < 0
2446 || item.Size >= (1 << 24)
2447 || item.Size == 0)
2448 _error_in_ACL = true;
2249 if (prevMainFile >= 0 && item.Size < (1 << 24) && item.Size != 0) 2449 if (prevMainFile >= 0 && item.Size < (1 << 24) && item.Size != 0)
2250 { 2450 {
2251 CItem &mainItem = _items[_refs[prevMainFile].Item]; 2451 CItem &mainItem = _items[_refs[prevMainFile].Item];
@@ -2253,7 +2453,7 @@ HRESULT CHandler::Open2(IInStream *stream,
2253 if (mainItem.ACL < 0) 2453 if (mainItem.ACL < 0)
2254 { 2454 {
2255 CByteBuffer acl; 2455 CByteBuffer acl;
2256 HRESULT res = tempBuf.Decode(EXTERNAL_CODECS_VARS item, inStream, unpacker, acl); 2456 const HRESULT res = tempBuf.Decode(EXTERNAL_CODECS_VARS item, inStream, unpacker, acl);
2257 if (!item.IsSplitAfter()) 2457 if (!item.IsSplitAfter())
2258 tempBuf.Clear(); 2458 tempBuf.Clear();
2259 if (res != S_OK) 2459 if (res != S_OK)
@@ -2261,10 +2461,9 @@ HRESULT CHandler::Open2(IInStream *stream,
2261 tempBuf.Clear(); 2461 tempBuf.Clear();
2262 if (res != S_FALSE && res != E_NOTIMPL) 2462 if (res != S_FALSE && res != E_NOTIMPL)
2263 return res; 2463 return res;
2464 _error_in_ACL = true;
2264 } 2465 }
2265 // RINOK(); 2466 else if (acl.Size() != 0)
2266
2267 if (res == S_OK && acl.Size() != 0)
2268 { 2467 {
2269 if (_acls.IsEmpty() || acl != _acls.Back()) 2468 if (_acls.IsEmpty() || acl != _acls.Back())
2270 _acls.Add(acl); 2469 _acls.Add(acl);
@@ -2274,7 +2473,7 @@ HRESULT CHandler::Open2(IInStream *stream,
2274 } 2473 }
2275 } 2474 }
2276 } 2475 }
2277 } 2476 } // item.IsService()
2278 2477
2279 if (needAdd) 2478 if (needAdd)
2280 { 2479 {
@@ -2291,6 +2490,8 @@ HRESULT CHandler::Open2(IInStream *stream,
2291 needAdd = false; 2490 needAdd = false;
2292 } 2491 }
2293 } 2492 }
2493 else
2494 _split_Error = true;
2294 } 2495 }
2295 } 2496 }
2296 2497
@@ -2300,7 +2501,6 @@ HRESULT CHandler::Open2(IInStream *stream,
2300 prevSplitFile = (int)_refs.Size(); 2501 prevSplitFile = (int)_refs.Size();
2301 if (!item.IsService()) 2502 if (!item.IsService())
2302 prevMainFile = (int)_refs.Size(); 2503 prevMainFile = (int)_refs.Size();
2303 _refs.Add(ref);
2304 } 2504 }
2305 } 2505 }
2306 2506
@@ -2315,11 +2515,13 @@ HRESULT CHandler::Open2(IInStream *stream,
2315 2515
2316 item.VolIndex = _arcs.Size() - 1; 2516 item.VolIndex = _arcs.Size() - 1;
2317 _items.Add(item); 2517 _items.Add(item);
2518 if (needAdd)
2519 _refs.Add(ref);
2318 2520
2319 if (openCallback && (_items.Size() & 0xFF) == 0) 2521 if (openCallback && (_items.Size() & 0xFF) == 0)
2320 { 2522 {
2321 UInt64 numFiles = _items.Size(); 2523 const UInt64 numFiles = _refs.Size(); // _items.Size()
2322 UInt64 numBytes = curBytes + item.DataPos; 2524 const UInt64 numBytes = curBytes + item.DataPos;
2323 RINOK(openCallback->SetCompleted(&numFiles, &numBytes)) 2525 RINOK(openCallback->SetCompleted(&numFiles, &numBytes))
2324 } 2526 }
2325 2527
@@ -2343,11 +2545,11 @@ HRESULT CHandler::Open2(IInStream *stream,
2343 } 2545 }
2344 2546
2345 FillLinks(); 2547 FillLinks();
2346
2347 return S_OK; 2548 return S_OK;
2348} 2549}
2349 2550
2350 2551
2552
2351Z7_COM7F_IMF(CHandler::Open(IInStream *stream, 2553Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
2352 const UInt64 *maxCheckStartPosition, 2554 const UInt64 *maxCheckStartPosition,
2353 IArchiveOpenCallback *openCallback)) 2555 IArchiveOpenCallback *openCallback))
@@ -2365,6 +2567,19 @@ Z7_COM7F_IMF(CHandler::Close())
2365 _errorFlags = 0; 2567 _errorFlags = 0;
2366 // _warningFlags = 0; 2568 // _warningFlags = 0;
2367 _isArc = false; 2569 _isArc = false;
2570 _comment_WasUsedInArc = false;
2571 _acl_Used = false;
2572 _error_in_ACL = false;
2573 _split_Error = false;
2574 _numBlocks = 0;
2575 _rar5comapt_mask = 0;
2576 _algo_Mask = 0; // (UInt64)0u - 1;
2577 for (unsigned i = 0; i < Z7_ARRAY_SIZE(_methodMasks); i++)
2578 {
2579 _methodMasks[i] = 0;
2580 _dictMaxSizes[i] = 0;
2581 }
2582
2368 _refs.Clear(); 2583 _refs.Clear();
2369 _items.Clear(); 2584 _items.Clear();
2370 _arcs.Clear(); 2585 _arcs.Clear();
@@ -2427,7 +2642,7 @@ Z7_COM7F_IMF(CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
2427 UInt32 cur = size; 2642 UInt32 cur = size;
2428 if (cur > _rem) 2643 if (cur > _rem)
2429 cur = (UInt32)_rem; 2644 cur = (UInt32)_rem;
2430 UInt32 num = cur; 2645 const UInt32 num = cur;
2431 HRESULT res = _stream->Read(data, cur, &cur); 2646 HRESULT res = _stream->Read(data, cur, &cur);
2432 _hash.Update(data, cur); 2647 _hash.Update(data, cur);
2433 realProcessedSize += cur; 2648 realProcessedSize += cur;
@@ -2492,29 +2707,24 @@ static inline int DecoderRes_to_OpRes(HRESULT res, bool crcOK)
2492static HRESULT CopyData_with_Progress(const Byte *data, size_t size, 2707static HRESULT CopyData_with_Progress(const Byte *data, size_t size,
2493 ISequentialOutStream *outStream, ICompressProgressInfo *progress) 2708 ISequentialOutStream *outStream, ICompressProgressInfo *progress)
2494{ 2709{
2495 size_t pos = 0; 2710 UInt64 pos64 = 0;
2496 2711 while (size)
2497 while (pos < size)
2498 { 2712 {
2499 const UInt32 kStepSize = ((UInt32)1 << 24); 2713 const UInt32 kStepSize = (UInt32)1 << 24;
2500 UInt32 cur32; 2714 UInt32 cur = kStepSize;
2501 { 2715 if (cur > size)
2502 size_t cur = size - pos; 2716 cur = (UInt32)size;
2503 if (cur > kStepSize) 2717 RINOK(outStream->Write(data, cur, &cur))
2504 cur = kStepSize; 2718 if (cur == 0)
2505 cur32 = (UInt32)cur;
2506 }
2507 RINOK(outStream->Write(data + pos, cur32, &cur32))
2508 if (cur32 == 0)
2509 return E_FAIL; 2719 return E_FAIL;
2510 pos += cur32; 2720 size -= cur;
2721 data += cur;
2722 pos64 += cur;
2511 if (progress) 2723 if (progress)
2512 { 2724 {
2513 UInt64 pos64 = pos;
2514 RINOK(progress->SetRatioInfo(&pos64, &pos64)) 2725 RINOK(progress->SetRatioInfo(&pos64, &pos64))
2515 } 2726 }
2516 } 2727 }
2517
2518 return S_OK; 2728 return S_OK;
2519} 2729}
2520 2730
@@ -2525,7 +2735,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2525 COM_TRY_BEGIN 2735 COM_TRY_BEGIN
2526 const bool allFilesMode = (numItems == (UInt32)(Int32)-1); 2736 const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
2527 if (allFilesMode) 2737 if (allFilesMode)
2528 numItems = _refs.Size(); 2738 numItems = (UInt32)_refs.Size();
2529 if (numItems == 0) 2739 if (numItems == 0)
2530 return S_OK; 2740 return S_OK;
2531 2741
@@ -2554,12 +2764,11 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2554 UInt64 total = 0; 2764 UInt64 total = 0;
2555 bool isThereUndefinedSize = false; 2765 bool isThereUndefinedSize = false;
2556 bool thereAreLinks = false; 2766 bool thereAreLinks = false;
2557
2558 { 2767 {
2559 unsigned solidLimit = 0; 2768 unsigned solidLimit = 0;
2560 for (UInt32 t = 0; t < numItems; t++) 2769 for (UInt32 t = 0; t < numItems; t++)
2561 { 2770 {
2562 unsigned index = allFilesMode ? t : indices[t]; 2771 const unsigned index = (unsigned)(allFilesMode ? t : indices[t]);
2563 const CRefItem &ref = _refs[index]; 2772 const CRefItem &ref = _refs[index];
2564 const CItem &item = _items[ref.Item]; 2773 const CItem &item = _items[ref.Item];
2565 const CItem &lastItem = _items[ref.Last]; 2774 const CItem &lastItem = _items[ref.Last];
@@ -2688,10 +2897,10 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2688 if (!testMode) 2897 if (!testMode)
2689 for (UInt32 t = 0; t < numItems; t++) 2898 for (UInt32 t = 0; t < numItems; t++)
2690 { 2899 {
2691 unsigned index = allFilesMode ? t : indices[t]; 2900 const unsigned index = (unsigned)(allFilesMode ? t : indices[t]);
2692 const CRefItem &ref = _refs[index]; 2901 const CRefItem &ref = _refs[index];
2693 2902
2694 int linkIndex = ref.Link; 2903 const int linkIndex = ref.Link;
2695 if (linkIndex < 0 || (unsigned)linkIndex >= index) 2904 if (linkIndex < 0 || (unsigned)linkIndex >= index)
2696 continue; 2905 continue;
2697 const CItem &linkItem = _items[_refs[(unsigned)linkIndex].Item]; 2906 const CItem &linkItem = _items[_refs[(unsigned)linkIndex].Item];
@@ -2711,38 +2920,139 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2711 } 2920 }
2712 2921
2713 2922
2923
2924 // ---------- MEMORY REQUEST ----------
2925 {
2926 UInt64 dictMaxSize = 0;
2927 for (UInt32 i = 0; i < _refs.Size(); i++)
2928 {
2929 if (extractStatuses[i] == 0)
2930 continue;
2931 const CRefItem &ref = _refs[i];
2932 const CItem &item = _items[ref.Item];
2933/*
2934 if (!item.IsDir() && !item.IsService() && item.NeedUse_as_CopyLink())
2935 {
2936 }
2937*/
2938 const unsigned algo = item.Get_AlgoVersion_RawBits();
2939 if (!item.IsDir() && algo < Z7_ARRAY_SIZE(_methodMasks))
2940 {
2941 const UInt64 d = item.Get_DictSize64();
2942 if (dictMaxSize < d)
2943 dictMaxSize = d;
2944 }
2945 }
2946 // we use callback, if dict exceeds (1 GB), because
2947 // client code can set low limit (1 GB) for allowed memory usage.
2948 const UInt64 k_MemLimit_for_Callback = (UInt64)1 << 30;
2949 if (dictMaxSize > (_memUsage_WasSet ?
2950 _memUsage_Decompress : k_MemLimit_for_Callback))
2951 {
2952 {
2953 CMyComPtr<IArchiveRequestMemoryUseCallback> requestMem;
2954 extractCallback->QueryInterface(IID_IArchiveRequestMemoryUseCallback, (void **)&requestMem);
2955 if (!requestMem)
2956 {
2957 if (_memUsage_WasSet)
2958 return E_OUTOFMEMORY;
2959 }
2960 else
2961 {
2962 UInt64 allowedSize = _memUsage_WasSet ?
2963 _memUsage_Decompress :
2964 (UInt64)1 << 32; // 4 GB is default allowed limit for RAR7
2965
2966 const UInt32 flags = (_memUsage_WasSet ?
2967 NRequestMemoryUseFlags::k_AllowedSize_WasForced |
2968 NRequestMemoryUseFlags::k_MLimit_Exceeded :
2969 (dictMaxSize > allowedSize) ?
2970 NRequestMemoryUseFlags::k_DefaultLimit_Exceeded:
2971 0)
2972 | NRequestMemoryUseFlags::k_SkipArc_IsExpected
2973 // | NRequestMemoryUseFlags::k_NoErrorMessage // for debug
2974 ;
2975
2976 // we set "Allow" for default case, if requestMem doesn't process anything.
2977 UInt32 answerFlags =
2978 (_memUsage_WasSet && dictMaxSize > allowedSize) ?
2979 NRequestMemoryAnswerFlags::k_Limit_Exceeded
2980 | NRequestMemoryAnswerFlags::k_SkipArc
2981 : NRequestMemoryAnswerFlags::k_Allow;
2982
2983 RINOK(requestMem->RequestMemoryUse(
2984 flags,
2985 NEventIndexType::kNoIndex,
2986 // NEventIndexType::kInArcIndex, // for debug
2987 0, // index
2988 NULL, // path
2989 dictMaxSize, &allowedSize, &answerFlags))
2990 if ( (answerFlags & NRequestMemoryAnswerFlags::k_Allow) == 0
2991 || (answerFlags & NRequestMemoryAnswerFlags::k_Stop)
2992 || (answerFlags & NRequestMemoryAnswerFlags::k_SkipArc)
2993 )
2994 {
2995 return E_OUTOFMEMORY;
2996 }
2997/*
2998 if ((answerFlags & NRequestMemoryAnswerFlags::k_AskForBigFile) == 0 &&
2999 (answerFlags & NRequestMemoryAnswerFlags::k_ReportForBigFile) == 0)
3000 {
3001 // requestMem.Release();
3002 }
3003*/
3004 }
3005 }
3006 }
3007 }
3008
3009
3010
3011 // ---------- UNPACK ----------
3012
2714 UInt64 totalUnpacked = 0; 3013 UInt64 totalUnpacked = 0;
2715 UInt64 totalPacked = 0; 3014 UInt64 totalPacked = 0;
2716 UInt64 curUnpackSize = 0; 3015 UInt64 curUnpackSize;
2717 UInt64 curPackSize = 0; 3016 UInt64 curPackSize;
2718 3017
2719 CUnpacker unpacker; 3018 CUnpacker unpacker;
2720 3019 unpacker.NeedCrc = _needChecksumCheck;
2721 CVolsInStream *volsInStreamSpec = new CVolsInStream; 3020 CMyComPtr2_Create<ISequentialInStream, CVolsInStream> volsInStream;
2722 CMyComPtr<ISequentialInStream> volsInStream = volsInStreamSpec; 3021 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
2723
2724 CLocalProgress *lps = new CLocalProgress;
2725 CMyComPtr<ICompressProgressInfo> progress = lps;
2726 lps->Init(extractCallback, false); 3022 lps->Init(extractCallback, false);
2727 3023
2728 // bool needClearSolid = true; 3024/*
3025 bool prevSolidWasSkipped = false;
3026 UInt64 solidDictSize_Skip = 0;
3027*/
2729 3028
2730 FOR_VECTOR (i, _refs) 3029 for (unsigned i = 0;; i++,
3030 totalUnpacked += curUnpackSize,
3031 totalPacked += curPackSize)
2731 { 3032 {
2732 if (extractStatuses[i] == 0)
2733 continue;
2734
2735 totalUnpacked += curUnpackSize;
2736 totalPacked += curPackSize;
2737 lps->InSize = totalPacked; 3033 lps->InSize = totalPacked;
2738 lps->OutSize = totalUnpacked; 3034 lps->OutSize = totalUnpacked;
2739 RINOK(lps->SetCur()) 3035 RINOK(lps->SetCur())
3036 {
3037 const unsigned num = _refs.Size();
3038 if (i >= num)
3039 break;
3040 for (;;)
3041 {
3042 if (extractStatuses[i] != 0)
3043 break;
3044 i++;
3045 if (i >= num)
3046 break;
3047 }
3048 if (i >= num)
3049 break;
3050 }
3051 curUnpackSize = 0;
3052 curPackSize = 0;
2740 3053
2741 CMyComPtr<ISequentialOutStream> realOutStream;
2742
2743 // isExtract means that we don't skip that item. So we need read data. 3054 // isExtract means that we don't skip that item. So we need read data.
2744 3055 const bool isExtract = ((extractStatuses[i] & kStatus_Extract) != 0);
2745 bool isExtract = ((extractStatuses[i] & kStatus_Extract) != 0);
2746 Int32 askMode = 3056 Int32 askMode =
2747 isExtract ? (testMode ? 3057 isExtract ? (testMode ?
2748 NExtract::NAskMode::kTest : 3058 NExtract::NAskMode::kTest :
@@ -2754,14 +3064,13 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2754 // if (!testMode) 3064 // if (!testMode)
2755 if ((extractStatuses[i] & kStatus_Link) != 0) 3065 if ((extractStatuses[i] & kStatus_Link) != 0)
2756 { 3066 {
2757 int bufIndex = FindLinkBuf(linkFiles, i); 3067 const int bufIndex = FindLinkBuf(linkFiles, i);
2758 if (bufIndex < 0) 3068 if (bufIndex < 0)
2759 return E_FAIL; 3069 return E_FAIL;
2760 unpacker.linkFile = &linkFiles[bufIndex]; 3070 unpacker.linkFile = &linkFiles[bufIndex];
2761 } 3071 }
2762 3072
2763 UInt32 index = i; 3073 const unsigned index = i;
2764
2765 const CRefItem *ref = &_refs[index]; 3074 const CRefItem *ref = &_refs[index];
2766 const CItem *item = &_items[ref->Item]; 3075 const CItem *item = &_items[ref->Item];
2767 const CItem &lastItem = _items[ref->Last]; 3076 const CItem &lastItem = _items[ref->Last];
@@ -2772,8 +3081,6 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2772 3081
2773 curPackSize = GetPackSize(index); 3082 curPackSize = GetPackSize(index);
2774 3083
2775 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
2776
2777 bool isSolid = false; 3084 bool isSolid = false;
2778 if (!item->IsService()) 3085 if (!item->IsService())
2779 { 3086 {
@@ -2782,6 +3089,52 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2782 unpacker.SolidAllowed = isSolid; 3089 unpacker.SolidAllowed = isSolid;
2783 } 3090 }
2784 3091
3092
3093 // ----- request mem -----
3094/*
3095 // link files are complicated cases. (ref->Link >= 0)
3096 // link file can refer to non-solid file that can have big dictionary
3097 // link file can refer to solid files that requres buffer
3098 if (!item->IsDir() && requestMem && ref->Link < 0)
3099 {
3100 bool needSkip = false;
3101 if (isSolid)
3102 needSkip = prevSolidWasSkipped;
3103 else
3104 {
3105 // isSolid == false
3106 const unsigned algo = item->Get_AlgoVersion_RawBits();
3107 // const unsigned m = item.Get_Method();
3108 if (algo < Z7_ARRAY_SIZE(_methodMasks))
3109 {
3110 solidDictSize_Skip = item->Get_DictSize64();
3111 if (solidDictSize_Skip > allowedSize)
3112 needSkip = true;
3113 }
3114 }
3115 if (needSkip)
3116 {
3117 UInt32 answerFlags = 0;
3118 UInt64 allowedSize_File = allowedSize;
3119 RINOK(requestMem->RequestMemoryUse(
3120 NRequestMemoryUseFlags::k_Limit_Exceeded |
3121 NRequestMemoryUseFlags::k_IsReport,
3122 NEventIndexType::kInArcIndex,
3123 index,
3124 NULL, // path
3125 solidDictSize_Skip, &allowedSize_File, &answerFlags))
3126 if (!item->IsService())
3127 prevSolidWasSkipped = true;
3128 continue;
3129 }
3130 }
3131 if (!item->IsService() && item->IsDir())
3132 prevSolidWasSkipped = false;
3133*/
3134
3135 CMyComPtr<ISequentialOutStream> realOutStream;
3136 RINOK(extractCallback->GetStream((UInt32)index, &realOutStream, askMode))
3137
2785 if (item->IsDir()) 3138 if (item->IsDir())
2786 { 3139 {
2787 RINOK(extractCallback->PrepareOperation(askMode)) 3140 RINOK(extractCallback->PrepareOperation(askMode))
@@ -2789,7 +3142,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2789 continue; 3142 continue;
2790 } 3143 }
2791 3144
2792 int index2 = ref->Link; 3145 const int index2 = ref->Link;
2793 3146
2794 int bufIndex = -1; 3147 int bufIndex = -1;
2795 3148
@@ -2880,7 +3233,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2880 if (needCallback) 3233 if (needCallback)
2881 if (realOutStream) 3234 if (realOutStream)
2882 { 3235 {
2883 RINOK(CopyData_with_Progress(linkFile.Data, linkFile.Data.Size(), realOutStream, progress)) 3236 RINOK(CopyData_with_Progress(linkFile.Data, linkFile.Data.Size(), realOutStream, lps))
2884 } 3237 }
2885 3238
2886 if (--linkFile.NumLinks == 0) 3239 if (--linkFile.NumLinks == 0)
@@ -2899,7 +3252,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2899 3252
2900 if (item->NeedUse_as_CopyLink()) 3253 if (item->NeedUse_as_CopyLink())
2901 { 3254 {
2902 int opRes = realOutStream ? 3255 const int opRes = realOutStream ?
2903 NExtract::NOperationResult::kUnsupportedMethod: 3256 NExtract::NOperationResult::kUnsupportedMethod:
2904 NExtract::NOperationResult::kOK; 3257 NExtract::NOperationResult::kOK;
2905 realOutStream.Release(); 3258 realOutStream.Release();
@@ -2907,9 +3260,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2907 continue; 3260 continue;
2908 } 3261 }
2909 3262
2910 volsInStreamSpec->Init(&_arcs, &_items, ref->Item); 3263 volsInStream->Init(&_arcs, &_items, ref->Item);
2911 3264
2912 UInt64 packSize = curPackSize; 3265 const UInt64 packSize = curPackSize;
2913 3266
2914 if (item->IsEncrypted()) 3267 if (item->IsEncrypted())
2915 if (!unpacker.getTextPassword) 3268 if (!unpacker.getTextPassword)
@@ -2927,9 +3280,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2927 3280
2928 bool crcOK = true; 3281 bool crcOK = true;
2929 if (result == S_OK) 3282 if (result == S_OK)
2930 result = unpacker.Code(*item, _items[ref->Last], packSize, volsInStream, realOutStream, progress, crcOK); 3283 result = unpacker.Code(*item, _items[ref->Last], packSize, volsInStream, realOutStream, lps, crcOK);
2931 realOutStream.Release(); 3284 realOutStream.Release();
2932 if (!volsInStreamSpec->CrcIsOK) 3285 if (!volsInStream->CrcIsOK)
2933 crcOK = false; 3286 crcOK = false;
2934 3287
2935 int opRes = crcOK ? 3288 int opRes = crcOK ?
@@ -2950,17 +3303,71 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2950 } 3303 }
2951 3304
2952 { 3305 {
2953 FOR_VECTOR (i, linkFiles) 3306 FOR_VECTOR (k, linkFiles)
2954 if (linkFiles[i].NumLinks != 0) 3307 if (linkFiles[k].NumLinks != 0)
2955 return E_FAIL; 3308 return E_FAIL;
2956 } 3309 }
2957 3310
2958 return S_OK; 3311 return S_OK;
2959
2960 COM_TRY_END 3312 COM_TRY_END
2961} 3313}
2962 3314
2963 3315
3316CHandler::CHandler()
3317{
3318 InitDefaults();
3319}
3320
3321void CHandler::InitDefaults()
3322{
3323 _needChecksumCheck = true;
3324 _memUsage_WasSet = false;
3325 _memUsage_Decompress = (UInt64)1 << 32;
3326}
3327
3328Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
3329{
3330 InitDefaults();
3331
3332 for (UInt32 i = 0; i < numProps; i++)
3333 {
3334 UString name = names[i];
3335 name.MakeLower_Ascii();
3336 if (name.IsEmpty())
3337 return E_INVALIDARG;
3338
3339 const PROPVARIANT &prop = values[i];
3340
3341 if (name.IsPrefixedBy_Ascii_NoCase("mt"))
3342 {
3343 }
3344 else if (name.IsPrefixedBy_Ascii_NoCase("memx"))
3345 {
3346 UInt64 memAvail;
3347 if (!NWindows::NSystem::GetRamSize(memAvail))
3348 memAvail = (UInt64)(sizeof(size_t)) << 28;
3349 UInt64 v;
3350 if (!ParseSizeString(name.Ptr(4), prop, memAvail, v))
3351 return E_INVALIDARG;
3352 _memUsage_Decompress = v;
3353 _memUsage_WasSet = true;
3354 }
3355 else if (name.IsPrefixedBy_Ascii_NoCase("crc"))
3356 {
3357 name.Delete(0, 3);
3358 UInt32 crcSize = 1;
3359 RINOK(ParsePropToUInt32(name, prop, crcSize))
3360 _needChecksumCheck = (crcSize != 0);
3361 }
3362 else
3363 {
3364 return E_INVALIDARG;
3365 }
3366 }
3367 return S_OK;
3368}
3369
3370
2964IMPL_ISetCompressCodecsInfo 3371IMPL_ISetCompressCodecsInfo
2965 3372
2966REGISTER_ARC_I( 3373REGISTER_ARC_I(
@@ -2973,29 +3380,78 @@ REGISTER_ARC_I(
2973}} 3380}}
2974 3381
2975 3382
2976Z7_CLASS_IMP_COM_1( 3383Z7_CLASS_IMP_COM_2(
2977 CBlake2spHasher 3384 CBlake2spHasher
2978 , IHasher 3385 , IHasher
3386 , ICompressSetCoderProperties
2979) 3387)
2980 CBlake2sp _blake; 3388 CAlignedBuffer1 _buf;
3389 // CBlake2sp _blake;
3390 #define Z7_BLACK2S_ALIGN_OBJECT_OFFSET 0
3391 CBlake2sp *Obj() { return (CBlake2sp *)(void *)((Byte *)_buf + Z7_BLACK2S_ALIGN_OBJECT_OFFSET); }
2981public: 3392public:
2982 Byte _mtDummy[1 << 7]; // it's public to eliminate clang warning: unused private field 3393 Byte _mtDummy[1 << 7]; // it's public to eliminate clang warning: unused private field
2983 CBlake2spHasher() { Init(); } 3394 CBlake2spHasher():
3395 _buf(sizeof(CBlake2sp) + Z7_BLACK2S_ALIGN_OBJECT_OFFSET)
3396 {
3397 Blake2sp_SetFunction(Obj(), 0);
3398 Blake2sp_InitState(Obj());
3399 }
2984}; 3400};
2985 3401
2986Z7_COM7F_IMF2(void, CBlake2spHasher::Init()) 3402Z7_COM7F_IMF2(void, CBlake2spHasher::Init())
2987{ 3403{
2988 Blake2sp_Init(&_blake); 3404 Blake2sp_InitState(Obj());
2989} 3405}
2990 3406
2991Z7_COM7F_IMF2(void, CBlake2spHasher::Update(const void *data, UInt32 size)) 3407Z7_COM7F_IMF2(void, CBlake2spHasher::Update(const void *data, UInt32 size))
2992{ 3408{
2993 Blake2sp_Update(&_blake, (const Byte *)data, size); 3409#if 1
3410 Blake2sp_Update(Obj(), (const Byte *)data, (size_t)size);
3411#else
3412 // for debug:
3413 for (;;)
3414 {
3415 if (size == 0)
3416 return;
3417 UInt32 size2 = (size * 0x85EBCA87) % size / 800;
3418 // UInt32 size2 = size / 2;
3419 if (size2 == 0)
3420 size2 = 1;
3421 Blake2sp_Update(Obj(), (const Byte *)data, size2);
3422 data = (const void *)((const Byte *)data + size2);
3423 size -= size2;
3424 }
3425#endif
2994} 3426}
2995 3427
2996Z7_COM7F_IMF2(void, CBlake2spHasher::Final(Byte *digest)) 3428Z7_COM7F_IMF2(void, CBlake2spHasher::Final(Byte *digest))
2997{ 3429{
2998 Blake2sp_Final(&_blake, digest); 3430 Blake2sp_Final(Obj(), digest);
2999} 3431}
3000 3432
3001REGISTER_HASHER(CBlake2spHasher, 0x202, "BLAKE2sp", BLAKE2S_DIGEST_SIZE) 3433Z7_COM7F_IMF(CBlake2spHasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))
3434{
3435 unsigned algo = 0;
3436 for (UInt32 i = 0; i < numProps; i++)
3437 {
3438 if (propIDs[i] == NCoderPropID::kDefaultProp)
3439 {
3440 const PROPVARIANT &prop = coderProps[i];
3441 if (prop.vt != VT_UI4)
3442 return E_INVALIDARG;
3443 /*
3444 if (prop.ulVal > Z7_BLAKE2S_ALGO_MAX)
3445 return E_NOTIMPL;
3446 */
3447 algo = (unsigned)prop.ulVal;
3448 }
3449 }
3450 if (!Blake2sp_SetFunction(Obj(), algo))
3451 return E_NOTIMPL;
3452 return S_OK;
3453}
3454
3455REGISTER_HASHER(CBlake2spHasher, 0x202, "BLAKE2sp", Z7_BLAKE2S_DIGEST_SIZE)
3456
3457static struct CBlake2sp_Prepare { CBlake2sp_Prepare() { z7_Black2sp_Prepare(); } } g_Blake2sp_Prepare;
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.h b/CPP/7zip/Archive/Rar/Rar5Handler.h
index 72e1efc..8f6581a 100644
--- a/CPP/7zip/Archive/Rar/Rar5Handler.h
+++ b/CPP/7zip/Archive/Rar/Rar5Handler.h
@@ -48,7 +48,8 @@ namespace NArcFlags
48 // const unsigned kLocked = 1 << 4; 48 // const unsigned kLocked = 1 << 4;
49} 49}
50 50
51const unsigned kArcExtraRecordType_Locator = 1; 51const unsigned kArcExtraRecordType_Locator = 1;
52const unsigned kArcExtraRecordType_Metadata = 2;
52 53
53namespace NLocatorFlags 54namespace NLocatorFlags
54{ 55{
@@ -56,6 +57,14 @@ namespace NLocatorFlags
56 const unsigned kRecovery = 1 << 1; 57 const unsigned kRecovery = 1 << 1;
57} 58}
58 59
60namespace NMetadataFlags
61{
62 const unsigned kArcName = 1 << 0;
63 const unsigned kCTime = 1 << 1;
64 const unsigned kUnixTime = 1 << 2;
65 const unsigned kNanoSec = 1 << 3;
66}
67
59namespace NFileFlags 68namespace NFileFlags
60{ 69{
61 const unsigned kIsDir = 1 << 0; 70 const unsigned kIsDir = 1 << 0;
@@ -68,6 +77,7 @@ namespace NMethodFlags
68{ 77{
69 // const unsigned kVersionMask = 0x3F; 78 // const unsigned kVersionMask = 0x3F;
70 const unsigned kSolid = 1 << 6; 79 const unsigned kSolid = 1 << 6;
80 const unsigned kRar5_Compat = 1u << 20;
71} 81}
72 82
73namespace NArcEndFlags 83namespace NArcEndFlags
@@ -181,7 +191,7 @@ struct CItem
181 AString Name; 191 AString Name;
182 192
183 unsigned VolIndex; 193 unsigned VolIndex;
184 int NextItem; 194 int NextItem; // in _items{}
185 195
186 UInt32 UnixMTime; 196 UInt32 UnixMTime;
187 UInt32 CRC; 197 UInt32 CRC;
@@ -201,9 +211,12 @@ struct CItem
201 211
202 void Clear() 212 void Clear()
203 { 213 {
204 CommonFlags = 0; 214 // CommonFlags = 0;
205 Flags = 0; 215 // Flags = 0;
206 216
217 // UnixMTime = 0;
218 // CRC = 0;
219
207 VolIndex = 0; 220 VolIndex = 0;
208 NextItem = -1; 221 NextItem = -1;
209 222
@@ -230,10 +243,46 @@ struct CItem
230 // && false; 243 // && false;
231 } 244 }
232 245
233 bool IsSolid() const { return ((UInt32)Method & NMethodFlags::kSolid) != 0; } 246 // rar docs: Solid flag can be set only for file headers and is never set for service headers.
234 unsigned GetAlgoVersion() const { return (unsigned)Method & 0x3F; } 247 bool IsSolid() const { return ((UInt32)Method & NMethodFlags::kSolid) != 0; }
235 unsigned GetMethod() const { return ((unsigned)Method >> 7) & 0x7; } 248 bool Is_Rar5_Compat() const { return ((UInt32)Method & NMethodFlags::kRar5_Compat) != 0; }
236 UInt32 GetDictSize() const { return (((UInt32)Method >> 10) & 0xF); } 249 unsigned Get_Rar5_CompatBit() const { return ((UInt32)Method >> 20) & 1; }
250
251 unsigned Get_AlgoVersion_RawBits() const { return (unsigned)Method & 0x3F; }
252 unsigned Get_AlgoVersion_HuffRev() const
253 {
254 unsigned w = (unsigned)Method & 0x3F;
255 if (w == 1 && Is_Rar5_Compat())
256 w = 0;
257 return w;
258 }
259 unsigned Get_Method() const { return ((unsigned)Method >> 7) & 0x7; }
260
261 unsigned Get_DictSize_Main() const
262 { return ((UInt32)Method >> 10) & (Get_AlgoVersion_RawBits() == 0 ? 0xf : 0x1f); }
263 unsigned Get_DictSize_Frac() const
264 {
265 // original-unrar ignores Frac, if (algo==0) (rar5):
266 if (Get_AlgoVersion_RawBits() == 0)
267 return 0;
268 return ((UInt32)Method >> 15) & 0x1f;
269 }
270 UInt64 Get_DictSize64() const
271 {
272 // ver 6.* check
273 // return (((UInt32)Method >> 10) & 0xF);
274 UInt64 winSize = 0;
275 const unsigned algo = Get_AlgoVersion_RawBits();
276 if (algo <= 1)
277 {
278 UInt32 w = 32;
279 if (algo == 1)
280 w += Get_DictSize_Frac();
281 winSize = (UInt64)w << (12 + Get_DictSize_Main());
282 }
283 return winSize;
284 }
285
237 286
238 bool IsService() const { return RecordType == NHeaderType::kService; } 287 bool IsService() const { return RecordType == NHeaderType::kService; }
239 288
@@ -255,9 +304,9 @@ struct CItem
255 int FindExtra_Blake() const 304 int FindExtra_Blake() const
256 { 305 {
257 unsigned size = 0; 306 unsigned size = 0;
258 int offset = FindExtra(NExtraID::kHash, size); 307 const int offset = FindExtra(NExtraID::kHash, size);
259 if (offset >= 0 308 if (offset >= 0
260 && size == BLAKE2S_DIGEST_SIZE + 1 309 && size == Z7_BLAKE2S_DIGEST_SIZE + 1
261 && Extra[(unsigned)offset] == kHashID_Blake2sp) 310 && Extra[(unsigned)offset] == kHashID_Blake2sp)
262 return offset + 1; 311 return offset + 1;
263 return -1; 312 return -1;
@@ -282,11 +331,17 @@ struct CItem
282 UInt32 a; 331 UInt32 a;
283 switch (HostOS) 332 switch (HostOS)
284 { 333 {
285 case kHost_Windows: a = Attrib; break; 334 case kHost_Windows:
286 case kHost_Unix: a = (Attrib << 16); break; 335 a = Attrib;
287 default: a = 0; 336 break;
337 case kHost_Unix:
338 a = Attrib << 16;
339 a |= 0x8000; // add posix mode marker
340 break;
341 default:
342 a = 0;
288 } 343 }
289 // if (IsDir()) a |= FILE_ATTRIBUTE_DIRECTORY; 344 if (IsDir()) a |= FILE_ATTRIBUTE_DIRECTORY;
290 return a; 345 return a;
291 } 346 }
292 347
@@ -305,10 +360,14 @@ struct CInArcInfo
305 bool EndOfArchive_was_Read; 360 bool EndOfArchive_was_Read;
306 361
307 bool IsEncrypted; 362 bool IsEncrypted;
363 bool Locator_Defined;
364 bool Locator_Error;
365 bool Metadata_Defined;
366 bool Metadata_Error;
367 bool UnknownExtraRecord;
368 bool Extra_Error;
369 bool UnsupportedFeature;
308 370
309 // CByteBuffer Extra;
310
311 /*
312 struct CLocator 371 struct CLocator
313 { 372 {
314 UInt64 Flags; 373 UInt64 Flags;
@@ -317,11 +376,32 @@ struct CInArcInfo
317 376
318 bool Is_QuickOpen() const { return (Flags & NLocatorFlags::kQuickOpen) != 0; } 377 bool Is_QuickOpen() const { return (Flags & NLocatorFlags::kQuickOpen) != 0; }
319 bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; } 378 bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; }
379
380 bool Parse(const Byte *p, size_t size);
381 CLocator():
382 Flags(0),
383 QuickOpen(0),
384 Recovery(0)
385 {}
320 }; 386 };
321 387
322 int FindExtra(unsigned extraID, unsigned &recordDataSize) const; 388 struct CMetadata
323 bool FindExtra_Locator(CLocator &locator) const; 389 {
324 */ 390 UInt64 Flags;
391 UInt64 CTime;
392 AString ArcName;
393
394 bool Parse(const Byte *p, size_t size);
395 CMetadata():
396 Flags(0),
397 CTime(0)
398 {}
399 };
400
401 CLocator Locator;
402 CMetadata Metadata;
403
404 bool ParseExtra(const Byte *p, size_t size);
325 405
326 CInArcInfo(): 406 CInArcInfo():
327 Flags(0), 407 Flags(0),
@@ -330,7 +410,14 @@ struct CInArcInfo
330 EndPos(0), 410 EndPos(0),
331 EndFlags(0), 411 EndFlags(0),
332 EndOfArchive_was_Read(false), 412 EndOfArchive_was_Read(false),
333 IsEncrypted(false) 413 IsEncrypted(false),
414 Locator_Defined(false),
415 Locator_Error(false),
416 Metadata_Defined(false),
417 Metadata_Error(false),
418 UnknownExtraRecord(false),
419 Extra_Error(false),
420 UnsupportedFeature(false)
334 {} 421 {}
335 422
336 /* 423 /*
@@ -342,7 +429,6 @@ struct CInArcInfo
342 EndPos = 0; 429 EndPos = 0;
343 EndFlags = 0; 430 EndFlags = 0;
344 EndOfArchive_was_Read = false; 431 EndOfArchive_was_Read = false;
345 Extra.Free();
346 } 432 }
347 */ 433 */
348 434
@@ -360,10 +446,10 @@ struct CInArcInfo
360 446
361struct CRefItem 447struct CRefItem
362{ 448{
363 unsigned Item; 449 unsigned Item; // First item in _items[]
364 unsigned Last; 450 unsigned Last; // Last item in _items[]
365 int Parent; 451 int Parent; // in _refs[], if alternate stream
366 int Link; 452 int Link; // in _refs[]
367}; 453};
368 454
369 455
@@ -377,32 +463,54 @@ struct CArc
377class CHandler Z7_final: 463class CHandler Z7_final:
378 public IInArchive, 464 public IInArchive,
379 public IArchiveGetRawProps, 465 public IArchiveGetRawProps,
466 public ISetProperties,
380 Z7_PUBLIC_ISetCompressCodecsInfo_IFEC 467 Z7_PUBLIC_ISetCompressCodecsInfo_IFEC
381 public CMyUnknownImp 468 public CMyUnknownImp
382{ 469{
383 Z7_COM_QI_BEGIN2(IInArchive) 470 Z7_COM_QI_BEGIN2(IInArchive)
384 Z7_COM_QI_ENTRY(IArchiveGetRawProps) 471 Z7_COM_QI_ENTRY(IArchiveGetRawProps)
472 Z7_COM_QI_ENTRY(ISetProperties)
385 Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC 473 Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC
386 Z7_COM_QI_END 474 Z7_COM_QI_END
387 Z7_COM_ADDREF_RELEASE 475 Z7_COM_ADDREF_RELEASE
388 476
389 Z7_IFACE_COM7_IMP(IInArchive) 477 Z7_IFACE_COM7_IMP(IInArchive)
390 Z7_IFACE_COM7_IMP(IArchiveGetRawProps) 478 Z7_IFACE_COM7_IMP(IArchiveGetRawProps)
479 Z7_IFACE_COM7_IMP(ISetProperties)
391 DECL_ISetCompressCodecsInfo 480 DECL_ISetCompressCodecsInfo
392 481
482 void InitDefaults();
483
484 bool _isArc;
485 bool _needChecksumCheck;
486 bool _memUsage_WasSet;
487 bool _comment_WasUsedInArc;
488 bool _acl_Used;
489 bool _error_in_ACL;
490 bool _split_Error;
393public: 491public:
394 CRecordVector<CRefItem> _refs; 492 CRecordVector<CRefItem> _refs;
395 CObjectVector<CItem> _items; 493 CObjectVector<CItem> _items;
494
495 CHandler();
396private: 496private:
397 CObjectVector<CArc> _arcs; 497 CObjectVector<CArc> _arcs;
398 CObjectVector<CByteBuffer> _acls; 498 CObjectVector<CByteBuffer> _acls;
399 499
400 UInt32 _errorFlags; 500 UInt32 _errorFlags;
401 // UInt32 _warningFlags; 501 // UInt32 _warningFlags;
402 bool _isArc; 502
503 UInt32 _numBlocks;
504 unsigned _rar5comapt_mask;
505 unsigned _methodMasks[2];
506 UInt64 _algo_Mask;
507 UInt64 _dictMaxSizes[2];
508
403 CByteBuffer _comment; 509 CByteBuffer _comment;
404 UString _missingVolName; 510 UString _missingVolName;
405 511
512 UInt64 _memUsage_Decompress;
513
406 DECL_EXTERNAL_CODECS_VARS 514 DECL_EXTERNAL_CODECS_VARS
407 515
408 UInt64 GetPackSize(unsigned refIndex) const; 516 UInt64 GetPackSize(unsigned refIndex) const;
diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h
index c4d8450..6a1da4f 100644
--- a/CPP/7zip/Archive/Rar/RarHandler.h
+++ b/CPP/7zip/Archive/Rar/RarHandler.h
@@ -80,6 +80,8 @@ class CHandler Z7_final:
80 Z7_IFACE_COM7_IMP(IInArchive) 80 Z7_IFACE_COM7_IMP(IInArchive)
81 DECL_ISetCompressCodecsInfo 81 DECL_ISetCompressCodecsInfo
82 82
83 bool _isArc;
84
83 CRecordVector<CRefItem> _refItems; 85 CRecordVector<CRefItem> _refItems;
84 CObjectVector<CItem> _items; 86 CObjectVector<CItem> _items;
85 CObjectVector<CArc> _arcs; 87 CObjectVector<CArc> _arcs;
@@ -87,7 +89,6 @@ class CHandler Z7_final:
87 // AString _errorMessage; 89 // AString _errorMessage;
88 UInt32 _errorFlags; 90 UInt32 _errorFlags;
89 UInt32 _warningFlags; 91 UInt32 _warningFlags;
90 bool _isArc;
91 UString _missingVolName; 92 UString _missingVolName;
92 93
93 DECL_EXTERNAL_CODECS_VARS 94 DECL_EXTERNAL_CODECS_VARS
@@ -99,7 +100,7 @@ class CHandler Z7_final:
99 void AddErrorMessage(const AString &s) 100 void AddErrorMessage(const AString &s)
100 { 101 {
101 if (!_errorMessage.IsEmpty()) 102 if (!_errorMessage.IsEmpty())
102 _errorMessage += '\n'; 103 _errorMessage.Add_LF();
103 _errorMessage += s; 104 _errorMessage += s;
104 } 105 }
105 */ 106 */
diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp
index e05ac26..da2b6ee 100644
--- a/CPP/7zip/Archive/RpmHandler.cpp
+++ b/CPP/7zip/Archive/RpmHandler.cpp
@@ -97,7 +97,15 @@ static const char * const k_CPUs[] =
97 , "ppc64" 97 , "ppc64"
98 , "sh" 98 , "sh"
99 , "xtensa" 99 , "xtensa"
100 , "aarch64" // 19 100 , "aarch64" // 19
101 , "mipsr6" // 20
102 , "mips64r6" // 21
103 , "riscv64" // 22
104 , "loongarch64" // 23
105 // , "24"
106 // , "25"
107 // , "loongarch64" // 26 : why 23 and 26 for loongarch64?
108 // 255 for some non specified arch
101}; 109};
102 110
103static const char * const k_OS[] = 111static const char * const k_OS[] =
@@ -128,8 +136,8 @@ static const char * const k_OS[] =
128 136
129struct CLead 137struct CLead
130{ 138{
131 unsigned char Major; 139 Byte Major;
132 unsigned char Minor; 140 // Byte Minor;
133 UInt16 Type; 141 UInt16 Type;
134 UInt16 Cpu; 142 UInt16 Cpu;
135 UInt16 Os; 143 UInt16 Os;
@@ -140,7 +148,7 @@ struct CLead
140 void Parse(const Byte *p) 148 void Parse(const Byte *p)
141 { 149 {
142 Major = p[4]; 150 Major = p[4];
143 Minor = p[5]; 151 // Minor = p[5];
144 Type = Get16(p + 6); 152 Type = Get16(p + 6);
145 Cpu= Get16(p + 8); 153 Cpu= Get16(p + 8);
146 memcpy(Name, p + 10, kNameSize); 154 memcpy(Name, p + 10, kNameSize);
@@ -205,7 +213,7 @@ Z7_class_CHandler_final: public CHandlerCont
205 AString _os; // linux 213 AString _os; // linux
206 214
207 AString _format; // cpio 215 AString _format; // cpio
208 AString _compressor; // xz, gzip, bzip2 216 AString _compressor; // xz, gzip, bzip2, lzma, zstd
209 217
210 CLead _lead; 218 CLead _lead;
211 219
@@ -326,16 +334,20 @@ void CHandler::AddSubFileExtension(AString &res) const
326 s = "bz2"; 334 s = "bz2";
327 else if (_compressor == "gzip") 335 else if (_compressor == "gzip")
328 s = "gz"; 336 s = "gz";
337 else if (_compressor == "zstd")
338 s = "zst";
329 } 339 }
330 else 340 else
331 { 341 {
332 const Byte *p = _payloadSig; 342 const Byte *p = _payloadSig;
333 if (p[0] == 0x1F && p[1] == 0x8B) 343 if (p[0] == 0x1F && p[1] == 0x8B && p[2] == 8)
334 s = "gz"; 344 s = "gz";
335 else if (p[0] == 0xFD && p[1] == '7' && p[2] == 'z' && p[3] == 'X' && p[4] == 'Z' && p[5] == 0) 345 else if (p[0] == 0xFD && p[1] == '7' && p[2] == 'z' && p[3] == 'X' && p[4] == 'Z' && p[5] == 0)
336 s = "xz"; 346 s = "xz";
337 else if (p[0] == 'B' && p[1] == 'Z' && p[2] == 'h' && p[3] >= '1' && p[3] <= '9') 347 else if (p[0] == 'B' && p[1] == 'Z' && p[2] == 'h' && p[3] >= '1' && p[3] <= '9')
338 s = "bz2"; 348 s = "bz2";
349 else if (p[0] == 0x28 && p[1] == 0xb5 && p[2] == 0x2f && p[3] == 0xfd)
350 s = "zst";
339 else 351 else
340 s = "lzma"; 352 s = "lzma";
341 } 353 }
@@ -466,12 +478,6 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
466 return S_OK; 478 return S_OK;
467} 479}
468 480
469#ifdef Z7_RPM_SHOW_METADATA
470static inline char GetHex(unsigned value)
471{
472 return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
473}
474#endif
475 481
476HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader) 482HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
477{ 483{
@@ -585,7 +591,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
585 if (rem2 == 0) 591 if (rem2 == 0)
586 return S_FALSE; 592 return S_FALSE;
587 if (t != 0) 593 if (t != 0)
588 _metadata += '\n'; 594 _metadata.Add_LF();
589 size_t j; 595 size_t j;
590 for (j = 0; j < rem2 && p2[j] != 0; j++); 596 for (j = 0; j < rem2 && p2[j] != 0; j++);
591 if (j == rem2) 597 if (j == rem2)
@@ -614,8 +620,8 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
614 for (UInt32 t = 0; t < entry.Count; t++) 620 for (UInt32 t = 0; t < entry.Count; t++)
615 { 621 {
616 const unsigned b = p[t]; 622 const unsigned b = p[t];
617 _metadata += GetHex((b >> 4) & 0xF); 623 _metadata += GET_HEX_CHAR_UPPER(b >> 4);
618 _metadata += GetHex(b & 0xF); 624 _metadata += GET_HEX_CHAR_UPPER(b & 0xF);
619 } 625 }
620 } 626 }
621 else 627 else
@@ -623,7 +629,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
623 // p = p; 629 // p = p;
624 } 630 }
625 631
626 _metadata += '\n'; 632 _metadata.Add_LF();
627 #endif 633 #endif
628 } 634 }
629 635
diff --git a/CPP/7zip/Archive/SparseHandler.cpp b/CPP/7zip/Archive/SparseHandler.cpp
index ab76f32..5e666ed 100644
--- a/CPP/7zip/Archive/SparseHandler.cpp
+++ b/CPP/7zip/Archive/SparseHandler.cpp
@@ -77,6 +77,15 @@ struct CChunk
77 UInt32 VirtBlock; 77 UInt32 VirtBlock;
78 Byte Fill [kFillSize]; 78 Byte Fill [kFillSize];
79 UInt64 PhyOffset; 79 UInt64 PhyOffset;
80
81 CChunk()
82 {
83 Fill[0] =
84 Fill[1] =
85 Fill[2] =
86 Fill[3] =
87 0;
88 }
80}; 89};
81 90
82static const Byte k_Signature[] = { 0x3a, 0xff, 0x26, 0xed, 1, 0 }; 91static const Byte k_Signature[] = { 0x3a, 0xff, 0x26, 0xed, 1, 0 };
diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp
index ae7ca03..bf89303 100644
--- a/CPP/7zip/Archive/SplitHandler.cpp
+++ b/CPP/7zip/Archive/SplitHandler.cpp
@@ -56,6 +56,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
56 case kpidPhySize: if (!_sizes.IsEmpty()) prop = _sizes[0]; break; 56 case kpidPhySize: if (!_sizes.IsEmpty()) prop = _sizes[0]; break;
57 case kpidTotalPhySize: prop = _totalSize; break; 57 case kpidTotalPhySize: prop = _totalSize; break;
58 case kpidNumVolumes: prop = (UInt32)_streams.Size(); break; 58 case kpidNumVolumes: prop = (UInt32)_streams.Size(); break;
59 default: break;
59 } 60 }
60 prop.Detach(value); 61 prop.Detach(value);
61 return S_OK; 62 return S_OK;
@@ -273,6 +274,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
273 case kpidPackSize: 274 case kpidPackSize:
274 prop = _totalSize; 275 prop = _totalSize;
275 break; 276 break;
277 default: break;
276 } 278 }
277 prop.Detach(value); 279 prop.Detach(value);
278 return S_OK; 280 return S_OK;
diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp
index 9c9ec03..46e0e1e 100644
--- a/CPP/7zip/Archive/SquashfsHandler.cpp
+++ b/CPP/7zip/Archive/SquashfsHandler.cpp
@@ -3,9 +3,10 @@
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../../../C/Alloc.h" 5#include "../../../C/Alloc.h"
6#include "../../../C/CpuArch.h"
7#include "../../../C/LzmaDec.h" 6#include "../../../C/LzmaDec.h"
8#include "../../../C/Xz.h" 7#include "../../../C/Xz.h"
8#include "../../../C/ZstdDec.h"
9#include "../../../C/CpuArch.h"
9 10
10#include "../../Common/ComTry.h" 11#include "../../Common/ComTry.h"
11#include "../../Common/MyLinux.h" 12#include "../../Common/MyLinux.h"
@@ -30,8 +31,8 @@
30namespace NArchive { 31namespace NArchive {
31namespace NSquashfs { 32namespace NSquashfs {
32 33
33static const UInt32 kNumFilesMax = (1 << 28); 34static const UInt32 kNumFilesMax = 1 << 28;
34static const unsigned kNumDirLevelsMax = (1 << 10); 35static const unsigned kNumDirLevelsMax = 1 << 10;
35 36
36// Layout: Header, Data, inodes, Directories, Fragments, UIDs, GIDs 37// Layout: Header, Data, inodes, Directories, Fragments, UIDs, GIDs
37 38
@@ -66,6 +67,8 @@ static const UInt32 kSignature32_B2 = 0x73687371;
66#define kMethod_LZMA 2 67#define kMethod_LZMA 2
67#define kMethod_LZO 3 68#define kMethod_LZO 3
68#define kMethod_XZ 4 69#define kMethod_XZ 4
70// #define kMethod_LZ4 5
71#define kMethod_ZSTD 6
69 72
70static const char * const k_Methods[] = 73static const char * const k_Methods[] =
71{ 74{
@@ -74,6 +77,8 @@ static const char * const k_Methods[] =
74 , "LZMA" 77 , "LZMA"
75 , "LZO" 78 , "LZO"
76 , "XZ" 79 , "XZ"
80 , "LZ4"
81 , "ZSTD"
77}; 82};
78 83
79static const unsigned kMetadataBlockSizeLog = 13; 84static const unsigned kMetadataBlockSizeLog = 13;
@@ -127,8 +132,8 @@ static const char * const k_Flags[] =
127 , "UNCOMPRESSED_IDS" 132 , "UNCOMPRESSED_IDS"
128}; 133};
129 134
130static const UInt32 kNotCompressedBit16 = (1 << 15); 135static const UInt32 kNotCompressedBit16 = 1 << 15;
131static const UInt32 kNotCompressedBit32 = (1 << 24); 136static const UInt32 kNotCompressedBit32 = 1 << 24;
132 137
133#define GET_COMPRESSED_BLOCK_SIZE(size) ((size) & ~kNotCompressedBit32) 138#define GET_COMPRESSED_BLOCK_SIZE(size) ((size) & ~kNotCompressedBit32)
134#define IS_COMPRESSED_BLOCK(size) (((size) & kNotCompressedBit32) == 0) 139#define IS_COMPRESSED_BLOCK(size) (((size) & kNotCompressedBit32) == 0)
@@ -835,6 +840,9 @@ struct CFrag
835Z7_CLASS_IMP_CHandler_IInArchive_1( 840Z7_CLASS_IMP_CHandler_IInArchive_1(
836 IInArchiveGetStream 841 IInArchiveGetStream
837) 842)
843 bool _noPropsLZMA;
844 bool _needCheckLzma;
845
838 CRecordVector<CItem> _items; 846 CRecordVector<CItem> _items;
839 CRecordVector<CNode> _nodes; 847 CRecordVector<CNode> _nodes;
840 CRecordVector<UInt32> _nodesPos; 848 CRecordVector<UInt32> _nodesPos;
@@ -845,16 +853,13 @@ Z7_CLASS_IMP_CHandler_IInArchive_1(
845 CByteBuffer _uids; 853 CByteBuffer _uids;
846 CByteBuffer _gids; 854 CByteBuffer _gids;
847 CHeader _h; 855 CHeader _h;
848 bool _noPropsLZMA;
849 bool _needCheckLzma;
850 856
851 UInt32 _openCodePage;
852
853 CMyComPtr<IInStream> _stream;
854 UInt64 _sizeCalculated; 857 UInt64 _sizeCalculated;
858 CMyComPtr<IInStream> _stream;
855 859
856 IArchiveOpenCallback *_openCallback; 860 IArchiveOpenCallback *_openCallback;
857 861
862 UInt32 _openCodePage;
858 int _nodeIndex; 863 int _nodeIndex;
859 CRecordVector<bool> _blockCompressed; 864 CRecordVector<bool> _blockCompressed;
860 CRecordVector<UInt64> _blockOffsets; 865 CRecordVector<UInt64> _blockOffsets;
@@ -864,25 +869,18 @@ Z7_CLASS_IMP_CHandler_IInArchive_1(
864 UInt32 _cachedPackBlockSize; 869 UInt32 _cachedPackBlockSize;
865 UInt32 _cachedUnpackBlockSize; 870 UInt32 _cachedUnpackBlockSize;
866 871
867 CLimitedSequentialInStream *_limitedInStreamSpec; 872 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> _limitedInStream;
868 CMyComPtr<ISequentialInStream> _limitedInStream; 873 CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> _outStream;
869 874 CMyComPtr2_Create<ISequentialOutStream, CDynBufSeqOutStream> _dynOutStream;
870 CBufPtrSeqOutStream *_outStreamSpec;
871 CMyComPtr<ISequentialOutStream> _outStream;
872
873 // NCompress::NLzma::CDecoder *_lzmaDecoderSpec;
874 // CMyComPtr<ICompressCoder> _lzmaDecoder;
875 875
876 NCompress::NZlib::CDecoder *_zlibDecoderSpec; 876 // CMyComPtr2<ICompressCoder, NCompress::NLzma::CDecoder> _lzmaDecoder;
877 CMyComPtr<ICompressCoder> _zlibDecoder; 877 CMyComPtr2<ICompressCoder, NCompress::NZlib::CDecoder> _zlibDecoder;
878 878
879 CXzUnpacker _xz; 879 CXzUnpacker _xz;
880 CZstdDecHandle _zstd;
880 881
881 CByteBuffer _inputBuffer; 882 CByteBuffer _inputBuffer;
882 883
883 CDynBufSeqOutStream *_dynOutStreamSpec;
884 CMyComPtr<ISequentialOutStream> _dynOutStream;
885
886 void ClearCache() 884 void ClearCache()
887 { 885 {
888 _cachedBlockStartPos = 0; 886 _cachedBlockStartPos = 0;
@@ -913,24 +911,18 @@ public:
913 ~CHandler() 911 ~CHandler()
914 { 912 {
915 XzUnpacker_Free(&_xz); 913 XzUnpacker_Free(&_xz);
914 if (_zstd)
915 ZstdDec_Destroy(_zstd);
916 } 916 }
917 917
918 HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize); 918 HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
919}; 919};
920 920
921 921
922CHandler::CHandler() 922CHandler::CHandler():
923 _zstd(NULL)
923{ 924{
924 XzUnpacker_Construct(&_xz, &g_Alloc); 925 XzUnpacker_Construct(&_xz, &g_Alloc);
925
926 _limitedInStreamSpec = new CLimitedSequentialInStream;
927 _limitedInStream = _limitedInStreamSpec;
928
929 _outStreamSpec = new CBufPtrSeqOutStream();
930 _outStream = _outStreamSpec;
931
932 _dynOutStreamSpec = new CDynBufSeqOutStream;
933 _dynOutStream = _dynOutStreamSpec;
934} 926}
935 927
936static const Byte kProps[] = 928static const Byte kProps[] =
@@ -1153,24 +1145,16 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
1153 1145
1154 if (method == kMethod_ZLIB) 1146 if (method == kMethod_ZLIB)
1155 { 1147 {
1156 if (!_zlibDecoder) 1148 _zlibDecoder.Create_if_Empty();
1157 { 1149 RINOK(_zlibDecoder.Interface()->Code(_limitedInStream, outStream, NULL, NULL, NULL))
1158 _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); 1150 if (inSize != _zlibDecoder->GetInputProcessedSize())
1159 _zlibDecoder = _zlibDecoderSpec;
1160 }
1161 RINOK(_zlibDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL))
1162 if (inSize != _zlibDecoderSpec->GetInputProcessedSize())
1163 return S_FALSE; 1151 return S_FALSE;
1164 } 1152 }
1165 /* 1153 /*
1166 else if (method == kMethod_LZMA) 1154 else if (method == kMethod_LZMA)
1167 { 1155 {
1168 if (!_lzmaDecoder) 1156 _lzmaDecoder.Create_if_Empty();
1169 { 1157 // _lzmaDecoder->FinishStream = true;
1170 _lzmaDecoderSpec = new NCompress::NLzma::CDecoder();
1171 // _lzmaDecoderSpec->FinishStream = true;
1172 _lzmaDecoder = _lzmaDecoderSpec;
1173 }
1174 const UInt32 kPropsSize = LZMA_PROPS_SIZE + 8; 1158 const UInt32 kPropsSize = LZMA_PROPS_SIZE + 8;
1175 Byte props[kPropsSize]; 1159 Byte props[kPropsSize];
1176 UInt32 propsSize; 1160 UInt32 propsSize;
@@ -1205,7 +1189,7 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
1205 Byte *dest = outBuf; 1189 Byte *dest = outBuf;
1206 if (!outBuf) 1190 if (!outBuf)
1207 { 1191 {
1208 dest = _dynOutStreamSpec->GetBufPtrForWriting(outSizeMax); 1192 dest = _dynOutStream->GetBufPtrForWriting(outSizeMax);
1209 if (!dest) 1193 if (!dest)
1210 return E_OUTOFMEMORY; 1194 return E_OUTOFMEMORY;
1211 } 1195 }
@@ -1253,10 +1237,67 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
1253 && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) 1237 && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
1254 return S_FALSE; 1238 return S_FALSE;
1255 } 1239 }
1240 else if (method == kMethod_ZSTD)
1241 {
1242 const Byte *src = _inputBuffer;
1243
1244 if (!_zstd)
1245 {
1246 _zstd = ZstdDec_Create(&g_AlignedAlloc, &g_AlignedAlloc);
1247 if (!_zstd)
1248 return E_OUTOFMEMORY;
1249 }
1250
1251 CZstdDecState state;
1252 ZstdDecState_Clear(&state);
1253
1254 state.inBuf = src;
1255 state.inLim = srcLen; // + 1; for debug
1256 // state.outStep = outSizeMax;
1257
1258 state.outBuf_fromCaller = dest;
1259 state.outBufSize_fromCaller = outSizeMax;
1260 // state.mustBeFinished = True;
1261
1262 ZstdDec_Init(_zstd);
1263 SRes sres;
1264 for (;;)
1265 {
1266 sres = ZstdDec_Decode(_zstd, &state);
1267 if (sres != SZ_OK)
1268 break;
1269 if (state.inLim == state.inPos
1270 && (state.status == ZSTD_STATUS_NEEDS_MORE_INPUT ||
1271 state.status == ZSTD_STATUS_FINISHED_FRAME))
1272 break;
1273 // sres = sres;
1274 // break; // for debug
1275 }
1276
1277 CZstdDecResInfo info;
1278 // ZstdDecInfo_Clear(&stat);
1279 // stat->InSize = state.inPos;
1280 ZstdDec_GetResInfo(_zstd, &state, sres, &info);
1281 sres = info.decode_SRes;
1282 if (sres == SZ_OK)
1283 {
1284 if (state.status != ZSTD_STATUS_FINISHED_FRAME
1285 // ||stat.UnexpededEnd
1286 || info.extraSize != 0
1287 || state.inLim != state.inPos)
1288 sres = SZ_ERROR_DATA;
1289 }
1290 if (sres != SZ_OK)
1291 return SResToHRESULT(sres);
1292 if (state.winPos > outSizeMax)
1293 return E_FAIL;
1294 // memcpy(dest, state.dic, state.dicPos);
1295 destLen = state.winPos;
1296 }
1256 else 1297 else
1257 { 1298 {
1258 ECoderStatus status; 1299 ECoderStatus status;
1259 SRes res = XzUnpacker_CodeFull(&_xz, 1300 const SRes res = XzUnpacker_CodeFull(&_xz,
1260 dest, &destLen, 1301 dest, &destLen,
1261 _inputBuffer, &srcLen, 1302 _inputBuffer, &srcLen,
1262 CODER_FINISH_END, &status); 1303 CODER_FINISH_END, &status);
@@ -1274,7 +1315,7 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
1274 *outBufWasWrittenSize = (UInt32)destLen; 1315 *outBufWasWrittenSize = (UInt32)destLen;
1275 } 1316 }
1276 else 1317 else
1277 _dynOutStreamSpec->UpdateSize(destLen); 1318 _dynOutStream->UpdateSize(destLen);
1278 } 1319 }
1279 return S_OK; 1320 return S_OK;
1280} 1321}
@@ -1298,17 +1339,17 @@ HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize)
1298 packSize = offset + size; 1339 packSize = offset + size;
1299 if (isCompressed) 1340 if (isCompressed)
1300 { 1341 {
1301 _limitedInStreamSpec->Init(size); 1342 _limitedInStream->Init(size);
1302 RINOK(Decompress(_dynOutStream, NULL, NULL, NULL, size, kMetadataBlockSize)) 1343 RINOK(Decompress(_dynOutStream, NULL, NULL, NULL, size, kMetadataBlockSize))
1303 } 1344 }
1304 else 1345 else
1305 { 1346 {
1306 // size != 0 here 1347 // size != 0 here
1307 Byte *buf = _dynOutStreamSpec->GetBufPtrForWriting(size); 1348 Byte *buf = _dynOutStream->GetBufPtrForWriting(size);
1308 if (!buf) 1349 if (!buf)
1309 return E_OUTOFMEMORY; 1350 return E_OUTOFMEMORY;
1310 RINOK(ReadStream_FALSE(_stream, buf, size)) 1351 RINOK(ReadStream_FALSE(_stream, buf, size))
1311 _dynOutStreamSpec->UpdateSize(size); 1352 _dynOutStream->UpdateSize(size);
1312 } 1353 }
1313 return S_OK; 1354 return S_OK;
1314} 1355}
@@ -1316,7 +1357,7 @@ HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize)
1316 1357
1317HRESULT CHandler::ReadMetadataBlock2() 1358HRESULT CHandler::ReadMetadataBlock2()
1318{ 1359{
1319 _dynOutStreamSpec->Init(); 1360 _dynOutStream->Init();
1320 UInt32 packSize = kMetadataBlockSize + 3; // check it 1361 UInt32 packSize = kMetadataBlockSize + 3; // check it
1321 return ReadMetadataBlock(packSize); 1362 return ReadMetadataBlock(packSize);
1322} 1363}
@@ -1327,25 +1368,25 @@ HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end)
1327 return S_FALSE; 1368 return S_FALSE;
1328 const UInt32 size = (UInt32)(end - start); 1369 const UInt32 size = (UInt32)(end - start);
1329 RINOK(Seek2(start)) 1370 RINOK(Seek2(start))
1330 _dynOutStreamSpec->Init(); 1371 _dynOutStream->Init();
1331 UInt32 packPos = 0; 1372 UInt32 packPos = 0;
1332 while (packPos != size) 1373 while (packPos != size)
1333 { 1374 {
1334 data.PackPos.Add(packPos); 1375 data.PackPos.Add(packPos);
1335 data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize()); 1376 data.UnpackPos.Add((UInt32)_dynOutStream->GetSize());
1336 if (packPos > size) 1377 if (packPos > size)
1337 return S_FALSE; 1378 return S_FALSE;
1338 UInt32 packSize = size - packPos; 1379 UInt32 packSize = size - packPos;
1339 RINOK(ReadMetadataBlock(packSize)) 1380 RINOK(ReadMetadataBlock(packSize))
1340 { 1381 {
1341 const size_t tSize = _dynOutStreamSpec->GetSize(); 1382 const size_t tSize = _dynOutStream->GetSize();
1342 if (tSize != (UInt32)tSize) 1383 if (tSize != (UInt32)tSize)
1343 return S_FALSE; 1384 return S_FALSE;
1344 } 1385 }
1345 packPos += packSize; 1386 packPos += packSize;
1346 } 1387 }
1347 data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize()); 1388 data.UnpackPos.Add((UInt32)_dynOutStream->GetSize());
1348 _dynOutStreamSpec->CopyToBuffer(data.Data); 1389 _dynOutStream->CopyToBuffer(data.Data);
1349 return S_OK; 1390 return S_OK;
1350} 1391}
1351 1392
@@ -1455,7 +1496,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned
1455 if (rem < nameOffset) 1496 if (rem < nameOffset)
1456 return S_FALSE; 1497 return S_FALSE;
1457 1498
1458 if ((UInt32)_items.Size() >= kNumFilesMax) 1499 if (_items.Size() >= kNumFilesMax)
1459 return S_FALSE; 1500 return S_FALSE;
1460 if (_openCallback) 1501 if (_openCallback)
1461 { 1502 {
@@ -1557,6 +1598,7 @@ HRESULT CHandler::Open2(IInStream *inStream)
1557 case kMethod_LZMA: 1598 case kMethod_LZMA:
1558 case kMethod_LZO: 1599 case kMethod_LZO:
1559 case kMethod_XZ: 1600 case kMethod_XZ:
1601 case kMethod_ZSTD:
1560 break; 1602 break;
1561 default: 1603 default:
1562 return E_NOTIMPL; 1604 return E_NOTIMPL;
@@ -1585,11 +1627,11 @@ HRESULT CHandler::Open2(IInStream *inStream)
1585 const UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4); 1627 const UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4);
1586 RINOK(Seek2(offset)) 1628 RINOK(Seek2(offset))
1587 RINOK(ReadMetadataBlock2()) 1629 RINOK(ReadMetadataBlock2())
1588 const UInt32 unpackSize = (UInt32)_dynOutStreamSpec->GetSize(); 1630 const UInt32 unpackSize = (UInt32)_dynOutStream->GetSize();
1589 if (unpackSize != kMetadataBlockSize) 1631 if (unpackSize != kMetadataBlockSize)
1590 if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1))) 1632 if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1)))
1591 return S_FALSE; 1633 return S_FALSE;
1592 const Byte *buf = _dynOutStreamSpec->GetBuffer(); 1634 const Byte *buf = _dynOutStream->GetBuffer();
1593 for (UInt32 j = 0; j < kMetadataBlockSize && j < unpackSize;) 1635 for (UInt32 j = 0; j < kMetadataBlockSize && j < unpackSize;)
1594 { 1636 {
1595 CFrag frag; 1637 CFrag frag;
@@ -1683,12 +1725,12 @@ HRESULT CHandler::Open2(IInStream *inStream)
1683 RINOK(Seek2(offset)) 1725 RINOK(Seek2(offset))
1684 // RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize)); 1726 // RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize));
1685 RINOK(ReadMetadataBlock2()) 1727 RINOK(ReadMetadataBlock2())
1686 const size_t unpackSize = _dynOutStreamSpec->GetSize(); 1728 const size_t unpackSize = _dynOutStream->GetSize();
1687 const UInt32 remSize = (i == numBlocks - 1) ? 1729 const UInt32 remSize = (i == numBlocks - 1) ?
1688 (size & (kMetadataBlockSize - 1)) : kMetadataBlockSize; 1730 (size & (kMetadataBlockSize - 1)) : kMetadataBlockSize;
1689 if (unpackSize != remSize) 1731 if (unpackSize != remSize)
1690 return S_FALSE; 1732 return S_FALSE;
1691 memcpy(_uids + kMetadataBlockSize * i, _dynOutStreamSpec->GetBuffer(), remSize); 1733 memcpy(_uids + kMetadataBlockSize * i, _dynOutStream->GetBuffer(), remSize);
1692 } 1734 }
1693 } 1735 }
1694 1736
@@ -1758,7 +1800,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
1758 COM_TRY_BEGIN 1800 COM_TRY_BEGIN
1759 { 1801 {
1760 Close(); 1802 Close();
1761 _limitedInStreamSpec->SetStream(stream); 1803 _limitedInStream->SetStream(stream);
1762 HRESULT res; 1804 HRESULT res;
1763 try 1805 try
1764 { 1806 {
@@ -1786,7 +1828,7 @@ Z7_COM7F_IMF(CHandler::Close())
1786 _openCodePage = CP_UTF8; 1828 _openCodePage = CP_UTF8;
1787 _sizeCalculated = 0; 1829 _sizeCalculated = 0;
1788 1830
1789 _limitedInStreamSpec->ReleaseStream(); 1831 _limitedInStream->ReleaseStream();
1790 _stream.Release(); 1832 _stream.Release();
1791 1833
1792 _items.Clear(); 1834 _items.Clear();
@@ -2126,11 +2168,11 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
2126 { 2168 {
2127 ClearCache(); 2169 ClearCache();
2128 RINOK(Seek2(blockOffset)) 2170 RINOK(Seek2(blockOffset))
2129 _limitedInStreamSpec->Init(packBlockSize); 2171 _limitedInStream->Init(packBlockSize);
2130 2172
2131 if (compressed) 2173 if (compressed)
2132 { 2174 {
2133 _outStreamSpec->Init((Byte *)_cachedBlock, _h.BlockSize); 2175 _outStream->Init((Byte *)_cachedBlock, _h.BlockSize);
2134 bool outBufWasWritten; 2176 bool outBufWasWritten;
2135 UInt32 outBufWasWrittenSize; 2177 UInt32 outBufWasWrittenSize;
2136 HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize); 2178 HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize);
@@ -2138,7 +2180,7 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
2138 if (outBufWasWritten) 2180 if (outBufWasWritten)
2139 _cachedUnpackBlockSize = outBufWasWrittenSize; 2181 _cachedUnpackBlockSize = outBufWasWrittenSize;
2140 else 2182 else
2141 _cachedUnpackBlockSize = (UInt32)_outStreamSpec->GetPos(); 2183 _cachedUnpackBlockSize = (UInt32)_outStream->GetPos();
2142 } 2184 }
2143 else 2185 else
2144 { 2186 {
@@ -2174,23 +2216,25 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2174 const CNode &node = _nodes[item.Node]; 2216 const CNode &node = _nodes[item.Node];
2175 totalSize += node.GetSize(); 2217 totalSize += node.GetSize();
2176 } 2218 }
2177 extractCallback->SetTotal(totalSize); 2219 RINOK(extractCallback->SetTotal(totalSize))
2178 2220
2179 UInt64 totalPackSize; 2221 UInt64 totalPackSize;
2180 totalSize = totalPackSize = 0; 2222 totalSize = totalPackSize = 0;
2181 2223
2182 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 2224 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
2183 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
2184
2185 CLocalProgress *lps = new CLocalProgress;
2186 CMyComPtr<ICompressProgressInfo> progress = lps;
2187 lps->Init(extractCallback, false); 2225 lps->Init(extractCallback, false);
2226 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
2188 2227
2189 for (i = 0; i < numItems; i++) 2228 for (i = 0;; i++)
2190 { 2229 {
2191 lps->InSize = totalPackSize; 2230 lps->InSize = totalPackSize;
2192 lps->OutSize = totalSize; 2231 lps->OutSize = totalSize;
2193 RINOK(lps->SetCur()) 2232 RINOK(lps->SetCur())
2233 if (i >= numItems)
2234 break;
2235
2236 int res;
2237 {
2194 CMyComPtr<ISequentialOutStream> outStream; 2238 CMyComPtr<ISequentialOutStream> outStream;
2195 const Int32 askMode = testMode ? 2239 const Int32 askMode = testMode ?
2196 NExtract::NAskMode::kTest : 2240 NExtract::NAskMode::kTest :
@@ -2207,7 +2251,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2207 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 2251 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
2208 continue; 2252 continue;
2209 } 2253 }
2210 UInt64 unpackSize = node.GetSize(); 2254 const UInt64 unpackSize = node.GetSize();
2211 totalSize += unpackSize; 2255 totalSize += unpackSize;
2212 UInt64 packSize; 2256 UInt64 packSize;
2213 if (GetPackSize(index, packSize, false)) 2257 if (GetPackSize(index, packSize, false))
@@ -2217,7 +2261,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2217 continue; 2261 continue;
2218 RINOK(extractCallback->PrepareOperation(askMode)) 2262 RINOK(extractCallback->PrepareOperation(askMode))
2219 2263
2220 int res = NExtract::NOperationResult::kDataError; 2264 res = NExtract::NOperationResult::kDataError;
2221 { 2265 {
2222 CMyComPtr<ISequentialInStream> inSeqStream; 2266 CMyComPtr<ISequentialInStream> inSeqStream;
2223 HRESULT hres = GetStream(index, &inSeqStream); 2267 HRESULT hres = GetStream(index, &inSeqStream);
@@ -2231,10 +2275,10 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2231 { 2275 {
2232 RINOK(hres) 2276 RINOK(hres)
2233 { 2277 {
2234 hres = copyCoder->Code(inSeqStream, outStream, NULL, NULL, progress); 2278 hres = copyCoder.Interface()->Code(inSeqStream, outStream, NULL, NULL, lps);
2235 if (hres == S_OK) 2279 if (hres == S_OK)
2236 { 2280 {
2237 if (copyCoderSpec->TotalSize == unpackSize) 2281 if (copyCoder->TotalSize == unpackSize)
2238 res = NExtract::NOperationResult::kOK; 2282 res = NExtract::NOperationResult::kOK;
2239 } 2283 }
2240 else if (hres == E_NOTIMPL) 2284 else if (hres == E_NOTIMPL)
@@ -2248,7 +2292,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2248 } 2292 }
2249 } 2293 }
2250 } 2294 }
2251 2295 }
2252 RINOK(extractCallback->SetOperationResult(res)) 2296 RINOK(extractCallback->SetOperationResult(res))
2253 } 2297 }
2254 2298
diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp
index ab704b6..b143d9a 100644
--- a/CPP/7zip/Archive/SwfHandler.cpp
+++ b/CPP/7zip/Archive/SwfHandler.cpp
@@ -179,10 +179,10 @@ Z7_class_CHandler_final:
179 CMyComPtr<ISequentialInStream> _seqStream; 179 CMyComPtr<ISequentialInStream> _seqStream;
180 CMyComPtr<IInStream> _stream; 180 CMyComPtr<IInStream> _stream;
181 181
182 #ifdef Z7_SWF_UPDATE 182#ifdef Z7_SWF_UPDATE
183 CSingleMethodProps _props; 183 CSingleMethodProps _props;
184 bool _lzmaMode; 184 bool _lzmaMode;
185 #endif 185#endif
186 186
187public: 187public:
188 #ifdef Z7_SWF_UPDATE 188 #ifdef Z7_SWF_UPDATE
@@ -333,6 +333,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
333 return E_INVALIDARG; 333 return E_INVALIDARG;
334 334
335 RINOK(extractCallback->SetTotal(_item.GetSize())) 335 RINOK(extractCallback->SetTotal(_item.GetSize()))
336 Int32 opRes;
337{
336 CMyComPtr<ISequentialOutStream> realOutStream; 338 CMyComPtr<ISequentialOutStream> realOutStream;
337 const Int32 askMode = testMode ? 339 const Int32 askMode = testMode ?
338 NExtract::NAskMode::kTest : 340 NExtract::NAskMode::kTest :
@@ -341,20 +343,18 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
341 if (!testMode && !realOutStream) 343 if (!testMode && !realOutStream)
342 return S_OK; 344 return S_OK;
343 345
344 extractCallback->PrepareOperation(askMode); 346 RINOK(extractCallback->PrepareOperation(askMode))
345 347
346 CDummyOutStream *outStreamSpec = new CDummyOutStream; 348 CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;
347 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); 349 outStream->SetStream(realOutStream);
348 outStreamSpec->SetStream(realOutStream); 350 outStream->Init();
349 outStreamSpec->Init(); 351 // realOutStream.Release();
350 realOutStream.Release();
351 352
352 CLocalProgress *lps = new CLocalProgress; 353 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
353 CMyComPtr<ICompressProgressInfo> progress = lps;
354 lps->Init(extractCallback, false); 354 lps->Init(extractCallback, false);
355 355
356 lps->InSize = _item.HeaderSize; 356 lps->InSize = _item.HeaderSize;
357 lps->OutSize = outStreamSpec->GetSize(); 357 lps->OutSize = outStream->GetSize();
358 RINOK(lps->SetCur()) 358 RINOK(lps->SetCur())
359 359
360 CItem item = _item; 360 CItem item = _item;
@@ -367,7 +367,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
367 367
368 CMyComPtr<ISequentialInStream> inStream2; 368 CMyComPtr<ISequentialInStream> inStream2;
369 369
370 UInt64 unpackSize = _item.GetSize() - (UInt32)8; 370 const UInt64 unpackSize = _item.GetSize() - (UInt32)8;
371 if (_item.IsZlib()) 371 if (_item.IsZlib())
372 { 372 {
373 _decoderZlibSpec = new NCompress::NZlib::CDecoder; 373 _decoderZlibSpec = new NCompress::NZlib::CDecoder;
@@ -403,11 +403,11 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
403 RINOK(_decoderLzmaSpec->SetDecoderProperties2(props, 5)) 403 RINOK(_decoderLzmaSpec->SetDecoderProperties2(props, 5))
404 } 404 }
405 RINOK(item.WriteHeader(outStream)) 405 RINOK(item.WriteHeader(outStream))
406 HRESULT result = _decoder->Code(inStream2, outStream, NULL, &unpackSize, progress); 406 const HRESULT result = _decoder->Code(inStream2, outStream, NULL, &unpackSize, lps);
407 Int32 opRes = NExtract::NOperationResult::kDataError; 407 opRes = NExtract::NOperationResult::kDataError;
408 if (result == S_OK) 408 if (result == S_OK)
409 { 409 {
410 if (item.GetSize() == outStreamSpec->GetSize()) 410 if (item.GetSize() == outStream->GetSize())
411 { 411 {
412 if (_item.IsZlib()) 412 if (_item.IsZlib())
413 { 413 {
@@ -425,7 +425,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
425 else if (result != S_FALSE) 425 else if (result != S_FALSE)
426 return result; 426 return result;
427 427
428 outStream.Release(); 428 // outStream.Release();
429 }
429 return extractCallback->SetOperationResult(opRes); 430 return extractCallback->SetOperationResult(opRes);
430 COM_TRY_END 431 COM_TRY_END
431} 432}
@@ -488,11 +489,10 @@ static HRESULT UpdateArchive(ISequentialOutStream *outStream, UInt64 size,
488 } 489 }
489 RINOK(item.WriteHeader(outStream)) 490 RINOK(item.WriteHeader(outStream))
490 491
491 CLocalProgress *lps = new CLocalProgress; 492 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
492 CMyComPtr<ICompressProgressInfo> progress = lps;
493 lps->Init(updateCallback, true); 493 lps->Init(updateCallback, true);
494 494
495 RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress)) 495 RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, lps))
496 UInt64 inputProcessed; 496 UInt64 inputProcessed;
497 if (lzmaMode) 497 if (lzmaMode)
498 { 498 {
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp
index d7fe175..29f28e8 100644
--- a/CPP/7zip/Archive/Tar/TarHandler.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandler.cpp
@@ -39,6 +39,9 @@ static const Byte kProps[] =
39 kpidCTime, 39 kpidCTime,
40 kpidATime, 40 kpidATime,
41 kpidPosixAttrib, 41 kpidPosixAttrib,
42#if 0
43 kpidAttrib,
44#endif
42 kpidUser, 45 kpidUser,
43 kpidGroup, 46 kpidGroup,
44 kpidUserId, 47 kpidUserId,
@@ -79,13 +82,14 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
79 UInt32 flags = 0; 82 UInt32 flags = 0;
80 if (!_isArc) 83 if (!_isArc)
81 flags |= kpv_ErrorFlags_IsNotArc; 84 flags |= kpv_ErrorFlags_IsNotArc;
82 else switch (_arc._error) 85 else switch ((int)_arc._error)
83 { 86 {
84 case k_ErrorType_UnexpectedEnd: flags = kpv_ErrorFlags_UnexpectedEnd; break; 87 case k_ErrorType_UnexpectedEnd: flags = kpv_ErrorFlags_UnexpectedEnd; break;
85 case k_ErrorType_Corrupted: flags = kpv_ErrorFlags_HeadersError; break; 88 case k_ErrorType_Corrupted: flags = kpv_ErrorFlags_HeadersError; break;
86 case k_ErrorType_OK: break; 89 // case k_ErrorType_OK: break;
87 // case k_ErrorType_Warning: break; 90 // case k_ErrorType_Warning: break;
88 // default: break; 91 // case k_ErrorType_OK:
92 default: break;
89 } 93 }
90 if (flags != 0) 94 if (flags != 0)
91 prop = flags; 95 prop = flags;
@@ -107,6 +111,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
107 { 111 {
108 case CP_OEMCP: name = "OEM"; break; 112 case CP_OEMCP: name = "OEM"; break;
109 case CP_UTF8: name = "UTF-8"; break; 113 case CP_UTF8: name = "UTF-8"; break;
114 default: break;
110 } 115 }
111 if (!name) 116 if (!name)
112 { 117 {
@@ -132,6 +137,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
132 if (_arc._are_mtime) s.Add_OptSpaced("mtime"); 137 if (_arc._are_mtime) s.Add_OptSpaced("mtime");
133 if (_arc._are_atime) s.Add_OptSpaced("atime"); 138 if (_arc._are_atime) s.Add_OptSpaced("atime");
134 if (_arc._are_ctime) s.Add_OptSpaced("ctime"); 139 if (_arc._are_ctime) s.Add_OptSpaced("ctime");
140 if (_arc._are_SCHILY_fflags) s.Add_OptSpaced("SCHILY.fflags");
135 if (_arc._is_PaxGlobal_Error) s.Add_OptSpaced("PAX_GLOBAL_ERROR"); 141 if (_arc._is_PaxGlobal_Error) s.Add_OptSpaced("PAX_GLOBAL_ERROR");
136 s.Add_OptSpaced(_encodingCharacts.GetCharactsString()); 142 s.Add_OptSpaced(_encodingCharacts.GetCharactsString());
137 prop = s; 143 prop = s;
@@ -149,6 +155,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
149 } 155 }
150 break; 156 break;
151 } 157 }
158 default: break;
152 } 159 }
153 prop.Detach(value); 160 prop.Detach(value);
154 return S_OK; 161 return S_OK;
@@ -354,8 +361,8 @@ Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
354 361
355CHandler::CHandler() 362CHandler::CHandler()
356{ 363{
357 copyCoderSpec = new NCompress::CCopyCoder(); 364 // copyCoder = new NCompress::CCopyCoder();
358 copyCoder = copyCoderSpec; 365 // copyCoder = copyCoder;
359 _openCodePage = CP_UTF8; 366 _openCodePage = CP_UTF8;
360 Init(); 367 Init();
361} 368}
@@ -367,9 +374,9 @@ HRESULT CHandler::SkipTo(UInt32 index)
367 if (_latestIsRead) 374 if (_latestIsRead)
368 { 375 {
369 const UInt64 packSize = _latestItem.Get_PackSize_Aligned(); 376 const UInt64 packSize = _latestItem.Get_PackSize_Aligned();
370 RINOK(copyCoder->Code(_seqStream, NULL, &packSize, &packSize, NULL)) 377 RINOK(copyCoder.Interface()->Code(_seqStream, NULL, &packSize, &packSize, NULL))
371 _arc._phySize += copyCoderSpec->TotalSize; 378 _arc._phySize += copyCoder->TotalSize;
372 if (copyCoderSpec->TotalSize != packSize) 379 if (copyCoder->TotalSize != packSize)
373 { 380 {
374 _arc._error = k_ErrorType_UnexpectedEnd; 381 _arc._error = k_ErrorType_UnexpectedEnd;
375 return S_FALSE; 382 return S_FALSE;
@@ -423,27 +430,17 @@ static void PaxTimeToProp(const CPaxTime &pt, NWindows::NCOM::CPropVariant &prop
423} 430}
424 431
425 432
426#define ValToHex(t) ((char)(((t) < 10) ? ('0' + (t)) : ('a' + ((t) - 10))))
427
428static void AddByteToHex2(unsigned val, AString &s)
429{
430 unsigned t;
431 t = val >> 4;
432 s += ValToHex(t);
433 t = val & 0xF;
434 s += ValToHex(t);
435}
436
437static void AddSpecCharToString(const char c, AString &s) 433static void AddSpecCharToString(const char c, AString &s)
438{ 434{
439 if ((Byte)c <= 0x20 || (Byte)c > 127) 435 if ((Byte)c <= 0x20 || (Byte)c > 127)
440 { 436 {
441 s += '['; 437 s.Add_Char('[');
442 AddByteToHex2((Byte)(c), s); 438 s.Add_Char(GET_HEX_CHAR_LOWER((Byte)c >> 4));
443 s += ']'; 439 s.Add_Char(GET_HEX_CHAR_LOWER(c & 15));
440 s.Add_Char(']');
444 } 441 }
445 else 442 else
446 s += c; 443 s.Add_Char(c);
447} 444}
448 445
449static void AddSpecUInt64(AString &s, const char *name, UInt64 v) 446static void AddSpecUInt64(AString &s, const char *name, UInt64 v)
@@ -453,7 +450,7 @@ static void AddSpecUInt64(AString &s, const char *name, UInt64 v)
453 s.Add_OptSpaced(name); 450 s.Add_OptSpaced(name);
454 if (v > 1) 451 if (v > 1)
455 { 452 {
456 s += ':'; 453 s.Add_Colon();
457 s.Add_UInt64(v); 454 s.Add_UInt64(v);
458 } 455 }
459 } 456 }
@@ -465,11 +462,36 @@ static void AddSpecBools(AString &s, const char *name, bool b1, bool b2)
465 { 462 {
466 s.Add_OptSpaced(name); 463 s.Add_OptSpaced(name);
467 if (b2) 464 if (b2)
468 s += '*'; 465 s.Add_Char('*');
469 } 466 }
470} 467}
471 468
472 469
470#if 0
471static bool Parse_Attrib_from_SCHILY_fflags(const AString &s, UInt32 &attribRes)
472{
473 UInt32 attrib = 0;
474 attribRes = attrib;
475 unsigned pos = 0;
476 while (pos < s.Len())
477 {
478 int pos2 = s.Find(',', pos);
479 if (pos2 < 0)
480 pos2 = (int)s.Len();
481 const AString str = s.Mid(pos, (unsigned)pos2 - pos);
482 if (str.IsEqualTo("hidden")) attrib |= FILE_ATTRIBUTE_HIDDEN;
483 else if (str.IsEqualTo("rdonly")) attrib |= FILE_ATTRIBUTE_READONLY;
484 else if (str.IsEqualTo("system")) attrib |= FILE_ATTRIBUTE_SYSTEM;
485 else
486 return false;
487 pos = (unsigned)pos2 + 1;
488 }
489 attribRes = attrib;
490 return true;
491}
492#endif
493
494
473Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) 495Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
474{ 496{
475 COM_TRY_BEGIN 497 COM_TRY_BEGIN
@@ -535,7 +557,30 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
535 PaxTimeToProp(item->PaxTimes.CTime, prop); 557 PaxTimeToProp(item->PaxTimes.CTime, prop);
536 break; 558 break;
537 case kpidPosixAttrib: prop = item->Get_Combined_Mode(); break; 559 case kpidPosixAttrib: prop = item->Get_Combined_Mode(); break;
538 560
561 // kpidAttrib has priority over kpidPosixAttrib in 7-Zip.
562 // but if we want kpidPosixAttrib priority for TAR, we disable kpidAttrib.
563#if 0
564 case kpidAttrib:
565 {
566 if (!item->SCHILY_fflags.IsEmpty())
567 {
568 UInt32 attrib = 0;
569 if (Parse_Attrib_from_SCHILY_fflags(item->SCHILY_fflags, attrib))
570 {
571 if (attrib != 0)
572 {
573 if (item->IsDir())
574 attrib |= FILE_ATTRIBUTE_DIRECTORY;
575 attrib |= ((UInt32)item->Get_Combined_Mode() << 16) | 0x8000; // FILE_ATTRIBUTE_UNIX_EXTENSION;
576 prop = attrib;
577 }
578 }
579 }
580 break;
581 }
582#endif
583
539 case kpidUser: 584 case kpidUser:
540 if (!item->User.IsEmpty()) 585 if (!item->User.IsEmpty())
541 TarStringToUnicode(item->User, prop); 586 TarStringToUnicode(item->User, prop);
@@ -634,7 +679,11 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
634 s.Add_OptSpaced("pax_linkpath"); 679 s.Add_OptSpaced("pax_linkpath");
635 if (item->pax_size_WasUsed) 680 if (item->pax_size_WasUsed)
636 s.Add_OptSpaced("pax_size"); 681 s.Add_OptSpaced("pax_size");
637 682 if (!item->SCHILY_fflags.IsEmpty())
683 {
684 s.Add_OptSpaced("SCHILY.fflags=");
685 s += item->SCHILY_fflags;
686 }
638 if (item->IsThereWarning()) 687 if (item->IsThereWarning())
639 s.Add_OptSpaced("WARNING"); 688 s.Add_OptSpaced("WARNING");
640 if (item->HeaderError) 689 if (item->HeaderError)
@@ -659,6 +708,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
659 } 708 }
660 // case kpidHeadersSize: prop = item->HeaderSize; break; // for debug 709 // case kpidHeadersSize: prop = item->HeaderSize; break; // for debug
661 // case kpidOffset: prop = item->HeaderPos; break; // for debug 710 // case kpidOffset: prop = item->HeaderPos; break; // for debug
711 default: break;
662 } 712 }
663 prop.Detach(value); 713 prop.Detach(value);
664 return S_OK; 714 return S_OK;
@@ -684,36 +734,29 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
684 UInt32 i; 734 UInt32 i;
685 for (i = 0; i < numItems; i++) 735 for (i = 0; i < numItems; i++)
686 totalSize += _items[allFilesMode ? i : indices[i]].Get_UnpackSize(); 736 totalSize += _items[allFilesMode ? i : indices[i]].Get_UnpackSize();
687 extractCallback->SetTotal(totalSize); 737 RINOK(extractCallback->SetTotal(totalSize))
688 738
689 UInt64 totalPackSize; 739 UInt64 totalPackSize;
690 totalSize = totalPackSize = 0; 740 totalSize = totalPackSize = 0;
691 741
692 CLocalProgress *lps = new CLocalProgress; 742 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
693 CMyComPtr<ICompressProgressInfo> progress = lps;
694 lps->Init(extractCallback, false); 743 lps->Init(extractCallback, false);
744 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
745 inStream->SetStream(stream);
746 CMyComPtr2_Create<ISequentialOutStream, CLimitedSequentialOutStream> outStreamSpec;
695 747
696 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 748 for (i = 0; ; i++)
697 CMyComPtr<ISequentialInStream> inStream(streamSpec);
698 streamSpec->SetStream(stream);
699
700 CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
701 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
702
703 for (i = 0; i < numItems || seqMode; i++)
704 { 749 {
705 lps->InSize = totalPackSize; 750 lps->InSize = totalPackSize;
706 lps->OutSize = totalSize; 751 lps->OutSize = totalSize;
707 RINOK(lps->SetCur()) 752 RINOK(lps->SetCur())
708 CMyComPtr<ISequentialOutStream> realOutStream; 753 if (i >= numItems && !seqMode)
709 Int32 askMode = testMode ? 754 break;
710 NExtract::NAskMode::kTest :
711 NExtract::NAskMode::kExtract;
712 const UInt32 index = allFilesMode ? i : indices[i]; 755 const UInt32 index = allFilesMode ? i : indices[i];
713 const CItemEx *item; 756 const CItemEx *item;
714 if (seqMode) 757 if (seqMode)
715 { 758 {
716 HRESULT res = SkipTo(index); 759 const HRESULT res = SkipTo(index);
717 if (res == E_INVALIDARG) 760 if (res == E_INVALIDARG)
718 break; 761 break;
719 RINOK(res) 762 RINOK(res)
@@ -722,6 +765,10 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
722 else 765 else
723 item = &_items[index]; 766 item = &_items[index];
724 767
768 Int32 askMode = testMode ?
769 NExtract::NAskMode::kTest :
770 NExtract::NAskMode::kExtract;
771 CMyComPtr<ISequentialOutStream> realOutStream;
725 RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) 772 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
726 const UInt64 unpackSize = item->Get_UnpackSize(); 773 const UInt64 unpackSize = item->Get_UnpackSize();
727 totalSize += unpackSize; 774 totalSize += unpackSize;
@@ -729,6 +776,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
729 if (item->IsDir()) 776 if (item->IsDir())
730 { 777 {
731 RINOK(extractCallback->PrepareOperation(askMode)) 778 RINOK(extractCallback->PrepareOperation(askMode))
779 // realOutStream.Release();
732 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 780 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
733 continue; 781 continue;
734 } 782 }
@@ -738,9 +786,10 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
738 if (!seqMode) 786 if (!seqMode)
739 { 787 {
740 /* 788 /*
741 // probably we must show extracting info it callback handler instead 789 // GetStream() creates link.
742 if (item->IsHardLink() || 790 // so we can show extracting info in GetStream() instead
743 item->IsSymLink()) 791 if (item->Is_HardLink() ||
792 item->Is_SymLink())
744 { 793 {
745 RINOK(extractCallback->PrepareOperation(askMode)) 794 RINOK(extractCallback->PrepareOperation(askMode))
746 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 795 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
@@ -779,8 +828,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
779 { 828 {
780 RINOK(InStream_SeekSet(_stream, item->Get_DataPos())) 829 RINOK(InStream_SeekSet(_stream, item->Get_DataPos()))
781 } 830 }
782 streamSpec->Init(item->Get_PackSize_Aligned()); 831 inStream->Init(item->Get_PackSize_Aligned());
783 RINOK(copyCoder->Code(inStream2, outStream, NULL, NULL, progress)) 832 RINOK(copyCoder.Interface()->Code(inStream2, outStreamSpec, NULL, NULL, lps))
784 } 833 }
785 if (outStreamSpec->GetRem() != 0) 834 if (outStreamSpec->GetRem() != 0)
786 opRes = NExtract::NOperationResult::kDataError; 835 opRes = NExtract::NOperationResult::kDataError;
diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h
index 451c2fd..f1ef3b6 100644
--- a/CPP/7zip/Archive/Tar/TarHandler.h
+++ b/CPP/7zip/Archive/Tar/TarHandler.h
@@ -42,8 +42,7 @@ private:
42 42
43 CArchive _arc; 43 CArchive _arc;
44 44
45 NCompress::CCopyCoder *copyCoderSpec; 45 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
46 CMyComPtr<ICompressCoder> copyCoder;
47 46
48 HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); 47 HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
49 HRESULT SkipTo(UInt32 index); 48 HRESULT SkipTo(UInt32 index);
diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
index c93a86e..bcbb35d 100644
--- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
@@ -257,8 +257,8 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
257 257
258 RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, utfFlags, true)) 258 RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, utfFlags, true))
259 if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/') 259 if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/')
260 ui.Name += '/'; 260 ui.Name.Add_Slash();
261 // ui.Name += '/'; // for debug 261 // ui.Name.Add_Slash(); // for debug
262 262
263 if (_posixMode) 263 if (_posixMode)
264 { 264 {
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp
index 90b6f84..22b8902 100644
--- a/CPP/7zip/Archive/Tar/TarIn.cpp
+++ b/CPP/7zip/Archive/Tar/TarIn.cpp
@@ -282,7 +282,7 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item)
282 { 282 {
283 item.Prefix_WasUsed = true; 283 item.Prefix_WasUsed = true;
284 ReadString(p, NFileHeader::kPrefixSize, item.Name); 284 ReadString(p, NFileHeader::kPrefixSize, item.Name);
285 item.Name += '/'; 285 item.Name.Add_Slash();
286 unsigned i; 286 unsigned i;
287 for (i = 0; i < NFileHeader::kNameSize; i++) 287 for (i = 0; i < NFileHeader::kNameSize; i++)
288 if (buf[i] == 0) 288 if (buf[i] == 0)
@@ -541,6 +541,7 @@ struct CPaxInfo: public CPaxTimes
541 bool Link_Defined; 541 bool Link_Defined;
542 bool User_Defined; 542 bool User_Defined;
543 bool Group_Defined; 543 bool Group_Defined;
544 bool SCHILY_fflags_Defined;
544 545
545 UInt64 Size; 546 UInt64 Size;
546 UInt32 UID; 547 UInt32 UID;
@@ -551,6 +552,7 @@ struct CPaxInfo: public CPaxTimes
551 AString User; 552 AString User;
552 AString Group; 553 AString Group;
553 AString UnknownLines; 554 AString UnknownLines;
555 AString SCHILY_fflags;
554 556
555 bool ParseID(const AString &val, bool &defined, UInt32 &res) 557 bool ParseID(const AString &val, bool &defined, UInt32 &res)
556 { 558 {
@@ -648,6 +650,7 @@ bool CPaxInfo::ParsePax(const CTempBuffer &tb, bool isFile)
648 Link_Defined = false; 650 Link_Defined = false;
649 User_Defined = false; 651 User_Defined = false;
650 Group_Defined = false; 652 Group_Defined = false;
653 SCHILY_fflags_Defined = false;
651 654
652 // CPaxTimes::Clear(); 655 // CPaxTimes::Clear();
653 656
@@ -759,6 +762,14 @@ bool CPaxInfo::ParsePax(const CTempBuffer &tb, bool isFile)
759 { parsed = ParsePaxTime(val, ATime, DoubleTagError); } 762 { parsed = ParsePaxTime(val, ATime, DoubleTagError); }
760 else if (name.IsEqualTo("ctime")) 763 else if (name.IsEqualTo("ctime"))
761 { parsed = ParsePaxTime(val, CTime, DoubleTagError); } 764 { parsed = ParsePaxTime(val, CTime, DoubleTagError); }
765 else if (name.IsEqualTo("SCHILY.fflags"))
766 {
767 if (SCHILY_fflags_Defined)
768 DoubleTagError = true;
769 SCHILY_fflags = val;
770 SCHILY_fflags_Defined = true;
771 parsed = true;
772 }
762 else 773 else
763 isDetectedName = false; 774 isDetectedName = false;
764 if (isDetectedName && !parsed) 775 if (isDetectedName && !parsed)
@@ -812,6 +823,7 @@ HRESULT CArchive::ReadItem2(CItemEx &item)
812 item.pax_size_WasUsed = false; 823 item.pax_size_WasUsed = false;
813 824
814 item.PaxExtra.Clear(); 825 item.PaxExtra.Clear();
826 item.SCHILY_fflags.Empty();
815 827
816 item.EncodingCharacts.Clear(); 828 item.EncodingCharacts.Clear();
817 829
@@ -1032,6 +1044,11 @@ HRESULT CArchive::ReadItem2(CItemEx &item)
1032 item.Group = paxInfo.Group; 1044 item.Group = paxInfo.Group;
1033 // item.pax_gname_WasUsed = true; 1045 // item.pax_gname_WasUsed = true;
1034 } 1046 }
1047 if (paxInfo.SCHILY_fflags_Defined)
1048 {
1049 item.SCHILY_fflags = paxInfo.SCHILY_fflags;
1050 // item.SCHILY_fflags_WasUsed = true;
1051 }
1035 if (paxInfo.UID_Defined) 1052 if (paxInfo.UID_Defined)
1036 { 1053 {
1037 item.UID = (UInt32)paxInfo.UID; 1054 item.UID = (UInt32)paxInfo.UID;
@@ -1098,6 +1115,7 @@ HRESULT CArchive::ReadItem(CItemEx &item)
1098 if (item.PaxTimes.MTime.IsDefined()) _are_mtime = true; 1115 if (item.PaxTimes.MTime.IsDefined()) _are_mtime = true;
1099 if (item.PaxTimes.ATime.IsDefined()) _are_atime = true; 1116 if (item.PaxTimes.ATime.IsDefined()) _are_atime = true;
1100 if (item.PaxTimes.CTime.IsDefined()) _are_ctime = true; 1117 if (item.PaxTimes.CTime.IsDefined()) _are_ctime = true;
1118 if (!item.SCHILY_fflags.IsEmpty()) _are_SCHILY_fflags = true;
1101 1119
1102 if (item.pax_path_WasUsed) 1120 if (item.pax_path_WasUsed)
1103 _are_pax_path = true; 1121 _are_pax_path = true;
diff --git a/CPP/7zip/Archive/Tar/TarIn.h b/CPP/7zip/Archive/Tar/TarIn.h
index 8c69057..edfc94a 100644
--- a/CPP/7zip/Archive/Tar/TarIn.h
+++ b/CPP/7zip/Archive/Tar/TarIn.h
@@ -61,6 +61,7 @@ public:
61 bool _are_LongName; 61 bool _are_LongName;
62 bool _are_LongLink; 62 bool _are_LongLink;
63 bool _pathPrefix_WasUsed; 63 bool _pathPrefix_WasUsed;
64 bool _are_SCHILY_fflags;
64 // bool _isSparse; 65 // bool _isSparse;
65 66
66 // temp internal vars for ReadItem(): 67 // temp internal vars for ReadItem():
@@ -110,6 +111,7 @@ public:
110 _are_LongName = false; 111 _are_LongName = false;
111 _are_LongLink = false; 112 _are_LongLink = false;
112 _pathPrefix_WasUsed = false; 113 _pathPrefix_WasUsed = false;
114 _are_SCHILY_fflags = false;
113 // _isSparse = false; 115 // _isSparse = false;
114 116
115 _is_Warning = false; 117 _is_Warning = false;
diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h
index 2e12c9d..112f38d 100644
--- a/CPP/7zip/Archive/Tar/TarItem.h
+++ b/CPP/7zip/Archive/Tar/TarItem.h
@@ -161,6 +161,7 @@ struct CItem
161 case NFileHeader::NLinkFlag::kPax_2: 161 case NFileHeader::NLinkFlag::kPax_2:
162 case NFileHeader::NLinkFlag::kGlobal: 162 case NFileHeader::NLinkFlag::kGlobal:
163 return true; 163 return true;
164 default: break;
164 } 165 }
165 return false; 166 return false;
166 } 167 }
@@ -195,6 +196,7 @@ struct CItem
195 case NFileHeader::NLinkFlag::kCharacter: return MY_LIN_S_IFCHR; 196 case NFileHeader::NLinkFlag::kCharacter: return MY_LIN_S_IFCHR;
196 case NFileHeader::NLinkFlag::kFIFO: return MY_LIN_S_IFIFO; 197 case NFileHeader::NLinkFlag::kFIFO: return MY_LIN_S_IFIFO;
197 // case return MY_LIN_S_IFSOCK; 198 // case return MY_LIN_S_IFSOCK;
199 default: break;
198 } 200 }
199 201
200 if (IsDir()) 202 if (IsDir())
@@ -218,6 +220,7 @@ struct CItem
218 // we also do it 220 // we also do it
219 return Name.Back() == '/'; 221 return Name.Back() == '/';
220 // return NItemName::HasTailSlash(Name, CP_OEMCP); 222 // return NItemName::HasTailSlash(Name, CP_OEMCP);
223 default: break;
221 } 224 }
222 return false; 225 return false;
223 } 226 }
@@ -347,6 +350,7 @@ struct CItemEx: public CItem
347 350
348 UInt64 Num_Pax_Records; 351 UInt64 Num_Pax_Records;
349 CPaxExtra PaxExtra; 352 CPaxExtra PaxExtra;
353 AString SCHILY_fflags;
350 354
351 CEncodingCharacts EncodingCharacts; 355 CEncodingCharacts EncodingCharacts;
352 356
diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp
index 26d0855..8a80c0c 100644
--- a/CPP/7zip/Archive/Tar/TarOut.cpp
+++ b/CPP/7zip/Archive/Tar/TarOut.cpp
@@ -232,7 +232,7 @@ static void AddPaxLine(AString &s, const char *name, const AString &val)
232 s += n; 232 s += n;
233 s.Add_Space(); 233 s.Add_Space();
234 s += name; 234 s += name;
235 s += '='; 235 s.Add_Char('=');
236 s += val; 236 s += val;
237 s.Add_LF(); 237 s.Add_LF();
238} 238}
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp
index 0b348e9..d4ed772 100644
--- a/CPP/7zip/Archive/Tar/TarUpdate.cpp
+++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp
@@ -184,23 +184,23 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
184 { 184 {
185 const CUpdateItem &ui = updateItems[i]; 185 const CUpdateItem &ui = updateItems[i];
186 if (ui.NewData) 186 if (ui.NewData)
187 {
188 if (ui.Size == (UInt64)(Int64)-1)
189 break;
187 complexity += ui.Size; 190 complexity += ui.Size;
191 }
188 else 192 else
189 complexity += inputItems[(unsigned)ui.IndexInArc].Get_FullSize_Aligned(); 193 complexity += inputItems[(unsigned)ui.IndexInArc].Get_FullSize_Aligned();
190 } 194 }
191 195
192 RINOK(updateCallback->SetTotal(complexity)) 196 if (i == updateItems.Size())
197 RINOK(updateCallback->SetTotal(complexity))
193 198
194 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 199 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
195 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
196
197 CLocalProgress *lps = new CLocalProgress;
198 CMyComPtr<ICompressProgressInfo> progress = lps;
199 lps->Init(updateCallback, true); 200 lps->Init(updateCallback, true);
200 201 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
201 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 202 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStreamLimited;
202 CMyComPtr<ISequentialInStream> inStreamLimited(streamSpec); 203 inStreamLimited->SetStream(inStream);
203 streamSpec->SetStream(inStream);
204 204
205 complexity = 0; 205 complexity = 0;
206 206
@@ -271,9 +271,10 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
271 item.SparseBlocks.Clear(); 271 item.SparseBlocks.Clear();
272 item.PackSize = ui.Size; 272 item.PackSize = ui.Size;
273 item.Size = ui.Size; 273 item.Size = ui.Size;
274#if 0
274 if (ui.Size == (UInt64)(Int64)-1) 275 if (ui.Size == (UInt64)(Int64)-1)
275 return E_INVALIDARG; 276 return E_INVALIDARG;
276 277#endif
277 CMyComPtr<ISequentialInStream> fileInStream; 278 CMyComPtr<ISequentialInStream> fileInStream;
278 279
279 bool needWrite = true; 280 bool needWrite = true;
@@ -353,6 +354,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
353 if (prop.vt != VT_UI8) 354 if (prop.vt != VT_UI8)
354 return E_INVALIDARG; 355 return E_INVALIDARG;
355 const UInt64 size = prop.uhVal.QuadPart; 356 const UInt64 size = prop.uhVal.QuadPart;
357 // printf("\nTAR after GetProperty(kpidSize size = %8d\n", (unsigned)size);
356 item.PackSize = size; 358 item.PackSize = size;
357 item.Size = size; 359 item.Size = size;
358 } 360 }
@@ -409,6 +411,11 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
409 411
410 if (needWrite) 412 if (needWrite)
411 { 413 {
414 if (fileInStream)
415 // if (item.PackSize == (UInt64)(Int64)-1)
416 if (item.Size == (UInt64)(Int64)-1)
417 return E_INVALIDARG;
418
412 const UInt64 headerPos = outArchive.Pos; 419 const UInt64 headerPos = outArchive.Pos;
413 // item.PackSize = ((UInt64)1 << 33); // for debug 420 // item.PackSize = ((UInt64)1 << 33); // for debug
414 421
@@ -420,6 +427,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
420 { 427 {
421 for (unsigned numPasses = 0;; numPasses++) 428 for (unsigned numPasses = 0;; numPasses++)
422 { 429 {
430 // printf("\nTAR numPasses = %d" " old size = %8d\n", numPasses, (unsigned)item.PackSize);
423 /* we support 2 attempts to write header: 431 /* we support 2 attempts to write header:
424 pass-0: main pass: 432 pass-0: main pass:
425 pass-1: additional pass, if size_of_file and size_of_header are changed */ 433 pass-1: additional pass, if size_of_file and size_of_header are changed */
@@ -431,12 +439,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
431 } 439 }
432 440
433 const UInt64 dataPos = outArchive.Pos; 441 const UInt64 dataPos = outArchive.Pos;
434 RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress)) 442 RINOK(copyCoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps))
435 outArchive.Pos += copyCoderSpec->TotalSize; 443 outArchive.Pos += copyCoder->TotalSize;
436 RINOK(outArchive.Write_AfterDataResidual(copyCoderSpec->TotalSize)) 444 RINOK(outArchive.Write_AfterDataResidual(copyCoder->TotalSize))
437 445 // printf("\nTAR after Code old size = %8d copyCoder->TotalSize = %8d \n", (unsigned)item.PackSize, (unsigned)copyCoder->TotalSize);
438 // if (numPasses >= 10) // for debug 446 // if (numPasses >= 10) // for debug
439 if (copyCoderSpec->TotalSize == item.PackSize) 447 if (copyCoder->TotalSize == item.PackSize)
440 break; 448 break;
441 449
442 if (opCallback) 450 if (opCallback)
@@ -451,7 +459,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
451 const UInt64 nextPos = outArchive.Pos; 459 const UInt64 nextPos = outArchive.Pos;
452 RINOK(outSeekStream->Seek(-(Int64)(nextPos - headerPos), STREAM_SEEK_CUR, NULL)) 460 RINOK(outSeekStream->Seek(-(Int64)(nextPos - headerPos), STREAM_SEEK_CUR, NULL))
453 outArchive.Pos = headerPos; 461 outArchive.Pos = headerPos;
454 item.PackSize = copyCoderSpec->TotalSize; 462 item.PackSize = copyCoder->TotalSize;
455 463
456 RINOK(outArchive.WriteHeader(item)) 464 RINOK(outArchive.WriteHeader(item))
457 465
@@ -537,12 +545,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
537 if (size != 0) 545 if (size != 0)
538 { 546 {
539 RINOK(InStream_SeekSet(inStream, pos)) 547 RINOK(InStream_SeekSet(inStream, pos))
540 streamSpec->Init(size); 548 inStreamLimited->Init(size);
541 if (outSeekStream && setRestriction) 549 if (outSeekStream && setRestriction)
542 RINOK(setRestriction->SetRestriction(0, 0)) 550 RINOK(setRestriction->SetRestriction(0, 0))
543 // 22.00 : we copy Residual data from old archive to new archive instead of zeroing 551 // 22.00 : we copy Residual data from old archive to new archive instead of zeroing
544 RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)) 552 RINOK(copyCoder.Interface()->Code(inStreamLimited, outStream, NULL, NULL, lps))
545 if (copyCoderSpec->TotalSize != size) 553 if (copyCoder->TotalSize != size)
546 return E_FAIL; 554 return E_FAIL;
547 outArchive.Pos += size; 555 outArchive.Pos += size;
548 // RINOK(outArchive.Write_AfterDataResidual(existItem.PackSize)); 556 // RINOK(outArchive.Write_AfterDataResidual(existItem.PackSize));
diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp
index ae6113f..7c74c80 100644
--- a/CPP/7zip/Archive/Udf/UdfHandler.cpp
+++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp
@@ -332,7 +332,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
332 332
333 for (i = 0; i < numItems; i++) 333 for (i = 0; i < numItems; i++)
334 { 334 {
335 UInt32 index = (allFilesMode ? i : indices[i]); 335 const UInt32 index = (allFilesMode ? i : indices[i]);
336 const CRef2 &ref2 = _refs2[index]; 336 const CRef2 &ref2 = _refs2[index];
337 const CRef &ref = _archive.LogVols[ref2.Vol].FileSets[ref2.Fs].Refs[ref2.Ref]; 337 const CRef &ref = _archive.LogVols[ref2.Vol].FileSets[ref2.Fs].Refs[ref2.Ref];
338 const CFile &file = _archive.Files[ref.FileIndex]; 338 const CFile &file = _archive.Files[ref.FileIndex];
@@ -340,24 +340,21 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
340 if (!item.IsDir()) 340 if (!item.IsDir())
341 totalSize += item.Size; 341 totalSize += item.Size;
342 } 342 }
343 extractCallback->SetTotal(totalSize); 343 RINOK(extractCallback->SetTotal(totalSize))
344 344
345 UInt64 currentTotalSize = 0; 345 UInt64 currentTotalSize = 0;
346 346
347 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 347 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
348 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
349
350 CLocalProgress *lps = new CLocalProgress;
351 CMyComPtr<ICompressProgressInfo> progress = lps;
352 lps->Init(extractCallback, false); 348 lps->Init(extractCallback, false);
349 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
350 CMyComPtr2_Create<ISequentialOutStream, CLimitedSequentialOutStream> outStream;
353 351
354 CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; 352 for (i = 0;; i++)
355 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
356
357 for (i = 0; i < numItems; i++)
358 { 353 {
359 lps->InSize = lps->OutSize = currentTotalSize; 354 lps->InSize = lps->OutSize = currentTotalSize;
360 RINOK(lps->SetCur()) 355 RINOK(lps->SetCur())
356 if (i >= numItems)
357 break;
361 CMyComPtr<ISequentialOutStream> realOutStream; 358 CMyComPtr<ISequentialOutStream> realOutStream;
362 const Int32 askMode = testMode ? 359 const Int32 askMode = testMode ?
363 NExtract::NAskMode::kTest : 360 NExtract::NAskMode::kTest :
@@ -383,24 +380,26 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
383 continue; 380 continue;
384 381
385 RINOK(extractCallback->PrepareOperation(askMode)) 382 RINOK(extractCallback->PrepareOperation(askMode))
386 outStreamSpec->SetStream(realOutStream); 383 outStream->SetStream(realOutStream);
387 realOutStream.Release(); 384 realOutStream.Release();
388 outStreamSpec->Init(item.Size); 385 outStream->Init(item.Size);
389 Int32 opRes; 386 Int32 opRes;
390 CMyComPtr<ISequentialInStream> udfInStream;
391 HRESULT res = GetStream(index, &udfInStream);
392 if (res == E_NOTIMPL)
393 opRes = NExtract::NOperationResult::kUnsupportedMethod;
394 else if (res != S_OK)
395 opRes = NExtract::NOperationResult::kDataError;
396 else
397 { 387 {
398 RINOK(copyCoder->Code(udfInStream, outStream, NULL, NULL, progress)) 388 CMyComPtr<ISequentialInStream> udfInStream;
399 opRes = outStreamSpec->IsFinishedOK() ? 389 const HRESULT res = GetStream(index, &udfInStream);
400 NExtract::NOperationResult::kOK: 390 if (res == E_NOTIMPL)
401 NExtract::NOperationResult::kDataError; 391 opRes = NExtract::NOperationResult::kUnsupportedMethod;
392 else if (res != S_OK)
393 opRes = NExtract::NOperationResult::kDataError;
394 else
395 {
396 RINOK(copyCoder.Interface()->Code(udfInStream, outStream, NULL, NULL, lps))
397 opRes = outStream->IsFinishedOK() ?
398 NExtract::NOperationResult::kOK:
399 NExtract::NOperationResult::kDataError;
400 }
402 } 401 }
403 outStreamSpec->ReleaseStream(); 402 outStream->ReleaseStream();
404 RINOK(extractCallback->SetOperationResult(opRes)) 403 RINOK(extractCallback->SetOperationResult(opRes))
405 } 404 }
406 return S_OK; 405 return S_OK;
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp
index 13d84e0..ce87c54 100644
--- a/CPP/7zip/Archive/Udf/UdfIn.cpp
+++ b/CPP/7zip/Archive/Udf/UdfIn.cpp
@@ -1731,7 +1731,7 @@ UString CInArchive::GetItemPath(unsigned volIndex, unsigned fsIndex, unsigned re
1731 UString newName2 = vol.GetName(); 1731 UString newName2 = vol.GetName();
1732 if (newName2.IsEmpty()) 1732 if (newName2.IsEmpty())
1733 newName2 = "Volume"; 1733 newName2 = "Volume";
1734 newName += '-'; 1734 newName.Add_Minus();
1735 newName += newName2; 1735 newName += newName2;
1736 UpdateWithName(name, newName); 1736 UpdateWithName(name, newName);
1737 } 1737 }
diff --git a/CPP/7zip/Archive/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp
index cd6fcbd..9462e97 100644
--- a/CPP/7zip/Archive/UefiHandler.cpp
+++ b/CPP/7zip/Archive/UefiHandler.cpp
@@ -10,9 +10,10 @@
10 10
11#include "../../../C/7zCrc.h" 11#include "../../../C/7zCrc.h"
12#include "../../../C/Alloc.h" 12#include "../../../C/Alloc.h"
13#include "../../../C/CpuArch.h"
14#include "../../../C/LzmaDec.h" 13#include "../../../C/LzmaDec.h"
14#include "../../../C/CpuArch.h"
15 15
16#include "../../Common/AutoPtr.h"
16#include "../../Common/ComTry.h" 17#include "../../Common/ComTry.h"
17#include "../../Common/IntToString.h" 18#include "../../Common/IntToString.h"
18#include "../../Common/MyBuffer.h" 19#include "../../Common/MyBuffer.h"
@@ -42,8 +43,8 @@
42namespace NArchive { 43namespace NArchive {
43namespace NUefi { 44namespace NUefi {
44 45
45static const size_t kBufTotalSizeMax = (1 << 29); 46static const size_t kBufTotalSizeMax = 1 << 29;
46static const unsigned kNumFilesMax = (1 << 18); 47static const unsigned kNumFilesMax = 1 << 18;
47static const unsigned kLevelMax = 64; 48static const unsigned kLevelMax = 64;
48 49
49static const Byte k_IntelMeSignature[] = 50static const Byte k_IntelMeSignature[] =
@@ -845,7 +846,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
845 case kpidErrorFlags: 846 case kpidErrorFlags:
846 { 847 {
847 UInt32 v = 0; 848 UInt32 v = 0;
848 if (!_headersError) v |= kpv_ErrorFlags_HeadersError; 849 if (_headersError) v |= kpv_ErrorFlags_HeadersError;
849 if (v != 0) 850 if (v != 0)
850 prop = v; 851 prop = v;
851 break; 852 break;
@@ -990,8 +991,8 @@ HRESULT CHandler::ParseSections(unsigned bufIndex, UInt32 posBase, UInt32 size,
990 { 991 {
991 if (sectSize < 4 + 5) 992 if (sectSize < 4 + 5)
992 return S_FALSE; 993 return S_FALSE;
993 UInt32 uncompressedSize = Get32(p + 4); 994 const UInt32 uncompressedSize = Get32(p + 4);
994 Byte compressionType = p[8]; 995 const Byte compressionType = p[8];
995 996
996 UInt32 newSectSize = sectSize - 9; 997 UInt32 newSectSize = sectSize - 9;
997 UInt32 newOffset = posBase + pos + 9; 998 UInt32 newOffset = posBase + pos + 9;
@@ -1014,21 +1015,16 @@ HRESULT CHandler::ParseSections(unsigned bufIndex, UInt32 posBase, UInt32 size,
1014 } 1015 }
1015 else if (compressionType == COMPRESSION_TYPE_LZH) 1016 else if (compressionType == COMPRESSION_TYPE_LZH)
1016 { 1017 {
1017 unsigned newBufIndex = AddBuf(uncompressedSize); 1018 const unsigned newBufIndex = AddBuf(uncompressedSize);
1018 CByteBuffer &buf = _bufs[newBufIndex]; 1019 CByteBuffer &buf = _bufs[newBufIndex];
1019 1020 CMyUniquePtr<NCompress::NLzh::NDecoder::CCoder> lzhDecoder;
1020 NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = NULL; 1021 lzhDecoder.Create_if_Empty();
1021 CMyComPtr<ICompressCoder> lzhDecoder;
1022
1023 lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
1024 lzhDecoder = lzhDecoderSpec;
1025
1026 { 1022 {
1027 const Byte *src = pStart; 1023 const Byte *src = pStart;
1028 if (newSectSize < 8) 1024 if (newSectSize < 8)
1029 return S_FALSE; 1025 return S_FALSE;
1030 UInt32 packSize = Get32(src); 1026 UInt32 packSize = Get32(src);
1031 UInt32 unpackSize = Get32(src + 4); 1027 const UInt32 unpackSize = Get32(src + 4);
1032 1028
1033 PRF(printf(" LZH packSize = %6x, unpackSize = %6x", packSize, unpackSize)); 1029 PRF(printf(" LZH packSize = %6x, unpackSize = %6x", packSize, unpackSize));
1034 1030
@@ -1041,14 +1037,10 @@ HRESULT CHandler::ParseSections(unsigned bufIndex, UInt32 posBase, UInt32 size,
1041 if (src[packSize] != 0) 1037 if (src[packSize] != 0)
1042 return S_FALSE; 1038 return S_FALSE;
1043 1039
1044 CBufInStream *inStreamSpec = new CBufInStream; 1040 CMyComPtr2_Create<IInStream, CBufInStream> inStream;
1045 CMyComPtr<IInStream> inStream = inStreamSpec; 1041 CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStream;
1046 1042 // const UInt64 uncompressedSize64 = uncompressedSize;
1047 CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; 1043 // lzhDecoder->FinishMode = true;
1048 CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
1049
1050 UInt64 uncompressedSize64 = uncompressedSize;
1051 lzhDecoderSpec->FinishMode = true;
1052 /* 1044 /*
1053 EFI 1.1 probably used LZH with small dictionary and (pbit = 4). It was named "Efi compression". 1045 EFI 1.1 probably used LZH with small dictionary and (pbit = 4). It was named "Efi compression".
1054 New version of compression code (named Tiano) uses LZH with (1 << 19) dictionary. 1046 New version of compression code (named Tiano) uses LZH with (1 << 19) dictionary.
@@ -1056,19 +1048,17 @@ HRESULT CHandler::ParseSections(unsigned bufIndex, UInt32 posBase, UInt32 size,
1056 We check both LZH versions: Tiano and then Efi. 1048 We check both LZH versions: Tiano and then Efi.
1057 */ 1049 */
1058 HRESULT res = S_FALSE; 1050 HRESULT res = S_FALSE;
1059
1060 for (unsigned m = 0 ; m < 2; m++) 1051 for (unsigned m = 0 ; m < 2; m++)
1061 { 1052 {
1062 inStreamSpec->Init(src, packSize); 1053 inStream->Init(src, packSize);
1063 outStreamSpec->Init(buf, uncompressedSize); 1054 outStream->Init(buf, uncompressedSize);
1064 lzhDecoderSpec->SetDictSize((m == 0) ? ((UInt32)1 << 19) : ((UInt32)1 << 14)); 1055 lzhDecoder->SetDictSize(m == 0 ? ((UInt32)1 << 19) : ((UInt32)1 << 14));
1065 res = lzhDecoder->Code(inStream, outStream, NULL, &uncompressedSize64, NULL); 1056 res = lzhDecoder->Code(inStream, outStream, uncompressedSize, NULL);
1066 if (res == S_OK) 1057 if (res == S_OK)
1067 break; 1058 break;
1068 } 1059 }
1069 RINOK(res) 1060 RINOK(res)
1070 } 1061 }
1071
1072 bool error2; 1062 bool error2;
1073 RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level, error2)) 1063 RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level, error2))
1074 } 1064 }
@@ -1781,49 +1771,48 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1781 UInt32 i; 1771 UInt32 i;
1782 for (i = 0; i < numItems; i++) 1772 for (i = 0; i < numItems; i++)
1783 totalSize += _items[_items2[allFilesMode ? i : indices[i]].MainIndex].Size; 1773 totalSize += _items[_items2[allFilesMode ? i : indices[i]].MainIndex].Size;
1784 extractCallback->SetTotal(totalSize); 1774 RINOK(extractCallback->SetTotal(totalSize))
1785 1775 totalSize = 0;
1786 UInt64 currentTotalSize = 0;
1787 1776
1788 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 1777 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1789 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
1790
1791 CLocalProgress *lps = new CLocalProgress;
1792 CMyComPtr<ICompressProgressInfo> progress = lps;
1793 lps->Init(extractCallback, false); 1778 lps->Init(extractCallback, false);
1779 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
1794 1780
1795 for (i = 0; i < numItems; i++) 1781 for (i = 0;; i++)
1796 { 1782 {
1797 lps->InSize = lps->OutSize = currentTotalSize; 1783 lps->InSize = lps->OutSize = totalSize;
1798 RINOK(lps->SetCur()) 1784 RINOK(lps->SetCur())
1799 CMyComPtr<ISequentialOutStream> realOutStream; 1785 if (i >= numItems)
1800 const Int32 askMode = testMode ? 1786 break;
1801 NExtract::NAskMode::kTest : 1787 Int32 opRes;
1802 NExtract::NAskMode::kExtract;
1803 const UInt32 index = allFilesMode ? i : indices[i];
1804 const CItem &item = _items[_items2[index].MainIndex];
1805 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
1806 currentTotalSize += item.Size;
1807
1808 if (!testMode && !realOutStream)
1809 continue;
1810 RINOK(extractCallback->PrepareOperation(askMode))
1811 if (testMode || item.IsDir)
1812 {
1813 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
1814 continue;
1815 }
1816 int res = NExtract::NOperationResult::kDataError;
1817 CMyComPtr<ISequentialInStream> inStream;
1818 GetStream(index, &inStream);
1819 if (inStream)
1820 { 1788 {
1821 RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)) 1789 CMyComPtr<ISequentialOutStream> realOutStream;
1822 if (copyCoderSpec->TotalSize == item.Size) 1790 const Int32 askMode = testMode ?
1823 res = NExtract::NOperationResult::kOK; 1791 NExtract::NAskMode::kTest :
1792 NExtract::NAskMode::kExtract;
1793 const UInt32 index = allFilesMode ? i : indices[i];
1794 const CItem &item = _items[_items2[index].MainIndex];
1795 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
1796 totalSize += item.Size;
1797 if (!testMode && !realOutStream)
1798 continue;
1799 RINOK(extractCallback->PrepareOperation(askMode))
1800 if (testMode || item.IsDir)
1801 opRes = NExtract::NOperationResult::kOK;
1802 else
1803 {
1804 opRes = NExtract::NOperationResult::kDataError;
1805 CMyComPtr<ISequentialInStream> inStream;
1806 GetStream(index, &inStream);
1807 if (inStream)
1808 {
1809 RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
1810 if (copyCoder->TotalSize == item.Size)
1811 opRes = NExtract::NOperationResult::kOK;
1812 }
1813 }
1824 } 1814 }
1825 realOutStream.Release(); 1815 RINOK(extractCallback->SetOperationResult(opRes))
1826 RINOK(extractCallback->SetOperationResult(res))
1827 } 1816 }
1828 return S_OK; 1817 return S_OK;
1829 COM_TRY_END 1818 COM_TRY_END
diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp
index e5bf997..2fef079 100644
--- a/CPP/7zip/Archive/VhdHandler.cpp
+++ b/CPP/7zip/Archive/VhdHandler.cpp
@@ -5,6 +5,7 @@
5#include "../../../C/CpuArch.h" 5#include "../../../C/CpuArch.h"
6 6
7#include "../../Common/ComTry.h" 7#include "../../Common/ComTry.h"
8#include "../../Common/IntToString.h"
8 9
9#include "../../Windows/PropVariant.h" 10#include "../../Windows/PropVariant.h"
10 11
@@ -278,9 +279,9 @@ Z7_class_CHandler_final: public CHandlerImg
278 if (mainName != anotherName && !anotherName.IsEmpty()) 279 if (mainName != anotherName && !anotherName.IsEmpty())
279 { 280 {
280 res.Add_Space(); 281 res.Add_Space();
281 res += '('; 282 res.Add_Char('(');
282 res += anotherName; 283 res += anotherName;
283 res += ')'; 284 res.Add_Char(')');
284 } 285 }
285 p = p->Parent; 286 p = p->Parent;
286 } 287 }
@@ -689,16 +690,6 @@ static void StringToAString(char *dest, UInt32 val)
689 *dest = 0; 690 *dest = 0;
690} 691}
691 692
692static void ConvertByteToHex(unsigned value, char *s)
693{
694 for (int i = 0; i < 2; i++)
695 {
696 unsigned t = value & 0xF;
697 value >>= 4;
698 s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
699 }
700}
701
702Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 693Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
703{ 694{
704 COM_TRY_BEGIN 695 COM_TRY_BEGIN
@@ -754,10 +745,8 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
754 } 745 }
755 case kpidId: 746 case kpidId:
756 { 747 {
757 char s[32 + 4]; 748 char s[sizeof(Footer.Id) * 2 + 2];
758 for (int i = 0; i < 16; i++) 749 ConvertDataToHex_Upper(s, Footer.Id, sizeof(Footer.Id));
759 ConvertByteToHex(Footer.Id[i], s + i * 2);
760 s[32] = 0;
761 prop = s; 750 prop = s;
762 break; 751 break;
763 } 752 }
@@ -949,13 +938,13 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
949 *stream = NULL; 938 *stream = NULL;
950 if (Footer.IsFixed()) 939 if (Footer.IsFixed())
951 { 940 {
952 CLimitedInStream *streamSpec = new CLimitedInStream; 941 CMyComPtr2<ISequentialInStream, CLimitedInStream> streamSpec;
953 CMyComPtr<ISequentialInStream> streamTemp = streamSpec; 942 streamSpec.Create_if_Empty();
954 streamSpec->SetStream(Stream); 943 streamSpec->SetStream(Stream);
955 // fixme : check (startOffset = 0) 944 // fixme : check (startOffset = 0)
956 streamSpec->InitAndSeek(_startOffset, Footer.CurrentSize); 945 streamSpec->InitAndSeek(_startOffset, Footer.CurrentSize);
957 RINOK(streamSpec->SeekToStart()) 946 RINOK(streamSpec->SeekToStart())
958 *stream = streamTemp.Detach(); 947 *stream = streamSpec.Detach();
959 return S_OK; 948 return S_OK;
960 } 949 }
961 if (!Footer.ThereIsDynamic() || !AreParentsOK()) 950 if (!Footer.ThereIsDynamic() || !AreParentsOK())
diff --git a/CPP/7zip/Archive/VhdxHandler.cpp b/CPP/7zip/Archive/VhdxHandler.cpp
index e3ddedd..ca450e5 100644
--- a/CPP/7zip/Archive/VhdxHandler.cpp
+++ b/CPP/7zip/Archive/VhdxHandler.cpp
@@ -7,6 +7,8 @@
7#include "../../../C/CpuArch.h" 7#include "../../../C/CpuArch.h"
8 8
9#include "../../Common/ComTry.h" 9#include "../../Common/ComTry.h"
10#include "../../Common/IntToString.h"
11#include "../../Common/StringToInt.h"
10#include "../../Common/MyBuffer.h" 12#include "../../Common/MyBuffer.h"
11 13
12#include "../../Windows/PropVariant.h" 14#include "../../Windows/PropVariant.h"
@@ -31,6 +33,7 @@ EXTERN_C_BEGIN
31// CRC-32C (Castagnoli) : reversed for poly 0x1EDC6F41 33// CRC-32C (Castagnoli) : reversed for poly 0x1EDC6F41
32#define k_Crc32c_Poly 0x82f63b78 34#define k_Crc32c_Poly 0x82f63b78
33 35
36MY_ALIGN(64)
34static UInt32 g_Crc32c_Table[256]; 37static UInt32 g_Crc32c_Table[256];
35 38
36static void Z7_FASTCALL Crc32c_GenerateTable() 39static void Z7_FASTCALL Crc32c_GenerateTable()
@@ -91,31 +94,13 @@ static bool IsZeroArr(const Byte *p, size_t size)
91} 94}
92 95
93 96
94#define ValToHex(t) ((char)(((t) < 10) ? ('0' + (t)) : ('a' + ((t) - 10))))
95
96static void AddByteToHex2(unsigned val, UString &s)
97{
98 unsigned t;
99 t = val >> 4;
100 s += ValToHex(t);
101 t = val & 0xF;
102 s += ValToHex(t);
103}
104
105
106static int HexToVal(const wchar_t c)
107{
108 if (c >= '0' && c <= '9') return c - '0';
109 if (c >= 'a' && c <= 'z') return c - 'a' + 10;
110 if (c >= 'A' && c <= 'Z') return c - 'A' + 10;
111 return -1;
112}
113 97
98Z7_FORCE_INLINE
114static int DecodeFrom2HexChars(const wchar_t *s) 99static int DecodeFrom2HexChars(const wchar_t *s)
115{ 100{
116 const int v0 = HexToVal(s[0]); if (v0 < 0) return -1; 101 unsigned v0 = (unsigned)s[0]; Z7_PARSE_HEX_DIGIT(v0, return -1;)
117 const int v1 = HexToVal(s[1]); if (v1 < 0) return -1; 102 unsigned v1 = (unsigned)s[1]; Z7_PARSE_HEX_DIGIT(v1, return -1;)
118 return (int)(((unsigned)v0 << 4) | (unsigned)v1); 103 return (int)((v0 << 4) | v1);
119} 104}
120 105
121 106
@@ -161,8 +146,9 @@ struct CGuid
161 146
162void CGuid::AddHexToString(UString &s) const 147void CGuid::AddHexToString(UString &s) const
163{ 148{
164 for (unsigned i = 0; i < 16; i++) 149 char temp[sizeof(Data) * 2 + 2];
165 AddByteToHex2(Data[i], s); 150 ConvertDataToHex_Lower(temp, Data, sizeof(Data));
151 s += temp;
166} 152}
167 153
168 154
@@ -274,7 +260,7 @@ struct CRegion
274}; 260};
275 261
276 262
277static const unsigned kRegionSize = 1 << 16; 263static const size_t kRegionSize = 1 << 16;
278static const unsigned kNumRegionEntriesMax = (1 << 11) - 1; 264static const unsigned kNumRegionEntriesMax = (1 << 11) - 1;
279 265
280bool CRegion::Parse(Byte *p) 266bool CRegion::Parse(Byte *p)
@@ -1576,7 +1562,7 @@ static void AddComment_Name(UString &s, const char *name)
1576static void AddComment_Bool(UString &s, const char *name, bool val) 1562static void AddComment_Bool(UString &s, const char *name, bool val)
1577{ 1563{
1578 AddComment_Name(s, name); 1564 AddComment_Name(s, name);
1579 s += val ? "+" : "-"; 1565 s.Add_Char(val ? '+' : '-');
1580 s.Add_LF(); 1566 s.Add_LF();
1581} 1567}
1582 1568
diff --git a/CPP/7zip/Archive/VmdkHandler.cpp b/CPP/7zip/Archive/VmdkHandler.cpp
index 0a6b967..9c293a3 100644
--- a/CPP/7zip/Archive/VmdkHandler.cpp
+++ b/CPP/7zip/Archive/VmdkHandler.cpp
@@ -815,7 +815,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
815 815
816 bool zlib = false; 816 bool zlib = false;
817 bool marker = false; 817 bool marker = false;
818 int algo = -1; 818 Int32 algo = -1;
819 819
820 FOR_VECTOR (i, _extents) 820 FOR_VECTOR (i, _extents)
821 { 821 {
@@ -829,7 +829,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
829 { 829 {
830 if (h.algo == 1) 830 if (h.algo == 1)
831 zlib = true; 831 zlib = true;
832 else if (algo != (int)h.algo) 832 else if (algo != h.algo)
833 { 833 {
834 s.Add_Space_if_NotEmpty(); 834 s.Add_Space_if_NotEmpty();
835 s.Add_UInt32(h.algo); 835 s.Add_UInt32(h.algo);
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp
index 7f96dcc..b21f673 100644
--- a/CPP/7zip/Archive/Wim/WimHandler.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandler.cpp
@@ -299,7 +299,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
299 299
300 if (numMethods == 1 && chunkSizeBits != 0) 300 if (numMethods == 1 && chunkSizeBits != 0)
301 { 301 {
302 res += ':'; 302 res.Add_Colon();
303 res.Add_UInt32((UInt32)chunkSizeBits); 303 res.Add_UInt32((UInt32)chunkSizeBits);
304 } 304 }
305 305
@@ -1055,27 +1055,23 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1055 1055
1056 RINOK(extractCallback->SetTotal(totalSize)) 1056 RINOK(extractCallback->SetTotal(totalSize))
1057 1057
1058 UInt64 currentTotalUnPacked = 0; 1058 totalSize = 0;
1059 UInt64 currentItemUnPacked; 1059 UInt64 currentItemUnPacked;
1060 1060
1061 int prevSuccessStreamIndex = -1; 1061 int prevSuccessStreamIndex = -1;
1062 1062
1063 CUnpacker unpacker; 1063 CUnpacker unpacker;
1064 1064
1065 CLocalProgress *lps = new CLocalProgress; 1065 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1066 CMyComPtr<ICompressProgressInfo> progress = lps;
1067 lps->Init(extractCallback, false); 1066 lps->Init(extractCallback, false);
1068 1067
1069 for (i = 0;; i++, 1068 for (i = 0;; i++,
1070 currentTotalUnPacked += currentItemUnPacked) 1069 totalSize += currentItemUnPacked)
1071 { 1070 {
1072 currentItemUnPacked = 0; 1071 currentItemUnPacked = 0;
1073
1074 lps->InSize = unpacker.TotalPacked; 1072 lps->InSize = unpacker.TotalPacked;
1075 lps->OutSize = currentTotalUnPacked; 1073 lps->OutSize = totalSize;
1076
1077 RINOK(lps->SetCur()) 1074 RINOK(lps->SetCur())
1078
1079 if (i >= numItems) 1075 if (i >= numItems)
1080 break; 1076 break;
1081 1077
@@ -1108,7 +1104,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1108 } 1104 }
1109 1105
1110 const CItem &item = _db.Items[_db.SortedItems[index]]; 1106 const CItem &item = _db.Items[_db.SortedItems[index]];
1111 int streamIndex = item.StreamIndex; 1107 const int streamIndex = item.StreamIndex;
1112 if (streamIndex < 0) 1108 if (streamIndex < 0)
1113 { 1109 {
1114 if (!item.IsDir) 1110 if (!item.IsDir)
@@ -1135,10 +1131,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1135 { 1131 {
1136 Byte digest[kHashSize]; 1132 Byte digest[kHashSize];
1137 const CVolume &vol = _volumes[si.PartNumber]; 1133 const CVolume &vol = _volumes[si.PartNumber];
1138 bool needDigest = !si.IsEmptyHash(); 1134 const bool needDigest = !si.IsEmptyHash() && !_disable_Sha1Check;
1139 1135 const HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header, &_db,
1140 HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header, &_db, 1136 realOutStream, lps, needDigest ? digest : NULL);
1141 realOutStream, progress, needDigest ? digest : NULL);
1142 1137
1143 if (res == S_OK) 1138 if (res == S_OK)
1144 { 1139 {
@@ -1216,6 +1211,13 @@ Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
1216 else if (name.IsPrefixedBy_Ascii_NoCase("memuse")) 1211 else if (name.IsPrefixedBy_Ascii_NoCase("memuse"))
1217 { 1212 {
1218 } 1213 }
1214 else if (name.IsPrefixedBy_Ascii_NoCase("crc"))
1215 {
1216 name.Delete(0, 3);
1217 UInt32 crcSize = 1;
1218 RINOK(ParsePropToUInt32(name, prop, crcSize))
1219 _disable_Sha1Check = (crcSize == 0);
1220 }
1219 else 1221 else
1220 { 1222 {
1221 bool processed = false; 1223 bool processed = false;
diff --git a/CPP/7zip/Archive/Wim/WimHandler.h b/CPP/7zip/Archive/Wim/WimHandler.h
index 60bb156..126d233 100644
--- a/CPP/7zip/Archive/Wim/WimHandler.h
+++ b/CPP/7zip/Archive/Wim/WimHandler.h
@@ -12,7 +12,7 @@
12namespace NArchive { 12namespace NArchive {
13namespace NWim { 13namespace NWim {
14 14
15static const Int32 kNumImagesMaxUpdate = (1 << 10); 15const Int32 kNumImagesMaxUpdate = 1 << 10;
16 16
17Z7_CLASS_IMP_CHandler_IInArchive_5( 17Z7_CLASS_IMP_CHandler_IInArchive_5(
18 IArchiveGetRawProps 18 IArchiveGetRawProps
@@ -23,17 +23,18 @@ Z7_CLASS_IMP_CHandler_IInArchive_5(
23) 23)
24 CDatabase _db; 24 CDatabase _db;
25 UInt32 _version; 25 UInt32 _version;
26 bool _isOldVersion;
27 UInt32 _bootIndex; 26 UInt32 _bootIndex;
28 27
29 CObjectVector<CVolume> _volumes; 28 CObjectVector<CVolume> _volumes;
30 CObjectVector<CWimXml> _xmls; 29 CObjectVector<CWimXml> _xmls;
31 // unsigned _nameLenForStreams; 30 // unsigned _nameLenForStreams;
32 bool _xmlInComments; 31
33
34 unsigned _numXmlItems; 32 unsigned _numXmlItems;
35 unsigned _numIgnoreItems; 33 unsigned _numIgnoreItems;
36 34
35 bool _isOldVersion;
36 bool _xmlInComments;
37
37 bool _xmlError; 38 bool _xmlError;
38 bool _isArc; 39 bool _isArc;
39 bool _unsupported; 40 bool _unsupported;
@@ -43,16 +44,17 @@ Z7_CLASS_IMP_CHandler_IInArchive_5(
43 int _defaultImageNumber; 44 int _defaultImageNumber;
44 45
45 bool _showImageNumber; 46 bool _showImageNumber;
46
47 bool _keepMode_ShowImageNumber; 47 bool _keepMode_ShowImageNumber;
48 bool _disable_Sha1Check;
48 49
49 UInt64 _phySize; 50 UInt64 _phySize;
50 int _firstVolumeIndex; 51 Int32 _firstVolumeIndex;
51 52
52 CHandlerTimeOptions _timeOptions; 53 CHandlerTimeOptions _timeOptions;
53 54
54 void InitDefaults() 55 void InitDefaults()
55 { 56 {
57 _disable_Sha1Check = false;
56 _set_use_ShowImageNumber = false; 58 _set_use_ShowImageNumber = false;
57 _set_showImageNumber = false; 59 _set_showImageNumber = false;
58 _defaultImageNumber = -1; 60 _defaultImageNumber = -1;
diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
index 5d9dea2..3b2cb31 100644
--- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
@@ -20,6 +20,8 @@
20#include "../../Crypto/RandGen.h" 20#include "../../Crypto/RandGen.h"
21#include "../../Crypto/Sha1Cls.h" 21#include "../../Crypto/Sha1Cls.h"
22 22
23#include "../Common/OutStreamWithSha1.h"
24
23#include "WimHandler.h" 25#include "WimHandler.h"
24 26
25using namespace NWindows; 27using namespace NWindows;
@@ -345,40 +347,6 @@ void CStreamInfo::WriteTo(Byte *p) const
345} 347}
346 348
347 349
348Z7_CLASS_IMP_NOQIB_1(
349 CInStreamWithSha1
350 , ISequentialInStream
351)
352 CMyComPtr<ISequentialInStream> _stream;
353 UInt64 _size;
354 // NCrypto::NSha1::CContext _sha;
355 CAlignedBuffer1 _sha;
356 CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; }
357public:
358 CInStreamWithSha1(): _sha(sizeof(CSha1)) {}
359 void SetStream(ISequentialInStream *stream) { _stream = stream; }
360 void Init()
361 {
362 _size = 0;
363 Sha1_Init(Sha());
364 }
365 void ReleaseStream() { _stream.Release(); }
366 UInt64 GetSize() const { return _size; }
367 void Final(Byte *digest) { Sha1_Final(Sha(), digest); }
368};
369
370Z7_COM7F_IMF(CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize))
371{
372 UInt32 realProcessedSize;
373 const HRESULT result = _stream->Read(data, size, &realProcessedSize);
374 _size += realProcessedSize;
375 Sha1_Update(Sha(), (const Byte *)data, realProcessedSize);
376 if (processedSize)
377 *processedSize = realProcessedSize;
378 return result;
379}
380
381
382static void SetFileTimeToMem(Byte *p, const FILETIME &ft) 350static void SetFileTimeToMem(Byte *p, const FILETIME &ft)
383{ 351{
384 Set32(p, ft.dwLowDateTime) 352 Set32(p, ft.dwLowDateTime)
@@ -599,14 +567,14 @@ void CDb::WriteOrderList(const CDir &tree)
599 567
600static void AddTag_ToString(AString &s, const char *name, const char *value) 568static void AddTag_ToString(AString &s, const char *name, const char *value)
601{ 569{
602 s += '<'; 570 s.Add_Char('<');
603 s += name; 571 s += name;
604 s += '>'; 572 s.Add_Char('>');
605 s += value; 573 s += value;
606 s += '<'; 574 s.Add_Char('<');
607 s += '/'; 575 s.Add_Slash();
608 s += name; 576 s += name;
609 s += '>'; 577 s.Add_Char('>');
610} 578}
611 579
612 580
@@ -620,7 +588,7 @@ static void AddTagUInt64_ToString(AString &s, const char *name, UInt64 value)
620 588
621static CXmlItem &AddUniqueTag(CXmlItem &parentItem, const char *name) 589static CXmlItem &AddUniqueTag(CXmlItem &parentItem, const char *name)
622{ 590{
623 int index = parentItem.FindSubTag(name); 591 const int index = parentItem.FindSubTag(name);
624 if (index < 0) 592 if (index < 0)
625 { 593 {
626 CXmlItem &subItem = parentItem.SubItems.AddNew(); 594 CXmlItem &subItem = parentItem.SubItems.AddNew();
@@ -679,8 +647,7 @@ static void AddTag_Time(CXmlItem &parentItem, const char *name, const FILETIME &
679 647
680static void AddTag_String_IfEmpty(CXmlItem &parentItem, const char *name, const char *value) 648static void AddTag_String_IfEmpty(CXmlItem &parentItem, const char *name, const char *value)
681{ 649{
682 int index = parentItem.FindSubTag(name); 650 if (parentItem.FindSubTag(name) >= 0)
683 if (index >= 0)
684 return; 651 return;
685 CXmlItem &tag = parentItem.SubItems.AddNew(); 652 CXmlItem &tag = parentItem.SubItems.AddNew();
686 tag.IsTag = true; 653 tag.IsTag = true;
@@ -1094,7 +1061,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1094 { 1061 {
1095 for (;;) 1062 for (;;)
1096 { 1063 {
1097 wchar_t c = *path++; 1064 const wchar_t c = *path++;
1098 if (c == 0) 1065 if (c == 0)
1099 break; 1066 break;
1100 if (c == WCHAR_PATH_SEPARATOR || c == L'/') 1067 if (c == WCHAR_PATH_SEPARATOR || c == L'/')
@@ -1382,12 +1349,9 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1382 RINOK(callback->SetTotal(complexity)) 1349 RINOK(callback->SetTotal(complexity))
1383 UInt64 totalComplexity = complexity; 1350 UInt64 totalComplexity = complexity;
1384 1351
1385 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 1352 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1386 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
1387
1388 CLocalProgress *lps = new CLocalProgress;
1389 CMyComPtr<ICompressProgressInfo> progress = lps;
1390 lps->Init(callback, true); 1353 lps->Init(callback, true);
1354 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
1391 1355
1392 complexity = 0; 1356 complexity = 0;
1393 1357
@@ -1419,8 +1383,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1419 1383
1420 UInt64 curPos = kHeaderSizeMax; 1384 UInt64 curPos = kHeaderSizeMax;
1421 1385
1422 CInStreamWithSha1 *inShaStreamSpec = new CInStreamWithSha1; 1386 CMyComPtr2_Create<ISequentialInStream, CInStreamWithSha1> inShaStream;
1423 CMyComPtr<ISequentialInStream> inShaStream = inShaStreamSpec;
1424 1387
1425 CLimitedSequentialInStream *inStreamLimitedSpec = NULL; 1388 CLimitedSequentialInStream *inStreamLimitedSpec = NULL;
1426 CMyComPtr<ISequentialInStream> inStreamLimited; 1389 CMyComPtr<ISequentialInStream> inStreamLimited;
@@ -1492,7 +1455,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1492 1455
1493 if (!rs.IsSolid() || rs.IsSolidSmall()) 1456 if (!rs.IsSolid() || rs.IsSolidSmall())
1494 { 1457 {
1495 const int find = AddUniqHash(&streams.Front(), sortedHashes, siOld.Hash, (int)streamIndex); 1458 const int find = AddUniqHash(streams.ConstData(), sortedHashes, siOld.Hash, (int)streamIndex);
1496 if (find != -1) 1459 if (find != -1)
1497 return E_FAIL; // two streams with same SHA-1 1460 return E_FAIL; // two streams with same SHA-1
1498 } 1461 }
@@ -1501,8 +1464,8 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1501 { 1464 {
1502 RINOK(InStream_SeekSet(_volumes[siOld.PartNumber].Stream, rs.Offset)) 1465 RINOK(InStream_SeekSet(_volumes[siOld.PartNumber].Stream, rs.Offset))
1503 inStreamLimitedSpec->Init(rs.PackSize); 1466 inStreamLimitedSpec->Init(rs.PackSize);
1504 RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)) 1467 RINOK(copyCoder.Interface()->Code(inStreamLimited, outStream, NULL, NULL, lps))
1505 if (copyCoderSpec->TotalSize != rs.PackSize) 1468 if (copyCoder->TotalSize != rs.PackSize)
1506 return E_FAIL; 1469 return E_FAIL;
1507 s.Resource.Offset = curPos; 1470 s.Resource.Offset = curPos;
1508 curPos += rs.PackSize; 1471 curPos += rs.PackSize;
@@ -1564,7 +1527,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1564 1527
1565 const CStreamInfo &siOld = _db.DataStreams[item.StreamIndex]; 1528 const CStreamInfo &siOld = _db.DataStreams[item.StreamIndex];
1566 1529
1567 const int index = AddUniqHash(&streams.Front(), sortedHashes, siOld.Hash, -1); 1530 const int index = AddUniqHash(streams.ConstData(), sortedHashes, siOld.Hash, -1);
1568 // we must have written that stream already 1531 // we must have written that stream already
1569 if (index == -1) 1532 if (index == -1)
1570 return E_FAIL; 1533 return E_FAIL;
@@ -1655,7 +1618,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1655 Byte hash[kHashSize]; 1618 Byte hash[kHashSize];
1656 sha1.Final(hash); 1619 sha1.Final(hash);
1657 1620
1658 int index = AddUniqHash(&streams.Front(), sortedHashes, hash, (int)streams.Size()); 1621 int index = AddUniqHash(streams.ConstData(), sortedHashes, hash, (int)streams.Size());
1659 1622
1660 if (index != -1) 1623 if (index != -1)
1661 streams[index].RefCount++; 1624 streams[index].RefCount++;
@@ -1684,13 +1647,13 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1684 } 1647 }
1685 else 1648 else
1686 { 1649 {
1687 inShaStreamSpec->SetStream(fileInStream); 1650 inShaStream->SetStream(fileInStream);
1688 1651
1689 CMyComPtr<IInStream> inSeekStream; 1652 CMyComPtr<IInStream> inSeekStream;
1690 fileInStream.QueryInterface(IID_IInStream, (void **)&inSeekStream); 1653 fileInStream.QueryInterface(IID_IInStream, (void **)&inSeekStream);
1691 1654
1692 fileInStream.Release(); 1655 fileInStream.Release();
1693 inShaStreamSpec->Init(); 1656 inShaStream->Init();
1694 UInt64 offsetBlockSize = 0; 1657 UInt64 offsetBlockSize = 0;
1695 /* 1658 /*
1696 if (useResourceCompression) 1659 if (useResourceCompression)
@@ -1711,16 +1674,16 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1711 1674
1712 if (inSeekStream /* && !sortedHashes.IsEmpty() */) 1675 if (inSeekStream /* && !sortedHashes.IsEmpty() */)
1713 { 1676 {
1714 RINOK(copyCoder->Code(inShaStream, NULL, NULL, NULL, progress)) 1677 RINOK(copyCoder.Interface()->Code(inShaStream, NULL, NULL, NULL, lps))
1715 size = copyCoderSpec->TotalSize; 1678 size = copyCoder->TotalSize;
1716 if (size == 0) 1679 if (size == 0)
1717 needWritePass = false; 1680 needWritePass = false;
1718 else 1681 else
1719 { 1682 {
1720 Byte hash[kHashSize]; 1683 Byte hash[kHashSize];
1721 inShaStreamSpec->Final(hash); 1684 inShaStream->Final(hash);
1722 1685
1723 index = AddUniqHash(&streams.Front(), sortedHashes, hash, -1); 1686 index = AddUniqHash(streams.ConstData(), sortedHashes, hash, -1);
1724 if (index != -1) 1687 if (index != -1)
1725 { 1688 {
1726 streams[index].RefCount++; 1689 streams[index].RefCount++;
@@ -1729,15 +1692,15 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1729 else 1692 else
1730 { 1693 {
1731 RINOK(InStream_SeekToBegin(inSeekStream)) 1694 RINOK(InStream_SeekToBegin(inSeekStream))
1732 inShaStreamSpec->Init(); 1695 inShaStream->Init();
1733 } 1696 }
1734 } 1697 }
1735 } 1698 }
1736 1699
1737 if (needWritePass) 1700 if (needWritePass)
1738 { 1701 {
1739 RINOK(copyCoder->Code(inShaStream, outStream, NULL, NULL, progress)) 1702 RINOK(copyCoder.Interface()->Code(inShaStream, outStream, NULL, NULL, lps))
1740 size = copyCoderSpec->TotalSize; 1703 size = copyCoder->TotalSize;
1741 } 1704 }
1742 1705
1743 if (size != 0) 1706 if (size != 0)
@@ -1746,9 +1709,9 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1746 { 1709 {
1747 Byte hash[kHashSize]; 1710 Byte hash[kHashSize];
1748 const UInt64 packSize = offsetBlockSize + size; 1711 const UInt64 packSize = offsetBlockSize + size;
1749 inShaStreamSpec->Final(hash); 1712 inShaStream->Final(hash);
1750 1713
1751 index = AddUniqHash(&streams.Front(), sortedHashes, hash, (int)streams.Size()); 1714 index = AddUniqHash(streams.ConstData(), sortedHashes, hash, (int)streams.Size());
1752 1715
1753 if (index != -1) 1716 if (index != -1)
1754 { 1717 {
@@ -1805,8 +1768,8 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1805 1768
1806 RINOK(InStream_SeekSet(_volumes[1].Stream, s.Resource.Offset)) 1769 RINOK(InStream_SeekSet(_volumes[1].Stream, s.Resource.Offset))
1807 inStreamLimitedSpec->Init(s.Resource.PackSize); 1770 inStreamLimitedSpec->Init(s.Resource.PackSize);
1808 RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)) 1771 RINOK(copyCoder.Interface()->Code(inStreamLimited, outStream, NULL, NULL, lps))
1809 if (copyCoderSpec->TotalSize != s.Resource.PackSize) 1772 if (copyCoder->TotalSize != s.Resource.PackSize)
1810 return E_FAIL; 1773 return E_FAIL;
1811 1774
1812 s.Resource.Offset = curPos; 1775 s.Resource.Offset = curPos;
@@ -1874,7 +1837,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
1874 Set32((Byte *)meta, (UInt32)pos) // size of security data 1837 Set32((Byte *)meta, (UInt32)pos) // size of security data
1875 } 1838 }
1876 1839
1877 db.Hashes = &streams.Front(); 1840 db.Hashes = streams.ConstData();
1878 db.WriteTree(tree, (Byte *)meta, pos); 1841 db.WriteTree(tree, (Byte *)meta, pos);
1879 1842
1880 { 1843 {
diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp
index ff118d8..614755a 100644
--- a/CPP/7zip/Archive/Wim/WimIn.cpp
+++ b/CPP/7zip/Archive/Wim/WimIn.cpp
@@ -34,19 +34,19 @@
34namespace NArchive { 34namespace NArchive {
35namespace NWim { 35namespace NWim {
36 36
37static int inline GetLog(UInt32 num) 37static bool inline GetLog_val_min_dest(const UInt32 val, unsigned i, unsigned &dest)
38{ 38{
39 for (int i = 0; i < 32; i++) 39 UInt32 v = (UInt32)1 << i;
40 if (((UInt32)1 << i) == num) 40 for (; i < 32; i++)
41 return i; 41 {
42 return -1; 42 if (v == val)
43} 43 {
44 44 dest = i;
45 45 return true;
46CUnpacker::~CUnpacker() 46 }
47{ 47 v += v;
48 if (lzmsDecoder) 48 }
49 delete lzmsDecoder; 49 return false;
50} 50}
51 51
52 52
@@ -64,25 +64,27 @@ HRESULT CUnpacker::UnpackChunk(
64 } 64 }
65 else if (method == NMethod::kLZX) 65 else if (method == NMethod::kLZX)
66 { 66 {
67 if (!lzxDecoder) 67 lzxDecoder.Create_if_Empty();
68 { 68 lzxDecoder->Set_WimMode(true);
69 lzxDecoderSpec = new NCompress::NLzx::CDecoder(true);
70 lzxDecoder = lzxDecoderSpec;
71 }
72 } 69 }
73 else if (method == NMethod::kLZMS) 70 else if (method == NMethod::kLZMS)
74 { 71 {
75 if (!lzmsDecoder) 72 lzmsDecoder.Create_if_Empty();
76 lzmsDecoder = new NCompress::NLzms::CDecoder();
77 } 73 }
78 else 74 else
79 return E_NOTIMPL; 75 return E_NOTIMPL;
80 76
81 const size_t chunkSize = (size_t)1 << chunkSizeBits; 77 const size_t chunkSize = (size_t)1 << chunkSizeBits;
82 78
83 unpackBuf.EnsureCapacity(chunkSize); 79 {
84 if (!unpackBuf.Data) 80 const unsigned
85 return E_OUTOFMEMORY; 81 kAdditionalOutputBufSize = MyMax(NCompress::NLzx::
82 kAdditionalOutputBufSize, NCompress::NXpress::
83 kAdditionalOutputBufSize);
84 unpackBuf.EnsureCapacity(chunkSize + kAdditionalOutputBufSize);
85 if (!unpackBuf.Data)
86 return E_OUTOFMEMORY;
87 }
86 88
87 HRESULT res = S_FALSE; 89 HRESULT res = S_FALSE;
88 size_t unpackedSize = 0; 90 size_t unpackedSize = 0;
@@ -95,30 +97,32 @@ HRESULT CUnpacker::UnpackChunk(
95 } 97 }
96 else if (inSize < chunkSize) 98 else if (inSize < chunkSize)
97 { 99 {
98 packBuf.EnsureCapacity(chunkSize); 100 const unsigned kAdditionalInputSize = 32;
101 packBuf.EnsureCapacity(chunkSize + kAdditionalInputSize);
99 if (!packBuf.Data) 102 if (!packBuf.Data)
100 return E_OUTOFMEMORY; 103 return E_OUTOFMEMORY;
101 104
102 RINOK(ReadStream_FALSE(inStream, packBuf.Data, inSize)) 105 RINOK(ReadStream_FALSE(inStream, packBuf.Data, inSize))
106 memset(packBuf.Data + inSize, 0xff, kAdditionalInputSize);
103 107
104 TotalPacked += inSize; 108 TotalPacked += inSize;
105 109
106 if (method == NMethod::kXPRESS) 110 if (method == NMethod::kXPRESS)
107 { 111 {
108 res = NCompress::NXpress::Decode(packBuf.Data, inSize, unpackBuf.Data, outSize); 112 res = NCompress::NXpress::Decode_WithExceedWrite(packBuf.Data, inSize, unpackBuf.Data, outSize);
109 if (res == S_OK) 113 if (res == S_OK)
110 unpackedSize = outSize; 114 unpackedSize = outSize;
111 } 115 }
112 else if (method == NMethod::kLZX) 116 else if (method == NMethod::kLZX)
113 { 117 {
114 res = lzxDecoderSpec->SetExternalWindow(unpackBuf.Data, chunkSizeBits); 118 res = lzxDecoder->Set_ExternalWindow_DictBits(unpackBuf.Data, chunkSizeBits);
115 if (res != S_OK) 119 if (res != S_OK)
116 return E_NOTIMPL; 120 return E_NOTIMPL;
117 lzxDecoderSpec->KeepHistoryForNext = false; 121 lzxDecoder->Set_KeepHistoryForNext(false);
118 lzxDecoderSpec->SetKeepHistory(false); 122 lzxDecoder->Set_KeepHistory(false);
119 res = lzxDecoderSpec->Code(packBuf.Data, inSize, (UInt32)outSize); 123 res = lzxDecoder->Code_WithExceedReadWrite(packBuf.Data, inSize, (UInt32)outSize);
120 unpackedSize = lzxDecoderSpec->GetUnpackSize(); 124 unpackedSize = lzxDecoder->GetUnpackSize();
121 if (res == S_OK && !lzxDecoderSpec->WasBlockFinished()) 125 if (res == S_OK && !lzxDecoder->WasBlockFinished())
122 res = S_FALSE; 126 res = S_FALSE;
123 } 127 }
124 else 128 else
@@ -158,26 +162,21 @@ HRESULT CUnpacker::Unpack2(
158{ 162{
159 if (!resource.IsCompressed() && !resource.IsSolid()) 163 if (!resource.IsCompressed() && !resource.IsSolid())
160 { 164 {
161 if (!copyCoder) 165 copyCoder.Create_if_Empty();
162 {
163 copyCoderSpec = new NCompress::CCopyCoder;
164 copyCoder = copyCoderSpec;
165 }
166 166
167 CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream(); 167 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> limitedStream;
168 CMyComPtr<ISequentialInStream> limitedStream = limitedStreamSpec; 168 limitedStream->SetStream(inStream);
169 limitedStreamSpec->SetStream(inStream);
170 169
171 RINOK(InStream_SeekSet(inStream, resource.Offset)) 170 RINOK(InStream_SeekSet(inStream, resource.Offset))
172 if (resource.PackSize != resource.UnpackSize) 171 if (resource.PackSize != resource.UnpackSize)
173 return S_FALSE; 172 return S_FALSE;
174 173
175 limitedStreamSpec->Init(resource.PackSize); 174 limitedStream->Init(resource.PackSize);
176 TotalPacked += resource.PackSize; 175 TotalPacked += resource.PackSize;
177 176
178 HRESULT res = copyCoder->Code(limitedStream, outStream, NULL, NULL, progress); 177 HRESULT res = copyCoder.Interface()->Code(limitedStream, outStream, NULL, NULL, progress);
179 178
180 if (res == S_OK && copyCoderSpec->TotalSize != resource.UnpackSize) 179 if (res == S_OK && copyCoder->TotalSize != resource.UnpackSize)
181 res = S_FALSE; 180 res = S_FALSE;
182 return res; 181 return res;
183 } 182 }
@@ -366,24 +365,13 @@ HRESULT CUnpacker::Unpack2(
366HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, const CHeader &header, const CDatabase *db, 365HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, const CHeader &header, const CDatabase *db,
367 ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest) 366 ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest)
368{ 367{
369 COutStreamWithSha1 *shaStreamSpec = NULL; 368 CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSha1> shaStream;
370 CMyComPtr<ISequentialOutStream> shaStream;
371
372 // outStream can be NULL, so we use COutStreamWithSha1 even if sha1 is not required 369 // outStream can be NULL, so we use COutStreamWithSha1 even if sha1 is not required
373 // if (digest) 370 shaStream->SetStream(outStream);
374 { 371 shaStream->Init(digest != NULL);
375 shaStreamSpec = new COutStreamWithSha1(); 372 const HRESULT res = Unpack2(inStream, resource, header, db, shaStream, progress);
376 shaStream = shaStreamSpec;
377 shaStreamSpec->SetStream(outStream);
378 shaStreamSpec->Init(digest != NULL);
379 outStream = shaStream;
380 }
381
382 HRESULT res = Unpack2(inStream, resource, header, db, outStream, progress);
383
384 if (digest) 373 if (digest)
385 shaStreamSpec->Final(digest); 374 shaStream->Final(digest);
386
387 return res; 375 return res;
388} 376}
389 377
@@ -394,21 +382,16 @@ HRESULT CUnpacker::UnpackData(IInStream *inStream,
394 CByteBuffer &buf, Byte *digest) 382 CByteBuffer &buf, Byte *digest)
395{ 383{
396 // if (resource.IsSolid()) return E_NOTIMPL; 384 // if (resource.IsSolid()) return E_NOTIMPL;
397
398 UInt64 unpackSize64 = resource.UnpackSize; 385 UInt64 unpackSize64 = resource.UnpackSize;
399 if (db) 386 if (db)
400 unpackSize64 = db->Get_UnpackSize_of_Resource(resource); 387 unpackSize64 = db->Get_UnpackSize_of_Resource(resource);
401 388 const size_t size = (size_t)unpackSize64;
402 size_t size = (size_t)unpackSize64;
403 if (size != unpackSize64) 389 if (size != unpackSize64)
404 return E_OUTOFMEMORY; 390 return E_OUTOFMEMORY;
405
406 buf.Alloc(size); 391 buf.Alloc(size);
407 392
408 CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream(); 393 CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStream;
409 CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; 394 outStream->Init((Byte *)buf, size);
410 outStreamSpec->Init((Byte *)buf, size);
411
412 return Unpack(inStream, resource, header, db, outStream, NULL, digest); 395 return Unpack(inStream, resource, header, db, outStream, NULL, digest);
413} 396}
414 397
@@ -900,10 +883,8 @@ HRESULT CHeader::Parse(const Byte *p, UInt64 &phySize)
900 ChunkSizeBits = kChunkSizeBits; 883 ChunkSizeBits = kChunkSizeBits;
901 if (ChunkSize != 0) 884 if (ChunkSize != 0)
902 { 885 {
903 const int log = GetLog(ChunkSize); 886 if (!GetLog_val_min_dest(ChunkSize, 12, ChunkSizeBits))
904 if (log < 12)
905 return S_FALSE; 887 return S_FALSE;
906 ChunkSizeBits = (unsigned)log;
907 } 888 }
908 } 889 }
909 890
@@ -1314,23 +1295,21 @@ HRESULT CDatabase::FillAndCheck(const CObjectVector<CVolume> &volumes)
1314 return S_FALSE; 1295 return S_FALSE;
1315 1296
1316 const UInt32 solidChunkSize = GetUi32(header + 8); 1297 const UInt32 solidChunkSize = GetUi32(header + 8);
1317 const int log = GetLog(solidChunkSize); 1298 if (!GetLog_val_min_dest(solidChunkSize, 8, ss.ChunkSizeBits))
1318 if (log < 8 || log > 31)
1319 return S_FALSE; 1299 return S_FALSE;
1320 ss.ChunkSizeBits = (unsigned)log;
1321 ss.Method = (Int32)GetUi32(header + 12); 1300 ss.Method = (Int32)GetUi32(header + 12);
1322 1301
1323 UInt64 numChunks64 = (ss.UnpackSize + (((UInt32)1 << ss.ChunkSizeBits) - 1)) >> ss.ChunkSizeBits; 1302 const UInt64 numChunks64 = (ss.UnpackSize + (((UInt32)1 << ss.ChunkSizeBits) - 1)) >> ss.ChunkSizeBits;
1324 UInt64 sizesBufSize64 = 4 * numChunks64; 1303 const UInt64 sizesBufSize64 = 4 * numChunks64;
1325 ss.HeadersSize = kSolidHeaderSize + sizesBufSize64; 1304 ss.HeadersSize = kSolidHeaderSize + sizesBufSize64;
1326 size_t sizesBufSize = (size_t)sizesBufSize64; 1305 const size_t sizesBufSize = (size_t)sizesBufSize64;
1327 if (sizesBufSize != sizesBufSize64) 1306 if (sizesBufSize != sizesBufSize64)
1328 return E_OUTOFMEMORY; 1307 return E_OUTOFMEMORY;
1329 sizesBuf.AllocAtLeast(sizesBufSize); 1308 sizesBuf.AllocAtLeast(sizesBufSize);
1330 1309
1331 RINOK(ReadStream_FALSE(inStream, sizesBuf, sizesBufSize)) 1310 RINOK(ReadStream_FALSE(inStream, sizesBuf, sizesBufSize))
1332 1311
1333 size_t numChunks = (size_t)numChunks64; 1312 const size_t numChunks = (size_t)numChunks64;
1334 ss.Chunks.Alloc(numChunks + 1); 1313 ss.Chunks.Alloc(numChunks + 1);
1335 1314
1336 UInt64 offset = 0; 1315 UInt64 offset = 0;
@@ -1439,7 +1418,7 @@ HRESULT CDatabase::FillAndCheck(const CObjectVector<CVolume> &volumes)
1439 1418
1440 { 1419 {
1441 { 1420 {
1442 const CStreamInfo *streams = &DataStreams.Front(); 1421 const CStreamInfo *streams = DataStreams.ConstData();
1443 1422
1444 if (IsOldVersion) 1423 if (IsOldVersion)
1445 { 1424 {
@@ -1481,7 +1460,7 @@ HRESULT CDatabase::FillAndCheck(const CObjectVector<CVolume> &volumes)
1481 hash += (item.IsAltStream ? 0x8 : 0x10); 1460 hash += (item.IsAltStream ? 0x8 : 0x10);
1482 UInt32 id = GetUi32(hash); 1461 UInt32 id = GetUi32(hash);
1483 if (id != 0) 1462 if (id != 0)
1484 item.StreamIndex = FindId(&DataStreams.Front(), sortedByHash, id); 1463 item.StreamIndex = FindId(DataStreams.ConstData(), sortedByHash, id);
1485 } 1464 }
1486 } 1465 }
1487 /* 1466 /*
@@ -1495,7 +1474,7 @@ HRESULT CDatabase::FillAndCheck(const CObjectVector<CVolume> &volumes)
1495 hash += (item.IsAltStream ? 0x10 : 0x40); 1474 hash += (item.IsAltStream ? 0x10 : 0x40);
1496 if (!IsEmptySha(hash)) 1475 if (!IsEmptySha(hash))
1497 { 1476 {
1498 item.StreamIndex = FindHash(&DataStreams.Front(), sortedByHash, hash); 1477 item.StreamIndex = FindHash(DataStreams.ConstData(), sortedByHash, hash);
1499 } 1478 }
1500 } 1479 }
1501 } 1480 }
@@ -1518,7 +1497,7 @@ HRESULT CDatabase::FillAndCheck(const CObjectVector<CVolume> &volumes)
1518 1497
1519 for (i = 0; i < Items.Size(); i++) 1498 for (i = 0; i < Items.Size(); i++)
1520 { 1499 {
1521 int streamIndex = Items[i].StreamIndex; 1500 const int streamIndex = Items[i].StreamIndex;
1522 if (streamIndex >= 0) 1501 if (streamIndex >= 0)
1523 refCounts[streamIndex]++; 1502 refCounts[streamIndex]++;
1524 } 1503 }
@@ -1773,13 +1752,12 @@ static bool ParseNumber32(const AString &s, UInt32 &res)
1773 1752
1774static bool ParseTime(const CXmlItem &item, FILETIME &ft, const char *tag) 1753static bool ParseTime(const CXmlItem &item, FILETIME &ft, const char *tag)
1775{ 1754{
1776 int index = item.FindSubTag(tag); 1755 const CXmlItem *timeItem = item.FindSubTag_GetPtr(tag);
1777 if (index >= 0) 1756 if (timeItem)
1778 { 1757 {
1779 const CXmlItem &timeItem = item.SubItems[index];
1780 UInt32 low = 0, high = 0; 1758 UInt32 low = 0, high = 0;
1781 if (ParseNumber32(timeItem.GetSubStringForTag("LOWPART"), low) && 1759 if (ParseNumber32(timeItem->GetSubStringForTag("LOWPART"), low) &&
1782 ParseNumber32(timeItem.GetSubStringForTag("HIGHPART"), high)) 1760 ParseNumber32(timeItem->GetSubStringForTag("HIGHPART"), high))
1783 { 1761 {
1784 ft.dwLowDateTime = low; 1762 ft.dwLowDateTime = low;
1785 ft.dwHighDateTime = high; 1763 ft.dwHighDateTime = high;
diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h
index 3de8456..71d0a3a 100644
--- a/CPP/7zip/Archive/Wim/WimIn.h
+++ b/CPP/7zip/Archive/Wim/WimIn.h
@@ -5,6 +5,7 @@
5 5
6#include "../../../../C/Alloc.h" 6#include "../../../../C/Alloc.h"
7 7
8#include "../../../Common/AutoPtr.h"
8#include "../../../Common/MyBuffer.h" 9#include "../../../Common/MyBuffer.h"
9#include "../../../Common/MyXml.h" 10#include "../../../Common/MyXml.h"
10 11
@@ -583,27 +584,23 @@ struct CMidBuf
583 { 584 {
584 if (size > _size) 585 if (size > _size)
585 { 586 {
586 ::MidFree(Data); 587 ::z7_AlignedFree(Data);
587 _size = 0; 588 _size = 0;
588 Data = (Byte *)::MidAlloc(size); 589 Data = (Byte *)::z7_AlignedAlloc(size);
589 if (Data) 590 if (Data)
590 _size = size; 591 _size = size;
591 } 592 }
592 } 593 }
593 594
594 ~CMidBuf() { ::MidFree(Data); } 595 ~CMidBuf() { ::z7_AlignedFree(Data); }
595}; 596};
596 597
597 598
598class CUnpacker 599class CUnpacker
599{ 600{
600 NCompress::CCopyCoder *copyCoderSpec; 601 CMyComPtr2<ICompressCoder, NCompress::CCopyCoder> copyCoder;
601 CMyComPtr<ICompressCoder> copyCoder; 602 CMyUniquePtr<NCompress::NLzx::CDecoder> lzxDecoder;
602 603 CMyUniquePtr<NCompress::NLzms::CDecoder> lzmsDecoder;
603 NCompress::NLzx::CDecoder *lzxDecoderSpec;
604 CMyComPtr<IUnknown> lzxDecoder;
605
606 NCompress::NLzms::CDecoder *lzmsDecoder;
607 604
608 CByteBuffer sizesBuf; 605 CByteBuffer sizesBuf;
609 606
@@ -637,7 +634,6 @@ public:
637 _unpackedChunkIndex(0), 634 _unpackedChunkIndex(0),
638 TotalPacked(0) 635 TotalPacked(0)
639 {} 636 {}
640 ~CUnpacker();
641 637
642 HRESULT Unpack( 638 HRESULT Unpack(
643 IInStream *inStream, 639 IInStream *inStream,
diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp
index c03128f..5112a16 100644
--- a/CPP/7zip/Archive/XarHandler.cpp
+++ b/CPP/7zip/Archive/XarHandler.cpp
@@ -2,6 +2,7 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../../../C/Sha256.h"
5#include "../../../C/CpuArch.h" 6#include "../../../C/CpuArch.h"
6 7
7#include "../../Common/ComTry.h" 8#include "../../Common/ComTry.h"
@@ -36,58 +37,205 @@ using namespace NWindows;
36namespace NArchive { 37namespace NArchive {
37namespace NXar { 38namespace NXar {
38 39
39static const size_t kXmlSizeMax = ((size_t )1 << 30) - (1 << 14); 40Z7_CLASS_IMP_NOQIB_1(
40static const size_t kXmlPackSizeMax = kXmlSizeMax; 41 CInStreamWithSha256
42 , ISequentialInStream
43)
44 CMyComPtr<ISequentialInStream> _stream;
45 CAlignedBuffer1 _sha;
46 UInt64 _size;
47
48 CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_sha; }
49public:
50 CInStreamWithSha256(): _sha(sizeof(CSha256)) {}
51 void SetStream(ISequentialInStream *stream) { _stream = stream; }
52 void Init()
53 {
54 _size = 0;
55 Sha256_Init(Sha());
56 }
57 void ReleaseStream() { _stream.Release(); }
58 UInt64 GetSize() const { return _size; }
59 void Final(Byte *digest) { Sha256_Final(Sha(), digest); }
60};
41 61
42/* 62Z7_COM7F_IMF(CInStreamWithSha256::Read(void *data, UInt32 size, UInt32 *processedSize))
43#define XAR_CKSUM_NONE 0 63{
44#define XAR_CKSUM_SHA1 1 64 UInt32 realProcessedSize;
45#define XAR_CKSUM_MD5 2 65 const HRESULT result = _stream->Read(data, size, &realProcessedSize);
66 _size += realProcessedSize;
67 Sha256_Update(Sha(), (const Byte *)data, realProcessedSize);
68 if (processedSize)
69 *processedSize = realProcessedSize;
70 return result;
71}
72
73
74Z7_CLASS_IMP_NOQIB_1(
75 COutStreamWithSha256
76 , ISequentialOutStream
77)
78 // bool _calculate;
79 CMyComPtr<ISequentialOutStream> _stream;
80 CAlignedBuffer1 _sha;
81 UInt64 _size;
82
83 CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_sha; }
84public:
85 COutStreamWithSha256(): _sha(sizeof(CSha256)) {}
86 void SetStream(ISequentialOutStream *stream) { _stream = stream; }
87 void ReleaseStream() { _stream.Release(); }
88 void Init(/* bool calculate = true */ )
89 {
90 // _calculate = calculate;
91 _size = 0;
92 Sha256_Init(Sha());
93 }
94 void InitSha256() { Sha256_Init(Sha()); }
95 UInt64 GetSize() const { return _size; }
96 void Final(Byte *digest) { Sha256_Final(Sha(), digest); }
97};
98
99Z7_COM7F_IMF(COutStreamWithSha256::Write(const void *data, UInt32 size, UInt32 *processedSize))
100{
101 HRESULT result = S_OK;
102 if (_stream)
103 result = _stream->Write(data, size, &size);
104 // if (_calculate)
105 Sha256_Update(Sha(), (const Byte *)data, size);
106 _size += size;
107 if (processedSize)
108 *processedSize = size;
109 return result;
110}
111
112// we limit supported xml sizes:
113// ((size_t)1 << (sizeof(size_t) / 2 + 28)) - (1u << 14);
114static const size_t kXmlSizeMax = ((size_t)1 << 30) - (1u << 14);
115static const size_t kXmlPackSizeMax = kXmlSizeMax;
46 116
47static const char * const k_ChecksumAlgos[] = 117#define XAR_CKSUM_NONE 0
118#define XAR_CKSUM_SHA1 1
119#define XAR_CKSUM_MD5 2
120#define XAR_CKSUM_SHA256 3
121#define XAR_CKSUM_SHA512 4
122// #define XAR_CKSUM_OTHER 3
123// fork version of xar can use (3) as special case,
124// where name of hash is stored as string at the end of header
125// we do not support such hash still.
126
127static const char * const k_ChecksumNames[] =
48{ 128{
49 "None" 129 "NONE"
50 , "SHA-1" 130 , "SHA1"
51 , "MD5" 131 , "MD5"
132 , "SHA256"
133 , "SHA512"
52}; 134};
53*/
54 135
55#define METHOD_NAME_ZLIB "zlib" 136static unsigned GetHashSize(int algo)
137{
138 if (algo <= XAR_CKSUM_NONE || algo > XAR_CKSUM_SHA512)
139 return 0;
140 if (algo == XAR_CKSUM_SHA1)
141 return SHA1_DIGEST_SIZE;
142 return (16u >> XAR_CKSUM_MD5) << algo;
143}
144
145#define METHOD_NAME_ZLIB "zlib"
146
147static int Find_ChecksumId_for_Name(const AString &style)
148{
149 for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_ChecksumNames); i++)
150 {
151 // old xars used upper case in "style"
152 // new xars use lower case in "style"
153 if (style.IsEqualTo_Ascii_NoCase(k_ChecksumNames[i]))
154 return (int)i;
155 }
156 return -1;
157}
158
159
160struct CCheckSum
161{
162 int AlgoNumber;
163 bool Error;
164 CByteBuffer Data;
165 AString Style;
166
167 CCheckSum(): AlgoNumber(-1), Error(false) {}
168 void AddNameToString(AString &s) const;
169};
170
171void CCheckSum::AddNameToString(AString &s) const
172{
173 if (Style.IsEmpty())
174 s.Add_OptSpaced("NO-CHECKSUM");
175 else
176 {
177 s.Add_OptSpaced(Style);
178 if (Error)
179 s += "-ERROR";
180 }
181}
56 182
57 183
58struct CFile 184struct CFile
59{ 185{
60 AString Name; 186 bool IsDir;
61 AString Method; 187 bool Is_SymLink;
188 bool HasData;
189 bool Mode_Defined;
190 bool INode_Defined;
191 bool UserId_Defined;
192 bool GroupId_Defined;
193 // bool Device_Defined;
194 bool Id_Defined;
195
196 int Parent;
197 UInt32 Mode;
198
62 UInt64 Size; 199 UInt64 Size;
63 UInt64 PackSize; 200 UInt64 PackSize;
64 UInt64 Offset; 201 UInt64 Offset;
65
66 UInt64 CTime;
67 UInt64 MTime; 202 UInt64 MTime;
203 UInt64 CTime;
68 UInt64 ATime; 204 UInt64 ATime;
69 UInt32 Mode; 205 UInt64 INode;
206 UInt64 UserId;
207 UInt64 GroupId;
208 // UInt64 Device;
70 209
210 AString Name;
211 AString Method;
71 AString User; 212 AString User;
72 AString Group; 213 AString Group;
214 // AString Id;
215 AString Type;
216 AString Link;
217 // AString LinkType;
218 // AString LinkFrom;
73 219
74 bool IsDir; 220 UInt64 Id;
75 bool HasData; 221 CCheckSum extracted_checksum;
76 bool ModeDefined; 222 CCheckSum archived_checksum;
77 bool Sha1IsDefined; 223
78 // bool packSha1IsDefined; 224 CFile(int parent):
79 225 IsDir(false),
80 Byte Sha1[SHA1_DIGEST_SIZE]; 226 Is_SymLink(false),
81 // Byte packSha1[SHA1_DIGEST_SIZE]; 227 HasData(false),
82 228 Mode_Defined(false),
83 int Parent; 229 INode_Defined(false),
84 230 UserId_Defined(false),
85 CFile(): 231 GroupId_Defined(false),
232 // Device_Defined(false),
233 Id_Defined(false),
234 Parent(parent),
235 Mode(0),
86 Size(0), PackSize(0), Offset(0), 236 Size(0), PackSize(0), Offset(0),
87 CTime(0), MTime(0), ATime(0), Mode(0), 237 MTime(0), CTime(0), ATime(0),
88 IsDir(false), HasData(false), ModeDefined(false), Sha1IsDefined(false), 238 INode(0)
89 /* packSha1IsDefined(false), */
90 Parent(-1)
91 {} 239 {}
92 240
93 bool IsCopyMethod() const 241 bool IsCopyMethod() const
@@ -97,36 +245,46 @@ struct CFile
97 245
98 void UpdateTotalPackSize(UInt64 &totalSize) const 246 void UpdateTotalPackSize(UInt64 &totalSize) const
99 { 247 {
100 UInt64 t = Offset + PackSize; 248 const UInt64 t = Offset + PackSize;
249 if (t >= Offset)
101 if (totalSize < t) 250 if (totalSize < t)
102 totalSize = t; 251 totalSize = t;
103 } 252 }
104}; 253};
105 254
106 255
107Z7_CLASS_IMP_CHandler_IInArchive_1( 256Z7_CLASS_IMP_CHandler_IInArchive_2(
257 IArchiveGetRawProps,
108 IInArchiveGetStream 258 IInArchiveGetStream
109) 259)
110 UInt64 _dataStartPos; 260 bool _is_pkg;
111 CMyComPtr<IInStream> _inStream; 261 bool _toc_CrcError;
112 CByteArr _xml;
113 size_t _xmlLen;
114 CObjectVector<CFile> _files; 262 CObjectVector<CFile> _files;
115 // UInt32 _checkSumAlgo; 263 CMyComPtr<IInStream> _inStream;
264 UInt64 _dataStartPos;
116 UInt64 _phySize; 265 UInt64 _phySize;
266 CAlignedBuffer _xmlBuf;
267 size_t _xmlLen;
268 // UInt64 CreationTime;
269 AString CreationTime_String;
270 UInt32 _checkSumAlgo;
117 Int32 _mainSubfile; 271 Int32 _mainSubfile;
118 bool _is_pkg;
119 272
120 HRESULT Open2(IInStream *stream); 273 HRESULT Open2(IInStream *stream);
121 HRESULT Extract(IInStream *stream);
122}; 274};
123 275
276
124static const Byte kArcProps[] = 277static const Byte kArcProps[] =
125{ 278{
126 kpidSubType, 279 kpidSubType,
127 kpidHeadersSize 280 // kpidHeadersSize,
281 kpidMethod,
282 kpidCTime
128}; 283};
129 284
285// #define kpidLinkType 250
286// #define kpidLinkFrom 251
287
130static const Byte kProps[] = 288static const Byte kProps[] =
131{ 289{
132 kpidPath, 290 kpidPath,
@@ -136,19 +294,25 @@ static const Byte kProps[] =
136 kpidCTime, 294 kpidCTime,
137 kpidATime, 295 kpidATime,
138 kpidPosixAttrib, 296 kpidPosixAttrib,
297 kpidType,
139 kpidUser, 298 kpidUser,
140 kpidGroup, 299 kpidGroup,
141 kpidMethod 300 kpidUserId,
301 kpidGroupId,
302 kpidINode,
303 // kpidDeviceMajor,
304 // kpidDeviceMinor,
305 kpidSymLink,
306 // kpidLinkType,
307 // kpidLinkFrom,
308 kpidMethod,
309 kpidId,
310 kpidOffset
142}; 311};
143 312
144IMP_IInArchive_Props 313IMP_IInArchive_Props
145IMP_IInArchive_ArcProps 314IMP_IInArchive_ArcProps
146 315
147#define PARSE_NUM(_num_, _dest_) \
148 { const char *end; _dest_ = ConvertStringToUInt32(p, &end); \
149 if ((unsigned)(end - p) != _num_) return 0; \
150 p += _num_ + 1; }
151
152static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res) 316static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res)
153{ 317{
154 const AString s (item.GetSubStringForTag(name)); 318 const AString s (item.GetSubStringForTag(name));
@@ -159,14 +323,26 @@ static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res)
159 return *end == 0; 323 return *end == 0;
160} 324}
161 325
162static UInt64 ParseTime(const CXmlItem &item, const char *name) 326
327#define PARSE_NUM(_num_, _dest_) \
328 { const char *end; _dest_ = ConvertStringToUInt32(p, &end); \
329 if ((unsigned)(end - p) != _num_) return 0; \
330 p += _num_ + 1; }
331
332static UInt64 ParseTime(const CXmlItem &item, const char *name /* , bool z_isRequired */ )
163{ 333{
164 const AString s (item.GetSubStringForTag(name)); 334 const AString s (item.GetSubStringForTag(name));
165 if (s.Len() < 20) 335 if (s.Len() < 20 /* (z_isRequired ? 20u : 19u) */)
166 return 0; 336 return 0;
167 const char *p = s; 337 const char *p = s;
168 if (p[ 4] != '-' || p[ 7] != '-' || p[10] != 'T' || 338 if (p[ 4] != '-' ||
169 p[13] != ':' || p[16] != ':' || p[19] != 'Z') 339 p[ 7] != '-' ||
340 p[10] != 'T' ||
341 p[13] != ':' ||
342 p[16] != ':')
343 return 0;
344 // if (z_isRequired)
345 if (p[19] != 'Z')
170 return 0; 346 return 0;
171 UInt32 year, month, day, hour, min, sec; 347 UInt32 year, month, day, hour, min, sec;
172 PARSE_NUM(4, year) 348 PARSE_NUM(4, year)
@@ -175,176 +351,261 @@ static UInt64 ParseTime(const CXmlItem &item, const char *name)
175 PARSE_NUM(2, hour) 351 PARSE_NUM(2, hour)
176 PARSE_NUM(2, min) 352 PARSE_NUM(2, min)
177 PARSE_NUM(2, sec) 353 PARSE_NUM(2, sec)
178
179 UInt64 numSecs; 354 UInt64 numSecs;
180 if (!NTime::GetSecondsSince1601(year, month, day, hour, min, sec, numSecs)) 355 if (!NTime::GetSecondsSince1601(year, month, day, hour, min, sec, numSecs))
181 return 0; 356 return 0;
182 return numSecs * 10000000; 357 return numSecs * 10000000;
183} 358}
184 359
185static int HexToByte(char c)
186{
187 if (c >= '0' && c <= '9') return c - '0';
188 if (c >= 'A' && c <= 'F') return c - 'A' + 10;
189 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
190 return -1;
191}
192 360
193static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest) 361static void ParseChecksum(const CXmlItem &item, const char *name, CCheckSum &checksum)
194{ 362{
195 const int index = item.FindSubTag(name); 363 const CXmlItem *checkItem = item.FindSubTag_GetPtr(name);
196 if (index < 0) 364 if (!checkItem)
197 return false; 365 return; // false;
198 const CXmlItem &checkItem = item.SubItems[index]; 366 checksum.Style = checkItem->GetPropVal("style");
199 const AString style (checkItem.GetPropVal("style")); 367 const AString s (checkItem->GetSubString());
200 if (style == "SHA1") 368 if ((s.Len() & 1) == 0 && s.Len() <= (2u << 7)) // 1024-bit max
201 { 369 {
202 const AString s (checkItem.GetSubString()); 370 const size_t size = s.Len() / 2;
203 if (s.Len() != SHA1_DIGEST_SIZE * 2) 371 CByteBuffer temp(size);
204 return false; 372 if ((size_t)(ParseHexString(s, temp) - temp) == size)
205 for (unsigned i = 0; i < s.Len(); i += 2)
206 { 373 {
207 const int b0 = HexToByte(s[i]); 374 checksum.Data = temp;
208 const int b1 = HexToByte(s[i + 1]); 375 const int index = Find_ChecksumId_for_Name(checksum.Style);
209 if (b0 < 0 || b1 < 0) 376 if (index >= 0 && checksum.Data.Size() == GetHashSize(index))
210 return false; 377 {
211 digest[i / 2] = (Byte)((b0 << 4) | b1); 378 checksum.AlgoNumber = index;
379 return;
380 }
212 } 381 }
213 return true;
214 } 382 }
215 return false; 383 checksum.Error = true;
216} 384}
217 385
218static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int parent) 386
387static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int parent, int level)
219{ 388{
220 if (!item.IsTag) 389 if (!item.IsTag)
221 return true; 390 return true;
391 if (level >= 1024)
392 return false;
222 if (item.Name == "file") 393 if (item.Name == "file")
223 { 394 {
224 CFile file; 395 CFile file(parent);
225 file.Parent = parent;
226 parent = (int)files.Size(); 396 parent = (int)files.Size();
397 {
398 const AString id = item.GetPropVal("id");
399 const char *end;
400 file.Id = ConvertStringToUInt64(id, &end);
401 if (*end == 0)
402 file.Id_Defined = true;
403 }
227 file.Name = item.GetSubStringForTag("name"); 404 file.Name = item.GetSubStringForTag("name");
228 const AString type (item.GetSubStringForTag("type")); 405 z7_xml_DecodeString(file.Name);
229 if (type == "directory") 406 {
230 file.IsDir = true; 407 const CXmlItem *typeItem = item.FindSubTag_GetPtr("type");
231 else if (type == "file") 408 if (typeItem)
232 file.IsDir = false; 409 {
233 else 410 file.Type = typeItem->GetSubString();
234 return false; 411 // file.LinkFrom = typeItem->GetPropVal("link");
412 if (file.Type == "directory")
413 file.IsDir = true;
414 else
415 {
416 // file.IsDir = false;
417 /*
418 else if (file.Type == "file")
419 {}
420 else if (file.Type == "hardlink")
421 {}
422 else
423 */
424 if (file.Type == "symlink")
425 file.Is_SymLink = true;
426 // file.IsDir = false;
427 }
428 }
429 }
430 {
431 const CXmlItem *linkItem = item.FindSubTag_GetPtr("link");
432 if (linkItem)
433 {
434 // file.LinkType = linkItem->GetPropVal("type");
435 file.Link = linkItem->GetSubString();
436 z7_xml_DecodeString(file.Link);
437 }
438 }
235 439
236 int dataIndex = item.FindSubTag("data"); 440 const CXmlItem *dataItem = item.FindSubTag_GetPtr("data");
237 if (dataIndex >= 0 && !file.IsDir) 441 if (dataItem && !file.IsDir)
238 { 442 {
239 file.HasData = true; 443 file.HasData = true;
240 const CXmlItem &dataItem = item.SubItems[dataIndex]; 444 if (!ParseUInt64(*dataItem, "size", file.Size))
241 if (!ParseUInt64(dataItem, "size", file.Size))
242 return false; 445 return false;
243 if (!ParseUInt64(dataItem, "length", file.PackSize)) 446 if (!ParseUInt64(*dataItem, "length", file.PackSize))
244 return false; 447 return false;
245 if (!ParseUInt64(dataItem, "offset", file.Offset)) 448 if (!ParseUInt64(*dataItem, "offset", file.Offset))
246 return false; 449 return false;
247 file.Sha1IsDefined = ParseSha1(dataItem, "extracted-checksum", file.Sha1); 450 ParseChecksum(*dataItem, "extracted-checksum", file.extracted_checksum);
248 // file.packSha1IsDefined = ParseSha1(dataItem, "archived-checksum", file.packSha1); 451 ParseChecksum(*dataItem, "archived-checksum", file.archived_checksum);
249 int encodingIndex = dataItem.FindSubTag("encoding"); 452 const CXmlItem *encodingItem = dataItem->FindSubTag_GetPtr("encoding");
250 if (encodingIndex >= 0) 453 if (encodingItem)
251 { 454 {
252 const CXmlItem &encodingItem = dataItem.SubItems[encodingIndex]; 455 AString s (encodingItem->GetPropVal("style"));
253 if (encodingItem.IsTag) 456 if (!s.IsEmpty())
254 { 457 {
255 AString s (encodingItem.GetPropVal("style")); 458 const AString appl ("application/");
256 if (!s.IsEmpty()) 459 if (s.IsPrefixedBy(appl))
257 { 460 {
258 const AString appl ("application/"); 461 s.DeleteFrontal(appl.Len());
259 if (s.IsPrefixedBy(appl)) 462 const AString xx ("x-");
463 if (s.IsPrefixedBy(xx))
260 { 464 {
261 s.DeleteFrontal(appl.Len()); 465 s.DeleteFrontal(xx.Len());
262 const AString xx ("x-"); 466 if (s == "gzip")
263 if (s.IsPrefixedBy(xx)) 467 s = METHOD_NAME_ZLIB;
264 {
265 s.DeleteFrontal(xx.Len());
266 if (s == "gzip")
267 s = METHOD_NAME_ZLIB;
268 }
269 } 468 }
270 file.Method = s;
271 } 469 }
470 file.Method = s;
272 } 471 }
273 } 472 }
274 } 473 }
275 474
475 file.INode_Defined = ParseUInt64(item, "inode", file.INode);
476 file.UserId_Defined = ParseUInt64(item, "uid", file.UserId);
477 file.GroupId_Defined = ParseUInt64(item, "gid", file.GroupId);
478 // file.Device_Defined = ParseUInt64(item, "deviceno", file.Device);
479 file.MTime = ParseTime(item, "mtime"); // z_IsRequied = true
276 file.CTime = ParseTime(item, "ctime"); 480 file.CTime = ParseTime(item, "ctime");
277 file.MTime = ParseTime(item, "mtime");
278 file.ATime = ParseTime(item, "atime"); 481 file.ATime = ParseTime(item, "atime");
279
280 { 482 {
281 const AString s (item.GetSubStringForTag("mode")); 483 const AString s (item.GetSubStringForTag("mode"));
282 if (s[0] == '0') 484 if (s[0] == '0')
283 { 485 {
284 const char *end; 486 const char *end;
285 file.Mode = ConvertOctStringToUInt32(s, &end); 487 file.Mode = ConvertOctStringToUInt32(s, &end);
286 file.ModeDefined = (*end == 0); 488 file.Mode_Defined = (*end == 0);
287 } 489 }
288 } 490 }
289
290 file.User = item.GetSubStringForTag("user"); 491 file.User = item.GetSubStringForTag("user");
291 file.Group = item.GetSubStringForTag("group"); 492 file.Group = item.GetSubStringForTag("group");
292 493
293 files.Add(file); 494 files.Add(file);
294 } 495 }
496
295 FOR_VECTOR (i, item.SubItems) 497 FOR_VECTOR (i, item.SubItems)
296 if (!AddItem(item.SubItems[i], files, parent)) 498 if (!AddItem(item.SubItems[i], files, parent, level + 1))
297 return false; 499 return false;
298 return true; 500 return true;
299} 501}
300 502
301HRESULT CHandler::Open2(IInStream *stream) 503
504
505struct CInStreamWithHash
302{ 506{
303 const UInt32 kHeaderSize = 0x1C; 507 CMyComPtr2_Create<ISequentialInStream, CInStreamWithSha1> inStreamSha1;
304 Byte buf[kHeaderSize]; 508 CMyComPtr2_Create<ISequentialInStream, CInStreamWithSha256> inStreamSha256;
305 RINOK(ReadStream_FALSE(stream, buf, kHeaderSize)) 509 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStreamLim;
306 UInt32 size = Get16(buf + 4);
307 // UInt32 ver = Get16(buf + 6); // == 1
308 if (Get32(buf) != 0x78617221 || size != kHeaderSize)
309 return S_FALSE;
310 510
311 UInt64 packSize = Get64(buf + 8); 511 void SetStreamAndInit(ISequentialInStream *stream, int algo);
312 UInt64 unpackSize = Get64(buf + 0x10); 512 bool CheckHash(int algo, const Byte *digest_from_arc) const;
513};
313 514
314 // _checkSumAlgo = Get32(buf + 0x18);
315 515
516void CInStreamWithHash::SetStreamAndInit(ISequentialInStream *stream, int algo)
517{
518 if (algo == XAR_CKSUM_SHA1)
519 {
520 inStreamSha1->SetStream(stream);
521 inStreamSha1->Init();
522 stream = inStreamSha1;
523 }
524 else if (algo == XAR_CKSUM_SHA256)
525 {
526 inStreamSha256->SetStream(stream);
527 inStreamSha256->Init();
528 stream = inStreamSha256;
529 }
530 inStreamLim->SetStream(stream);
531}
532
533bool CInStreamWithHash::CheckHash(int algo, const Byte *digest_from_arc) const
534{
535 if (algo == XAR_CKSUM_SHA1)
536 {
537 Byte digest[SHA1_DIGEST_SIZE];
538 inStreamSha1->Final(digest);
539 if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0)
540 return false;
541 }
542 else if (algo == XAR_CKSUM_SHA256)
543 {
544 Byte digest[SHA256_DIGEST_SIZE];
545 inStreamSha256->Final(digest);
546 if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0)
547 return false;
548 }
549 return true;
550}
551
552
553HRESULT CHandler::Open2(IInStream *stream)
554{
555 const unsigned kHeaderSize = 28;
556 UInt32 buf32[kHeaderSize / sizeof(UInt32)];
557 RINOK(ReadStream_FALSE(stream, buf32, kHeaderSize))
558 const unsigned headerSize = Get16((const Byte *)(const void *)buf32 + 4);
559 // xar library now writes 1 to version field.
560 // some old xars could have version == 0 ?
561 // specification allows (headerSize != 28),
562 // but we don't expect big value in (headerSize).
563 // so we restrict (headerSize) with 64 bytes to reduce false open.
564 const unsigned kHeaderSize_MAX = 64;
565 if (Get32(buf32) != 0x78617221 // signature: "xar!"
566 || headerSize < kHeaderSize
567 || headerSize > kHeaderSize_MAX
568 || Get16((const Byte *)(const void *)buf32 + 6) > 1 // version
569 )
570 return S_FALSE;
571 _checkSumAlgo = Get32(buf32 + 6);
572 const UInt64 packSize = Get64(buf32 + 2);
573 const UInt64 unpackSize = Get64(buf32 + 4);
316 if (packSize >= kXmlPackSizeMax || 574 if (packSize >= kXmlPackSizeMax ||
317 unpackSize >= kXmlSizeMax) 575 unpackSize >= kXmlSizeMax)
318 return S_FALSE; 576 return S_FALSE;
319 577 /* some xar archives can have padding bytes at offset 28,
320 _dataStartPos = kHeaderSize + packSize; 578 or checksum algorithm name at offset 28 (in xar fork, if cksum_alg==3)
579 But we didn't see such xar archives.
580 */
581 if (headerSize != kHeaderSize)
582 {
583 RINOK(InStream_SeekSet(stream, headerSize))
584 }
585 _dataStartPos = headerSize + packSize;
321 _phySize = _dataStartPos; 586 _phySize = _dataStartPos;
322 587
323 _xml.Alloc((size_t)unpackSize + 1); 588 _xmlBuf.Alloc((size_t)unpackSize + 1);
589 if (!_xmlBuf.IsAllocated())
590 return E_OUTOFMEMORY;
324 _xmlLen = (size_t)unpackSize; 591 _xmlLen = (size_t)unpackSize;
325 592
326 NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder(); 593 CInStreamWithHash hashStream;
327 CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec; 594 {
328 595 CMyComPtr2_Create<ICompressCoder, NCompress::NZlib::CDecoder> zlibCoder;
329 CLimitedSequentialInStream *inStreamLimSpec = new CLimitedSequentialInStream; 596 hashStream.SetStreamAndInit(stream, (int)(unsigned)_checkSumAlgo);
330 CMyComPtr<ISequentialInStream> inStreamLim(inStreamLimSpec); 597 hashStream.inStreamLim->Init(packSize);
331 inStreamLimSpec->SetStream(stream); 598 CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStreamLim;
332 inStreamLimSpec->Init(packSize); 599 outStreamLim->Init(_xmlBuf, (size_t)unpackSize);
333 600 RINOK(zlibCoder.Interface()->Code(hashStream.inStreamLim, outStreamLim, NULL, &unpackSize, NULL))
334 CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream; 601 if (outStreamLim->GetPos() != (size_t)unpackSize)
335 CMyComPtr<ISequentialOutStream> outStreamLim(outStreamLimSpec); 602 return S_FALSE;
336 outStreamLimSpec->Init(_xml, (size_t)unpackSize); 603 }
337 604 _xmlBuf[(size_t)unpackSize] = 0;
338 RINOK(zlibCoder->Code(inStreamLim, outStreamLim, NULL, NULL, NULL)) 605 if (strlen((const char *)(const Byte *)_xmlBuf) != (size_t)unpackSize)
339
340 if (outStreamLimSpec->GetPos() != (size_t)unpackSize)
341 return S_FALSE; 606 return S_FALSE;
342
343 _xml[(size_t)unpackSize] = 0;
344 if (strlen((const char *)(const Byte *)_xml) != unpackSize) return S_FALSE;
345
346 CXml xml; 607 CXml xml;
347 if (!xml.Parse((const char *)(const Byte *)_xml)) 608 if (!xml.Parse((const char *)(const Byte *)_xmlBuf))
348 return S_FALSE; 609 return S_FALSE;
349 610
350 if (!xml.Root.IsTagged("xar") || xml.Root.SubItems.Size() != 1) 611 if (!xml.Root.IsTagged("xar") || xml.Root.SubItems.Size() != 1)
@@ -352,7 +613,40 @@ HRESULT CHandler::Open2(IInStream *stream)
352 const CXmlItem &toc = xml.Root.SubItems[0]; 613 const CXmlItem &toc = xml.Root.SubItems[0];
353 if (!toc.IsTagged("toc")) 614 if (!toc.IsTagged("toc"))
354 return S_FALSE; 615 return S_FALSE;
355 if (!AddItem(toc, _files, -1)) 616
617 // CreationTime = ParseTime(toc, "creation-time", false); // z_IsRequied
618 CreationTime_String = toc.GetSubStringForTag("creation-time");
619 {
620 // we suppose that offset of checksum is always 0;
621 // but [TOC].xml contains exact offset value in <checksum> block.
622 const UInt64 offset = 0;
623 const unsigned hashSize = GetHashSize((int)(unsigned)_checkSumAlgo);
624 if (hashSize)
625 {
626 /*
627 const CXmlItem *csItem = toc.FindSubTag_GetPtr("checksum");
628 if (csItem)
629 {
630 const int checkSumAlgo2 = Find_ChecksumId_for_Name(csItem->GetPropVal("style"));
631 UInt64 csSize, csOffset;
632 if (ParseUInt64(*csItem, "size", csSize) &&
633 ParseUInt64(*csItem, "offset", csOffset) &&
634 csSize == hashSize &&
635 (unsigned)checkSumAlgo2 == _checkSumAlgo)
636 offset = csOffset;
637 }
638 */
639 CByteBuffer digest_from_arc(hashSize);
640 RINOK(InStream_SeekSet(stream, _dataStartPos + offset))
641 RINOK(ReadStream_FALSE(stream, digest_from_arc, hashSize))
642 if (!hashStream.CheckHash((int)(unsigned)_checkSumAlgo, digest_from_arc))
643 _toc_CrcError = true;
644 }
645 }
646
647 if (!AddItem(toc, _files,
648 -1, // parent
649 0)) // level
356 return S_FALSE; 650 return S_FALSE;
357 651
358 UInt64 totalPackSize = 0; 652 UInt64 totalPackSize = 0;
@@ -362,19 +656,25 @@ HRESULT CHandler::Open2(IInStream *stream)
362 { 656 {
363 const CFile &file = _files[i]; 657 const CFile &file = _files[i];
364 file.UpdateTotalPackSize(totalPackSize); 658 file.UpdateTotalPackSize(totalPackSize);
365 if (file.Name == "Payload" || file.Name == "Content") 659 if (file.Parent == -1)
366 { 660 {
367 _mainSubfile = (Int32)(int)i; 661 if (file.Name == "Payload" || file.Name == "Content")
368 numMainFiles++; 662 {
663 _mainSubfile = (Int32)(int)i;
664 numMainFiles++;
665 }
666 else if (file.Name == "PackageInfo")
667 _is_pkg = true;
369 } 668 }
370 else if (file.Name == "PackageInfo")
371 _is_pkg = true;
372 } 669 }
373 670
374 if (numMainFiles > 1) 671 if (numMainFiles > 1)
375 _mainSubfile = -1; 672 _mainSubfile = -1;
376 673
377 _phySize = _dataStartPos + totalPackSize; 674 const UInt64 k_PhySizeLim = (UInt64)1 << 62;
675 _phySize = (totalPackSize > k_PhySizeLim - _dataStartPos) ?
676 k_PhySizeLim :
677 _dataStartPos + totalPackSize;
378 678
379 return S_OK; 679 return S_OK;
380} 680}
@@ -386,8 +686,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
386 COM_TRY_BEGIN 686 COM_TRY_BEGIN
387 { 687 {
388 Close(); 688 Close();
389 if (Open2(stream) != S_OK) 689 RINOK(Open2(stream))
390 return S_FALSE;
391 _inStream = stream; 690 _inStream = stream;
392 } 691 }
393 return S_OK; 692 return S_OK;
@@ -397,21 +696,26 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
397Z7_COM7F_IMF(CHandler::Close()) 696Z7_COM7F_IMF(CHandler::Close())
398{ 697{
399 _phySize = 0; 698 _phySize = 0;
699 _dataStartPos = 0;
400 _inStream.Release(); 700 _inStream.Release();
401 _files.Clear(); 701 _files.Clear();
402 _xmlLen = 0; 702 _xmlLen = 0;
403 _xml.Free(); 703 _xmlBuf.Free();
404 _mainSubfile = -1; 704 _mainSubfile = -1;
405 _is_pkg = false; 705 _is_pkg = false;
706 _toc_CrcError = false;
707 _checkSumAlgo = 0;
708 // CreationTime = 0;
709 CreationTime_String.Empty();
406 return S_OK; 710 return S_OK;
407} 711}
408 712
409Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) 713Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
410{ 714{
411 *numItems = _files.Size() 715 *numItems = _files.Size()
412 #ifdef XAR_SHOW_RAW 716#ifdef XAR_SHOW_RAW
413 + 1 717 + 1
414 #endif 718#endif
415 ; 719 ;
416 return S_OK; 720 return S_OK;
417} 721}
@@ -443,40 +747,82 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
443 NCOM::CPropVariant prop; 747 NCOM::CPropVariant prop;
444 switch (propID) 748 switch (propID)
445 { 749 {
446 case kpidHeadersSize: prop = _dataStartPos; break; 750 // case kpidHeadersSize: prop = _dataStartPos; break;
447 case kpidPhySize: prop = _phySize; break; 751 case kpidPhySize: prop = _phySize; break;
448 case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break; 752 case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
449 case kpidSubType: if (_is_pkg) prop = "pkg"; break; 753 case kpidSubType: if (_is_pkg) prop = "pkg"; break;
450 case kpidExtension: prop = _is_pkg ? "pkg" : "xar"; break; 754 case kpidExtension: prop = _is_pkg ? "pkg" : "xar"; break;
755 case kpidCTime:
756 {
757 // it's local time. We can transfer it to UTC time, if we use FILETIME.
758 // TimeToProp(CreationTime, prop); break;
759 if (!CreationTime_String.IsEmpty())
760 prop = CreationTime_String;
761 break;
762 }
763 case kpidMethod:
764 {
765 AString s;
766 if (_checkSumAlgo < Z7_ARRAY_SIZE(k_ChecksumNames))
767 s = k_ChecksumNames[_checkSumAlgo];
768 else
769 {
770 s += "Checksum";
771 s.Add_UInt32(_checkSumAlgo);
772 }
773 prop = s;
774 break;
775 }
776 case kpidWarningFlags:
777 {
778 UInt32 v = 0;
779 if (_toc_CrcError) v |= kpv_ErrorFlags_CrcError;
780 prop = v;
781 break;
782 }
783 case kpidINode: prop = true; break;
784 case kpidIsTree: prop = true; break;
451 } 785 }
452 prop.Detach(value); 786 prop.Detach(value);
453 return S_OK; 787 return S_OK;
454 COM_TRY_END 788 COM_TRY_END
455} 789}
456 790
791
792/*
793inline UInt32 MY_dev_major(UInt64 dev)
794{
795 return ((UInt32)(dev >> 8) & (UInt32)0xfff) | ((UInt32)(dev >> 32) & ~(UInt32)0xfff);
796}
797inline UInt32 MY_dev_minor(UInt64 dev)
798{
799 return ((UInt32)(dev) & 0xff) | ((UInt32)(dev >> 12) & ~(UInt32)0xff);
800}
801*/
802
457Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) 803Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
458{ 804{
459 COM_TRY_BEGIN 805 COM_TRY_BEGIN
460 NCOM::CPropVariant prop; 806 NCOM::CPropVariant prop;
461 807
462 #ifdef XAR_SHOW_RAW 808#ifdef XAR_SHOW_RAW
463 if (index == _files.Size()) 809 if (index >= _files.Size())
464 { 810 {
465 switch (propID) 811 switch (propID)
466 { 812 {
467 case kpidPath: prop = "[TOC].xml"; break; 813 case kpidName:
814 case kpidPath:
815 prop = "[TOC].xml"; break;
468 case kpidSize: 816 case kpidSize:
469 case kpidPackSize: prop = (UInt64)_xmlLen; break; 817 case kpidPackSize: prop = (UInt64)_xmlLen; break;
470 } 818 }
471 } 819 }
472 else 820 else
473 #endif 821#endif
474 { 822 {
475 const CFile &item = _files[index]; 823 const CFile &item = _files[index];
476 switch (propID) 824 switch (propID)
477 { 825 {
478 case kpidMethod: Utf8StringToProp(item.Method, prop); break;
479
480 case kpidPath: 826 case kpidPath:
481 { 827 {
482 AString path; 828 AString path;
@@ -486,37 +832,98 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
486 const CFile &item2 = _files[cur]; 832 const CFile &item2 = _files[cur];
487 if (!path.IsEmpty()) 833 if (!path.IsEmpty())
488 path.InsertAtFront(CHAR_PATH_SEPARATOR); 834 path.InsertAtFront(CHAR_PATH_SEPARATOR);
835// #define XAR_EMPTY_NAME_REPLACEMENT "[]"
489 if (item2.Name.IsEmpty()) 836 if (item2.Name.IsEmpty())
490 path.Insert(0, "unknown"); 837 {
838 AString s('[');
839 s.Add_UInt32(cur);
840 s.Add_Char(']');
841 path.Insert(0, s);
842 }
491 else 843 else
492 path.Insert(0, item2.Name); 844 path.Insert(0, item2.Name);
493 cur = (unsigned)item2.Parent;
494 if (item2.Parent < 0) 845 if (item2.Parent < 0)
495 break; 846 break;
847 cur = (unsigned)item2.Parent;
496 } 848 }
497
498 Utf8StringToProp(path, prop); 849 Utf8StringToProp(path, prop);
499 break; 850 break;
500 } 851 }
501 852
853 case kpidName:
854 {
855 if (item.Name.IsEmpty())
856 {
857 AString s('[');
858 s.Add_UInt32(index);
859 s.Add_Char(']');
860 prop = s;
861 }
862 else
863 Utf8StringToProp(item.Name, prop);
864 break;
865 }
866
502 case kpidIsDir: prop = item.IsDir; break; 867 case kpidIsDir: prop = item.IsDir; break;
503 case kpidSize: if (!item.IsDir) prop = item.Size; break;
504 case kpidPackSize: if (!item.IsDir) prop = item.PackSize; break;
505 868
869 case kpidSize: if (item.HasData && !item.IsDir) prop = item.Size; break;
870 case kpidPackSize: if (item.HasData && !item.IsDir) prop = item.PackSize; break;
871
872 case kpidMethod:
873 {
874 if (item.HasData)
875 {
876 AString s = item.Method;
877 item.extracted_checksum.AddNameToString(s);
878 item.archived_checksum.AddNameToString(s);
879 Utf8StringToProp(s, prop);
880 }
881 break;
882 }
883
506 case kpidMTime: TimeToProp(item.MTime, prop); break; 884 case kpidMTime: TimeToProp(item.MTime, prop); break;
507 case kpidCTime: TimeToProp(item.CTime, prop); break; 885 case kpidCTime: TimeToProp(item.CTime, prop); break;
508 case kpidATime: TimeToProp(item.ATime, prop); break; 886 case kpidATime: TimeToProp(item.ATime, prop); break;
887
509 case kpidPosixAttrib: 888 case kpidPosixAttrib:
510 if (item.ModeDefined) 889 if (item.Mode_Defined)
511 { 890 {
512 UInt32 mode = item.Mode; 891 UInt32 mode = item.Mode;
513 if ((mode & MY_LIN_S_IFMT) == 0) 892 if ((mode & MY_LIN_S_IFMT) == 0)
514 mode |= (item.IsDir ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG); 893 mode |= (
894 item.Is_SymLink ? MY_LIN_S_IFLNK :
895 item.IsDir ? MY_LIN_S_IFDIR :
896 MY_LIN_S_IFREG);
515 prop = mode; 897 prop = mode;
516 } 898 }
517 break; 899 break;
518 case kpidUser: Utf8StringToProp(item.User, prop); break; 900
901 case kpidType: Utf8StringToProp(item.Type, prop); break;
902 case kpidUser: Utf8StringToProp(item.User, prop); break;
519 case kpidGroup: Utf8StringToProp(item.Group, prop); break; 903 case kpidGroup: Utf8StringToProp(item.Group, prop); break;
904 case kpidSymLink: if (item.Is_SymLink) Utf8StringToProp(item.Link, prop); break;
905
906 case kpidUserId: if (item.UserId_Defined) prop = item.UserId; break;
907 case kpidGroupId: if (item.GroupId_Defined) prop = item.GroupId; break;
908 case kpidINode: if (item.INode_Defined) prop = item.INode; break;
909 case kpidId: if (item.Id_Defined) prop = item.Id; break;
910 // Utf8StringToProp(item.Id, prop);
911 /*
912 case kpidDeviceMajor: if (item.Device_Defined) prop = (UInt32)MY_dev_major(item.Device); break;
913 case kpidDeviceMinor: if (item.Device_Defined) prop = (UInt32)MY_dev_minor(item.Device); break;
914 case kpidLinkType:
915 if (!item.LinkType.IsEmpty())
916 Utf8StringToProp(item.LinkType, prop);
917 break;
918 case kpidLinkFrom:
919 if (!item.LinkFrom.IsEmpty())
920 Utf8StringToProp(item.LinkFrom, prop);
921 break;
922 */
923 case kpidOffset:
924 if (item.HasData)
925 prop = _dataStartPos + item.Offset;
926 break;
520 } 927 }
521 } 928 }
522 prop.Detach(value); 929 prop.Detach(value);
@@ -524,75 +931,170 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
524 COM_TRY_END 931 COM_TRY_END
525} 932}
526 933
934
935// for debug:
936// #define Z7_XAR_SHOW_CHECKSUM_PACK
937
938#ifdef Z7_XAR_SHOW_CHECKSUM_PACK
939enum
940{
941 kpidChecksumPack = kpidUserDefined
942};
943#endif
944
945static const Byte kRawProps[] =
946{
947 kpidChecksum
948#ifdef Z7_XAR_SHOW_CHECKSUM_PACK
949 , kpidCRC // instead of kpidUserDefined / kpidCRC
950#endif
951};
952
953Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))
954{
955 *numProps = Z7_ARRAY_SIZE(kRawProps);
956 return S_OK;
957}
958
959Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID))
960{
961 *propID = kRawProps[index];
962 *name = NULL;
963
964#ifdef Z7_XAR_SHOW_CHECKSUM_PACK
965 if (index != 0)
966 {
967 *propID = kpidChecksumPack;
968 *name = NWindows::NCOM::AllocBstrFromAscii("archived-checksum");
969 }
970#endif
971 return S_OK;
972}
973
974Z7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))
975{
976 *parentType = NParentType::kDir;
977 *parent = (UInt32)(Int32)-1;
978#ifdef XAR_SHOW_RAW
979 if (index >= _files.Size())
980 return S_OK;
981#endif
982 {
983 const CFile &item = _files[index];
984 *parent = (UInt32)(Int32)item.Parent;
985 }
986 return S_OK;
987}
988
989
990Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))
991{
992 *data = NULL;
993 *dataSize = 0;
994 *propType = 0;
995
996 // COM_TRY_BEGIN
997 NCOM::CPropVariant prop;
998
999 if (propID == kpidChecksum)
1000 {
1001#ifdef XAR_SHOW_RAW
1002 if (index >= _files.Size())
1003 {
1004 // case kpidPath: prop = "[TOC].xml"; break;
1005 }
1006 else
1007#endif
1008 {
1009 const CFile &item = _files[index];
1010 const size_t size = item.extracted_checksum.Data.Size();
1011 if (size != 0)
1012 {
1013 *dataSize = (UInt32)size;
1014 *propType = NPropDataType::kRaw;
1015 *data = item.extracted_checksum.Data;
1016 }
1017 }
1018 }
1019
1020#ifdef Z7_XAR_SHOW_CHECKSUM_PACK
1021 if (propID == kpidChecksumPack)
1022 {
1023#ifdef XAR_SHOW_RAW
1024 if (index >= _files.Size())
1025 {
1026 // we can show digest check sum here
1027 }
1028 else
1029#endif
1030 {
1031 const CFile &item = _files[index];
1032 const size_t size = (UInt32)item.archived_checksum.Data.Size();
1033 if (size != 0)
1034 {
1035 *dataSize = (UInt32)size;
1036 *propType = NPropDataType::kRaw;
1037 *data = item.archived_checksum.Data;
1038 }
1039 }
1040 }
1041#endif
1042 return S_OK;
1043}
1044
1045
1046
1047
527Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, 1048Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
528 Int32 testMode, IArchiveExtractCallback *extractCallback)) 1049 Int32 testMode, IArchiveExtractCallback *extractCallback))
529{ 1050{
530 COM_TRY_BEGIN 1051 COM_TRY_BEGIN
531 const bool allFilesMode = (numItems == (UInt32)(Int32)-1); 1052 const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
532 if (allFilesMode) 1053 if (allFilesMode)
533 numItems = _files.Size(); 1054 numItems = _files.Size()
1055#ifdef XAR_SHOW_RAW
1056 + 1
1057#endif
1058 ;
534 if (numItems == 0) 1059 if (numItems == 0)
535 return S_OK; 1060 return S_OK;
536 UInt64 totalSize = 0; 1061 UInt64 totalSize = 0;
537 UInt32 i; 1062 UInt32 i;
538 for (i = 0; i < numItems; i++) 1063 for (i = 0; i < numItems; i++)
539 { 1064 {
540 UInt32 index = (allFilesMode ? i : indices[i]); 1065 const UInt32 index = allFilesMode ? i : indices[i];
541 #ifdef XAR_SHOW_RAW 1066#ifdef XAR_SHOW_RAW
542 if (index == _files.Size()) 1067 if (index >= _files.Size())
543 totalSize += _xmlLen; 1068 totalSize += _xmlLen;
544 else 1069 else
545 #endif 1070#endif
546 totalSize += _files[index].Size; 1071 totalSize += _files[index].Size;
547 } 1072 }
548 extractCallback->SetTotal(totalSize); 1073 RINOK(extractCallback->SetTotal(totalSize))
549
550 UInt64 currentPackTotal = 0;
551 UInt64 currentUnpTotal = 0;
552 UInt64 currentPackSize = 0;
553 UInt64 currentUnpSize = 0;
554
555 const UInt32 kZeroBufSize = (1 << 14);
556 CByteBuffer zeroBuf(kZeroBufSize);
557 memset(zeroBuf, 0, kZeroBufSize);
558
559 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
560 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
561 1074
562 NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder(); 1075 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
563 CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec;
564
565 NCompress::NBZip2::CDecoder *bzip2CoderSpec = new NCompress::NBZip2::CDecoder();
566 CMyComPtr<ICompressCoder> bzip2Coder = bzip2CoderSpec;
567
568 NCompress::NDeflate::NDecoder::CCOMCoder *deflateCoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder();
569 CMyComPtr<ICompressCoder> deflateCoder = deflateCoderSpec;
570
571 CLocalProgress *lps = new CLocalProgress;
572 CMyComPtr<ICompressProgressInfo> progress = lps;
573 lps->Init(extractCallback, false); 1076 lps->Init(extractCallback, false);
574 1077 CInStreamWithHash inHashStream;
575 CLimitedSequentialInStream *inStreamSpec = new CLimitedSequentialInStream; 1078 CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSha1> outStreamSha1;
576 CMyComPtr<ISequentialInStream> inStream(inStreamSpec); 1079 CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSha256> outStreamSha256;
577 inStreamSpec->SetStream(_inStream); 1080 CMyComPtr2_Create<ISequentialOutStream, CLimitedSequentialOutStream> outStreamLim;
578 1081 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
1082 CMyComPtr2_Create<ICompressCoder, NCompress::NZlib::CDecoder> zlibCoder;
1083 CMyComPtr2_Create<ICompressCoder, NCompress::NBZip2::CDecoder> bzip2Coder;
1084 bzip2Coder->FinishMode = true;
579 1085
580 CLimitedSequentialOutStream *outStreamLimSpec = new CLimitedSequentialOutStream; 1086 UInt64 cur_PackSize, cur_UnpSize;
581 CMyComPtr<ISequentialOutStream> outStream(outStreamLimSpec);
582 1087
583 COutStreamWithSha1 *outStreamSha1Spec = new COutStreamWithSha1; 1088 for (i = 0;; i++,
1089 lps->InSize += cur_PackSize,
1090 lps->OutSize += cur_UnpSize)
584 { 1091 {
585 CMyComPtr<ISequentialOutStream> outStreamSha1(outStreamSha1Spec); 1092 cur_PackSize = 0;
586 outStreamLimSpec->SetStream(outStreamSha1); 1093 cur_UnpSize = 0;
587 }
588
589 for (i = 0; i < numItems; i++, currentPackTotal += currentPackSize, currentUnpTotal += currentUnpSize)
590 {
591 lps->InSize = currentPackTotal;
592 lps->OutSize = currentUnpTotal;
593 currentPackSize = 0;
594 currentUnpSize = 0;
595 RINOK(lps->SetCur()) 1094 RINOK(lps->SetCur())
1095 if (i >= numItems)
1096 break;
1097
596 CMyComPtr<ISequentialOutStream> realOutStream; 1098 CMyComPtr<ISequentialOutStream> realOutStream;
597 const Int32 askMode = testMode ? 1099 const Int32 askMode = testMode ?
598 NExtract::NAskMode::kTest : 1100 NExtract::NAskMode::kTest :
@@ -606,6 +1108,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
606 if (item.IsDir) 1108 if (item.IsDir)
607 { 1109 {
608 RINOK(extractCallback->PrepareOperation(askMode)) 1110 RINOK(extractCallback->PrepareOperation(askMode))
1111 realOutStream.Release();
609 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 1112 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
610 continue; 1113 continue;
611 } 1114 }
@@ -615,39 +1118,63 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
615 continue; 1118 continue;
616 RINOK(extractCallback->PrepareOperation(askMode)) 1119 RINOK(extractCallback->PrepareOperation(askMode))
617 1120
618 outStreamSha1Spec->SetStream(realOutStream);
619 realOutStream.Release();
620
621 Int32 opRes = NExtract::NOperationResult::kOK; 1121 Int32 opRes = NExtract::NOperationResult::kOK;
622 #ifdef XAR_SHOW_RAW 1122
623 if (index == _files.Size()) 1123#ifdef XAR_SHOW_RAW
1124 if (index >= _files.Size())
624 { 1125 {
625 outStreamSha1Spec->Init(false); 1126 cur_PackSize = cur_UnpSize = _xmlLen;
626 outStreamLimSpec->Init(_xmlLen); 1127 if (realOutStream)
627 RINOK(WriteStream(outStream, _xml, _xmlLen)) 1128 RINOK(WriteStream(realOutStream, _xmlBuf, _xmlLen))
628 currentPackSize = currentUnpSize = _xmlLen; 1129 realOutStream.Release();
629 } 1130 }
630 else 1131 else
631 #endif 1132#endif
632 { 1133 {
633 const CFile &item = _files[index]; 1134 const CFile &item = _files[index];
634 if (item.HasData) 1135 if (!item.HasData)
1136 realOutStream.Release();
1137 else
635 { 1138 {
636 currentPackSize = item.PackSize; 1139 cur_PackSize = item.PackSize;
637 currentUnpSize = item.Size; 1140 cur_UnpSize = item.Size;
638 1141
639 RINOK(InStream_SeekSet(_inStream, _dataStartPos + item.Offset)) 1142 RINOK(InStream_SeekSet(_inStream, _dataStartPos + item.Offset))
640 inStreamSpec->Init(item.PackSize); 1143
641 outStreamSha1Spec->Init(item.Sha1IsDefined); 1144 inHashStream.SetStreamAndInit(_inStream, item.archived_checksum.AlgoNumber);
642 outStreamLimSpec->Init(item.Size); 1145 inHashStream.inStreamLim->Init(item.PackSize);
1146
1147 const int checksum_method = item.extracted_checksum.AlgoNumber;
1148 if (checksum_method == XAR_CKSUM_SHA1)
1149 {
1150 outStreamLim->SetStream(outStreamSha1);
1151 outStreamSha1->SetStream(realOutStream);
1152 outStreamSha1->Init();
1153 }
1154 else if (checksum_method == XAR_CKSUM_SHA256)
1155 {
1156 outStreamLim->SetStream(outStreamSha256);
1157 outStreamSha256->SetStream(realOutStream);
1158 outStreamSha256->Init();
1159 }
1160 else
1161 outStreamLim->SetStream(realOutStream);
1162
1163 realOutStream.Release();
1164
1165 // outStreamSha1->Init(item.Sha1IsDefined);
1166
1167 outStreamLim->Init(item.Size);
643 HRESULT res = S_OK; 1168 HRESULT res = S_OK;
644 1169
645 ICompressCoder *coder = NULL; 1170 ICompressCoder *coder = NULL;
646 if (item.IsCopyMethod()) 1171 if (item.IsCopyMethod())
1172 {
647 if (item.PackSize == item.Size) 1173 if (item.PackSize == item.Size)
648 coder = copyCoder; 1174 coder = copyCoder;
649 else 1175 else
650 opRes = NExtract::NOperationResult::kUnsupportedMethod; 1176 opRes = NExtract::NOperationResult::kUnsupportedMethod;
1177 }
651 else if (item.Method == METHOD_NAME_ZLIB) 1178 else if (item.Method == METHOD_NAME_ZLIB)
652 coder = zlibCoder; 1179 coder = zlibCoder;
653 else if (item.Method == "bzip2") 1180 else if (item.Method == "bzip2")
@@ -656,11 +1183,11 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
656 opRes = NExtract::NOperationResult::kUnsupportedMethod; 1183 opRes = NExtract::NOperationResult::kUnsupportedMethod;
657 1184
658 if (coder) 1185 if (coder)
659 res = coder->Code(inStream, outStream, NULL, NULL, progress); 1186 res = coder->Code(inHashStream.inStreamLim, outStreamLim, NULL, &item.Size, lps);
660 1187
661 if (res != S_OK) 1188 if (res != S_OK)
662 { 1189 {
663 if (!outStreamLimSpec->IsFinishedOK()) 1190 if (!outStreamLim->IsFinishedOK())
664 opRes = NExtract::NOperationResult::kDataError; 1191 opRes = NExtract::NOperationResult::kDataError;
665 else if (res != S_FALSE) 1192 else if (res != S_FALSE)
666 return res; 1193 return res;
@@ -670,27 +1197,38 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
670 1197
671 if (opRes == NExtract::NOperationResult::kOK) 1198 if (opRes == NExtract::NOperationResult::kOK)
672 { 1199 {
673 if (outStreamLimSpec->IsFinishedOK() && 1200 if (outStreamLim->IsFinishedOK())
674 outStreamSha1Spec->GetSize() == item.Size)
675 { 1201 {
676 if (!outStreamLimSpec->IsFinishedOK()) 1202 if (checksum_method == XAR_CKSUM_SHA1)
677 { 1203 {
678 opRes = NExtract::NOperationResult::kDataError; 1204 Byte digest[SHA1_DIGEST_SIZE];
1205 outStreamSha1->Final(digest);
1206 if (memcmp(digest, item.extracted_checksum.Data, SHA1_DIGEST_SIZE) != 0)
1207 opRes = NExtract::NOperationResult::kCRCError;
679 } 1208 }
680 else if (item.Sha1IsDefined) 1209 else if (checksum_method == XAR_CKSUM_SHA256)
681 { 1210 {
682 Byte digest[SHA1_DIGEST_SIZE]; 1211 Byte digest[SHA256_DIGEST_SIZE];
683 outStreamSha1Spec->Final(digest); 1212 outStreamSha256->Final(digest);
684 if (memcmp(digest, item.Sha1, SHA1_DIGEST_SIZE) != 0) 1213 if (memcmp(digest, item.extracted_checksum.Data, SHA256_DIGEST_SIZE) != 0)
685 opRes = NExtract::NOperationResult::kCRCError; 1214 opRes = NExtract::NOperationResult::kCRCError;
686 } 1215 }
1216 if (opRes == NExtract::NOperationResult::kOK)
1217 if (!inHashStream.CheckHash(
1218 item.archived_checksum.AlgoNumber,
1219 item.archived_checksum.Data))
1220 opRes = NExtract::NOperationResult::kCRCError;
687 } 1221 }
688 else 1222 else
689 opRes = NExtract::NOperationResult::kDataError; 1223 opRes = NExtract::NOperationResult::kDataError;
690 } 1224 }
1225 if (checksum_method == XAR_CKSUM_SHA1)
1226 outStreamSha1->ReleaseStream();
1227 else if (checksum_method == XAR_CKSUM_SHA256)
1228 outStreamSha256->ReleaseStream();
691 } 1229 }
1230 outStreamLim->ReleaseStream();
692 } 1231 }
693 outStreamSha1Spec->ReleaseStream();
694 RINOK(extractCallback->SetOperationResult(opRes)) 1232 RINOK(extractCallback->SetOperationResult(opRes))
695 } 1233 }
696 return S_OK; 1234 return S_OK;
@@ -701,14 +1239,14 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
701{ 1239{
702 *stream = NULL; 1240 *stream = NULL;
703 COM_TRY_BEGIN 1241 COM_TRY_BEGIN
704 #ifdef XAR_SHOW_RAW 1242#ifdef XAR_SHOW_RAW
705 if (index == _files.Size()) 1243 if (index >= _files.Size())
706 { 1244 {
707 Create_BufInStream_WithNewBuffer(_xml, _xmlLen, stream); 1245 Create_BufInStream_WithNewBuffer(_xmlBuf, _xmlLen, stream);
708 return S_OK; 1246 return S_OK;
709 } 1247 }
710 else 1248 else
711 #endif 1249#endif
712 { 1250 {
713 const CFile &item = _files[index]; 1251 const CFile &item = _files[index];
714 if (item.HasData && item.IsCopyMethod() && item.PackSize == item.Size) 1252 if (item.HasData && item.IsCopyMethod() && item.PackSize == item.Size)
@@ -718,7 +1256,12 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
718 COM_TRY_END 1256 COM_TRY_END
719} 1257}
720 1258
721static const Byte k_Signature[] = { 'x', 'a', 'r', '!', 0, 0x1C }; 1259// 0x1c == 28 is expected header size value for most archives.
1260// but we want to support another (rare case) headers sizes.
1261// so we must reduce signature to 4 or 5 bytes.
1262static const Byte k_Signature[] =
1263// { 'x', 'a', 'r', '!', 0, 0x1C, 0 };
1264 { 'x', 'a', 'r', '!', 0 };
722 1265
723REGISTER_ARC_I( 1266REGISTER_ARC_I(
724 "Xar", "xar pkg xip", NULL, 0xE1, 1267 "Xar", "xar pkg xip", NULL, 0xE1,
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
index 976817c..7ced4e1 100644
--- a/CPP/7zip/Archive/XzHandler.cpp
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -76,11 +76,15 @@ Z7_class_CHandler_final:
76 Z7_IFACE_COM7_IMP(IOutArchive) 76 Z7_IFACE_COM7_IMP(IOutArchive)
77 #endif 77 #endif
78 78
79 CXzStatInfo _stat; // it's stat from backward parsing
80 CXzStatInfo _stat2; // it's data from forward parsing, if the decoder was called
81 SRes _stat2_decode_SRes;
82 bool _stat_defined; 79 bool _stat_defined;
83 bool _stat2_defined; 80 bool _stat2_defined;
81 bool _isArc;
82 bool _needSeekToStart;
83 bool _firstBlockWasRead;
84 SRes _stat2_decode_SRes;
85
86 CXzStatInfo _stat; // it's stat from backward parsing
87 CXzStatInfo _stat2; // it's data from forward parsing, if the decoder was called
84 88
85 const CXzStatInfo *GetStat() const 89 const CXzStatInfo *GetStat() const
86 { 90 {
@@ -89,10 +93,6 @@ Z7_class_CHandler_final:
89 return NULL; 93 return NULL;
90 } 94 }
91 95
92 bool _isArc;
93 bool _needSeekToStart;
94 bool _firstBlockWasRead;
95
96 AString _methodsString; 96 AString _methodsString;
97 97
98 98
@@ -134,7 +134,7 @@ Z7_class_CHandler_final:
134 #endif 134 #endif
135 decoder._memUsage = _memUsage_Decompress; 135 decoder._memUsage = _memUsage_Decompress;
136 136
137 HRESULT hres = decoder.Decode(seqInStream, outStream, 137 const HRESULT hres = decoder.Decode(seqInStream, outStream,
138 NULL, // *outSizeLimit 138 NULL, // *outSizeLimit
139 true, // finishStream 139 true, // finishStream
140 progress); 140 progress);
@@ -151,6 +151,11 @@ Z7_class_CHandler_final:
151 } 151 }
152 } 152 }
153 153
154 if (hres == S_OK && progress)
155 {
156 // RINOK(
157 progress->SetRatioInfo(&decoder.Stat.InSize, &decoder.Stat.OutSize);
158 }
154 return hres; 159 return hres;
155 } 160 }
156 161
@@ -207,17 +212,6 @@ static const Byte kArcProps[] =
207IMP_IInArchive_Props 212IMP_IInArchive_Props
208IMP_IInArchive_ArcProps 213IMP_IInArchive_ArcProps
209 214
210static inline char GetHex(unsigned value)
211{
212 return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
213}
214
215static inline void AddHexToString(AString &s, Byte value)
216{
217 s += GetHex(value >> 4);
218 s += GetHex(value & 0xF);
219}
220
221static void Lzma2PropToString(AString &s, unsigned prop) 215static void Lzma2PropToString(AString &s, unsigned prop)
222{ 216{
223 char c = 0; 217 char c = 0;
@@ -236,7 +230,7 @@ static void Lzma2PropToString(AString &s, unsigned prop)
236 } 230 }
237 s.Add_UInt32(size); 231 s.Add_UInt32(size);
238 if (c != 0) 232 if (c != 0)
239 s += c; 233 s.Add_Char(c);
240} 234}
241 235
242struct CMethodNamePair 236struct CMethodNamePair
@@ -256,6 +250,7 @@ static const CMethodNamePair g_NamePairs[] =
256 { XZ_ID_ARMT, "ARMT" }, 250 { XZ_ID_ARMT, "ARMT" },
257 { XZ_ID_SPARC, "SPARC" }, 251 { XZ_ID_SPARC, "SPARC" },
258 { XZ_ID_ARM64, "ARM64" }, 252 { XZ_ID_ARM64, "ARM64" },
253 { XZ_ID_RISCV, "RISCV" },
259 { XZ_ID_LZMA2, "LZMA2" } 254 { XZ_ID_LZMA2, "LZMA2" }
260}; 255};
261 256
@@ -279,7 +274,7 @@ static void AddMethodString(AString &s, const CXzFilter &f)
279 274
280 if (f.propsSize > 0) 275 if (f.propsSize > 0)
281 { 276 {
282 s += ':'; 277 s.Add_Colon();
283 if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) 278 if (f.id == XZ_ID_LZMA2 && f.propsSize == 1)
284 Lzma2PropToString(s, f.props[0]); 279 Lzma2PropToString(s, f.props[0]);
285 else if (f.id == XZ_ID_Delta && f.propsSize == 1) 280 else if (f.id == XZ_ID_Delta && f.propsSize == 1)
@@ -288,10 +283,14 @@ static void AddMethodString(AString &s, const CXzFilter &f)
288 s.Add_UInt32((UInt32)f.props[0] + 16 + 2); 283 s.Add_UInt32((UInt32)f.props[0] + 16 + 2);
289 else 284 else
290 { 285 {
291 s += '['; 286 s.Add_Char('[');
292 for (UInt32 bi = 0; bi < f.propsSize; bi++) 287 for (UInt32 bi = 0; bi < f.propsSize; bi++)
293 AddHexToString(s, f.props[bi]); 288 {
294 s += ']'; 289 const unsigned v = f.props[bi];
290 s.Add_Char(GET_HEX_CHAR_UPPER(v >> 4));
291 s.Add_Char(GET_HEX_CHAR_UPPER(v & 15));
292 }
293 s.Add_Char(']');
295 } 294 }
296 } 295 }
297} 296}
@@ -387,6 +386,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
387 // if (_blocks) prop = (UInt32)0; 386 // if (_blocks) prop = (UInt32)0;
388 break; 387 break;
389 } 388 }
389 default: break;
390 } 390 }
391 prop.Detach(value); 391 prop.Detach(value);
392 return S_OK; 392 return S_OK;
@@ -409,6 +409,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value))
409 case kpidSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; 409 case kpidSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break;
410 case kpidPackSize: if (stat) prop = stat->InSize; break; 410 case kpidPackSize: if (stat) prop = stat->InSize; break;
411 case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; 411 case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
412 default: break;
412 } 413 }
413 prop.Detach(value); 414 prop.Detach(value);
414 return S_OK; 415 return S_OK;
@@ -488,6 +489,7 @@ static HRESULT SRes_to_Open_HRESULT(SRes res)
488 case SZ_ERROR_NO_ARCHIVE: 489 case SZ_ERROR_NO_ARCHIVE:
489 return S_FALSE; 490 return S_FALSE;
490 */ 491 */
492 default: break;
491 } 493 }
492 return S_FALSE; 494 return S_FALSE;
493} 495}
@@ -737,11 +739,9 @@ CXzUnpackerCPP2::~CXzUnpackerCPP2()
737} 739}
738 740
739 741
740Z7_CLASS_IMP_COM_1( 742Z7_CLASS_IMP_IInStream(
741 CInStream 743 CInStream
742 , IInStream
743) 744)
744 Z7_IFACE_COM7_IMP(ISequentialInStream)
745 745
746 UInt64 _virtPos; 746 UInt64 _virtPos;
747public: 747public:
@@ -760,9 +760,7 @@ public:
760 // _startPos = startPos; 760 // _startPos = startPos;
761 } 761 }
762 762
763 CHandler *_handlerSpec; 763 CMyComPtr2<IInArchive, CHandler> _handlerSpec;
764 CMyComPtr<IUnknown> _handler;
765
766 // ~CInStream(); 764 // ~CInStream();
767}; 765};
768 766
@@ -922,7 +920,7 @@ Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
922 const size_t rem = _cacheSize - offset; 920 const size_t rem = _cacheSize - offset;
923 if (size > rem) 921 if (size > rem)
924 size = (UInt32)rem; 922 size = (UInt32)rem;
925 memcpy(data, _cache + offset, size); 923 memcpy(data, _cache.ConstData() + offset, size);
926 _virtPos += size; 924 _virtPos += size;
927 if (processedSize) 925 if (processedSize)
928 *processedSize = size; 926 *processedSize = size;
@@ -977,15 +975,15 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
977 return S_FALSE; 975 return S_FALSE;
978 } 976 }
979 977
980 CInStream *spec = new CInStream; 978 CMyComPtr2<ISequentialInStream, CInStream> spec;
981 CMyComPtr<ISequentialInStream> specStream = spec; 979 spec.Create_if_Empty();
982 spec->_cache.Alloc((size_t)_maxBlocksSize); 980 spec->_cache.Alloc((size_t)_maxBlocksSize);
983 spec->_handlerSpec = this; 981 spec->_handlerSpec.SetFromCls(this);
984 spec->_handler = (IInArchive *)this; 982 // spec->_handler = (IInArchive *)this;
985 spec->Size = _stat.OutSize; 983 spec->Size = _stat.OutSize;
986 spec->InitAndSeek(); 984 spec->InitAndSeek();
987 985
988 *stream = specStream.Detach(); 986 *stream = spec.Detach();
989 return S_OK; 987 return S_OK;
990 988
991 COM_TRY_END 989 COM_TRY_END
@@ -1032,10 +1030,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1032 const CXzStatInfo *stat = GetStat(); 1030 const CXzStatInfo *stat = GetStat();
1033 1031
1034 if (stat) 1032 if (stat)
1035 extractCallback->SetTotal(stat->InSize); 1033 RINOK(extractCallback->SetTotal(stat->InSize))
1036 1034
1037 UInt64 currentTotalPacked = 0; 1035 UInt64 currentTotalPacked = 0;
1038 RINOK(extractCallback->SetCompleted(&currentTotalPacked)) 1036 RINOK(extractCallback->SetCompleted(&currentTotalPacked))
1037 Int32 opRes;
1038 {
1039 CMyComPtr<ISequentialOutStream> realOutStream; 1039 CMyComPtr<ISequentialOutStream> realOutStream;
1040 const Int32 askMode = testMode ? 1040 const Int32 askMode = testMode ?
1041 NExtract::NAskMode::kTest : 1041 NExtract::NAskMode::kTest :
@@ -1046,10 +1046,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1046 if (!testMode && !realOutStream) 1046 if (!testMode && !realOutStream)
1047 return S_OK; 1047 return S_OK;
1048 1048
1049 extractCallback->PrepareOperation(askMode); 1049 RINOK(extractCallback->PrepareOperation(askMode))
1050 1050
1051 CLocalProgress *lps = new CLocalProgress; 1051 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1052 CMyComPtr<ICompressProgressInfo> lpsRef = lps;
1053 lps->Init(extractCallback, true); 1052 lps->Init(extractCallback, true);
1054 1053
1055 if (_needSeekToStart) 1054 if (_needSeekToStart)
@@ -1064,17 +1063,18 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1064 1063
1065 NCompress::NXz::CDecoder decoder; 1064 NCompress::NXz::CDecoder decoder;
1066 1065
1067 HRESULT hres = Decode(decoder, _seqStream, realOutStream, lpsRef); 1066 const HRESULT hres = Decode(decoder, _seqStream, realOutStream, lps);
1068 1067
1069 if (!decoder.MainDecodeSRes_wasUsed) 1068 if (!decoder.MainDecodeSRes_wasUsed)
1070 return hres == S_OK ? E_FAIL : hres; 1069 return hres == S_OK ? E_FAIL : hres;
1071 1070
1072 Int32 opRes = Get_Extract_OperationResult(decoder); 1071 opRes = Get_Extract_OperationResult(decoder);
1073 if (opRes == NExtract::NOperationResult::kOK 1072 if (opRes == NExtract::NOperationResult::kOK
1074 && hres != S_OK) 1073 && hres != S_OK)
1075 opRes = NExtract::NOperationResult::kDataError; 1074 opRes = NExtract::NOperationResult::kDataError;
1076 1075
1077 realOutStream.Release(); 1076 // realOutStream.Release();
1077 }
1078 return extractCallback->SetOperationResult(opRes); 1078 return extractCallback->SetOperationResult(opRes);
1079 COM_TRY_END 1079 COM_TRY_END
1080} 1080}
@@ -1143,10 +1143,9 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1143 dataSize = prop.uhVal.QuadPart; 1143 dataSize = prop.uhVal.QuadPart;
1144 } 1144 }
1145 1145
1146 NCompress::NXz::CEncoder *encoderSpec = new NCompress::NXz::CEncoder; 1146 CMyComPtr2_Create<ICompressCoder, NCompress::NXz::CEncoder> encoder;
1147 CMyComPtr<ICompressCoder> encoder = encoderSpec;
1148 1147
1149 CXzProps &xzProps = encoderSpec->xzProps; 1148 CXzProps &xzProps = encoder->xzProps;
1150 CLzma2EncProps &lzma2Props = xzProps.lzma2Props; 1149 CLzma2EncProps &lzma2Props = xzProps.lzma2Props;
1151 1150
1152 lzma2Props.lzmaProps.level = GetLevel(); 1151 lzma2Props.lzmaProps.level = GetLevel();
@@ -1155,7 +1154,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1155 /* 1154 /*
1156 { 1155 {
1157 NCOM::CPropVariant prop = (UInt64)dataSize; 1156 NCOM::CPropVariant prop = (UInt64)dataSize;
1158 RINOK(encoderSpec->SetCoderProp(NCoderPropID::kReduceSize, prop)) 1157 RINOK(encoder->SetCoderProp(NCoderPropID::kReduceSize, prop))
1159 } 1158 }
1160 */ 1159 */
1161 1160
@@ -1231,7 +1230,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1231 xzProps.lzma2Props.blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID; 1230 xzProps.lzma2Props.blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID;
1232 } 1231 }
1233 1232
1234 RINOK(encoderSpec->SetCheckSize(_crcSize)) 1233 RINOK(encoder->SetCheckSize(_crcSize))
1235 1234
1236 { 1235 {
1237 CXzFilterProps &filter = xzProps.filterProps; 1236 CXzFilterProps &filter = xzProps.filterProps;
@@ -1266,7 +1265,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1266 FOR_VECTOR (j, m.Props) 1265 FOR_VECTOR (j, m.Props)
1267 { 1266 {
1268 const CProp &prop = m.Props[j]; 1267 const CProp &prop = m.Props[j];
1269 RINOK(encoderSpec->SetCoderProp(prop.Id, prop.Value)) 1268 RINOK(encoder->SetCoderProp(prop.Id, prop.Value))
1270 } 1269 }
1271 } 1270 }
1272 1271
@@ -1286,10 +1285,9 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1286 } 1285 }
1287 } 1286 }
1288 RINOK(updateCallback->SetTotal(dataSize)) 1287 RINOK(updateCallback->SetTotal(dataSize))
1289 CLocalProgress *lps = new CLocalProgress; 1288 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1290 CMyComPtr<ICompressProgressInfo> progress = lps;
1291 lps->Init(updateCallback, true); 1289 lps->Init(updateCallback, true);
1292 RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress)) 1290 RINOK(encoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps))
1293 } 1291 }
1294 1292
1295 return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); 1293 return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
@@ -1316,11 +1314,10 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1316 RINOK(InStream_SeekToBegin(_stream)) 1314 RINOK(InStream_SeekToBegin(_stream))
1317 } 1315 }
1318 1316
1319 CLocalProgress *lps = new CLocalProgress; 1317 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1320 CMyComPtr<ICompressProgressInfo> progress = lps;
1321 lps->Init(updateCallback, true); 1318 lps->Init(updateCallback, true);
1322 1319
1323 return NCompress::CopyStream(_stream, outStream, progress); 1320 return NCompress::CopyStream(_stream, outStream, lps);
1324 1321
1325 COM_TRY_END 1322 COM_TRY_END
1326} 1323}
diff --git a/CPP/7zip/Archive/ZHandler.cpp b/CPP/7zip/Archive/ZHandler.cpp
index 18e712a..1caef34 100644
--- a/CPP/7zip/Archive/ZHandler.cpp
+++ b/CPP/7zip/Archive/ZHandler.cpp
@@ -89,7 +89,7 @@ API_FUNC_static_IsArc IsArc_Z(const Byte *p, size_t size)
89 if (size < 3) 89 if (size < 3)
90 return k_IsArc_Res_NEED_MORE; 90 return k_IsArc_Res_NEED_MORE;
91 if (size > NCompress::NZ::kRecommendedCheckSize) 91 if (size > NCompress::NZ::kRecommendedCheckSize)
92 size = NCompress::NZ::kRecommendedCheckSize; 92 size = NCompress::NZ::kRecommendedCheckSize;
93 if (!NCompress::NZ::CheckStream(p, size)) 93 if (!NCompress::NZ::CheckStream(p, size))
94 return k_IsArc_Res_NO; 94 return k_IsArc_Res_NO;
95 return k_IsArc_Res_YES; 95 return k_IsArc_Res_YES;
@@ -166,13 +166,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
166 return S_OK; 166 return S_OK;
167 if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) 167 if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
168 return E_INVALIDARG; 168 return E_INVALIDARG;
169 169 RINOK(extractCallback->SetTotal(_packSize))
170 extractCallback->SetTotal(_packSize);
171
172 UInt64 currentTotalPacked = 0; 170 UInt64 currentTotalPacked = 0;
173
174 RINOK(extractCallback->SetCompleted(&currentTotalPacked)) 171 RINOK(extractCallback->SetCompleted(&currentTotalPacked))
175 172
173 int opRes;
174 {
176 CMyComPtr<ISequentialOutStream> realOutStream; 175 CMyComPtr<ISequentialOutStream> realOutStream;
177 const Int32 askMode = testMode ? 176 const Int32 askMode = testMode ?
178 NExtract::NAskMode::kTest : 177 NExtract::NAskMode::kTest :
@@ -183,37 +182,33 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
183 if (!testMode && !realOutStream) 182 if (!testMode && !realOutStream)
184 return S_OK; 183 return S_OK;
185 184
186 extractCallback->PrepareOperation(askMode); 185 RINOK(extractCallback->PrepareOperation(askMode))
187 186
188 CDummyOutStream *outStreamSpec = new CDummyOutStream; 187 CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;
189 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); 188 outStream->SetStream(realOutStream);
190 outStreamSpec->SetStream(realOutStream); 189 outStream->Init();
191 outStreamSpec->Init(); 190 // realOutStream.Release();
192 realOutStream.Release();
193 191
194 CLocalProgress *lps = new CLocalProgress; 192 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
195 CMyComPtr<ICompressProgressInfo> progress = lps;
196 lps->Init(extractCallback, true); 193 lps->Init(extractCallback, true);
197 194
198 RINOK(InStream_SeekToBegin(_stream)) 195 RINOK(InStream_SeekToBegin(_stream))
199 196
200 NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder; 197 NCompress::NZ::CDecoder decoder;
201 CMyComPtr<ICompressCoder> decoder = decoderSpec;
202
203 int opRes;
204 { 198 {
205 HRESULT result = decoder->Code(_stream, outStream, NULL, NULL, progress); 199 const HRESULT hres = decoder.Code(_stream, outStream, lps);
206 if (result == S_FALSE) 200 if (hres == S_FALSE)
207 opRes = NExtract::NOperationResult::kDataError; 201 opRes = NExtract::NOperationResult::kDataError;
208 else 202 else
209 { 203 {
210 RINOK(result) 204 RINOK(hres)
211 opRes = NExtract::NOperationResult::kOK; 205 opRes = NExtract::NOperationResult::kOK;
212 } 206 }
213 } 207 }
214 // _unpackSize = outStreamSpec->GetSize(); 208 // _unpackSize = outStreamSpec->GetSize();
215 // _unpackSize_Defined = true; 209 // _unpackSize_Defined = true;
216 outStream.Release(); 210 // outStream.Release();
211 }
217 return extractCallback->SetOperationResult(opRes); 212 return extractCallback->SetOperationResult(opRes);
218 COM_TRY_END 213 COM_TRY_END
219} 214}
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
index 8af84b4..43d68c7 100644
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
@@ -40,24 +40,18 @@ Z7_CLASS_IMP_NOQIB_3(
40 , ICompressSetCoderPropertiesOpt 40 , ICompressSetCoderPropertiesOpt
41) 41)
42public: 42public:
43 NCompress::NLzma::CEncoder *EncoderSpec; 43 CMyComPtr2<ICompressCoder, NCompress::NLzma::CEncoder> Encoder;
44 CMyComPtr<ICompressCoder> Encoder;
45 Byte Header[kLzmaHeaderSize]; 44 Byte Header[kLzmaHeaderSize];
46}; 45};
47 46
48Z7_COM7F_IMF(CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)) 47Z7_COM7F_IMF(CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))
49{ 48{
50 if (!Encoder) 49 Encoder.Create_if_Empty();
51 { 50 CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStream;
52 EncoderSpec = new NCompress::NLzma::CEncoder; 51 outStream->Init(Header + 4, kLzmaPropsSize);
53 Encoder = EncoderSpec; 52 RINOK(Encoder->SetCoderProperties(propIDs, props, numProps))
54 } 53 RINOK(Encoder->WriteCoderProperties(outStream))
55 CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; 54 if (outStream->GetPos() != kLzmaPropsSize)
56 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
57 outStreamSpec->Init(Header + 4, kLzmaPropsSize);
58 RINOK(EncoderSpec->SetCoderProperties(propIDs, props, numProps))
59 RINOK(EncoderSpec->WriteCoderProperties(outStream))
60 if (outStreamSpec->GetPos() != kLzmaPropsSize)
61 return E_FAIL; 55 return E_FAIL;
62 Header[0] = MY_VER_MAJOR; 56 Header[0] = MY_VER_MAJOR;
63 Header[1] = MY_VER_MINOR; 57 Header[1] = MY_VER_MINOR;
@@ -68,21 +62,19 @@ Z7_COM7F_IMF(CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPV
68 62
69Z7_COM7F_IMF(CLzmaEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)) 63Z7_COM7F_IMF(CLzmaEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))
70{ 64{
71 return EncoderSpec->SetCoderPropertiesOpt(propIDs, props, numProps); 65 return Encoder->SetCoderPropertiesOpt(propIDs, props, numProps);
72} 66}
73 67
74Z7_COM7F_IMF(CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 68Z7_COM7F_IMF(CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
75 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)) 69 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
76{ 70{
77 RINOK(WriteStream(outStream, Header, kLzmaHeaderSize)) 71 RINOK(WriteStream(outStream, Header, kLzmaHeaderSize))
78 return Encoder->Code(inStream, outStream, inSize, outSize, progress); 72 return Encoder.Interface()->Code(inStream, outStream, inSize, outSize, progress);
79} 73}
80 74
81 75
82CAddCommon::CAddCommon(): 76CAddCommon::CAddCommon():
83 _copyCoderSpec(NULL),
84 _isLzmaEos(false), 77 _isLzmaEos(false),
85 _cryptoStreamSpec(NULL),
86 _buf(NULL) 78 _buf(NULL)
87 {} 79 {}
88 80
@@ -181,9 +173,10 @@ HRESULT CAddCommon::Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, U
181 opRes.LzmaEos = oneMethodMain->Get_Lzma_Eos(); 173 opRes.LzmaEos = oneMethodMain->Get_Lzma_Eos();
182 break; 174 break;
183 } 175 }
176 default: break;
184 } 177 }
185 if (opRes.ExtractVersion < ver) 178 if (opRes.ExtractVersion < ver)
186 opRes.ExtractVersion = ver; 179 opRes.ExtractVersion = ver;
187 180
188 return S_OK; 181 return S_OK;
189} 182}
@@ -205,8 +198,7 @@ HRESULT CAddCommon::Compress(
205 return E_INVALIDARG; 198 return E_INVALIDARG;
206 } 199 }
207 200
208 CSequentialInStreamWithCRC *inSecCrcStreamSpec = new CSequentialInStreamWithCRC; 201 CMyComPtr2_Create<ISequentialInStream, CSequentialInStreamWithCRC> inCrcStream;
209 CMyComPtr<ISequentialInStream> inCrcStream = inSecCrcStreamSpec;
210 202
211 CMyComPtr<IInStream> inStream2; 203 CMyComPtr<IInStream> inStream2;
212 if (!inSeqMode) 204 if (!inSeqMode)
@@ -220,9 +212,9 @@ HRESULT CAddCommon::Compress(
220 } 212 }
221 } 213 }
222 214
223 inSecCrcStreamSpec->SetStream(inStream); 215 inCrcStream->SetStream(inStream);
224 inSecCrcStreamSpec->SetFullSize(expectedDataSize_IsConfirmed ? expectedDataSize : (UInt64)(Int64)-1); 216 inCrcStream->SetFullSize(expectedDataSize_IsConfirmed ? expectedDataSize : (UInt64)(Int64)-1);
225 // inSecCrcStreamSpec->Init(); 217 // inCrcStream->Init();
226 218
227 unsigned numTestMethods = _options.MethodSequence.Size(); 219 unsigned numTestMethods = _options.MethodSequence.Size();
228 // numTestMethods != 0 220 // numTestMethods != 0
@@ -250,7 +242,7 @@ HRESULT CAddCommon::Compress(
250 242
251 for (unsigned i = 0; i < numTestMethods; i++) 243 for (unsigned i = 0; i < numTestMethods; i++)
252 { 244 {
253 inSecCrcStreamSpec->Init(); 245 inCrcStream->Init();
254 246
255 if (i != 0) 247 if (i != 0)
256 { 248 {
@@ -278,18 +270,15 @@ HRESULT CAddCommon::Compress(
278 { 270 {
279 opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto; 271 opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto;
280 272
281 if (!_cryptoStream) 273 if (!_cryptoStream.IsDefined())
282 { 274 _cryptoStream.SetFromCls(new CFilterCoder(true));
283 _cryptoStreamSpec = new CFilterCoder(true);
284 _cryptoStream = _cryptoStreamSpec;
285 }
286 275
287 if (_options.IsAesMode) 276 if (_options.IsAesMode)
288 { 277 {
289 opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes; 278 opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes;
290 if (!_cryptoStreamSpec->Filter) 279 if (!_cryptoStream->Filter)
291 { 280 {
292 _cryptoStreamSpec->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder; 281 _cryptoStream->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder;
293 _filterAesSpec->SetKeyMode(_options.AesKeyMode); 282 _filterAesSpec->SetKeyMode(_options.AesKeyMode);
294 RINOK(_filterAesSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len())) 283 RINOK(_filterAesSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len()))
295 } 284 }
@@ -297,9 +286,9 @@ HRESULT CAddCommon::Compress(
297 } 286 }
298 else 287 else
299 { 288 {
300 if (!_cryptoStreamSpec->Filter) 289 if (!_cryptoStream->Filter)
301 { 290 {
302 _cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder; 291 _cryptoStream->Filter = _filterSpec = new NCrypto::NZip::CEncoder;
303 _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len()); 292 _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len());
304 } 293 }
305 294
@@ -317,7 +306,7 @@ HRESULT CAddCommon::Compress(
317 RINOK(CalcStreamCRC(inStream, crc)) 306 RINOK(CalcStreamCRC(inStream, crc))
318 crc_IsCalculated = true; 307 crc_IsCalculated = true;
319 RINOK(InStream_SeekToBegin(inStream2)) 308 RINOK(InStream_SeekToBegin(inStream2))
320 inSecCrcStreamSpec->Init(); 309 inCrcStream->Init();
321 } 310 }
322 check = (crc >> 16); 311 check = (crc >> 16);
323 } 312 }
@@ -328,13 +317,13 @@ HRESULT CAddCommon::Compress(
328 if (method == NCompressionMethod::kStore) 317 if (method == NCompressionMethod::kStore)
329 { 318 {
330 needCode = false; 319 needCode = false;
331 RINOK(_cryptoStreamSpec->Code(inCrcStream, outStream, NULL, NULL, progress)) 320 RINOK(_cryptoStream->Code(inCrcStream, outStream, NULL, NULL, progress))
332 } 321 }
333 else 322 else
334 { 323 {
335 RINOK(_cryptoStreamSpec->SetOutStream(outStream)) 324 RINOK(_cryptoStream->SetOutStream(outStream))
336 RINOK(_cryptoStreamSpec->InitEncoder()) 325 RINOK(_cryptoStream->InitEncoder())
337 outStreamReleaser.FilterCoder = _cryptoStreamSpec; 326 outStreamReleaser.FilterCoder = _cryptoStream.ClsPtr();
338 } 327 }
339 } 328 }
340 329
@@ -344,17 +333,13 @@ HRESULT CAddCommon::Compress(
344 { 333 {
345 case NCompressionMethod::kStore: 334 case NCompressionMethod::kStore:
346 { 335 {
347 if (!_copyCoderSpec) 336 _copyCoder.Create_if_Empty();
348 {
349 _copyCoderSpec = new NCompress::CCopyCoder;
350 _copyCoder = _copyCoderSpec;
351 }
352 CMyComPtr<ISequentialOutStream> outStreamNew; 337 CMyComPtr<ISequentialOutStream> outStreamNew;
353 if (_options.Password_Defined) 338 if (_options.Password_Defined)
354 outStreamNew = _cryptoStream; 339 outStreamNew = _cryptoStream;
355 else 340 else
356 outStreamNew = outStream; 341 outStreamNew = outStream;
357 RINOK(_copyCoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress)) 342 RINOK(_copyCoder.Interface()->Code(inCrcStream, outStreamNew, NULL, NULL, progress))
358 break; 343 break;
359 } 344 }
360 345
@@ -426,7 +411,7 @@ HRESULT CAddCommon::Compress(
426 } 411 }
427 } 412 }
428 if (method == NCompressionMethod::kLZMA) 413 if (method == NCompressionMethod::kLZMA)
429 _isLzmaEos = _lzmaEncoder->EncoderSpec->IsWriteEndMark(); 414 _isLzmaEos = _lzmaEncoder->Encoder->IsWriteEndMark();
430 } 415 }
431 416
432 if (method == NCompressionMethod::kLZMA) 417 if (method == NCompressionMethod::kLZMA)
@@ -460,7 +445,7 @@ HRESULT CAddCommon::Compress(
460 445
461 if (_options.Password_Defined) 446 if (_options.Password_Defined)
462 { 447 {
463 RINOK(_cryptoStreamSpec->OutStreamFinish()) 448 RINOK(_cryptoStream->OutStreamFinish())
464 } 449 }
465 } 450 }
466 451
@@ -475,12 +460,12 @@ HRESULT CAddCommon::Compress(
475 RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize)) 460 RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize))
476 461
477 { 462 {
478 opRes.CRC = inSecCrcStreamSpec->GetCRC(); 463 opRes.CRC = inCrcStream->GetCRC();
479 opRes.UnpackSize = inSecCrcStreamSpec->GetSize(); 464 opRes.UnpackSize = inCrcStream->GetSize();
480 opRes.Method = method; 465 opRes.Method = method;
481 } 466 }
482 467
483 if (!inSecCrcStreamSpec->WasFinished()) 468 if (!inCrcStream->WasFinished())
484 return E_FAIL; 469 return E_FAIL;
485 470
486 if (_options.Password_Defined) 471 if (_options.Password_Defined)
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h
index 051915c..e72ec7b 100644
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.h
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h
@@ -39,15 +39,13 @@ struct CCompressingResult
39class CAddCommon MY_UNCOPYABLE 39class CAddCommon MY_UNCOPYABLE
40{ 40{
41 CCompressionMethodMode _options; 41 CCompressionMethodMode _options;
42 NCompress::CCopyCoder *_copyCoderSpec; 42 CMyComPtr2<ICompressCoder, NCompress::CCopyCoder> _copyCoder;
43 CMyComPtr<ICompressCoder> _copyCoder;
44 43
45 CMyComPtr<ICompressCoder> _compressEncoder; 44 CMyComPtr<ICompressCoder> _compressEncoder;
46 Byte _compressExtractVersion; 45 Byte _compressExtractVersion;
47 bool _isLzmaEos; 46 bool _isLzmaEos;
48 47
49 CFilterCoder *_cryptoStreamSpec; 48 CMyComPtr2<ISequentialOutStream, CFilterCoder> _cryptoStream;
50 CMyComPtr<ISequentialOutStream> _cryptoStream;
51 49
52 NCrypto::NZip::CEncoder *_filterSpec; 50 NCrypto::NZip::CEncoder *_filterSpec;
53 NCrypto::NWzAes::CEncoder *_filterAesSpec; 51 NCrypto::NWzAes::CEncoder *_filterAesSpec;
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp
index 5f022cc..c6b6e39 100644
--- a/CPP/7zip/Archive/Zip/ZipHandler.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp
@@ -18,22 +18,15 @@
18#include "../../Common/StreamUtils.h" 18#include "../../Common/StreamUtils.h"
19 19
20#include "../../Compress/CopyCoder.h" 20#include "../../Compress/CopyCoder.h"
21 21#ifndef Z7_ZIP_LZFSE_DISABLE
22#ifdef Z7_EXTERNAL_CODECS
23#ifndef SUPPORT_LZFSE
24#define SUPPORT_LZFSE
25#endif
26#endif
27
28#ifdef SUPPORT_LZFSE
29#include "../../Compress/LzfseDecoder.h" 22#include "../../Compress/LzfseDecoder.h"
30#endif 23#endif
31
32#include "../../Compress/LzmaDecoder.h" 24#include "../../Compress/LzmaDecoder.h"
33#include "../../Compress/ImplodeDecoder.h" 25#include "../../Compress/ImplodeDecoder.h"
34#include "../../Compress/PpmdZip.h" 26#include "../../Compress/PpmdZip.h"
35#include "../../Compress/ShrinkDecoder.h" 27#include "../../Compress/ShrinkDecoder.h"
36#include "../../Compress/XzDecoder.h" 28#include "../../Compress/XzDecoder.h"
29#include "../../Compress/ZstdDecoder.h"
37 30
38#include "../../Crypto/WzAes.h" 31#include "../../Crypto/WzAes.h"
39#include "../../Crypto/ZipCrypto.h" 32#include "../../Crypto/ZipCrypto.h"
@@ -341,6 +334,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
341 } 334 }
342 335
343 // case kpidIsAltStream: prop = true; break; 336 // case kpidIsAltStream: prop = true; break;
337 default: break;
344 } 338 }
345 return prop.Detach(value); 339 return prop.Detach(value);
346 COM_TRY_END 340 COM_TRY_END
@@ -546,7 +540,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
546 else 540 else
547 { 541 {
548 m += kMethod_StrongCrypto; 542 m += kMethod_StrongCrypto;
549 m += ':'; 543 m.Add_Colon();
550 m.Add_UInt32(f.AlgId); 544 m.Add_UInt32(f.AlgId);
551 } 545 }
552 if (f.CertificateIsUsed()) 546 if (f.CertificateIsUsed())
@@ -567,7 +561,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
567 s = kMethodNames1[id]; 561 s = kMethodNames1[id];
568 else 562 else
569 { 563 {
570 int id2 = (int)id - (int)kMethodNames2Start; 564 const int id2 = (int)id - (int)kMethodNames2Start;
571 if (id2 >= 0 && (unsigned)id2 < kNumMethodNames2) 565 if (id2 >= 0 && (unsigned)id2 < kNumMethodNames2)
572 s = kMethodNames2[id2]; 566 s = kMethodNames2[id2];
573 } 567 }
@@ -588,7 +582,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
588 } 582 }
589 else if (id == NFileHeader::NCompressionMethod::kDeflate) 583 else if (id == NFileHeader::NCompressionMethod::kDeflate)
590 { 584 {
591 m += ':'; 585 m.Add_Colon();
592 m += kDeflateLevels[level]; 586 m += kDeflateLevels[level];
593 level = 0; 587 level = 0;
594 } 588 }
@@ -684,6 +678,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
684 } 678 }
685 break; 679 break;
686 */ 680 */
681 default: break;
687 } 682 }
688 683
689 return prop.Detach(value); 684 return prop.Detach(value);
@@ -808,18 +803,9 @@ Z7_CLASS_IMP_NOQIB_3(
808 , ICompressGetInStreamProcessedSize 803 , ICompressGetInStreamProcessedSize
809) 804)
810public: 805public:
811 NCompress::NLzma::CDecoder *DecoderSpec; 806 CMyComPtr2_Create<ICompressCoder, NCompress::NLzma::CDecoder> Decoder;
812 CMyComPtr<ICompressCoder> Decoder;
813
814 CLzmaDecoder();
815}; 807};
816 808
817CLzmaDecoder::CLzmaDecoder()
818{
819 DecoderSpec = new NCompress::NLzma::CDecoder;
820 Decoder = DecoderSpec;
821}
822
823static const unsigned kZipLzmaPropsSize = 4 + LZMA_PROPS_SIZE; 809static const unsigned kZipLzmaPropsSize = 4 + LZMA_PROPS_SIZE;
824 810
825Z7_COM7F_IMF(CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 811Z7_COM7F_IMF(CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
@@ -829,7 +815,7 @@ Z7_COM7F_IMF(CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStr
829 RINOK(ReadStream_FALSE(inStream, buf, kZipLzmaPropsSize)) 815 RINOK(ReadStream_FALSE(inStream, buf, kZipLzmaPropsSize))
830 if (buf[2] != LZMA_PROPS_SIZE || buf[3] != 0) 816 if (buf[2] != LZMA_PROPS_SIZE || buf[3] != 0)
831 return E_NOTIMPL; 817 return E_NOTIMPL;
832 RINOK(DecoderSpec->SetDecoderProperties2(buf + 4, LZMA_PROPS_SIZE)) 818 RINOK(Decoder->SetDecoderProperties2(buf + 4, LZMA_PROPS_SIZE))
833 UInt64 inSize2 = 0; 819 UInt64 inSize2 = 0;
834 if (inSize) 820 if (inSize)
835 { 821 {
@@ -838,18 +824,18 @@ Z7_COM7F_IMF(CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStr
838 return S_FALSE; 824 return S_FALSE;
839 inSize2 -= kZipLzmaPropsSize; 825 inSize2 -= kZipLzmaPropsSize;
840 } 826 }
841 return Decoder->Code(inStream, outStream, inSize ? &inSize2 : NULL, outSize, progress); 827 return Decoder.Interface()->Code(inStream, outStream, inSize ? &inSize2 : NULL, outSize, progress);
842} 828}
843 829
844Z7_COM7F_IMF(CLzmaDecoder::SetFinishMode(UInt32 finishMode)) 830Z7_COM7F_IMF(CLzmaDecoder::SetFinishMode(UInt32 finishMode))
845{ 831{
846 DecoderSpec->FinishStream = (finishMode != 0); 832 Decoder->FinishStream = (finishMode != 0);
847 return S_OK; 833 return S_OK;
848} 834}
849 835
850Z7_COM7F_IMF(CLzmaDecoder::GetInStreamProcessedSize(UInt64 *value)) 836Z7_COM7F_IMF(CLzmaDecoder::GetInStreamProcessedSize(UInt64 *value))
851{ 837{
852 *value = DecoderSpec->GetInputProcessedSize() + kZipLzmaPropsSize; 838 *value = Decoder->GetInputProcessedSize() + kZipLzmaPropsSize;
853 return S_OK; 839 return S_OK;
854} 840}
855 841
@@ -869,26 +855,17 @@ struct CMethodItem
869 855
870class CZipDecoder 856class CZipDecoder
871{ 857{
872 NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec; 858 CMyComPtr2<ICompressFilter, NCrypto::NZip::CDecoder> _zipCryptoDecoder;
873 NCrypto::NZipStrong::CDecoder *_pkAesDecoderSpec; 859 CMyComPtr2<ICompressFilter, NCrypto::NZipStrong::CDecoder> _pkAesDecoder;
874 NCrypto::NWzAes::CDecoder *_wzAesDecoderSpec; 860 CMyComPtr2<ICompressFilter, NCrypto::NWzAes::CDecoder> _wzAesDecoder;
875
876 CMyComPtr<ICompressFilter> _zipCryptoDecoder;
877 CMyComPtr<ICompressFilter> _pkAesDecoder;
878 CMyComPtr<ICompressFilter> _wzAesDecoder;
879 861
880 CFilterCoder *filterStreamSpec; 862 CMyComPtr2<ISequentialInStream, CFilterCoder> filterStream;
881 CMyComPtr<ISequentialInStream> filterStream;
882 CMyComPtr<ICryptoGetTextPassword> getTextPassword; 863 CMyComPtr<ICryptoGetTextPassword> getTextPassword;
883 CObjectVector<CMethodItem> methodItems; 864 CObjectVector<CMethodItem> methodItems;
884 865
885 CLzmaDecoder *lzmaDecoderSpec; 866 CLzmaDecoder *lzmaDecoderSpec;
886public: 867public:
887 CZipDecoder(): 868 CZipDecoder():
888 _zipCryptoDecoderSpec(NULL),
889 _pkAesDecoderSpec(NULL),
890 _wzAesDecoderSpec(NULL),
891 filterStreamSpec(NULL),
892 lzmaDecoderSpec(NULL) 869 lzmaDecoderSpec(NULL)
893 {} 870 {}
894 871
@@ -1051,15 +1028,12 @@ HRESULT CZipDecoder::Decode(
1051 } 1028 }
1052 } 1029 }
1053 1030
1054 COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; 1031 CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;
1055 CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; 1032 outStream->SetStream(realOutStream);
1056 outStreamSpec->SetStream(realOutStream); 1033 outStream->Init(needCRC);
1057 outStreamSpec->Init(needCRC);
1058 1034
1059 CMyComPtr<ISequentialInStream> packStream; 1035 CMyComPtr<ISequentialInStream> packStream;
1060 1036 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
1061 CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream;
1062 CMyComPtr<ISequentialInStream> inStream(limitedStreamSpec);
1063 1037
1064 { 1038 {
1065 UInt64 packSize = item.PackSize; 1039 UInt64 packSize = item.PackSize;
@@ -1075,8 +1049,8 @@ HRESULT CZipDecoder::Decode(
1075 res = NExtract::NOperationResult::kUnavailable; 1049 res = NExtract::NOperationResult::kUnavailable;
1076 return S_OK; 1050 return S_OK;
1077 } 1051 }
1078 limitedStreamSpec->SetStream(packStream); 1052 inStream->SetStream(packStream);
1079 limitedStreamSpec->Init(packSize); 1053 inStream->Init(packSize);
1080 } 1054 }
1081 1055
1082 1056
@@ -1089,13 +1063,9 @@ HRESULT CZipDecoder::Decode(
1089 if (wzAesMode) 1063 if (wzAesMode)
1090 { 1064 {
1091 id = aesField.Method; 1065 id = aesField.Method;
1092 if (!_wzAesDecoder) 1066 _wzAesDecoder.Create_if_Empty();
1093 {
1094 _wzAesDecoderSpec = new NCrypto::NWzAes::CDecoder;
1095 _wzAesDecoder = _wzAesDecoderSpec;
1096 }
1097 cryptoFilter = _wzAesDecoder; 1067 cryptoFilter = _wzAesDecoder;
1098 if (!_wzAesDecoderSpec->SetKeyMode(aesField.Strength)) 1068 if (!_wzAesDecoder->SetKeyMode(aesField.Strength))
1099 { 1069 {
1100 res = NExtract::NOperationResult::kUnsupportedMethod; 1070 res = NExtract::NOperationResult::kUnsupportedMethod;
1101 return S_OK; 1071 return S_OK;
@@ -1103,20 +1073,12 @@ HRESULT CZipDecoder::Decode(
1103 } 1073 }
1104 else if (pkAesMode) 1074 else if (pkAesMode)
1105 { 1075 {
1106 if (!_pkAesDecoder) 1076 _pkAesDecoder.Create_if_Empty();
1107 {
1108 _pkAesDecoderSpec = new NCrypto::NZipStrong::CDecoder;
1109 _pkAesDecoder = _pkAesDecoderSpec;
1110 }
1111 cryptoFilter = _pkAesDecoder; 1077 cryptoFilter = _pkAesDecoder;
1112 } 1078 }
1113 else 1079 else
1114 { 1080 {
1115 if (!_zipCryptoDecoder) 1081 _zipCryptoDecoder.Create_if_Empty();
1116 {
1117 _zipCryptoDecoderSpec = new NCrypto::NZip::CDecoder;
1118 _zipCryptoDecoder = _zipCryptoDecoderSpec;
1119 }
1120 cryptoFilter = _zipCryptoDecoder; 1082 cryptoFilter = _zipCryptoDecoder;
1121 } 1083 }
1122 1084
@@ -1135,15 +1097,17 @@ HRESULT CZipDecoder::Decode(
1135 AString_Wipe charPassword; 1097 AString_Wipe charPassword;
1136 if (password) 1098 if (password)
1137 { 1099 {
1138 /* 1100#if 0 && defined(_WIN32)
1139 // 22.00: do we need UTF-8 passwords here ? 1101 // do we need UTF-8 passwords here ?
1140 if (item.IsUtf8()) // 22.00 1102 if (item.GetHostOS() == NFileHeader::NHostOS::kUnix // 24.05
1103 // || item.IsUtf8() // 22.00
1104 )
1141 { 1105 {
1142 // throw 1; 1106 // throw 1;
1143 ConvertUnicodeToUTF8((LPCOLESTR)password, charPassword); 1107 ConvertUnicodeToUTF8((LPCOLESTR)password, charPassword);
1144 } 1108 }
1145 else 1109 else
1146 */ 1110#endif
1147 { 1111 {
1148 UnicodeStringToMultiByte2(charPassword, (LPCOLESTR)password, CP_ACP); 1112 UnicodeStringToMultiByte2(charPassword, (LPCOLESTR)password, CP_ACP);
1149 } 1113 }
@@ -1202,10 +1166,12 @@ HRESULT CZipDecoder::Decode(
1202 mi.Coder = new NCompress::NXz::CComDecoder; 1166 mi.Coder = new NCompress::NXz::CComDecoder;
1203 else if (id == NFileHeader::NCompressionMethod::kPPMd) 1167 else if (id == NFileHeader::NCompressionMethod::kPPMd)
1204 mi.Coder = new NCompress::NPpmdZip::CDecoder(true); 1168 mi.Coder = new NCompress::NPpmdZip::CDecoder(true);
1205 #ifdef SUPPORT_LZFSE 1169 else if (id == NFileHeader::NCompressionMethod::kZstdWz)
1170 mi.Coder = new NCompress::NZstd::CDecoder();
1171#ifndef Z7_ZIP_LZFSE_DISABLE
1206 else if (id == NFileHeader::NCompressionMethod::kWzAES) 1172 else if (id == NFileHeader::NCompressionMethod::kWzAES)
1207 mi.Coder = new NCompress::NLzfse::CDecoder; 1173 mi.Coder = new NCompress::NLzfse::CDecoder;
1208 #endif 1174#endif
1209 else 1175 else
1210 { 1176 {
1211 CMethodId szMethodID; 1177 CMethodId szMethodID;
@@ -1288,21 +1254,18 @@ HRESULT CZipDecoder::Decode(
1288 HRESULT result = S_OK; 1254 HRESULT result = S_OK;
1289 if (item.IsEncrypted()) 1255 if (item.IsEncrypted())
1290 { 1256 {
1291 if (!filterStream) 1257 if (!filterStream.IsDefined())
1292 { 1258 filterStream.SetFromCls(new CFilterCoder(false));
1293 filterStreamSpec = new CFilterCoder(false);
1294 filterStream = filterStreamSpec;
1295 }
1296 1259
1297 filterReleaser.FilterCoder = filterStreamSpec; 1260 filterReleaser.FilterCoder = filterStream.ClsPtr();
1298 filterStreamSpec->Filter = cryptoFilter; 1261 filterStream->Filter = cryptoFilter;
1299 1262
1300 if (wzAesMode) 1263 if (wzAesMode)
1301 { 1264 {
1302 result = _wzAesDecoderSpec->ReadHeader(inStream); 1265 result = _wzAesDecoder->ReadHeader(inStream);
1303 if (result == S_OK) 1266 if (result == S_OK)
1304 { 1267 {
1305 if (!_wzAesDecoderSpec->Init_and_CheckPassword()) 1268 if (!_wzAesDecoder->Init_and_CheckPassword())
1306 { 1269 {
1307 res = NExtract::NOperationResult::kWrongPassword; 1270 res = NExtract::NOperationResult::kWrongPassword;
1308 return S_OK; 1271 return S_OK;
@@ -1312,11 +1275,11 @@ HRESULT CZipDecoder::Decode(
1312 else if (pkAesMode) 1275 else if (pkAesMode)
1313 { 1276 {
1314 isFullStreamExpected = false; 1277 isFullStreamExpected = false;
1315 result =_pkAesDecoderSpec->ReadHeader(inStream, item.Crc, item.Size); 1278 result = _pkAesDecoder->ReadHeader(inStream, item.Crc, item.Size);
1316 if (result == S_OK) 1279 if (result == S_OK)
1317 { 1280 {
1318 bool passwOK; 1281 bool passwOK;
1319 result = _pkAesDecoderSpec->Init_and_CheckPassword(passwOK); 1282 result = _pkAesDecoder->Init_and_CheckPassword(passwOK);
1320 if (result == S_OK && !passwOK) 1283 if (result == S_OK && !passwOK)
1321 { 1284 {
1322 res = NExtract::NOperationResult::kWrongPassword; 1285 res = NExtract::NOperationResult::kWrongPassword;
@@ -1326,10 +1289,10 @@ HRESULT CZipDecoder::Decode(
1326 } 1289 }
1327 else 1290 else
1328 { 1291 {
1329 result = _zipCryptoDecoderSpec->ReadHeader(inStream); 1292 result = _zipCryptoDecoder->ReadHeader(inStream);
1330 if (result == S_OK) 1293 if (result == S_OK)
1331 { 1294 {
1332 _zipCryptoDecoderSpec->Init_BeforeDecode(); 1295 _zipCryptoDecoder->Init_BeforeDecode();
1333 1296
1334 /* Info-ZIP modification to ZipCrypto format: 1297 /* Info-ZIP modification to ZipCrypto format:
1335 if bit 3 of the general purpose bit flag is set, 1298 if bit 3 of the general purpose bit flag is set,
@@ -1337,10 +1300,10 @@ HRESULT CZipDecoder::Decode(
1337 Info-ZIP code probably writes 2 bytes of File Time. 1300 Info-ZIP code probably writes 2 bytes of File Time.
1338 We check only 1 byte. */ 1301 We check only 1 byte. */
1339 1302
1340 // UInt32 v1 = GetUi16(_zipCryptoDecoderSpec->_header + NCrypto::NZip::kHeaderSize - 2); 1303 // UInt32 v1 = GetUi16(_zipCryptoDecoder->_header + NCrypto::NZip::kHeaderSize - 2);
1341 // UInt32 v2 = (item.HasDescriptor() ? (item.Time & 0xFFFF) : (item.Crc >> 16)); 1304 // UInt32 v2 = (item.HasDescriptor() ? (item.Time & 0xFFFF) : (item.Crc >> 16));
1342 1305
1343 Byte v1 = _zipCryptoDecoderSpec->_header[NCrypto::NZip::kHeaderSize - 1]; 1306 Byte v1 = _zipCryptoDecoder->_header[NCrypto::NZip::kHeaderSize - 1];
1344 Byte v2 = (Byte)(item.HasDescriptor() ? (item.Time >> 8) : (item.Crc >> 24)); 1307 Byte v2 = (Byte)(item.HasDescriptor() ? (item.Time >> 8) : (item.Crc >> 24));
1345 1308
1346 if (v1 != v2) 1309 if (v1 != v2)
@@ -1361,7 +1324,7 @@ HRESULT CZipDecoder::Decode(
1361 RINOK(setFinishMode->SetFinishMode(BoolToUInt(true))) 1324 RINOK(setFinishMode->SetFinishMode(BoolToUInt(true)))
1362 } 1325 }
1363 1326
1364 const UInt64 coderPackSize = limitedStreamSpec->GetRem(); 1327 const UInt64 coderPackSize = inStream->GetRem();
1365 1328
1366 if (id == NFileHeader::NCompressionMethod::kStore && item.IsEncrypted()) 1329 if (id == NFileHeader::NCompressionMethod::kStore && item.IsEncrypted())
1367 { 1330 {
@@ -1377,7 +1340,7 @@ HRESULT CZipDecoder::Decode(
1377 { 1340 {
1378 padStreamSpec = new COutStreamWithPadPKCS7; 1341 padStreamSpec = new COutStreamWithPadPKCS7;
1379 padStream = padStreamSpec; 1342 padStream = padStreamSpec;
1380 padSize = _pkAesDecoderSpec->GetPadSize((UInt32)item.Size); 1343 padSize = _pkAesDecoder->GetPadSize((UInt32)item.Size);
1381 padStreamSpec->SetStream(outStream); 1344 padStreamSpec->SetStream(outStream);
1382 padStreamSpec->Init(item.Size, padSize); 1345 padStreamSpec->Init(item.Size, padSize);
1383 } 1346 }
@@ -1394,12 +1357,12 @@ HRESULT CZipDecoder::Decode(
1394 size = expectedSize; 1357 size = expectedSize;
1395 } 1358 }
1396 1359
1397 result = filterStreamSpec->Code(inStream, padStream ? 1360 result = filterStream->Code(inStream, padStream ?
1398 (ISequentialOutStream *)padStream : 1361 padStream.Interface() :
1399 (ISequentialOutStream *)outStream, 1362 outStream.Interface(),
1400 NULL, &size, compressProgress); 1363 NULL, &size, compressProgress);
1401 1364
1402 if (outStreamSpec->GetSize() != item.Size) 1365 if (outStream->GetSize() != item.Size)
1403 truncatedError = true; 1366 truncatedError = true;
1404 1367
1405 if (pkAesMode) 1368 if (pkAesMode)
@@ -1415,20 +1378,20 @@ HRESULT CZipDecoder::Decode(
1415 if (item.IsEncrypted()) 1378 if (item.IsEncrypted())
1416 { 1379 {
1417 readFromFilter = true; 1380 readFromFilter = true;
1418 inStreamReleaser.FilterCoder = filterStreamSpec; 1381 inStreamReleaser.FilterCoder = filterStream.ClsPtr();
1419 RINOK(filterStreamSpec->SetInStream(inStream)) 1382 RINOK(filterStream->SetInStream(inStream))
1420 1383
1421 /* IFilter::Init() does nothing in all zip crypto filters. 1384 /* IFilter::Init() does nothing in all zip crypto filters.
1422 So we can call any Initialize function in CFilterCoder. */ 1385 So we can call any Initialize function in CFilterCoder. */
1423 1386
1424 RINOK(filterStreamSpec->Init_NoSubFilterInit()) 1387 RINOK(filterStream->Init_NoSubFilterInit())
1425 // RINOK(filterStreamSpec->SetOutStreamSize(NULL)); 1388 // RINOK(filterStream->SetOutStreamSize(NULL));
1426 } 1389 }
1427 1390
1428 try { 1391 try {
1429 result = coder->Code(readFromFilter ? 1392 result = coder->Code(readFromFilter ?
1430 (ISequentialInStream *)filterStream : 1393 filterStream.Interface() :
1431 (ISequentialInStream *)inStream, 1394 inStream.Interface(),
1432 outStream, 1395 outStream,
1433 isFullStreamExpected ? &coderPackSize : NULL, 1396 isFullStreamExpected ? &coderPackSize : NULL,
1434 // NULL, 1397 // NULL,
@@ -1448,7 +1411,7 @@ HRESULT CZipDecoder::Decode(
1448 { 1411 {
1449 if (pkAesMode) 1412 if (pkAesMode)
1450 { 1413 {
1451 const UInt32 padSize = _pkAesDecoderSpec->GetPadSize((UInt32)processed); 1414 const UInt32 padSize = _pkAesDecoder->GetPadSize((UInt32)processed);
1452 if (processed + padSize > coderPackSize) 1415 if (processed + padSize > coderPackSize)
1453 truncatedError = true; 1416 truncatedError = true;
1454 else if (processed + padSize < coderPackSize) 1417 else if (processed + padSize < coderPackSize)
@@ -1514,7 +1477,7 @@ HRESULT CZipDecoder::Decode(
1514 } 1477 }
1515 1478
1516 if (result == S_OK && id == NFileHeader::NCompressionMethod::kLZMA) 1479 if (result == S_OK && id == NFileHeader::NCompressionMethod::kLZMA)
1517 if (!lzmaDecoderSpec->DecoderSpec->CheckFinishStatus(item.IsLzmaEOS())) 1480 if (!lzmaDecoderSpec->Decoder->CheckFinishStatus(item.IsLzmaEOS()))
1518 lzmaEosError = true; 1481 lzmaEosError = true;
1519 } 1482 }
1520 1483
@@ -1533,32 +1496,32 @@ HRESULT CZipDecoder::Decode(
1533 bool crcOK = true; 1496 bool crcOK = true;
1534 bool authOk = true; 1497 bool authOk = true;
1535 if (needCRC) 1498 if (needCRC)
1536 crcOK = (outStreamSpec->GetCRC() == item.Crc); 1499 crcOK = (outStream->GetCRC() == item.Crc);
1537 1500
1538 if (useUnpackLimit) 1501 if (useUnpackLimit)
1539 if (outStreamSpec->GetSize() != item.Size) 1502 if (outStream->GetSize() != item.Size)
1540 truncatedError = true; 1503 truncatedError = true;
1541 1504
1542 if (wzAesMode) 1505 if (wzAesMode)
1543 { 1506 {
1544 const UInt64 unpackSize = outStreamSpec->GetSize(); 1507 const UInt64 unpackSize = outStream->GetSize();
1545 const UInt64 packSize = limitedStreamSpec->GetSize(); 1508 const UInt64 packSize = inStream->GetSize();
1546 bool thereAreData = false; 1509 bool thereAreData = false;
1547 // read to the end from filter or from packed stream 1510 // read to the end from filter or from packed stream
1548 if (SkipStreamData(readFromFilter ? 1511 if (SkipStreamData(readFromFilter ?
1549 (ISequentialInStream *)filterStream : 1512 filterStream.Interface() :
1550 (ISequentialInStream *)inStream, 1513 inStream.Interface(),
1551 compressProgress, packSize, unpackSize, thereAreData) != S_OK) 1514 compressProgress, packSize, unpackSize, thereAreData) != S_OK)
1552 authOk = false; 1515 authOk = false;
1553 if (needReminderCheck && thereAreData) 1516 if (needReminderCheck && thereAreData)
1554 dataAfterEnd = true; 1517 dataAfterEnd = true;
1555 1518
1556 if (limitedStreamSpec->GetRem() != 0) 1519 if (inStream->GetRem() != 0)
1557 truncatedError = true; 1520 truncatedError = true;
1558 else 1521 else
1559 { 1522 {
1560 limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize); 1523 inStream->Init(NCrypto::NWzAes::kMacSize);
1561 if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) 1524 if (_wzAesDecoder->CheckMac(inStream, authOk) != S_OK)
1562 authOk = false; 1525 authOk = false;
1563 } 1526 }
1564 } 1527 }
@@ -1617,8 +1580,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1617 CZipDecoder myDecoder; 1580 CZipDecoder myDecoder;
1618 UInt64 cur_Unpacked, cur_Packed; 1581 UInt64 cur_Unpacked, cur_Packed;
1619 1582
1620 CLocalProgress *lps = new CLocalProgress; 1583 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1621 CMyComPtr<ICompressProgressInfo> progress = lps;
1622 lps->Init(extractCallback, false); 1584 lps->Init(extractCallback, false);
1623 1585
1624 for (i = 0;; i++, 1586 for (i = 0;; i++,
@@ -1640,6 +1602,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1640 NExtract::NAskMode::kTest : 1602 NExtract::NAskMode::kTest :
1641 NExtract::NAskMode::kExtract; 1603 NExtract::NAskMode::kExtract;
1642 1604
1605 Int32 opRes;
1606 {
1643 CMyComPtr<ISequentialOutStream> realOutStream; 1607 CMyComPtr<ISequentialOutStream> realOutStream;
1644 RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) 1608 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
1645 1609
@@ -1689,25 +1653,24 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1689 1653
1690 RINOK(extractCallback->PrepareOperation(askMode)) 1654 RINOK(extractCallback->PrepareOperation(askMode))
1691 1655
1692 Int32 res;
1693 const HRESULT hres = myDecoder.Decode( 1656 const HRESULT hres = myDecoder.Decode(
1694 EXTERNAL_CODECS_VARS 1657 EXTERNAL_CODECS_VARS
1695 m_Archive, item, realOutStream, extractCallback, 1658 m_Archive, item, realOutStream, extractCallback,
1696 progress, 1659 lps,
1697 #ifndef Z7_ST 1660 #ifndef Z7_ST
1698 _props._numThreads, _props._memUsage_Decompress, 1661 _props._numThreads, _props._memUsage_Decompress,
1699 #endif 1662 #endif
1700 res); 1663 opRes);
1701 1664
1702 RINOK(hres) 1665 RINOK(hres)
1703 realOutStream.Release(); 1666 // realOutStream.Release();
1704 1667
1705 if (res == NExtract::NOperationResult::kOK && headersError) 1668 if (opRes == NExtract::NOperationResult::kOK && headersError)
1706 res = NExtract::NOperationResult::kHeadersError; 1669 opRes = NExtract::NOperationResult::kHeadersError;
1707 1670 }
1708 RINOK(extractCallback->SetOperationResult(res)) 1671 RINOK(extractCallback->SetOperationResult(opRes))
1709 } 1672 }
1710 1673
1711 COM_TRY_END 1674 COM_TRY_END
1712} 1675}
1713 1676
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index 19699b5..46ccf3d 100644
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -515,17 +515,25 @@ Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
515 return E_INVALIDARG; 515 return E_INVALIDARG;
516 { 516 {
517 const wchar_t *m = prop.bstrVal; 517 const wchar_t *m = prop.bstrVal;
518 if (IsString1PrefixedByString2_NoCase_Ascii(m, "aes")) 518 if (IsString1PrefixedByString2_NoCase_Ascii(m, "AES"))
519 { 519 {
520 m += 3; 520 m += 3;
521 if (StringsAreEqual_Ascii(m, "128")) 521 UInt32 v = 3;
522 _props.AesKeyMode = 1; 522 if (*m != 0)
523 else if (StringsAreEqual_Ascii(m, "192")) 523 {
524 _props.AesKeyMode = 2; 524 if (*m == '-')
525 else if (StringsAreEqual_Ascii(m, "256") || m[0] == 0) 525 m++;
526 _props.AesKeyMode = 3; 526 const wchar_t *end;
527 else 527 v = ConvertStringToUInt32(m, &end);
528 return E_INVALIDARG; 528 if (*end != 0 || v % 64 != 0)
529 return E_INVALIDARG;
530 v /= 64;
531 v -= 2;
532 if (v >= 3)
533 return E_INVALIDARG;
534 v++;
535 }
536 _props.AesKeyMode = (Byte)v;
529 _props.IsAesMode = true; 537 _props.IsAesMode = true;
530 m_ForceAesMode = true; 538 m_ForceAesMode = true;
531 } 539 }
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index 4236df7..788810f 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -2282,10 +2282,10 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,
2282 { 2282 {
2283 UString volName = Vols.BaseName; 2283 UString volName = Vols.BaseName;
2284 { 2284 {
2285 volName += (char)(Vols.IsUpperCase ? 'Z' : 'z'); 2285 volName.Add_Char(Vols.IsUpperCase ? 'Z' : 'z');
2286 unsigned v = i + 1; 2286 const unsigned v = i + 1;
2287 if (v < 10) 2287 if (v < 10)
2288 volName += '0'; 2288 volName.Add_Char('0');
2289 volName.Add_UInt32(v); 2289 volName.Add_UInt32(v);
2290 } 2290 }
2291 2291
diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp
index a77643b..5684cac 100644
--- a/CPP/7zip/Archive/Zip/ZipItem.cpp
+++ b/CPP/7zip/Archive/Zip/ZipItem.cpp
@@ -55,15 +55,15 @@ void CExtraSubBlock::PrintInfo(AString &s) const
55 { 55 {
56 if (Data.Size() >= 1) 56 if (Data.Size() >= 1)
57 { 57 {
58 s += ':'; 58 s.Add_Colon();
59 const Byte flags = Data[0]; 59 const Byte flags = Data[0];
60 if (flags & 1) s += 'M'; 60 if (flags & 1) s.Add_Char('M');
61 if (flags & 2) s += 'A'; 61 if (flags & 2) s.Add_Char('A');
62 if (flags & 4) s += 'C'; 62 if (flags & 4) s.Add_Char('C');
63 const UInt32 size = (UInt32)(Data.Size()) - 1; 63 const UInt32 size = (UInt32)(Data.Size()) - 1;
64 if (size % 4 == 0) 64 if (size % 4 == 0)
65 { 65 {
66 s += ':'; 66 s.Add_Colon();
67 s.Add_UInt32(size / 4); 67 s.Add_UInt32(size / 4);
68 } 68 }
69 } 69 }
@@ -88,7 +88,7 @@ void CExtraSubBlock::PrintInfo(AString &s) const
88 } 88 }
89 } 89 }
90 { 90 {
91 char sz[32]; 91 char sz[16];
92 sz[0] = '0'; 92 sz[0] = '0';
93 sz[1] = 'x'; 93 sz[1] = 'x';
94 ConvertUInt32ToHex(ID, sz + 2); 94 ConvertUInt32ToHex(ID, sz + 2);
@@ -291,6 +291,7 @@ bool CItem::IsDir() const
291 case NHostOS::kHPFS: 291 case NHostOS::kHPFS:
292 case NHostOS::kVFAT: 292 case NHostOS::kVFAT:
293 return true; 293 return true;
294 default: break;
294 } 295 }
295 } 296 }
296 297
@@ -360,6 +361,7 @@ UInt32 CItem::GetWinAttrib() const
360 // #endif 361 // #endif
361 } 362 }
362 break; 363 break;
364 default: break;
363 } 365 }
364 if (IsDir()) // test it; 366 if (IsDir()) // test it;
365 winAttrib |= FILE_ATTRIBUTE_DIRECTORY; 367 winAttrib |= FILE_ATTRIBUTE_DIRECTORY;
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index e6d881c..b2742b7 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -976,7 +976,7 @@ static HRESULT Update2(
976 976
977 complexity = 0; 977 complexity = 0;
978 978
979 const Byte method = options.MethodSequence.Front(); 979 const Byte method = options.MethodSequence.FrontItem();
980 980
981 COneMethodInfo *oneMethodMain = NULL; 981 COneMethodInfo *oneMethodMain = NULL;
982 if (!options2._methods.IsEmpty()) 982 if (!options2._methods.IsEmpty())
@@ -1310,7 +1310,7 @@ static HRESULT Update2(
1310 1310
1311 { 1311 {
1312 NWindows::NSynchronization::CCriticalSectionLock lock(mtProgressMixerSpec->Mixer2->CriticalSection); 1312 NWindows::NSynchronization::CCriticalSectionLock lock(mtProgressMixerSpec->Mixer2->CriticalSection);
1313 HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); 1313 const HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
1314 if (res == S_FALSE) 1314 if (res == S_FALSE)
1315 { 1315 {
1316 complexity += ui.Size; 1316 complexity += ui.Size;
@@ -1395,7 +1395,7 @@ static HRESULT Update2(
1395 if (ui.NewData) 1395 if (ui.NewData)
1396 { 1396 {
1397 // bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir()); 1397 // bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir());
1398 bool isDir = ui.IsDir; 1398 const bool isDir = ui.IsDir;
1399 1399
1400 if (isDir) 1400 if (isDir)
1401 { 1401 {
@@ -1471,7 +1471,7 @@ static HRESULT Update2(
1471 } 1471 }
1472 1472
1473 { 1473 {
1474 CThreadInfo &thread = threads.Threads[threadIndices.Front()]; 1474 CThreadInfo &thread = threads.Threads[threadIndices.FrontItem()];
1475 if (!thread.OutStreamSpec->WasUnlockEventSent()) 1475 if (!thread.OutStreamSpec->WasUnlockEventSent())
1476 { 1476 {
1477 CMyComPtr<IOutStream> outStream; 1477 CMyComPtr<IOutStream> outStream;
@@ -1481,11 +1481,11 @@ static HRESULT Update2(
1481 } 1481 }
1482 } 1482 }
1483 1483
1484 WRes wres = mtSem.Semaphore.Lock(); 1484 const WRes wres = mtSem.Semaphore.Lock();
1485 if (wres != 0) 1485 if (wres != 0)
1486 return HRESULT_FROM_WIN32(wres); 1486 return HRESULT_FROM_WIN32(wres);
1487 1487
1488 int ti = mtSem.GetFreeItem(); 1488 const int ti = mtSem.GetFreeItem();
1489 if (ti < 0) 1489 if (ti < 0)
1490 return E_FAIL; 1490 return E_FAIL;
1491 1491
@@ -1617,9 +1617,9 @@ Z7_COM7F_IMF(CSeekOutStream::SetSize(UInt64 newSize))
1617} 1617}
1618*/ 1618*/
1619 1619
1620static const size_t kCacheBlockSize = (1 << 20); 1620static const size_t kCacheBlockSize = 1 << 20;
1621static const size_t kCacheSize = (kCacheBlockSize << 2); 1621static const size_t kCacheSize = kCacheBlockSize << 2;
1622static const size_t kCacheMask = (kCacheSize - 1); 1622static const size_t kCacheMask = kCacheSize - 1;
1623 1623
1624Z7_CLASS_IMP_NOQIB_2( 1624Z7_CLASS_IMP_NOQIB_2(
1625 CCacheOutStream 1625 CCacheOutStream
@@ -1628,55 +1628,66 @@ Z7_CLASS_IMP_NOQIB_2(
1628) 1628)
1629 Z7_IFACE_COM7_IMP(ISequentialOutStream) 1629 Z7_IFACE_COM7_IMP(ISequentialOutStream)
1630 1630
1631 CMyComPtr<IOutStream> _stream; 1631 HRESULT _hres;
1632 CMyComPtr<ISequentialOutStream> _seqStream; 1632 CMyComPtr<ISequentialOutStream> _seqStream;
1633 CMyComPtr<IOutStream> _stream;
1634 CMyComPtr<IStreamSetRestriction> _setRestriction;
1633 Byte *_cache; 1635 Byte *_cache;
1636 size_t _cachedSize;
1637 UInt64 _cachedPos;
1634 UInt64 _virtPos; 1638 UInt64 _virtPos;
1635 UInt64 _virtSize; 1639 UInt64 _virtSize;
1636 UInt64 _phyPos; 1640 UInt64 _phyPos;
1637 UInt64 _phySize; // <= _virtSize 1641 UInt64 _phySize;
1638 UInt64 _cachedPos; // (_cachedPos + _cachedSize) <= _virtSize
1639 size_t _cachedSize;
1640 HRESULT _hres;
1641
1642 UInt64 _restrict_begin; 1642 UInt64 _restrict_begin;
1643 UInt64 _restrict_end; 1643 UInt64 _restrict_end;
1644 UInt64 _restrict_phy; // begin
1645 CMyComPtr<IStreamSetRestriction> _setRestriction;
1646 1644
1647 HRESULT MyWrite(size_t size); 1645 HRESULT FlushFromCache(size_t size);
1648 HRESULT MyWriteBlock() 1646 HRESULT FlushNonRestrictedBlocks();
1647 HRESULT FlushCache();
1648 HRESULT SetRestriction_ForWrite(size_t writeSize) const;
1649
1650 HRESULT SeekPhy(UInt64 pos)
1649 { 1651 {
1650 return MyWrite(kCacheBlockSize - ((size_t)_cachedPos & (kCacheBlockSize - 1))); 1652 if (pos == _phyPos)
1653 return S_OK;
1654 if (!_stream)
1655 return E_NOTIMPL;
1656 _hres = _stream->Seek((Int64)pos, STREAM_SEEK_SET, &_phyPos);
1657 if (_hres == S_OK && _phyPos != pos)
1658 _hres = E_FAIL;
1659 return _hres;
1651 } 1660 }
1652 HRESULT WriteNonRestrictedBlocks(); 1661
1653 HRESULT FlushCache();
1654public: 1662public:
1655 CCacheOutStream(): _cache(NULL) {} 1663 CCacheOutStream(): _cache(NULL) {}
1656 ~CCacheOutStream(); 1664 ~CCacheOutStream();
1657 bool Allocate(); 1665 bool Allocate()
1666 {
1667 if (!_cache)
1668 _cache = (Byte *)::MidAlloc(kCacheSize);
1669 return _cache != NULL;
1670 }
1658 HRESULT Init(ISequentialOutStream *seqStream, IOutStream *stream, IStreamSetRestriction *setRestriction); 1671 HRESULT Init(ISequentialOutStream *seqStream, IOutStream *stream, IStreamSetRestriction *setRestriction);
1659 HRESULT FinalFlush(); 1672 HRESULT FinalFlush();
1660}; 1673};
1661 1674
1662 1675CCacheOutStream::~CCacheOutStream()
1663bool CCacheOutStream::Allocate()
1664{ 1676{
1665 if (!_cache) 1677 ::MidFree(_cache);
1666 _cache = (Byte *)::MidAlloc(kCacheSize);
1667 return (_cache != NULL);
1668} 1678}
1669 1679
1680
1670HRESULT CCacheOutStream::Init(ISequentialOutStream *seqStream, IOutStream *stream, IStreamSetRestriction *setRestriction) 1681HRESULT CCacheOutStream::Init(ISequentialOutStream *seqStream, IOutStream *stream, IStreamSetRestriction *setRestriction)
1671{ 1682{
1672 _cachedPos = 0;
1673 _cachedSize = 0;
1674 _hres = S_OK; 1683 _hres = S_OK;
1675 _restrict_begin = 0; 1684 _cachedSize = 0;
1676 _restrict_end = 0; 1685 _cachedPos = 0;
1677 _restrict_phy = 0;
1678 _virtPos = 0; 1686 _virtPos = 0;
1679 _virtSize = 0; 1687 _virtSize = 0;
1688 // by default we have no restriction
1689 _restrict_begin = 0;
1690 _restrict_end = 0;
1680 _seqStream = seqStream; 1691 _seqStream = seqStream;
1681 _stream = stream; 1692 _stream = stream;
1682 _setRestriction = setRestriction; 1693 _setRestriction = setRestriction;
@@ -1692,63 +1703,99 @@ HRESULT CCacheOutStream::Init(ISequentialOutStream *seqStream, IOutStream *strea
1692} 1703}
1693 1704
1694 1705
1695/* it writes up to (size) bytes from cache. 1706/* we call SetRestriction_ForWrite() just before Write() from cache.
1696 (size > _cachedSize) is allowed */ 1707 (_phyPos == _cachedPos)
1708 (writeSize != 0)
1709*/
1710HRESULT CCacheOutStream::SetRestriction_ForWrite(size_t writeSize) const
1711{
1712 if (!_setRestriction)
1713 return S_OK;
1714 PRF(printf("\n-- CCacheOutStream::SetRestriction_ForWrite _cachedPos = 0x%x, writeSize = %d\n", (unsigned)_cachedPos, (unsigned)writeSize));
1715 UInt64 begin = _restrict_begin;
1716 UInt64 end = _restrict_end;
1717 const UInt64 phyPos = _phyPos;
1718 if (phyPos != _cachedPos) return E_FAIL;
1719 if (phyPos == _phySize)
1720 {
1721 // The writing will be to the end of phy stream.
1722 // So we will try to use non-restricted write, if possible.
1723 if (begin == end)
1724 begin = _virtPos; // _virtSize; // it's supposed that (_virtSize == _virtPos)
1725 if (phyPos + writeSize <= begin)
1726 {
1727 // the write is not restricted
1728 PRF(printf("\n+++ write is not restricted \n"));
1729 begin = 0;
1730 end = 0;
1731 }
1732 else
1733 {
1734 if (begin > phyPos)
1735 begin = phyPos;
1736 end = (UInt64)(Int64)-1;
1737 }
1738 }
1739 else
1740 {
1741 // (phyPos != _phySize)
1742 if (begin == end || begin > phyPos)
1743 begin = phyPos;
1744 end = (UInt64)(Int64)-1;
1745 }
1746 return _setRestriction->SetRestriction(begin, end);
1747}
1748
1697 1749
1698HRESULT CCacheOutStream::MyWrite(size_t size) 1750/* it writes up to (size) bytes from cache.
1751 (size > _cachedSize) is allowed
1752*/
1753HRESULT CCacheOutStream::FlushFromCache(size_t size)
1699{ 1754{
1700 PRF(printf("\n-- CCacheOutStream::MyWrite %u\n", (unsigned)size)); 1755 PRF(printf("\n-- CCacheOutStream::FlushFromCache %u\n", (unsigned)size));
1701 if (_hres != S_OK) 1756 if (_hres != S_OK)
1702 return _hres; 1757 return _hres;
1703 while (size != 0 && _cachedSize != 0) 1758 if (size == 0 || _cachedSize == 0)
1759 return S_OK;
1760 RINOK(SeekPhy(_cachedPos))
1761 for (;;)
1704 { 1762 {
1705 if (_phyPos != _cachedPos) 1763 // (_phyPos == _cachedPos)
1706 {
1707 if (!_stream)
1708 return E_FAIL;
1709 _hres = _stream->Seek((Int64)_cachedPos, STREAM_SEEK_SET, &_phyPos);
1710 RINOK(_hres)
1711 if (_phyPos != _cachedPos)
1712 {
1713 _hres = E_FAIL;
1714 return _hres;
1715 }
1716 }
1717 const size_t pos = (size_t)_cachedPos & kCacheMask; 1764 const size_t pos = (size_t)_cachedPos & kCacheMask;
1718 size_t curSize = kCacheSize - pos; 1765 size_t cur = kCacheSize - pos;
1719 curSize = MyMin(curSize, _cachedSize); 1766 cur = MyMin(cur, _cachedSize);
1720 curSize = MyMin(curSize, size); 1767 cur = MyMin(cur, size);
1721 _hres = WriteStream(_seqStream, _cache + pos, curSize); 1768 _hres = SetRestriction_ForWrite(cur);
1769 RINOK(_hres)
1770 PRF(printf("\n-- CCacheOutStream::WriteFromCache _phyPos = 0x%x, size = %d\n", (unsigned)_phyPos, (unsigned)cur));
1771 _hres = WriteStream(_seqStream, _cache + pos, cur);
1722 RINOK(_hres) 1772 RINOK(_hres)
1723 _phyPos += curSize; 1773 _phyPos += cur;
1724 if (_phySize < _phyPos) 1774 if (_phySize < _phyPos)
1725 _phySize = _phyPos; 1775 _phySize = _phyPos;
1726 _cachedPos += curSize; 1776 _cachedPos += cur;
1727 _cachedSize -= curSize; 1777 _cachedSize -= cur;
1728 size -= curSize; 1778 size -= cur;
1779 if (size == 0 || _cachedSize == 0)
1780 return S_OK;
1729 } 1781 }
1730
1731 if (_setRestriction)
1732 if (_restrict_begin == _restrict_end || _cachedPos <= _restrict_begin)
1733 if (_restrict_phy < _cachedPos)
1734 {
1735 _restrict_phy = _cachedPos;
1736 return _setRestriction->SetRestriction(_cachedPos, (UInt64)(Int64)-1);
1737 }
1738 return S_OK;
1739} 1782}
1740 1783
1741 1784
1742HRESULT CCacheOutStream::WriteNonRestrictedBlocks() 1785HRESULT CCacheOutStream::FlushNonRestrictedBlocks()
1743{ 1786{
1744 for (;;) 1787 for (;;)
1745 { 1788 {
1746 const size_t size = kCacheBlockSize - ((size_t)_cachedPos & (kCacheBlockSize - 1)); 1789 const size_t size = kCacheBlockSize - ((size_t)_cachedPos & (kCacheBlockSize - 1));
1747 if (_cachedSize < size) 1790 if (_cachedSize < size)
1748 break; 1791 break;
1749 if (_restrict_begin != _restrict_end && _cachedPos + size > _restrict_begin) 1792 UInt64 begin = _restrict_begin;
1793 if (begin == _restrict_end)
1794 begin = _virtPos;
1795 // we don't flush the data to restricted area
1796 if (_cachedPos + size > begin)
1750 break; 1797 break;
1751 RINOK(MyWrite(size)) 1798 RINOK(FlushFromCache(size))
1752 } 1799 }
1753 return S_OK; 1800 return S_OK;
1754} 1801}
@@ -1756,7 +1803,7 @@ HRESULT CCacheOutStream::WriteNonRestrictedBlocks()
1756 1803
1757HRESULT CCacheOutStream::FlushCache() 1804HRESULT CCacheOutStream::FlushCache()
1758{ 1805{
1759 return MyWrite(_cachedSize); 1806 return FlushFromCache(_cachedSize);
1760} 1807}
1761 1808
1762HRESULT CCacheOutStream::FinalFlush() 1809HRESULT CCacheOutStream::FinalFlush()
@@ -1770,25 +1817,17 @@ HRESULT CCacheOutStream::FinalFlush()
1770 { 1817 {
1771 // it's unexpected 1818 // it's unexpected
1772 RINOK(_stream->SetSize(_virtSize)) 1819 RINOK(_stream->SetSize(_virtSize))
1820 _phySize = _virtSize;
1773 } 1821 }
1774 if (_virtPos != _phyPos) 1822 _hres = SeekPhy(_virtPos);
1775 {
1776 RINOK(_stream->Seek((Int64)_virtPos, STREAM_SEEK_SET, NULL))
1777 }
1778 } 1823 }
1779 return S_OK; 1824 return _hres;
1780}
1781
1782
1783CCacheOutStream::~CCacheOutStream()
1784{
1785 ::MidFree(_cache);
1786} 1825}
1787 1826
1788 1827
1789Z7_COM7F_IMF(CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) 1828Z7_COM7F_IMF(CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
1790{ 1829{
1791 PRF(printf("\n-- CCacheOutStream::Write %u\n", (unsigned)size)); 1830 PRF(printf("\n==== CCacheOutStream::Write virtPos=0x%x, %u\n", (unsigned)_virtPos, (unsigned)size));
1792 1831
1793 if (processedSize) 1832 if (processedSize)
1794 *processedSize = 0; 1833 *processedSize = 0;
@@ -1804,38 +1843,74 @@ Z7_COM7F_IMF(CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *proce
1804 RINOK(FlushCache()) 1843 RINOK(FlushCache())
1805 } 1844 }
1806 1845
1807 // ---------- Writing data to cache ----------
1808
1809 if (_cachedSize == 0) 1846 if (_cachedSize == 0)
1810 _cachedPos = _virtPos; 1847 _cachedPos = _virtPos;
1811 1848
1812 const size_t pos = (size_t)_virtPos & kCacheMask; 1849 const size_t pos = (size_t)_virtPos & kCacheMask;
1813 size = (UInt32)MyMin((size_t)size, kCacheSize - pos);
1814 const UInt64 cachedEnd = _cachedPos + _cachedSize;
1815
1816 // (_virtPos >= _cachedPos) (_virtPos <= cachedEnd)
1817
1818 if (_virtPos != cachedEnd)
1819 { 1850 {
1820 // _virtPos < cachedEnd 1851 const size_t blockRem = kCacheBlockSize - ((size_t)_virtPos & (kCacheBlockSize - 1));
1852 if (size > blockRem)
1853 size = (UInt32)blockRem;
1854 }
1855 // _cachedPos <= _virtPos <= _cachedPos + _cachedSize
1856 const UInt64 cachedRem = _cachedPos + _cachedSize - _virtPos;
1857 if (cachedRem)
1858 {
1859 // _virtPos < _cachedPos + _cachedSize
1821 // we rewrite only existing data in cache. So _cachedSize will be not changed 1860 // we rewrite only existing data in cache. So _cachedSize will be not changed
1822 size = (UInt32)MyMin((size_t)size, (size_t)(cachedEnd - _virtPos)); 1861 if (size > cachedRem)
1862 size = (UInt32)cachedRem;
1823 } 1863 }
1824 else 1864 else
1825 { 1865 {
1826 // _virtPos == cachedEnd 1866 // _virtPos == _cachedPos + _cachedSize
1827 // so we need to add new data to the end of cache 1867 // so we need to add new data to the end of cache
1828 if (_cachedSize == kCacheSize) 1868 if (_cachedSize == kCacheSize)
1829 { 1869 {
1830 // cache is full. So we flush part of cache 1870 // cache is full. So we need to flush some part of cache.
1831 RINOK(MyWriteBlock()) 1871 // we flush only one block, but we are allowed to flush any size here
1872 RINOK(FlushFromCache(kCacheBlockSize - ((size_t)_cachedPos & (kCacheBlockSize - 1))))
1832 } 1873 }
1833 // _cachedSize != kCacheSize 1874 // _cachedSize != kCacheSize
1834 // so we have some space for new data in cache 1875 // so we have some space for new data in cache
1835 const size_t startPos = (size_t)_cachedPos & kCacheMask; 1876 if (_cachedSize == 0)
1836 // we don't allow new data to overwrite old start data in cache. 1877 {
1837 if (startPos > pos) 1878 /* this code is optional (for optimization):
1838 size = (UInt32)MyMin((size_t)size, (size_t)(startPos - pos)); 1879 we write data directly without cache,
1880 if there is no restriction and we have full block. */
1881 if (_restrict_begin == _restrict_end
1882 && size == kCacheBlockSize)
1883 {
1884 RINOK(SeekPhy(_virtPos))
1885 if (_setRestriction)
1886 {
1887 _hres = _setRestriction->SetRestriction(_restrict_begin, _restrict_end);
1888 RINOK(_hres)
1889 }
1890 PRF(printf("\n-- CCacheOutStream::WriteDirectly _phyPos = 0x%x, size = %d\n", (unsigned)_phyPos, (unsigned)size));
1891 _hres = WriteStream(_seqStream, data, size);
1892 RINOK(_hres)
1893 if (processedSize)
1894 *processedSize = size;
1895 _virtPos += size;
1896 if (_virtSize < _virtPos)
1897 _virtSize = _virtPos;
1898 _phyPos += size;
1899 if (_phySize < _phyPos)
1900 _phySize = _phyPos;
1901 return S_OK;
1902 }
1903 }
1904 else // (_cachedSize != 0)
1905 {
1906 const size_t startPos = (size_t)_cachedPos & kCacheMask;
1907 // we don't allow new data to overwrite old start data in cache.
1908 // (startPos == pos) here means that cache is empty.
1909 // (startPos == pos) is not possible here.
1910 if (startPos > pos)
1911 size = (UInt32)MyMin((size_t)size, (size_t)(startPos - pos));
1912 }
1913 // _virtPos == (_cachedPos + _cachedSize) still
1839 _cachedSize += size; 1914 _cachedSize += size;
1840 } 1915 }
1841 1916
@@ -1845,13 +1920,13 @@ Z7_COM7F_IMF(CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *proce
1845 _virtPos += size; 1920 _virtPos += size;
1846 if (_virtSize < _virtPos) 1921 if (_virtSize < _virtPos)
1847 _virtSize = _virtPos; 1922 _virtSize = _virtPos;
1848 return WriteNonRestrictedBlocks(); 1923 return FlushNonRestrictedBlocks();
1849} 1924}
1850 1925
1851 1926
1852Z7_COM7F_IMF(CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) 1927Z7_COM7F_IMF(CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
1853{ 1928{
1854 PRF(printf("\n-- CCacheOutStream::Seek seekOrigin=%d Seek =%u\n", seekOrigin, (unsigned)offset)); 1929 PRF(printf("\n==== CCacheOutStream::Seek seekOrigin=%d Seek =%u\n", seekOrigin, (unsigned)offset));
1855 switch (seekOrigin) 1930 switch (seekOrigin)
1856 { 1931 {
1857 case STREAM_SEEK_SET: break; 1932 case STREAM_SEEK_SET: break;
@@ -1872,35 +1947,63 @@ Z7_COM7F_IMF(CCacheOutStream::SetSize(UInt64 newSize))
1872{ 1947{
1873 if (_hres != S_OK) 1948 if (_hres != S_OK)
1874 return _hres; 1949 return _hres;
1875 _virtSize = newSize; 1950
1876 1951 if (newSize <= _cachedPos || _cachedSize == 0)
1877 if (newSize <= _cachedPos)
1878 { 1952 {
1879 _cachedSize = 0; 1953 _cachedSize = 0;
1880 _cachedPos = newSize; 1954 _cachedPos = newSize;
1881 } 1955 }
1882 else 1956 else
1883 { 1957 {
1958 // _cachedSize != 0
1884 // newSize > _cachedPos 1959 // newSize > _cachedPos
1885 const UInt64 offset = newSize - _cachedPos; 1960 const UInt64 offset = newSize - _cachedPos;
1886 if (offset <= _cachedSize) 1961 if (offset <= _cachedSize)
1887 { 1962 {
1963 // newSize is inside cached block or is touching cached block.
1964 // so we reduce cache
1888 _cachedSize = (size_t)offset; 1965 _cachedSize = (size_t)offset;
1889 if (_phySize <= newSize) 1966 if (_phySize <= newSize)
1890 return S_OK; 1967 return S_OK; // _phySize will be restored later after cache flush
1968 // (_phySize > newSize)
1969 // so we must reduce phyStream size to (newSize) or to (_cachedPos)
1970 // newPhySize = _cachedPos; // optional reduce to _cachedPos
1891 } 1971 }
1892 else 1972 else
1893 { 1973 {
1894 // newSize > _cachedPos + _cachedSize 1974 // newSize > _cachedPos + _cachedSize
1895 // So we flush cache 1975 /* It's possible that we need to write zeros,
1896 RINOK(FlushCache()) 1976 if new size is larger than old size.
1977 We don't optimize for possible cases here.
1978 So we just flush the cache. */
1979 _hres = FlushCache();
1897 } 1980 }
1898 } 1981 }
1899 1982
1983 _virtSize = newSize;
1984
1985 if (_hres != S_OK)
1986 return _hres;
1987
1900 if (newSize != _phySize) 1988 if (newSize != _phySize)
1901 { 1989 {
1902 if (!_stream) 1990 if (!_stream)
1903 return E_NOTIMPL; 1991 return E_NOTIMPL;
1992 // if (_phyPos > newSize)
1993 RINOK(SeekPhy(newSize))
1994 if (_setRestriction)
1995 {
1996 UInt64 begin = _restrict_begin;
1997 UInt64 end = _restrict_end;
1998 if (_cachedSize != 0)
1999 {
2000 if (begin > _cachedPos)
2001 begin = _cachedPos;
2002 end = (UInt64)(Int64)-1;
2003 }
2004 _hres = _setRestriction->SetRestriction(begin, end);
2005 RINOK(_hres)
2006 }
1904 _hres = _stream->SetSize(newSize); 2007 _hres = _stream->SetSize(newSize);
1905 RINOK(_hres) 2008 RINOK(_hres)
1906 _phySize = newSize; 2009 _phySize = newSize;
@@ -1911,10 +2014,10 @@ Z7_COM7F_IMF(CCacheOutStream::SetSize(UInt64 newSize))
1911 2014
1912Z7_COM7F_IMF(CCacheOutStream::SetRestriction(UInt64 begin, UInt64 end)) 2015Z7_COM7F_IMF(CCacheOutStream::SetRestriction(UInt64 begin, UInt64 end))
1913{ 2016{
1914 PRF(printf("\n============ CCacheOutStream::SetRestriction %u, %u\n", (unsigned)begin, (unsigned)end)); 2017 PRF(printf("\n============ CCacheOutStream::SetRestriction 0x%x, %u\n", (unsigned)begin, (unsigned)end));
1915 _restrict_begin = begin; 2018 _restrict_begin = begin;
1916 _restrict_end = end; 2019 _restrict_end = end;
1917 return WriteNonRestrictedBlocks(); 2020 return FlushNonRestrictedBlocks();
1918} 2021}
1919 2022
1920 2023
@@ -1971,6 +2074,11 @@ HRESULT Update(
1971 } 2074 }
1972 } 2075 }
1973 2076
2077 outSeqMode = (outStreamReal == NULL);
2078 if (outSeqMode)
2079 setRestriction.Release();
2080 /* CCacheOutStream works as non-restricted by default.
2081 So we use (setRestriction == NULL) for outSeqMode */
1974 // bool use_cacheStream = true; 2082 // bool use_cacheStream = true;
1975 // if (use_cacheStream) 2083 // if (use_cacheStream)
1976 { 2084 {
@@ -1980,7 +2088,8 @@ HRESULT Update(
1980 return E_OUTOFMEMORY; 2088 return E_OUTOFMEMORY;
1981 RINOK(cacheStream->Init(seqOutStream, outStreamReal, setRestriction)) 2089 RINOK(cacheStream->Init(seqOutStream, outStreamReal, setRestriction))
1982 setRestriction.Release(); 2090 setRestriction.Release();
1983 setRestriction = cacheStream; 2091 if (!outSeqMode)
2092 setRestriction = cacheStream;
1984 } 2093 }
1985 /* 2094 /*
1986 else if (!outStreamReal) 2095 else if (!outStreamReal)
@@ -1992,7 +2101,6 @@ HRESULT Update(
1992 else 2101 else
1993 outStream = outStreamReal; 2102 outStream = outStreamReal;
1994 */ 2103 */
1995 outSeqMode = (outStreamReal == NULL);
1996 } 2104 }
1997 2105
1998 COutArchive outArchive; 2106 COutArchive outArchive;
diff --git a/CPP/7zip/Archive/ZstdHandler.cpp b/CPP/7zip/Archive/ZstdHandler.cpp
new file mode 100644
index 0000000..b9c0fb7
--- /dev/null
+++ b/CPP/7zip/Archive/ZstdHandler.cpp
@@ -0,0 +1,1147 @@
1// ZstdHandler.cpp
2
3#include "StdAfx.h"
4
5// #define Z7_USE_ZSTD_ORIG_DECODER
6// #define Z7_USE_ZSTD_COMPRESSION
7
8#include "../../Common/ComTry.h"
9
10#include "../Common/MethodProps.h"
11#include "../Common/ProgressUtils.h"
12#include "../Common/RegisterArc.h"
13#include "../Common/StreamUtils.h"
14
15#include "../Compress/CopyCoder.h"
16#include "../Compress/ZstdDecoder.h"
17#ifdef Z7_USE_ZSTD_ORIG_DECODER
18#include "../Compress/Zstd2Decoder.h"
19#endif
20
21#ifdef Z7_USE_ZSTD_COMPRESSION
22#include "../Compress/ZstdEncoder.h"
23#include "../Compress/ZstdEncoderProps.h"
24#include "Common/HandlerOut.h"
25#endif
26
27#include "Common/DummyOutStream.h"
28
29#include "../../../C/CpuArch.h"
30
31using namespace NWindows;
32
33namespace NArchive {
34namespace NZstd {
35
36#define DESCRIPTOR_Get_DictionaryId_Flag(d) ((d) & 3)
37#define DESCRIPTOR_FLAG_CHECKSUM (1 << 2)
38#define DESCRIPTOR_FLAG_RESERVED (1 << 3)
39#define DESCRIPTOR_FLAG_UNUSED (1 << 4)
40#define DESCRIPTOR_FLAG_SINGLE (1 << 5)
41#define DESCRIPTOR_Get_ContentSize_Flag3(d) ((d) >> 5)
42#define DESCRIPTOR_Is_ContentSize_Defined(d) (((d) & 0xe0) != 0)
43
44struct CFrameHeader
45{
46 Byte Descriptor;
47 Byte WindowDescriptor;
48 UInt32 DictionaryId;
49 UInt64 ContentSize;
50
51 /* by zstd specification:
52 the decoder must check that (Is_Reserved() == false)
53 the decoder must ignore Unused_bit */
54 bool Is_Reserved() const { return (Descriptor & DESCRIPTOR_FLAG_RESERVED) != 0; }
55 bool Is_Checksum() const { return (Descriptor & DESCRIPTOR_FLAG_CHECKSUM) != 0; }
56 bool Is_SingleSegment() const { return (Descriptor & DESCRIPTOR_FLAG_SINGLE) != 0; }
57 bool Is_ContentSize_Defined() const { return DESCRIPTOR_Is_ContentSize_Defined(Descriptor); }
58 unsigned Get_DictionaryId_Flag() const { return DESCRIPTOR_Get_DictionaryId_Flag(Descriptor); }
59 unsigned Get_ContentSize_Flag3() const { return DESCRIPTOR_Get_ContentSize_Flag3(Descriptor); }
60
61 const Byte *Parse(const Byte *p, int size)
62 {
63 if ((unsigned)size < 2)
64 return NULL;
65 Descriptor = *p++;
66 size--;
67 {
68 Byte w = 0;
69 if (!Is_SingleSegment())
70 {
71 w = *p++;
72 size--;
73 }
74 WindowDescriptor = w;
75 }
76 {
77 unsigned n = Get_DictionaryId_Flag();
78 UInt32 d = 0;
79 if (n)
80 {
81 n = (unsigned)1 << (n - 1);
82 if ((size -= (int)n) < 0)
83 return NULL;
84 d = GetUi32(p) & ((UInt32)(Int32)-1 >> (32 - 8u * n));
85 p += n;
86 }
87 DictionaryId = d;
88 }
89 {
90 unsigned n = Get_ContentSize_Flag3();
91 UInt64 v = 0;
92 if (n)
93 {
94 n >>= 1;
95 if (n == 1)
96 v = 256;
97 n = (unsigned)1 << n;
98 if ((size -= (int)n) < 0)
99 return NULL;
100 v += GetUi64(p) & ((UInt64)(Int64)-1 >> (64 - 8u * n));
101 p += n;
102 }
103 ContentSize = v;
104 }
105 return p;
106 }
107};
108
109
110
111class CHandler Z7_final:
112 public IInArchive,
113 public IArchiveOpenSeq,
114 public ISetProperties,
115#ifdef Z7_USE_ZSTD_COMPRESSION
116 public IOutArchive,
117#endif
118 public CMyUnknownImp
119{
120 Z7_COM_QI_BEGIN2(IInArchive)
121 Z7_COM_QI_ENTRY(IArchiveOpenSeq)
122 Z7_COM_QI_ENTRY(ISetProperties)
123#ifdef Z7_USE_ZSTD_COMPRESSION
124 Z7_COM_QI_ENTRY(IOutArchive)
125#endif
126 Z7_COM_QI_END
127 Z7_COM_ADDREF_RELEASE
128
129 Z7_IFACE_COM7_IMP(IInArchive)
130 Z7_IFACE_COM7_IMP(IArchiveOpenSeq)
131 Z7_IFACE_COM7_IMP(ISetProperties)
132#ifdef Z7_USE_ZSTD_COMPRESSION
133 Z7_IFACE_COM7_IMP(IOutArchive)
134#endif
135
136 bool _isArc;
137 bool _needSeekToStart;
138 // bool _dataAfterEnd;
139 // bool _needMoreInput;
140 bool _unsupportedBlock;
141
142 bool _wasParsed;
143 bool _phySize_Decoded_Defined;
144 bool _unpackSize_Defined; // decoded
145 bool _decoded_Info_Defined;
146
147 bool _parseMode;
148 bool _disableHash;
149 // bool _smallMode;
150
151 UInt64 _phySize;
152 UInt64 _phySize_Decoded;
153 UInt64 _unpackSize;
154
155 CZstdDecInfo _parsed_Info;
156 CZstdDecInfo _decoded_Info;
157
158 CMyComPtr<IInStream> _stream;
159 CMyComPtr<ISequentialInStream> _seqStream;
160
161#ifdef Z7_USE_ZSTD_COMPRESSION
162 CSingleMethodProps _props;
163#endif
164
165public:
166 CHandler():
167 _parseMode(false),
168 _disableHash(false)
169 // _smallMode(false)
170 {}
171};
172
173
174static const Byte kProps[] =
175{
176 kpidSize,
177 kpidPackSize
178};
179
180static const Byte kArcProps[] =
181{
182 kpidNumStreams,
183 kpidNumBlocks,
184 kpidMethod,
185 // kpidChecksum
186 kpidCRC
187};
188
189IMP_IInArchive_Props
190IMP_IInArchive_ArcProps
191
192
193// static const unsigned kBlockType_Raw = 0;
194static const unsigned kBlockType_RLE = 1;
195// static const unsigned kBlockType_Compressed = 2;
196static const unsigned kBlockType_Reserved = 3;
197/*
198static const char * const kNames[] =
199{
200 "RAW"
201 , "RLE"
202 , "Compressed"
203 , "Reserved"
204};
205*/
206
207static void Add_UInt64(AString &s, const char *name, UInt64 v)
208{
209 s.Add_OptSpaced(name);
210 s.Add_Colon();
211 s.Add_UInt64(v);
212}
213
214
215static void PrintSize(AString &s, UInt64 w)
216{
217 char c = 0;
218 if ((w & ((1 << 30) - 1)) == 0) { c = 'G'; w >>= 30; }
219 else if ((w & ((1 << 20) - 1)) == 0) { c = 'M'; w >>= 20; }
220 else if ((w & ((1 << 10) - 1)) == 0) { c = 'K'; w >>= 10; }
221 s.Add_UInt64(w);
222 if (c)
223 {
224 s.Add_Char(c);
225 s += "iB";
226 }
227}
228
229
230Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
231{
232 NCOM::CPropVariant prop;
233
234 CZstdDecInfo *p = NULL;
235 if (_wasParsed || !_decoded_Info_Defined)
236 p = &_parsed_Info;
237 else if (_decoded_Info_Defined)
238 p = &_decoded_Info;
239
240 switch (propID)
241 {
242 case kpidPhySize:
243 if (_wasParsed)
244 prop = _phySize;
245 else if (_phySize_Decoded_Defined)
246 prop = _phySize_Decoded;
247 break;
248
249 case kpidUnpackSize:
250 if (_unpackSize_Defined)
251 prop = _unpackSize;
252 break;
253
254 case kpidNumStreams:
255 if (p)
256 if (_wasParsed || _decoded_Info_Defined)
257 prop = p->num_DataFrames;
258 break;
259
260 case kpidNumBlocks:
261 if (p)
262 if (_wasParsed || _decoded_Info_Defined)
263 prop = p->num_Blocks;
264 break;
265
266 // case kpidChecksum:
267 case kpidCRC:
268 if (p)
269 if (p->checksum_Defined && p->num_DataFrames == 1)
270 prop = p->checksum; // it's checksum from last frame
271 break;
272
273 case kpidMethod:
274 {
275 AString s;
276 s.Add_OptSpaced(p == &_decoded_Info ?
277 "decoded:" : _wasParsed ?
278 "parsed:" :
279 "header-open-only:");
280
281 if (p->dictionaryId != 0)
282 {
283 if (p->are_DictionaryId_Different)
284 s.Add_OptSpaced("different-dictionary-IDs");
285 s.Add_OptSpaced("dictionary-ID:");
286 s.Add_UInt32(p->dictionaryId);
287 }
288 /*
289 if (ContentSize_Defined)
290 {
291 s.Add_OptSpaced("ContentSize=");
292 s.Add_UInt64(ContentSize_Total);
293 }
294 */
295 // if (p->are_Checksums)
296 if (p->descriptor_OR & DESCRIPTOR_FLAG_CHECKSUM)
297 s.Add_OptSpaced("XXH64");
298 if (p->descriptor_NOT_OR & DESCRIPTOR_FLAG_CHECKSUM)
299 s.Add_OptSpaced("NO-XXH64");
300
301 if (p->descriptor_OR & DESCRIPTOR_FLAG_UNUSED)
302 s.Add_OptSpaced("unused_bit");
303
304 if (p->descriptor_OR & DESCRIPTOR_FLAG_SINGLE)
305 s.Add_OptSpaced("single-segments");
306
307 if (p->descriptor_NOT_OR & DESCRIPTOR_FLAG_SINGLE)
308 {
309 // Add_UInt64(s, "wnd-descriptors", p->num_WindowDescriptors);
310 s.Add_OptSpaced("wnd-desc-log-MAX:");
311 // WindowDescriptor_MAX = 16 << 3; // for debug
312 const unsigned e = p->windowDescriptor_MAX >> 3;
313 s.Add_UInt32(e + 10);
314 const unsigned m = p->windowDescriptor_MAX & 7;
315 if (m != 0)
316 {
317 s.Add_Dot();
318 s.Add_UInt32(m);
319 }
320 }
321
322 if (DESCRIPTOR_Is_ContentSize_Defined(p->descriptor_OR) ||
323 (p->descriptor_NOT_OR & DESCRIPTOR_FLAG_SINGLE))
324 /*
325 if (p->are_ContentSize_Known ||
326 p->are_WindowDescriptors)
327 */
328 {
329 s.Add_OptSpaced("wnd-MAX:");
330 PrintSize(s, p->windowSize_MAX);
331 if (p->windowSize_MAX != p->windowSize_Allocate_MAX)
332 {
333 s.Add_OptSpaced("wnd-use-MAX:");
334 PrintSize(s, p->windowSize_Allocate_MAX);
335 }
336 }
337
338 if (p->num_DataFrames != 1)
339 Add_UInt64(s, "data-frames", p->num_DataFrames);
340 if (p->num_SkipFrames != 0)
341 {
342 Add_UInt64(s, "skip-frames", p->num_SkipFrames);
343 Add_UInt64(s, "skip-frames-size-total", p->skipFrames_Size);
344 }
345
346 if (p->are_ContentSize_Unknown)
347 s.Add_OptSpaced("unknown-content-size");
348
349 if (DESCRIPTOR_Is_ContentSize_Defined(p->descriptor_OR))
350 {
351 Add_UInt64(s, "content-size-frame-max", p->contentSize_MAX);
352 Add_UInt64(s, "content-size-total", p->contentSize_Total);
353 }
354
355 /*
356 for (unsigned i = 0; i < 4; i++)
357 {
358 const UInt64 n = p->num_Blocks_forType[i];
359 if (n)
360 {
361 s.Add_OptSpaced(kNames[i]);
362 s += "-blocks:";
363 s.Add_UInt64(n);
364
365 s.Add_OptSpaced(kNames[i]);
366 s += "-block-bytes:";
367 s.Add_UInt64(p->num_BlockBytes_forType[i]);
368 }
369 }
370 */
371 prop = s;
372 break;
373 }
374
375 case kpidErrorFlags:
376 {
377 UInt32 v = 0;
378 if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
379 // if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
380 // if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
381 if (_unsupportedBlock) v |= kpv_ErrorFlags_UnsupportedMethod;
382 /*
383 if (_parsed_Info.numBlocks_forType[kBlockType_Reserved])
384 v |= kpv_ErrorFlags_UnsupportedMethod;
385 */
386 prop = v;
387 break;
388 }
389
390 default: break;
391 }
392 prop.Detach(value);
393 return S_OK;
394}
395
396
397Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
398{
399 *numItems = 1;
400 return S_OK;
401}
402
403Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
404{
405 NCOM::CPropVariant prop;
406 switch (propID)
407 {
408 case kpidPackSize:
409 if (_wasParsed)
410 prop = _phySize;
411 else if (_phySize_Decoded_Defined)
412 prop = _phySize_Decoded;
413 break;
414
415 case kpidSize:
416 if (_wasParsed && !_parsed_Info.are_ContentSize_Unknown)
417 prop = _parsed_Info.contentSize_Total;
418 else if (_unpackSize_Defined)
419 prop = _unpackSize;
420 break;
421
422 default: break;
423 }
424 prop.Detach(value);
425 return S_OK;
426}
427
428static const unsigned kSignatureSize = 4;
429static const Byte k_Signature[kSignatureSize] = { 0x28, 0xb5, 0x2f, 0xfd } ;
430
431static const UInt32 kDataFrameSignature32 = 0xfd2fb528;
432static const UInt32 kSkipFrameSignature = 0x184d2a50;
433static const UInt32 kSkipFrameSignature_Mask = 0xfffffff0;
434
435/*
436API_FUNC_static_IsArc IsArc_Zstd(const Byte *p, size_t size)
437{
438 if (size < kSignatureSize)
439 return k_IsArc_Res_NEED_MORE;
440 if (memcmp(p, k_Signature, kSignatureSize) != 0)
441 {
442 const UInt32 v = GetUi32(p);
443 if ((v & kSkipFrameSignature_Mask) != kSkipFrameSignature)
444 return k_IsArc_Res_NO;
445 return k_IsArc_Res_YES;
446 }
447 p += 4;
448 // return k_IsArc_Res_YES;
449}
450}
451*/
452
453// kBufSize must be >= (ZSTD_FRAMEHEADERSIZE_MAX = 18)
454// we use big buffer for fast parsing of worst case small blocks.
455static const unsigned kBufSize =
456 1 << 9;
457 // 1 << 14; // fastest in real file
458
459struct CStreamBuffer
460{
461 unsigned pos;
462 unsigned lim;
463 IInStream *Stream;
464 UInt64 StreamOffset;
465 Byte buf[kBufSize];
466
467 CStreamBuffer():
468 pos(0),
469 lim(0),
470 StreamOffset(0)
471 {}
472 unsigned Avail() const { return lim - pos; }
473 const Byte *GetPtr() const { return &buf[pos]; }
474 UInt64 GetCurOffset() const { return StreamOffset - Avail(); }
475 void SkipInBuf(UInt32 size) { pos += size; }
476 HRESULT Skip(UInt32 size);
477 HRESULT Read(unsigned num);
478};
479
480HRESULT CStreamBuffer::Skip(UInt32 size)
481{
482 unsigned rem = lim - pos;
483 if (rem != 0)
484 {
485 if (rem > size)
486 rem = size;
487 pos += rem;
488 size -= rem;
489 if (pos != lim)
490 return S_OK;
491 }
492 if (size == 0)
493 return S_OK;
494 return Stream->Seek(size, STREAM_SEEK_CUR, &StreamOffset);
495}
496
497HRESULT CStreamBuffer::Read(unsigned num)
498{
499 if (lim - pos >= num)
500 return S_OK;
501 if (pos != 0)
502 {
503 lim -= pos;
504 memmove(buf, buf + pos, lim);
505 pos = 0;
506 }
507 size_t processed = kBufSize - ((unsigned)StreamOffset & (kBufSize - 1));
508 const unsigned avail = kBufSize - lim;
509 num -= lim;
510 if (avail < processed || processed < num)
511 processed = avail;
512 const HRESULT res = ReadStream(Stream, buf + lim, &processed);
513 StreamOffset += processed;
514 lim += (unsigned)processed;
515 return res;
516}
517
518
519static const unsigned k_ZSTD_FRAMEHEADERSIZE_MAX = 4 + 14;
520
521Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))
522{
523 COM_TRY_BEGIN
524 Close();
525
526 CZstdDecInfo *p = &_parsed_Info;
527 // p->are_ContentSize_Unknown = False;
528 CStreamBuffer sb;
529 sb.Stream = stream;
530
531 for (;;)
532 {
533 RINOK(sb.Read(k_ZSTD_FRAMEHEADERSIZE_MAX))
534 if (sb.Avail() < kSignatureSize)
535 break;
536
537 if (callback && (ZstdDecInfo_GET_NUM_FRAMES(p) & 0xFFF) == 2)
538 {
539 const UInt64 numBytes = sb.GetCurOffset();
540 RINOK(callback->SetCompleted(NULL, &numBytes))
541 }
542
543 const UInt32 v = GetUi32(sb.GetPtr());
544 if (v != kDataFrameSignature32)
545 {
546 if ((v & kSkipFrameSignature_Mask) != kSkipFrameSignature)
547 break;
548 _phySize = sb.GetCurOffset() + 8;
549 p->num_SkipFrames++;
550 sb.SkipInBuf(4);
551 if (sb.Avail() < 4)
552 break;
553 const UInt32 size = GetUi32(sb.GetPtr());
554 p->skipFrames_Size += size;
555 sb.SkipInBuf(4);
556 _phySize = sb.GetCurOffset() + size;
557 RINOK(sb.Skip(size))
558 continue;
559 }
560
561 p->num_DataFrames++;
562 // _numStreams_Defined = true;
563 sb.SkipInBuf(4);
564 CFrameHeader fh;
565 {
566 const Byte *data = fh.Parse(sb.GetPtr(), (int)sb.Avail());
567 if (!data)
568 {
569 // _needMoreInput = true;
570 // we set size for one byte more to show that stream was truncated
571 _phySize = sb.StreamOffset + 1;
572 break;
573 }
574 if (fh.Is_Reserved())
575 {
576 // we don't want false detection
577 if (ZstdDecInfo_GET_NUM_FRAMES(p) == 1)
578 return S_FALSE;
579 // _phySize = sb.GetCurOffset();
580 break;
581 }
582 sb.SkipInBuf((unsigned)(data - sb.GetPtr()));
583 }
584
585 p->descriptor_OR = (Byte)(p->descriptor_OR | fh.Descriptor);
586 p->descriptor_NOT_OR = (Byte)(p->descriptor_NOT_OR | ~fh.Descriptor);
587
588 // _numBlocks_Defined = true;
589 // if (fh.Get_DictionaryId_Flag())
590 // p->dictionaryId_Cur = fh.DictionaryId;
591 if (fh.DictionaryId != 0)
592 {
593 if (p->dictionaryId == 0)
594 p->dictionaryId = fh.DictionaryId;
595 else if (p->dictionaryId != fh.DictionaryId)
596 p->are_DictionaryId_Different = True;
597 }
598
599 UInt32 blockSizeAllowedMax = (UInt32)1 << 17;
600 {
601 UInt64 winSize = fh.ContentSize;
602 UInt64 winSize_forAllocate = fh.ContentSize;
603 if (!fh.Is_SingleSegment())
604 {
605 if (p->windowDescriptor_MAX < fh.WindowDescriptor)
606 p->windowDescriptor_MAX = fh.WindowDescriptor;
607 const unsigned e = (fh.WindowDescriptor >> 3);
608 const unsigned m = (fh.WindowDescriptor & 7);
609 winSize = (UInt64)(8 + m) << (e + 10 - 3);
610 if (!fh.Is_ContentSize_Defined()
611 || fh.DictionaryId != 0
612 || winSize_forAllocate > winSize)
613 winSize_forAllocate = winSize;
614 // p->are_WindowDescriptors = true;
615 }
616 else
617 {
618 // p->are_SingleSegments = True;
619 }
620 if (blockSizeAllowedMax > winSize)
621 blockSizeAllowedMax = (UInt32)winSize;
622 if (p->windowSize_MAX < winSize)
623 p->windowSize_MAX = winSize;
624 if (p->windowSize_Allocate_MAX < winSize_forAllocate)
625 p->windowSize_Allocate_MAX = winSize_forAllocate;
626 }
627
628 if (fh.Is_ContentSize_Defined())
629 {
630 // p->are_ContentSize_Known = True;
631 p->contentSize_Total += fh.ContentSize;
632 if (p->contentSize_MAX < fh.ContentSize)
633 p->contentSize_MAX = fh.ContentSize;
634 }
635 else
636 {
637 p->are_ContentSize_Unknown = True;
638 }
639
640 p->checksum_Defined = false;
641
642 // p->numBlocks_forType[3] += 99; // for debug
643
644 if (!_parseMode)
645 {
646 if (ZstdDecInfo_GET_NUM_FRAMES(p) == 1)
647 break;
648 }
649
650 _wasParsed = true;
651
652 bool blocksWereParsed = false;
653
654 for (;;)
655 {
656 if (callback && (p->num_Blocks & 0xFFF) == 2)
657 {
658 // Sleep(10);
659 const UInt64 numBytes = sb.GetCurOffset();
660 RINOK(callback->SetCompleted(NULL, &numBytes))
661 }
662 _phySize = sb.GetCurOffset() + 3;
663 RINOK(sb.Read(3))
664 if (sb.Avail() < 3)
665 {
666 // _needMoreInput = true;
667 // return S_FALSE;
668 break; // change it
669 }
670 const unsigned pos = sb.pos;
671 sb.pos = pos + 3;
672 UInt32 b = 0;
673 b += (UInt32)sb.buf[pos];
674 b += (UInt32)sb.buf[pos + 1] << (8 * 1);
675 b += (UInt32)sb.buf[pos + 2] << (8 * 2);
676 p->num_Blocks++;
677 const unsigned blockType = (b >> 1) & 3;
678 UInt32 size = b >> 3;
679 // p->num_Blocks_forType[blockType]++;
680 // p->num_BlockBytes_forType[blockType] += size;
681 if (size > blockSizeAllowedMax
682 || blockType == kBlockType_Reserved)
683 {
684 _unsupportedBlock = true;
685 if (ZstdDecInfo_GET_NUM_FRAMES(p) == 1 && p->num_Blocks == 1)
686 return S_FALSE;
687 break;
688 }
689 if (blockType == kBlockType_RLE)
690 size = 1;
691 _phySize = sb.GetCurOffset() + size;
692 RINOK(sb.Skip(size))
693 if (b & 1)
694 {
695 // it's last block
696 blocksWereParsed = true;
697 break;
698 }
699 }
700
701 if (!blocksWereParsed)
702 break;
703
704 if (fh.Is_Checksum())
705 {
706 _phySize = sb.GetCurOffset() + 4;
707 RINOK(sb.Read(4))
708 if (sb.Avail() < 4)
709 break;
710 p->checksum_Defined = true;
711 // if (p->num_DataFrames == 1)
712 p->checksum = GetUi32(sb.GetPtr());
713 sb.SkipInBuf(4);
714 }
715 }
716
717 if (ZstdDecInfo_GET_NUM_FRAMES(p) == 0)
718 return S_FALSE;
719
720 _needSeekToStart = true;
721 // } // _parseMode
722 _isArc = true;
723 _stream = stream;
724 _seqStream = stream;
725
726 return S_OK;
727 COM_TRY_END
728}
729
730
731Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))
732{
733 Close();
734 _isArc = true;
735 _seqStream = stream;
736 return S_OK;
737}
738
739
740Z7_COM7F_IMF(CHandler::Close())
741{
742 _isArc = false;
743 _needSeekToStart = false;
744 // _dataAfterEnd = false;
745 // _needMoreInput = false;
746 _unsupportedBlock = false;
747
748 _wasParsed = false;
749 _phySize_Decoded_Defined = false;
750 _unpackSize_Defined = false;
751 _decoded_Info_Defined = false;
752
753 ZstdDecInfo_CLEAR(&_parsed_Info)
754 ZstdDecInfo_CLEAR(&_decoded_Info)
755
756 _phySize = 0;
757 _phySize_Decoded = 0;
758 _unpackSize = 0;
759
760 _seqStream.Release();
761 _stream.Release();
762 return S_OK;
763}
764
765
766Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
767 Int32 testMode, IArchiveExtractCallback *extractCallback))
768{
769 COM_TRY_BEGIN
770 if (numItems == 0)
771 return S_OK;
772 if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
773 return E_INVALIDARG;
774 if (_wasParsed)
775 {
776 RINOK(extractCallback->SetTotal(_phySize))
777 }
778
779 Int32 opRes;
780 {
781 CMyComPtr<ISequentialOutStream> realOutStream;
782 const Int32 askMode = testMode ?
783 NExtract::NAskMode::kTest :
784 NExtract::NAskMode::kExtract;
785 RINOK(extractCallback->GetStream(0, &realOutStream, askMode))
786 if (!testMode && !realOutStream)
787 return S_OK;
788
789 extractCallback->PrepareOperation(askMode);
790
791 if (_needSeekToStart)
792 {
793 if (!_stream)
794 return E_FAIL;
795 RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL))
796 }
797 else
798 _needSeekToStart = true;
799
800 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
801 lps->Init(extractCallback, true);
802
803#ifdef Z7_USE_ZSTD_ORIG_DECODER
804 CMyComPtr2_Create<ICompressCoder, NCompress::NZstd2::CDecoder> decoder;
805#else
806 CMyComPtr2_Create<ICompressCoder, NCompress::NZstd::CDecoder> decoder;
807#endif
808
809 CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStreamSpec;
810 outStreamSpec->SetStream(realOutStream);
811 outStreamSpec->Init();
812 // realOutStream.Release();
813
814 decoder->FinishMode = true;
815#ifndef Z7_USE_ZSTD_ORIG_DECODER
816 decoder->DisableHash = _disableHash;
817#endif
818
819 // _dataAfterEnd = false;
820 // _needMoreInput = false;
821 const HRESULT hres = decoder.Interface()->Code(_seqStream, outStreamSpec, NULL, NULL, lps);
822 /*
823 {
824 UInt64 t1 = decoder->GetInputProcessedSize();
825 // for debug
826 const UInt32 kTempSize = 64;
827 Byte buf[kTempSize];
828 UInt32 processedSize = 0;
829 RINOK(decoder->ReadUnusedFromInBuf(buf, kTempSize, &processedSize))
830 processedSize -= processedSize;
831 UInt64 t2 = decoder->GetInputProcessedSize();
832 t2 = t2;
833 t1 = t1;
834 }
835 */
836 const UInt64 outSize = outStreamSpec->GetSize();
837 // }
838
839 // if (hres == E_ABORT) return hres;
840 opRes = NExtract::NOperationResult::kDataError;
841
842 if (hres == E_OUTOFMEMORY)
843 {
844 return hres;
845 // opRes = NExtract::NOperationResult::kMemError;
846 }
847 else if (hres == S_OK || hres == S_FALSE)
848 {
849#ifndef Z7_USE_ZSTD_ORIG_DECODER
850 _decoded_Info_Defined = true;
851 _decoded_Info = decoder->_state.info;
852 // NumDataFrames_Decoded = decoder->_state.info.num_DataFrames;
853 // NumSkipFrames_Decoded = decoder->_state.info.num_SkipFrames;
854 const UInt64 inSize = decoder->_inProcessed;
855#else
856 const UInt64 inSize = decoder->GetInputProcessedSize();
857#endif
858 _phySize_Decoded = inSize;
859 _phySize_Decoded_Defined = true;
860
861 _unpackSize_Defined = true;
862 _unpackSize = outSize;
863
864 // RINOK(
865 lps.Interface()->SetRatioInfo(&inSize, &outSize);
866
867#ifdef Z7_USE_ZSTD_ORIG_DECODER
868 if (hres == S_OK)
869 opRes = NExtract::NOperationResult::kOK;
870#else
871 if (decoder->ResInfo.decode_SRes == SZ_ERROR_CRC)
872 {
873 opRes = NExtract::NOperationResult::kCRCError;
874 }
875 else if (decoder->ResInfo.decode_SRes == SZ_ERROR_NO_ARCHIVE)
876 {
877 _isArc = false;
878 opRes = NExtract::NOperationResult::kIsNotArc;
879 }
880 else if (decoder->ResInfo.decode_SRes == SZ_ERROR_INPUT_EOF)
881 opRes = NExtract::NOperationResult::kUnexpectedEnd;
882 else
883 {
884 if (hres == S_OK && decoder->ResInfo.decode_SRes == SZ_OK)
885 opRes = NExtract::NOperationResult::kOK;
886 if (decoder->ResInfo.extraSize)
887 {
888 // if (inSize == 0) _isArc = false;
889 opRes = NExtract::NOperationResult::kDataAfterEnd;
890 }
891 /*
892 if (decoder->ResInfo.unexpededEnd)
893 opRes = NExtract::NOperationResult::kUnexpectedEnd;
894 */
895 }
896#endif
897 }
898 else if (hres == E_NOTIMPL)
899 {
900 opRes = NExtract::NOperationResult::kUnsupportedMethod;
901 }
902 else
903 return hres;
904 }
905
906 return extractCallback->SetOperationResult(opRes);
907
908 COM_TRY_END
909}
910
911
912
913Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
914{
915 // return _props.SetProperties(names, values, numProps);
916 // _smallMode = false;
917 _disableHash = false;
918 _parseMode = false;
919 // _parseMode = true; // for debug
920#ifdef Z7_USE_ZSTD_COMPRESSION
921 _props.Init();
922#endif
923
924 for (UInt32 i = 0; i < numProps; i++)
925 {
926 UString name = names[i];
927 const PROPVARIANT &value = values[i];
928
929 if (name.IsEqualTo("parse"))
930 {
931 bool parseMode = true;
932 RINOK(PROPVARIANT_to_bool(value, parseMode))
933 _parseMode = parseMode;
934 continue;
935 }
936 if (name.IsPrefixedBy_Ascii_NoCase("crc"))
937 {
938 name.Delete(0, 3);
939 UInt32 crcSize = 4;
940 RINOK(ParsePropToUInt32(name, value, crcSize))
941 if (crcSize == 0)
942 _disableHash = true;
943 else if (crcSize == 4)
944 _disableHash = false;
945 else
946 return E_INVALIDARG;
947 continue;
948 }
949#ifdef Z7_USE_ZSTD_COMPRESSION
950 /*
951 if (name.IsEqualTo("small"))
952 {
953 bool smallMode = true;
954 RINOK(PROPVARIANT_to_bool(value, smallMode))
955 _smallMode = smallMode;
956 continue;
957 }
958 */
959 RINOK(_props.SetProperty(names[i], value))
960#endif
961 }
962 return S_OK;
963}
964
965
966
967
968#ifdef Z7_USE_ZSTD_COMPRESSION
969
970Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType))
971{
972 *timeType = GET_FileTimeType_NotDefined_for_GetFileTimeType;
973 // *timeType = NFileTimeType::kUnix;
974 return S_OK;
975}
976
977
978Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
979 IArchiveUpdateCallback *updateCallback))
980{
981 COM_TRY_BEGIN
982
983 if (numItems != 1)
984 return E_INVALIDARG;
985 {
986 CMyComPtr<IStreamSetRestriction> setRestriction;
987 outStream->QueryInterface(IID_IStreamSetRestriction, (void **)&setRestriction);
988 if (setRestriction)
989 RINOK(setRestriction->SetRestriction(0, 0))
990 }
991 Int32 newData, newProps;
992 UInt32 indexInArchive;
993 if (!updateCallback)
994 return E_FAIL;
995 RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive))
996
997 if (IntToBool(newProps))
998 {
999 {
1000 NCOM::CPropVariant prop;
1001 RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop))
1002 if (prop.vt != VT_EMPTY)
1003 if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
1004 return E_INVALIDARG;
1005 }
1006 }
1007
1008 if (IntToBool(newData))
1009 {
1010 UInt64 size;
1011 {
1012 NCOM::CPropVariant prop;
1013 RINOK(updateCallback->GetProperty(0, kpidSize, &prop))
1014 if (prop.vt != VT_UI8)
1015 return E_INVALIDARG;
1016 size = prop.uhVal.QuadPart;
1017 }
1018
1019 if (!_props.MethodName.IsEmpty()
1020 && !_props.MethodName.IsEqualTo_Ascii_NoCase("zstd"))
1021 return E_INVALIDARG;
1022
1023 {
1024 CMyComPtr<ISequentialInStream> fileInStream;
1025 RINOK(updateCallback->GetStream(0, &fileInStream))
1026 if (!fileInStream)
1027 return S_FALSE;
1028 {
1029 CMyComPtr<IStreamGetSize> streamGetSize;
1030 fileInStream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
1031 if (streamGetSize)
1032 {
1033 UInt64 size2;
1034 if (streamGetSize->GetSize(&size2) == S_OK)
1035 size = size2;
1036 }
1037 }
1038 RINOK(updateCallback->SetTotal(size))
1039
1040 CMethodProps props2 = _props;
1041
1042#ifndef Z7_ST
1043 /*
1044 CSingleMethodProps (_props)
1045 derives from
1046 CMethodProps (props2)
1047 So we transfer additional variable (num Threads) to CMethodProps list of properties
1048 */
1049
1050 UInt32 numThreads = _props._numThreads;
1051
1052 if (numThreads > Z7_ZSTDMT_NBWORKERS_MAX)
1053 numThreads = Z7_ZSTDMT_NBWORKERS_MAX;
1054
1055 if (_props.FindProp(NCoderPropID::kNumThreads) < 0)
1056 {
1057 if (!_props._numThreads_WasForced
1058 && numThreads >= 1
1059 && _props._memUsage_WasSet)
1060 {
1061 NCompress::NZstd::CEncoderProps zstdProps;
1062 RINOK(zstdProps.SetFromMethodProps(_props))
1063 ZstdEncProps_NormalizeFull(&zstdProps.EncProps);
1064 numThreads = ZstdEncProps_GetNumThreads_for_MemUsageLimit(
1065 &zstdProps.EncProps, _props._memUsage_Compress, numThreads);
1066 }
1067 props2.AddProp_NumThreads(numThreads);
1068 }
1069
1070#endif // Z7_ST
1071
1072 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1073 lps->Init(updateCallback, true);
1074 {
1075 CMyComPtr2_Create<ICompressCoder, NCompress::NZstd::CEncoder> encoder;
1076 // size = 1 << 24; // for debug
1077 RINOK(props2.SetCoderProps(encoder.ClsPtr(), size != (UInt64)(Int64)-1 ? &size : NULL))
1078 // encoderSpec->_props.SmallFileOpt = _smallMode;
1079 // we must set kExpectedDataSize just before Code().
1080 encoder->SrcSizeHint64 = size;
1081 /*
1082 CMyComPtr<ICompressSetCoderPropertiesOpt> optProps;
1083 _compressEncoder->QueryInterface(IID_ICompressSetCoderPropertiesOpt, (void**)&optProps);
1084 if (optProps)
1085 {
1086 PROPID propID = NCoderPropID::kExpectedDataSize;
1087 NWindows::NCOM::CPropVariant prop = (UInt64)size;
1088 // RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1))
1089 RINOK(encoderSpec->SetCoderPropertiesOpt(&propID, &prop, 1))
1090 }
1091 */
1092 RINOK(encoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps))
1093 }
1094 }
1095 return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
1096 }
1097
1098 if (indexInArchive != 0)
1099 return E_INVALIDARG;
1100
1101 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1102 lps->Init(updateCallback, true);
1103
1104 CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
1105 updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
1106 if (opCallback)
1107 {
1108 RINOK(opCallback->ReportOperation(
1109 NEventIndexType::kInArcIndex, 0,
1110 NUpdateNotifyOp::kReplicate))
1111 }
1112
1113 if (_stream)
1114 RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL))
1115
1116 return NCompress::CopyStream(_stream, outStream, lps);
1117
1118 COM_TRY_END
1119}
1120#endif
1121
1122
1123
1124#ifndef Z7_USE_ZSTD_COMPRESSION
1125#undef IMP_CreateArcOut
1126#define IMP_CreateArcOut
1127#undef CreateArcOut
1128#define CreateArcOut NULL
1129#endif
1130
1131#ifdef Z7_USE_ZSTD_COMPRESSION
1132REGISTER_ARC_IO(
1133 "zstd2", "zst tzst", "* .tar", 0xe + 1,
1134 k_Signature, 0
1135 , NArcInfoFlags::kKeepName
1136 , 0
1137 , NULL)
1138#else
1139REGISTER_ARC_IO(
1140 "zstd", "zst tzst", "* .tar", 0xe,
1141 k_Signature, 0
1142 , NArcInfoFlags::kKeepName
1143 , 0
1144 , NULL)
1145#endif
1146
1147}}
diff --git a/CPP/7zip/Asm.mak b/CPP/7zip/Asm.mak
index c4073e8..4ee0823 100644
--- a/CPP/7zip/Asm.mak
+++ b/CPP/7zip/Asm.mak
@@ -1,8 +1,11 @@
1!IFDEF ASM_OBJS 1!IFDEF ASM_OBJS
2!IF "$(CPU)" == "ARM" 2!IF "$(PLATFORM)" == "arm64"
3$(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm 3$(ASM_OBJS): ../../../../Asm/arm64/$(*B).S
4 $(COMPL_ASM_CLANG)
5!ELSEIF "$(PLATFORM)" == "arm"
6$(ASM_OBJS): ../../../../Asm/arm/$(*B).asm
4 $(COMPL_ASM) 7 $(COMPL_ASM)
5!ELSEIF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM64" 8!ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips"
6$(ASM_OBJS): ../../../../Asm/x86/$(*B).asm 9$(ASM_OBJS): ../../../../Asm/x86/$(*B).asm
7 $(COMPL_ASM) 10 $(COMPL_ASM)
8!ENDIF 11!ENDIF
diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp
index 65c81c4..beed5a7 100644
--- a/CPP/7zip/Bundles/Alone/Alone.dsp
+++ b/CPP/7zip/Bundles/Alone/Alone.dsp
@@ -69,8 +69,7 @@ LINK32=link.exe
69# PROP Ignore_Export_Lib 0 69# PROP Ignore_Export_Lib 0
70# PROP Target_Dir "" 70# PROP Target_Dir ""
71# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 71# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
72# ADD CPP /nologo /Gz /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "Z7_LONG_PATH" /D "Z7_LARGE_PAGES" /D "Z7_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c 72# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "Z7_LONG_PATH" /D "Z7_LARGE_PAGES" /D "Z7_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
73# SUBTRACT CPP /WX
74# ADD BASE RSC /l 0x419 /d "_DEBUG" 73# ADD BASE RSC /l 0x419 /d "_DEBUG"
75# ADD RSC /l 0x419 /d "_DEBUG" 74# ADD RSC /l 0x419 /d "_DEBUG"
76BSC32=bscmake.exe 75BSC32=bscmake.exe
@@ -194,6 +193,7 @@ SOURCE=..\..\UI\Console\List.h
194# Begin Source File 193# Begin Source File
195 194
196SOURCE=..\..\UI\Console\Main.cpp 195SOURCE=..\..\UI\Console\Main.cpp
196# ADD CPP /D "Z7_PROG_VARIANT_A"
197# End Source File 197# End Source File
198# Begin Source File 198# Begin Source File
199 199
@@ -274,6 +274,10 @@ SOURCE=..\..\..\Common\Common.h
274# End Source File 274# End Source File
275# Begin Source File 275# Begin Source File
276 276
277SOURCE=..\..\..\Common\Common0.h
278# End Source File
279# Begin Source File
280
277SOURCE=..\..\..\Common\ComTry.h 281SOURCE=..\..\..\Common\ComTry.h
278# End Source File 282# End Source File
279# Begin Source File 283# Begin Source File
@@ -450,6 +454,10 @@ SOURCE=..\..\..\Common\Wildcard.h
450# End Source File 454# End Source File
451# Begin Source File 455# Begin Source File
452 456
457SOURCE=..\..\..\Common\Xxh64Reg.cpp
458# End Source File
459# Begin Source File
460
453SOURCE=..\..\..\Common\XzCrc64Init.cpp 461SOURCE=..\..\..\Common\XzCrc64Init.cpp
454# End Source File 462# End Source File
455# Begin Source File 463# Begin Source File
@@ -1190,6 +1198,20 @@ SOURCE=..\..\Compress\Lzx.h
1190# Begin Source File 1198# Begin Source File
1191 1199
1192SOURCE=..\..\Compress\LzxDecoder.cpp 1200SOURCE=..\..\Compress\LzxDecoder.cpp
1201
1202!IF "$(CFG)" == "Alone - Win32 Release"
1203
1204# ADD CPP /O2
1205# SUBTRACT CPP /YX /Yc /Yu
1206
1207!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
1208
1209!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
1210
1211!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
1212
1213!ENDIF
1214
1193# End Source File 1215# End Source File
1194# Begin Source File 1216# Begin Source File
1195 1217
@@ -1202,6 +1224,20 @@ SOURCE=..\..\Compress\LzxDecoder.h
1202# Begin Source File 1224# Begin Source File
1203 1225
1204SOURCE=..\..\Compress\QuantumDecoder.cpp 1226SOURCE=..\..\Compress\QuantumDecoder.cpp
1227
1228!IF "$(CFG)" == "Alone - Win32 Release"
1229
1230# ADD CPP /O2
1231# SUBTRACT CPP /YX /Yc /Yu
1232
1233!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
1234
1235!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
1236
1237!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
1238
1239!ENDIF
1240
1205# End Source File 1241# End Source File
1206# Begin Source File 1242# Begin Source File
1207 1243
@@ -1300,6 +1336,14 @@ SOURCE=..\..\Compress\XzEncoder.cpp
1300 1336
1301SOURCE=..\..\Compress\XzEncoder.h 1337SOURCE=..\..\Compress\XzEncoder.h
1302# End Source File 1338# End Source File
1339# Begin Source File
1340
1341SOURCE=..\..\Compress\ZstdDecoder.cpp
1342# End Source File
1343# Begin Source File
1344
1345SOURCE=..\..\Compress\ZstdDecoder.h
1346# End Source File
1303# End Group 1347# End Group
1304# Begin Group "Archive" 1348# Begin Group "Archive"
1305 1349
@@ -1486,6 +1530,8 @@ SOURCE=..\..\Archive\Zip\ZipCompressionMode.h
1486# Begin Source File 1530# Begin Source File
1487 1531
1488SOURCE=..\..\Archive\Zip\ZipHandler.cpp 1532SOURCE=..\..\Archive\Zip\ZipHandler.cpp
1533# ADD CPP /D "Z7_ZIP_LZFSE_DISABLE"
1534# SUBTRACT CPP /YX /Yc /Yu
1489# End Source File 1535# End Source File
1490# Begin Source File 1536# Begin Source File
1491 1537
@@ -1692,6 +1738,10 @@ SOURCE=..\..\Archive\SplitHandler.cpp
1692 1738
1693SOURCE=..\..\Archive\XzHandler.cpp 1739SOURCE=..\..\Archive\XzHandler.cpp
1694# End Source File 1740# End Source File
1741# Begin Source File
1742
1743SOURCE=..\..\Archive\ZstdHandler.cpp
1744# End Source File
1695# End Group 1745# End Group
1696# Begin Group "UI Common" 1746# Begin Group "UI Common"
1697 1747
@@ -3077,6 +3127,10 @@ SOURCE=..\..\..\..\C\Ppmd8Enc.c
3077# End Source File 3127# End Source File
3078# Begin Source File 3128# Begin Source File
3079 3129
3130SOURCE=..\..\..\..\C\Precomp.h
3131# End Source File
3132# Begin Source File
3133
3080SOURCE=..\..\..\..\C\RotateDefs.h 3134SOURCE=..\..\..\..\C\RotateDefs.h
3081# End Source File 3135# End Source File
3082# Begin Source File 3136# Begin Source File
@@ -3229,6 +3283,62 @@ SOURCE=..\..\..\..\C\Threads.c
3229 3283
3230SOURCE=..\..\..\..\C\Threads.h 3284SOURCE=..\..\..\..\C\Threads.h
3231# End Source File 3285# End Source File
3286# Begin Source File
3287
3288SOURCE=..\..\..\..\C\Xxh64.c
3289
3290!IF "$(CFG)" == "Alone - Win32 Release"
3291
3292# ADD CPP /O2
3293# SUBTRACT CPP /YX /Yc /Yu
3294
3295!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
3296
3297# SUBTRACT CPP /YX /Yc /Yu
3298
3299!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
3300
3301# SUBTRACT CPP /YX /Yc /Yu
3302
3303!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
3304
3305# SUBTRACT CPP /YX /Yc /Yu
3306
3307!ENDIF
3308
3309# End Source File
3310# Begin Source File
3311
3312SOURCE=..\..\..\..\C\Xxh64.h
3313# End Source File
3314# Begin Source File
3315
3316SOURCE=..\..\..\..\C\ZstdDec.c
3317
3318!IF "$(CFG)" == "Alone - Win32 Release"
3319
3320# ADD CPP /O2
3321# SUBTRACT CPP /YX /Yc /Yu
3322
3323!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
3324
3325# SUBTRACT CPP /YX /Yc /Yu
3326
3327!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
3328
3329# SUBTRACT CPP /YX /Yc /Yu
3330
3331!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
3332
3333# SUBTRACT CPP /YX /Yc /Yu
3334
3335!ENDIF
3336
3337# End Source File
3338# Begin Source File
3339
3340SOURCE=..\..\..\..\C\ZstdDec.h
3341# End Source File
3232# End Group 3342# End Group
3233# End Target 3343# End Target
3234# End Project 3344# End Project
diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile
index bad953a..7547590 100644
--- a/CPP/7zip/Bundles/Alone/makefile
+++ b/CPP/7zip/Bundles/Alone/makefile
@@ -1,4 +1,10 @@
1PROG = 7za.exe 1PROG = 7za.exe
2
3CFLAGS = $(CFLAGS) -DZ7_ZIP_LZFSE_DISABLE
4# -DZ7_PROG_VARIANT_A
5# CONSOLE_VARIANT_FLAGS=-DZ7_PROG_VARIANT_A
6# ZIP_FLAGS=-DZ7_ZIP_LZFSE_DISABLE
7
2# USE_C_AES = 1 8# USE_C_AES = 1
3# USE_C_SHA = 1 9# USE_C_SHA = 1
4# USE_C_LZFINDOPT = 1 10# USE_C_LZFINDOPT = 1
@@ -20,10 +26,11 @@ COMMON_OBJS = \
20 $O\UTFConvert.obj \ 26 $O\UTFConvert.obj \
21 $O\MyVector.obj \ 27 $O\MyVector.obj \
22 $O\Wildcard.obj \ 28 $O\Wildcard.obj \
23 $O\XzCrc64Init.obj \
24 $O\XzCrc64Reg.obj \
25 $O\Sha1Reg.obj \ 29 $O\Sha1Reg.obj \
26 $O\Sha256Reg.obj \ 30 $O\Sha256Reg.obj \
31 $O\Xxh64Reg.obj \
32 $O\XzCrc64Init.obj \
33 $O\XzCrc64Reg.obj \
27 34
28WIN_OBJS = \ 35WIN_OBJS = \
29 $O\DLL.obj \ 36 $O\DLL.obj \
@@ -76,6 +83,7 @@ AR_OBJS = \
76 $O\LzmaHandler.obj \ 83 $O\LzmaHandler.obj \
77 $O\SplitHandler.obj \ 84 $O\SplitHandler.obj \
78 $O\XzHandler.obj \ 85 $O\XzHandler.obj \
86 $O\ZstdHandler.obj \
79 87
80AR_COMMON_OBJS = \ 88AR_COMMON_OBJS = \
81 $O\CoderMixer2.obj \ 89 $O\CoderMixer2.obj \
@@ -169,6 +177,10 @@ COMPRESS_OBJS = \
169 $O\ShrinkDecoder.obj \ 177 $O\ShrinkDecoder.obj \
170 $O\XzDecoder.obj \ 178 $O\XzDecoder.obj \
171 $O\XzEncoder.obj \ 179 $O\XzEncoder.obj \
180 $O\ZstdDecoder.obj \
181
182# $O\LzfseDecoder.obj \
183# $O\ZstdRegister.obj \
172 184
173CRYPTO_OBJS = \ 185CRYPTO_OBJS = \
174 $O\7zAes.obj \ 186 $O\7zAes.obj \
@@ -212,10 +224,12 @@ C_OBJS = \
212 $O\Sort.obj \ 224 $O\Sort.obj \
213 $O\SwapBytes.obj \ 225 $O\SwapBytes.obj \
214 $O\Threads.obj \ 226 $O\Threads.obj \
227 $O\Xxh64.obj \
215 $O\Xz.obj \ 228 $O\Xz.obj \
216 $O\XzDec.obj \ 229 $O\XzDec.obj \
217 $O\XzEnc.obj \ 230 $O\XzEnc.obj \
218 $O\XzIn.obj \ 231 $O\XzIn.obj \
232 $O\ZstdDec.obj \
219 233
220!include "../../UI/Console/Console.mak" 234!include "../../UI/Console/Console.mak"
221 235
diff --git a/CPP/7zip/Bundles/Alone/makefile.gcc b/CPP/7zip/Bundles/Alone/makefile.gcc
index cb7e828..621c0ce 100644
--- a/CPP/7zip/Bundles/Alone/makefile.gcc
+++ b/CPP/7zip/Bundles/Alone/makefile.gcc
@@ -1,18 +1,13 @@
1PROG = 7za 1PROG = 7za
2 2
3CONSOLE_VARIANT_FLAGS=-DZ7_PROG_VARIANT_A
4ZIP_FLAGS=-DZ7_ZIP_LZFSE_DISABLE
3 5
4 6
5# IS_X64 = 1 7# IS_X64 = 1
6# USE_ASM = 1 8# USE_ASM = 1
7# ST_MODE = 1 9# ST_MODE = 1
8 10
9include ../../LzmaDec_gcc.mak
10
11
12LOCAL_FLAGS_ST =
13MT_OBJS =
14
15
16ifdef SystemDrive 11ifdef SystemDrive
17IS_MINGW = 1 12IS_MINGW = 1
18else 13else
@@ -22,6 +17,13 @@ IS_MINGW = 1
22endif 17endif
23endif 18endif
24 19
20include ../../LzmaDec_gcc.mak
21
22
23LOCAL_FLAGS_ST =
24MT_OBJS =
25
26
25ifdef ST_MODE 27ifdef ST_MODE
26 28
27LOCAL_FLAGS_ST = -DZ7_ST 29LOCAL_FLAGS_ST = -DZ7_ST
@@ -36,13 +38,14 @@ else
36 38
37MT_OBJS = \ 39MT_OBJS = \
38 $O/LzFindMt.o \ 40 $O/LzFindMt.o \
39 $O/StreamBinder.o \ 41 $O/LzFindOpt.o \
40 $O/Synchronization.o \ 42 $O/Threads.o \
41 $O/VirtThread.o \
42 $O/MemBlocks.o \ 43 $O/MemBlocks.o \
43 $O/OutMemStream.o \ 44 $O/OutMemStream.o \
44 $O/ProgressMt.o \ 45 $O/ProgressMt.o \
45 $O/Threads.o \ 46 $O/StreamBinder.o \
47 $O/Synchronization.o \
48 $O/VirtThread.o \
46 49
47endif 50endif
48 51
@@ -53,10 +56,11 @@ LOCAL_FLAGS_SYS =
53ifdef IS_MINGW 56ifdef IS_MINGW
54 57
55LOCAL_FLAGS_SYS = \ 58LOCAL_FLAGS_SYS = \
56 -DZ7_LARGE_PAGES \
57 -DZ7_LONG_PATH \
58 -DZ7_DEVICE_FILE \ 59 -DZ7_DEVICE_FILE \
59 60
61# -DZ7_LARGE_PAGES \
62# -DZ7_LONG_PATH \
63
60SYS_OBJS = \ 64SYS_OBJS = \
61 $O/FileSystem.o \ 65 $O/FileSystem.o \
62 $O/Registry.o \ 66 $O/Registry.o \
@@ -77,7 +81,6 @@ LOCAL_FLAGS = \
77 $(LOCAL_FLAGS_SYS) \ 81 $(LOCAL_FLAGS_SYS) \
78 82
79 83
80
81CONSOLE_OBJS = \ 84CONSOLE_OBJS = \
82 $O/BenchCon.o \ 85 $O/BenchCon.o \
83 $O/ConsoleClose.o \ 86 $O/ConsoleClose.o \
@@ -122,22 +125,22 @@ COMMON_OBJS = \
122 $O/ListFileUtils.o \ 125 $O/ListFileUtils.o \
123 $O/LzFindPrepare.o \ 126 $O/LzFindPrepare.o \
124 $O/MyString.o \ 127 $O/MyString.o \
128 $O/MyVector.o \
125 $O/NewHandler.o \ 129 $O/NewHandler.o \
126 $O/StdInStream.o \
127 $O/StdOutStream.o \
128 $O/Sha1Prepare.o \ 130 $O/Sha1Prepare.o \
129 $O/Sha1Reg.o \ 131 $O/Sha1Reg.o \
130 $O/Sha256Prepare.o \ 132 $O/Sha256Prepare.o \
131 $O/Sha256Reg.o \ 133 $O/Sha256Reg.o \
134 $O/StdInStream.o \
135 $O/StdOutStream.o \
132 $O/StringConvert.o \ 136 $O/StringConvert.o \
133 $O/StringToInt.o \ 137 $O/StringToInt.o \
134 $O/UTFConvert.o \ 138 $O/UTFConvert.o \
135 $O/MyVector.o \
136 $O/Wildcard.o \ 139 $O/Wildcard.o \
140 $O/Xxh64Reg.o \
137 $O/XzCrc64Init.o \ 141 $O/XzCrc64Init.o \
138 $O/XzCrc64Reg.o \ 142 $O/XzCrc64Reg.o \
139 143
140
141WIN_OBJS = \ 144WIN_OBJS = \
142 $O/ErrorMsg.o \ 145 $O/ErrorMsg.o \
143 $O/FileDir.o \ 146 $O/FileDir.o \
@@ -152,7 +155,6 @@ WIN_OBJS = \
152 $O/SystemInfo.o \ 155 $O/SystemInfo.o \
153 $O/TimeUtils.o \ 156 $O/TimeUtils.o \
154 157
155
1567ZIP_COMMON_OBJS = \ 1587ZIP_COMMON_OBJS = \
157 $O/CreateCoder.o \ 159 $O/CreateCoder.o \
158 $O/CWrappers.o \ 160 $O/CWrappers.o \
@@ -179,6 +181,7 @@ AR_OBJS = \
179 $O/LzmaHandler.o \ 181 $O/LzmaHandler.o \
180 $O/SplitHandler.o \ 182 $O/SplitHandler.o \
181 $O/XzHandler.o \ 183 $O/XzHandler.o \
184 $O/ZstdHandler.o \
182 185
183AR_COMMON_OBJS = \ 186AR_COMMON_OBJS = \
184 $O/CoderMixer2.o \ 187 $O/CoderMixer2.o \
@@ -269,6 +272,10 @@ COMPRESS_OBJS = \
269 $O/ShrinkDecoder.o \ 272 $O/ShrinkDecoder.o \
270 $O/XzDecoder.o \ 273 $O/XzDecoder.o \
271 $O/XzEncoder.o \ 274 $O/XzEncoder.o \
275 $O/ZstdDecoder.o \
276
277# $O/LzfseDecoder.o \
278# $O/ZstdRegister.o
272 279
273CRYPTO_OBJS = \ 280CRYPTO_OBJS = \
274 $O/7zAes.o \ 281 $O/7zAes.o \
@@ -283,7 +290,11 @@ CRYPTO_OBJS = \
283 $O/ZipStrong.o \ 290 $O/ZipStrong.o \
284 291
285C_OBJS = \ 292C_OBJS = \
293 $O/7zCrc.o \
294 $O/7zCrcOpt.o \
286 $O/7zStream.o \ 295 $O/7zStream.o \
296 $O/Aes.o \
297 $O/AesOpt.o \
287 $O/Alloc.o \ 298 $O/Alloc.o \
288 $O/Bcj2.o \ 299 $O/Bcj2.o \
289 $O/Bcj2Enc.o \ 300 $O/Bcj2Enc.o \
@@ -295,7 +306,6 @@ C_OBJS = \
295 $O/Delta.o \ 306 $O/Delta.o \
296 $O/HuffEnc.o \ 307 $O/HuffEnc.o \
297 $O/LzFind.o \ 308 $O/LzFind.o \
298 $O/LzFindOpt.o \
299 $O/Lzma2Dec.o \ 309 $O/Lzma2Dec.o \
300 $O/Lzma2DecMt.o \ 310 $O/Lzma2DecMt.o \
301 $O/Lzma2Enc.o \ 311 $O/Lzma2Enc.o \
@@ -309,22 +319,21 @@ C_OBJS = \
309 $O/Ppmd8.o \ 319 $O/Ppmd8.o \
310 $O/Ppmd8Dec.o \ 320 $O/Ppmd8Dec.o \
311 $O/Ppmd8Enc.o \ 321 $O/Ppmd8Enc.o \
322 $O/Sha1.o \
323 $O/Sha1Opt.o \
324 $O/Sha256.o \
325 $O/Sha256Opt.o \
312 $O/Sort.o \ 326 $O/Sort.o \
313 $O/SwapBytes.o \ 327 $O/SwapBytes.o \
328 $O/Xxh64.o \
314 $O/Xz.o \ 329 $O/Xz.o \
315 $O/XzDec.o \ 330 $O/XzDec.o \
316 $O/XzEnc.o \ 331 $O/XzEnc.o \
317 $O/XzIn.o \ 332 $O/XzIn.o \
318 $O/XzCrc64.o \ 333 $O/XzCrc64.o \
319 $O/XzCrc64Opt.o \ 334 $O/XzCrc64Opt.o \
320 $O/7zCrc.o \ 335 $O/ZstdDec.o \
321 $O/7zCrcOpt.o \ 336
322 $O/Aes.o \
323 $O/AesOpt.o \
324 $O/Sha256.o \
325 $O/Sha256Opt.o \
326 $O/Sha1.o \
327 $O/Sha1Opt.o \
328 337
329OBJS = \ 338OBJS = \
330 $(LZMA_DEC_OPT_OBJS) \ 339 $(LZMA_DEC_OPT_OBJS) \
diff --git a/CPP/7zip/Bundles/Alone2/makefile b/CPP/7zip/Bundles/Alone2/makefile
index 4cb7718..af89d66 100644
--- a/CPP/7zip/Bundles/Alone2/makefile
+++ b/CPP/7zip/Bundles/Alone2/makefile
@@ -1,7 +1,9 @@
1PROG = 7zz.exe 1PROG = 7zz.exe
2# USE_C_AES = 1 2# USE_C_AES = 1
3# USE_C_SHA = 1 3# USE_C_SHA = 1
4
4CFLAGS = $(CFLAGS) -DZ7_PROG_VARIANT_Z 5CFLAGS = $(CFLAGS) -DZ7_PROG_VARIANT_Z
6# CONSOLE_VARIANT_FLAGS=-DZ7_PROG_VARIANT_Z
5 7
6!include "../Format7zF/Arc.mak" 8!include "../Format7zF/Arc.mak"
7!include "../../UI/Console/Console.mak" 9!include "../../UI/Console/Console.mak"
diff --git a/CPP/7zip/Bundles/Alone2/makefile.gcc b/CPP/7zip/Bundles/Alone2/makefile.gcc
index f767b0d..2785aea 100644
--- a/CPP/7zip/Bundles/Alone2/makefile.gcc
+++ b/CPP/7zip/Bundles/Alone2/makefile.gcc
@@ -1,11 +1,11 @@
1PROG = 7zz 1PROG = 7zz
2 2
3CONSOLE_VARIANT_FLAGS=-DZ7_PROG_VARIANT_Z
4
3# IS_X64 = 1 5# IS_X64 = 1
4# USE_ASM = 1 6# USE_ASM = 1
5# ST_MODE = 1 7# ST_MODE = 1
6 8
7CONSOLE_VARIANT_FLAGS=-DZ7_PROG_VARIANT_Z
8
9include ../Format7zF/Arc_gcc.mak 9include ../Format7zF/Arc_gcc.mak
10 10
11ifdef SystemDrive 11ifdef SystemDrive
@@ -17,13 +17,16 @@ IS_MINGW = 1
17endif 17endif
18endif 18endif
19 19
20LOCAL_FLAGS_SYS =
21
20ifdef IS_MINGW 22ifdef IS_MINGW
21 23
22LOCAL_FLAGS_SYS = \ 24LOCAL_FLAGS_SYS = \
23 -DZ7_LARGE_PAGES \
24 -DZ7_LONG_PATH \
25 -DZ7_DEVICE_FILE \ 25 -DZ7_DEVICE_FILE \
26 26
27# -DZ7_LONG_PATH \
28# -DZ7_DEVICE_FILE \
29
27SYS_OBJS = \ 30SYS_OBJS = \
28 $O/FileSystem.o \ 31 $O/FileSystem.o \
29 $O/Registry.o \ 32 $O/Registry.o \
@@ -67,7 +70,6 @@ UI_COMMON_OBJS = \
67 $O/UpdatePair.o \ 70 $O/UpdatePair.o \
68 $O/UpdateProduce.o \ 71 $O/UpdateProduce.o \
69 72
70
71CONSOLE_OBJS = \ 73CONSOLE_OBJS = \
72 $O/BenchCon.o \ 74 $O/BenchCon.o \
73 $O/ConsoleClose.o \ 75 $O/ConsoleClose.o \
diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsp b/CPP/7zip/Bundles/Alone7z/Alone.dsp
index ef4ec60..317a88f 100644
--- a/CPP/7zip/Bundles/Alone7z/Alone.dsp
+++ b/CPP/7zip/Bundles/Alone7z/Alone.dsp
@@ -270,6 +270,10 @@ SOURCE=..\..\..\Common\Common.h
270# End Source File 270# End Source File
271# Begin Source File 271# Begin Source File
272 272
273SOURCE=..\..\..\Common\Common0.h
274# End Source File
275# Begin Source File
276
273SOURCE=..\..\..\Common\ComTry.h 277SOURCE=..\..\..\Common\ComTry.h
274# End Source File 278# End Source File
275# Begin Source File 279# Begin Source File
@@ -342,6 +346,10 @@ SOURCE=..\..\..\Common\MyInitGuid.h
342# End Source File 346# End Source File
343# Begin Source File 347# Begin Source File
344 348
349SOURCE=..\..\..\Common\MyLinux.h
350# End Source File
351# Begin Source File
352
345SOURCE=..\..\..\Common\MyString.cpp 353SOURCE=..\..\..\Common\MyString.cpp
346# End Source File 354# End Source File
347# Begin Source File 355# Begin Source File
@@ -366,6 +374,10 @@ SOURCE=..\..\..\Common\MyVector.h
366# End Source File 374# End Source File
367# Begin Source File 375# Begin Source File
368 376
377SOURCE=..\..\MyVersion.h
378# End Source File
379# Begin Source File
380
369SOURCE=..\..\..\Common\MyWindows.cpp 381SOURCE=..\..\..\Common\MyWindows.cpp
370# End Source File 382# End Source File
371# Begin Source File 383# Begin Source File
@@ -566,6 +578,10 @@ SOURCE=..\..\..\Windows\Registry.h
566# End Source File 578# End Source File
567# Begin Source File 579# Begin Source File
568 580
581SOURCE=..\..\..\Windows\SecurityUtils.h
582# End Source File
583# Begin Source File
584
569SOURCE=..\..\..\Windows\Synchronization.h 585SOURCE=..\..\..\Windows\Synchronization.h
570# End Source File 586# End Source File
571# Begin Source File 587# Begin Source File
@@ -1130,6 +1146,10 @@ SOURCE=..\..\UI\Common\DefaultName.h
1130# End Source File 1146# End Source File
1131# Begin Source File 1147# Begin Source File
1132 1148
1149SOURCE=..\..\UI\Common\DirItem.h
1150# End Source File
1151# Begin Source File
1152
1133SOURCE=..\..\UI\Common\EnumDirItems.cpp 1153SOURCE=..\..\UI\Common\EnumDirItems.cpp
1134# End Source File 1154# End Source File
1135# Begin Source File 1155# Begin Source File
@@ -1493,6 +1513,10 @@ SOURCE=..\..\..\..\C\7zTypes.h
1493# End Source File 1513# End Source File
1494# Begin Source File 1514# Begin Source File
1495 1515
1516SOURCE=..\..\..\..\C\7zVersion.h
1517# End Source File
1518# Begin Source File
1519
1496SOURCE=..\..\..\..\C\7zWindows.h 1520SOURCE=..\..\..\..\C\7zWindows.h
1497# End Source File 1521# End Source File
1498# Begin Source File 1522# Begin Source File
@@ -1611,7 +1635,26 @@ SOURCE=..\..\..\..\C\Bcj2Enc.c
1611# Begin Source File 1635# Begin Source File
1612 1636
1613SOURCE=..\..\..\..\C\Bra.c 1637SOURCE=..\..\..\..\C\Bra.c
1638
1639!IF "$(CFG)" == "Alone - Win32 Release"
1640
1641# ADD CPP /O2
1642# SUBTRACT CPP /YX /Yc /Yu
1643
1644!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
1645
1646# SUBTRACT CPP /YX /Yc /Yu
1647
1648!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
1649
1614# SUBTRACT CPP /YX /Yc /Yu 1650# SUBTRACT CPP /YX /Yc /Yu
1651
1652!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
1653
1654# SUBTRACT CPP /YX /Yc /Yu
1655
1656!ENDIF
1657
1615# End Source File 1658# End Source File
1616# Begin Source File 1659# Begin Source File
1617 1660
@@ -1930,6 +1973,10 @@ SOURCE=..\..\..\..\C\MtDec.h
1930# End Source File 1973# End Source File
1931# Begin Source File 1974# Begin Source File
1932 1975
1976SOURCE=..\..\..\..\C\Precomp.h
1977# End Source File
1978# Begin Source File
1979
1933SOURCE=..\..\..\..\C\RotateDefs.h 1980SOURCE=..\..\..\..\C\RotateDefs.h
1934# End Source File 1981# End Source File
1935# Begin Source File 1982# Begin Source File
diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile
index 1f857c5..89584e1 100644
--- a/CPP/7zip/Bundles/Alone7z/makefile
+++ b/CPP/7zip/Bundles/Alone7z/makefile
@@ -2,8 +2,13 @@ PROG = 7zr.exe
2 2
3# USE_C_AES = 1 3# USE_C_AES = 1
4# USE_C_SHA = 1 4# USE_C_SHA = 1
5# USE_C_CRC64 = 1
6# USE_C_CRC = 1
7# NO_ASM_GNU=1
8# NO_ASM=1
5 9
6CFLAGS = $(CFLAGS) -DZ7_PROG_VARIANT_R 10CFLAGS = $(CFLAGS) -DZ7_PROG_VARIANT_R
11# CONSOLE_VARIANT_FLAGS=-DZ7_PROG_VARIANT_R
7 12
8COMMON_OBJS = \ 13COMMON_OBJS = \
9 $O\CommandLineParser.obj \ 14 $O\CommandLineParser.obj \
diff --git a/CPP/7zip/Bundles/Alone7z/makefile.gcc b/CPP/7zip/Bundles/Alone7z/makefile.gcc
index 6d92c19..a31475e 100644
--- a/CPP/7zip/Bundles/Alone7z/makefile.gcc
+++ b/CPP/7zip/Bundles/Alone7z/makefile.gcc
@@ -37,9 +37,11 @@ else
37MT_OBJS = \ 37MT_OBJS = \
38 $O/LzFindMt.o \ 38 $O/LzFindMt.o \
39 $O/LzFindOpt.o \ 39 $O/LzFindOpt.o \
40 $O/Threads.o \
40 $O/StreamBinder.o \ 41 $O/StreamBinder.o \
41 $O/VirtThread.o \ 42 $O/VirtThread.o \
42 $O/Threads.o \ 43
44
43 45
44 46
45 47
@@ -52,10 +54,11 @@ LOCAL_FLAGS_SYS =
52ifdef IS_MINGW 54ifdef IS_MINGW
53 55
54LOCAL_FLAGS_SYS = \ 56LOCAL_FLAGS_SYS = \
55 -DZ7_LARGE_PAGES \
56 -DZ7_LONG_PATH \
57 -DZ7_DEVICE_FILE \ 57 -DZ7_DEVICE_FILE \
58 58
59# -DZ7_LARGE_PAGES \
60# -DZ7_LONG_PATH \
61
59SYS_OBJS = \ 62SYS_OBJS = \
60 $O/FileSystem.o \ 63 $O/FileSystem.o \
61 $O/Registry.o \ 64 $O/Registry.o \
@@ -79,7 +82,6 @@ LOCAL_FLAGS = \
79CONSOLE_OBJS = \ 82CONSOLE_OBJS = \
80 $O/BenchCon.o \ 83 $O/BenchCon.o \
81 $O/ConsoleClose.o \ 84 $O/ConsoleClose.o \
82 $O/DynLimBuf.o \
83 $O/ExtractCallbackConsole.o \ 85 $O/ExtractCallbackConsole.o \
84 $O/HashCon.o \ 86 $O/HashCon.o \
85 $O/List.o \ 87 $O/List.o \
@@ -116,6 +118,7 @@ COMMON_OBJS = \
116 $O/CommandLineParser.o \ 118 $O/CommandLineParser.o \
117 $O/CRC.o \ 119 $O/CRC.o \
118 $O/CrcReg.o \ 120 $O/CrcReg.o \
121 $O/DynLimBuf.o \
119 $O/IntToString.o \ 122 $O/IntToString.o \
120 $O/ListFileUtils.o \ 123 $O/ListFileUtils.o \
121 $O/LzFindPrepare.o \ 124 $O/LzFindPrepare.o \
@@ -124,10 +127,10 @@ COMMON_OBJS = \
124 $O/NewHandler.o \ 127 $O/NewHandler.o \
125 $O/Sha256Prepare.o \ 128 $O/Sha256Prepare.o \
126 $O/Sha256Reg.o \ 129 $O/Sha256Reg.o \
127 $O/StringConvert.o \
128 $O/StringToInt.o \
129 $O/StdInStream.o \ 130 $O/StdInStream.o \
130 $O/StdOutStream.o \ 131 $O/StdOutStream.o \
132 $O/StringConvert.o \
133 $O/StringToInt.o \
131 $O/UTFConvert.o \ 134 $O/UTFConvert.o \
132 $O/Wildcard.o \ 135 $O/Wildcard.o \
133 $O/XzCrc64Init.o \ 136 $O/XzCrc64Init.o \
@@ -225,7 +228,11 @@ CRYPTO_OBJS = \
225 $O/RandGen.o \ 228 $O/RandGen.o \
226 229
227C_OBJS = \ 230C_OBJS = \
231 $O/7zCrc.o \
232 $O/7zCrcOpt.o \
228 $O/7zStream.o \ 233 $O/7zStream.o \
234 $O/Aes.o \
235 $O/AesOpt.o \
229 $O/Alloc.o \ 236 $O/Alloc.o \
230 $O/Bcj2.o \ 237 $O/Bcj2.o \
231 $O/Bcj2Enc.o \ 238 $O/Bcj2Enc.o \
@@ -251,10 +258,6 @@ C_OBJS = \
251 $O/XzIn.o \ 258 $O/XzIn.o \
252 $O/XzCrc64.o \ 259 $O/XzCrc64.o \
253 $O/XzCrc64Opt.o \ 260 $O/XzCrc64Opt.o \
254 $O/7zCrc.o \
255 $O/7zCrcOpt.o \
256 $O/Aes.o \
257 $O/AesOpt.o \
258 261
259 262
260OBJS = \ 263OBJS = \
diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp
index 402dd2c..6e55d92 100644
--- a/CPP/7zip/Bundles/Fm/FM.dsp
+++ b/CPP/7zip/Bundles/Fm/FM.dsp
@@ -661,6 +661,18 @@ SOURCE=..\..\UI\FileManager\BrowseDialog.h
661# End Source File 661# End Source File
662# Begin Source File 662# Begin Source File
663 663
664SOURCE=..\..\UI\FileManager\BrowseDialog2.cpp
665# End Source File
666# Begin Source File
667
668SOURCE=..\..\UI\FileManager\BrowseDialog2.h
669# End Source File
670# Begin Source File
671
672SOURCE=..\..\UI\FileManager\BrowseDialog2Res.h
673# End Source File
674# Begin Source File
675
664SOURCE=..\..\UI\FileManager\ComboDialog.cpp 676SOURCE=..\..\UI\FileManager\ComboDialog.cpp
665# End Source File 677# End Source File
666# Begin Source File 678# Begin Source File
@@ -705,6 +717,18 @@ SOURCE=..\..\UI\FileManager\ListViewDialog.h
705# End Source File 717# End Source File
706# Begin Source File 718# Begin Source File
707 719
720SOURCE=..\..\UI\FileManager\MemDialog.cpp
721# End Source File
722# Begin Source File
723
724SOURCE=..\..\UI\FileManager\MemDialog.h
725# End Source File
726# Begin Source File
727
728SOURCE=..\..\UI\FileManager\MemDialogRes.h
729# End Source File
730# Begin Source File
731
708SOURCE=..\..\UI\FileManager\MessagesDialog.cpp 732SOURCE=..\..\UI\FileManager\MessagesDialog.cpp
709# End Source File 733# End Source File
710# Begin Source File 734# Begin Source File
diff --git a/CPP/7zip/Bundles/Fm/makefile b/CPP/7zip/Bundles/Fm/makefile
index 33b5320..de74f76 100644
--- a/CPP/7zip/Bundles/Fm/makefile
+++ b/CPP/7zip/Bundles/Fm/makefile
@@ -1,6 +1,6 @@
1PROG = 7zFM.exe 1PROG = 7zFM.exe
2 2
3CFLAGS = $(CFLAGS) -DZ7_LARGE_PAGES 3# CFLAGS = $(CFLAGS) -DZ7_LARGE_PAGES
4 4
5!include "../Format7zF/Arc.mak" 5!include "../Format7zF/Arc.mak"
6 6
diff --git a/CPP/7zip/Bundles/Format7z/makefile b/CPP/7zip/Bundles/Format7z/makefile
index d20a3c1..fe6f94d 100644
--- a/CPP/7zip/Bundles/Format7z/makefile
+++ b/CPP/7zip/Bundles/Format7z/makefile
@@ -25,6 +25,7 @@ WIN_OBJS = \
25 $O\PropVariant.obj \ 25 $O\PropVariant.obj \
26 $O\Synchronization.obj \ 26 $O\Synchronization.obj \
27 $O\System.obj \ 27 $O\System.obj \
28 $O\TimeUtils.obj \
28 29
297ZIP_COMMON_OBJS = \ 307ZIP_COMMON_OBJS = \
30 $O\CreateCoder.obj \ 31 $O\CreateCoder.obj \
diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak
index 37b400e..3d8a430 100644
--- a/CPP/7zip/Bundles/Format7zF/Arc.mak
+++ b/CPP/7zip/Bundles/Format7zF/Arc.mak
@@ -15,6 +15,7 @@ COMMON_OBJS = \
15 $O\StringToInt.obj \ 15 $O\StringToInt.obj \
16 $O\UTFConvert.obj \ 16 $O\UTFConvert.obj \
17 $O\Wildcard.obj \ 17 $O\Wildcard.obj \
18 $O\Xxh64Reg.obj \
18 $O\XzCrc64Init.obj \ 19 $O\XzCrc64Init.obj \
19 $O\XzCrc64Reg.obj \ 20 $O\XzCrc64Reg.obj \
20 21
@@ -98,6 +99,7 @@ AR_OBJS = \
98 $O\XarHandler.obj \ 99 $O\XarHandler.obj \
99 $O\XzHandler.obj \ 100 $O\XzHandler.obj \
100 $O\ZHandler.obj \ 101 $O\ZHandler.obj \
102 $O\ZstdHandler.obj \
101 103
102AR_COMMON_OBJS = \ 104AR_COMMON_OBJS = \
103 $O\CoderMixer2.obj \ 105 $O\CoderMixer2.obj \
@@ -233,6 +235,7 @@ COMPRESS_OBJS = \
233 $O\ZlibDecoder.obj \ 235 $O\ZlibDecoder.obj \
234 $O\ZlibEncoder.obj \ 236 $O\ZlibEncoder.obj \
235 $O\ZDecoder.obj \ 237 $O\ZDecoder.obj \
238 $O\ZstdDecoder.obj \
236 239
237CRYPTO_OBJS = \ 240CRYPTO_OBJS = \
238 $O\7zAes.obj \ 241 $O\7zAes.obj \
@@ -283,10 +286,12 @@ C_OBJS = \
283 $O\Sort.obj \ 286 $O\Sort.obj \
284 $O\SwapBytes.obj \ 287 $O\SwapBytes.obj \
285 $O\Threads.obj \ 288 $O\Threads.obj \
289 $O\Xxh64.obj \
286 $O\Xz.obj \ 290 $O\Xz.obj \
287 $O\XzDec.obj \ 291 $O\XzDec.obj \
288 $O\XzEnc.obj \ 292 $O\XzEnc.obj \
289 $O\XzIn.obj \ 293 $O\XzIn.obj \
294 $O\ZstdDec.obj \
290 295
291!include "../../Aes.mak" 296!include "../../Aes.mak"
292!include "../../Crc.mak" 297!include "../../Crc.mak"
diff --git a/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak
index 404d917..ff5a3f9 100644
--- a/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak
+++ b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak
@@ -27,13 +27,13 @@ else
27MT_OBJS = \ 27MT_OBJS = \
28 $O/LzFindMt.o \ 28 $O/LzFindMt.o \
29 $O/LzFindOpt.o \ 29 $O/LzFindOpt.o \
30 $O/StreamBinder.o \ 30 $O/Threads.o \
31 $O/Synchronization.o \
32 $O/VirtThread.o \
33 $O/MemBlocks.o \ 31 $O/MemBlocks.o \
34 $O/OutMemStream.o \ 32 $O/OutMemStream.o \
35 $O/ProgressMt.o \ 33 $O/ProgressMt.o \
36 $O/Threads.o \ 34 $O/StreamBinder.o \
35 $O/Synchronization.o \
36 $O/VirtThread.o \
37 37
38endif 38endif
39 39
@@ -58,6 +58,7 @@ COMMON_OBJS = \
58 $O/StringToInt.o \ 58 $O/StringToInt.o \
59 $O/UTFConvert.o \ 59 $O/UTFConvert.o \
60 $O/Wildcard.o \ 60 $O/Wildcard.o \
61 $O/Xxh64Reg.o \
61 $O/XzCrc64Init.o \ 62 $O/XzCrc64Init.o \
62 $O/XzCrc64Reg.o \ 63 $O/XzCrc64Reg.o \
63 64
@@ -135,6 +136,10 @@ AR_OBJS = \
135 $O/XarHandler.o \ 136 $O/XarHandler.o \
136 $O/XzHandler.o \ 137 $O/XzHandler.o \
137 $O/ZHandler.o \ 138 $O/ZHandler.o \
139 $O/ZstdHandler.o \
140
141# $O/AvbHandler.o
142# $O/LvmHandler.o
138 143
139AR_COMMON_OBJS = \ 144AR_COMMON_OBJS = \
140 $O/CoderMixer2.o \ 145 $O/CoderMixer2.o \
@@ -269,6 +274,7 @@ COMPRESS_OBJS = \
269 $O/ZlibDecoder.o \ 274 $O/ZlibDecoder.o \
270 $O/ZlibEncoder.o \ 275 $O/ZlibEncoder.o \
271 $O/ZDecoder.o \ 276 $O/ZDecoder.o \
277 $O/ZstdDecoder.o \
272 278
273ifdef DISABLE_RAR 279ifdef DISABLE_RAR
274DISABLE_RAR_COMPRESS=1 280DISABLE_RAR_COMPRESS=1
@@ -309,7 +315,11 @@ endif
309 315
310C_OBJS = \ 316C_OBJS = \
311 $O/7zBuf2.o \ 317 $O/7zBuf2.o \
318 $O/7zCrc.o \
319 $O/7zCrcOpt.o \
312 $O/7zStream.o \ 320 $O/7zStream.o \
321 $O/Aes.o \
322 $O/AesOpt.o \
313 $O/Alloc.o \ 323 $O/Alloc.o \
314 $O/Bcj2.o \ 324 $O/Bcj2.o \
315 $O/Bcj2Enc.o \ 325 $O/Bcj2Enc.o \
@@ -336,22 +346,20 @@ C_OBJS = \
336 $O/Ppmd8.o \ 346 $O/Ppmd8.o \
337 $O/Ppmd8Dec.o \ 347 $O/Ppmd8Dec.o \
338 $O/Ppmd8Enc.o \ 348 $O/Ppmd8Enc.o \
349 $O/Sha1.o \
350 $O/Sha1Opt.o \
351 $O/Sha256.o \
352 $O/Sha256Opt.o \
339 $O/Sort.o \ 353 $O/Sort.o \
354 $O/SwapBytes.o \
355 $O/Xxh64.o \
340 $O/Xz.o \ 356 $O/Xz.o \
341 $O/XzDec.o \ 357 $O/XzDec.o \
342 $O/XzEnc.o \ 358 $O/XzEnc.o \
343 $O/XzIn.o \ 359 $O/XzIn.o \
344 $O/XzCrc64.o \ 360 $O/XzCrc64.o \
345 $O/XzCrc64Opt.o \ 361 $O/XzCrc64Opt.o \
346 $O/7zCrc.o \ 362 $O/ZstdDec.o \
347 $O/7zCrcOpt.o \
348 $O/Aes.o \
349 $O/AesOpt.o \
350 $O/Sha256.o \
351 $O/Sha256Opt.o \
352 $O/Sha1.o \
353 $O/Sha1Opt.o \
354 $O/SwapBytes.o \
355 363
356ARC_OBJS = \ 364ARC_OBJS = \
357 $(LZMA_DEC_OPT_OBJS) \ 365 $(LZMA_DEC_OPT_OBJS) \
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
index a0c5d83..6e28288 100644
--- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp
+++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
@@ -195,6 +195,10 @@ SOURCE=..\..\Archive\Icons\z.ico
195 195
196SOURCE=..\..\Archive\Icons\zip.ico 196SOURCE=..\..\Archive\Icons\zip.ico
197# End Source File 197# End Source File
198# Begin Source File
199
200SOURCE=..\..\Archive\Icons\zst.ico
201# End Source File
198# End Group 202# End Group
199# Begin Source File 203# Begin Source File
200 204
@@ -231,10 +235,18 @@ SOURCE=.\StdAfx.h
231# PROP Default_Filter "" 235# PROP Default_Filter ""
232# Begin Source File 236# Begin Source File
233 237
238SOURCE=..\..\..\Common\AutoPtr.h
239# End Source File
240# Begin Source File
241
234SOURCE=..\..\..\Common\Common.h 242SOURCE=..\..\..\Common\Common.h
235# End Source File 243# End Source File
236# Begin Source File 244# Begin Source File
237 245
246SOURCE=..\..\..\Common\Common0.h
247# End Source File
248# Begin Source File
249
238SOURCE=..\..\..\Common\ComTry.h 250SOURCE=..\..\..\Common\ComTry.h
239# End Source File 251# End Source File
240# Begin Source File 252# Begin Source File
@@ -403,6 +415,10 @@ SOURCE=..\..\..\Common\Wildcard.h
403# End Source File 415# End Source File
404# Begin Source File 416# Begin Source File
405 417
418SOURCE=..\..\..\Common\Xxh64Reg.cpp
419# End Source File
420# Begin Source File
421
406SOURCE=..\..\..\Common\XzCrc64Init.cpp 422SOURCE=..\..\..\Common\XzCrc64Init.cpp
407# End Source File 423# End Source File
408# Begin Source File 424# Begin Source File
@@ -1069,6 +1085,14 @@ SOURCE=..\..\Compress\ZDecoder.cpp
1069 1085
1070SOURCE=..\..\Compress\ZDecoder.h 1086SOURCE=..\..\Compress\ZDecoder.h
1071# End Source File 1087# End Source File
1088# Begin Source File
1089
1090SOURCE=..\..\Compress\ZstdDecoder.cpp
1091# End Source File
1092# Begin Source File
1093
1094SOURCE=..\..\Compress\ZstdDecoder.h
1095# End Source File
1072# End Group 1096# End Group
1073# Begin Group "Crypto" 1097# Begin Group "Crypto"
1074 1098
@@ -2253,6 +2277,46 @@ SOURCE=..\..\..\..\C\Threads.c
2253 2277
2254SOURCE=..\..\..\..\C\Threads.h 2278SOURCE=..\..\..\..\C\Threads.h
2255# End Source File 2279# End Source File
2280# Begin Source File
2281
2282SOURCE=..\..\..\..\C\Xxh64.c
2283
2284!IF "$(CFG)" == "7z - Win32 Release"
2285
2286# ADD CPP /O2
2287# SUBTRACT CPP /YX /Yc /Yu
2288
2289!ELSEIF "$(CFG)" == "7z - Win32 Debug"
2290
2291# SUBTRACT CPP /YX /Yc /Yu
2292
2293!ENDIF
2294
2295# End Source File
2296# Begin Source File
2297
2298SOURCE=..\..\..\..\C\Xxh64.h
2299# End Source File
2300# Begin Source File
2301
2302SOURCE=..\..\..\..\C\ZstdDec.c
2303
2304!IF "$(CFG)" == "7z - Win32 Release"
2305
2306# ADD CPP /O2
2307# SUBTRACT CPP /YX /Yc /Yu
2308
2309!ELSEIF "$(CFG)" == "7z - Win32 Debug"
2310
2311# SUBTRACT CPP /YX /Yc /Yu
2312
2313!ENDIF
2314
2315# End Source File
2316# Begin Source File
2317
2318SOURCE=..\..\..\..\C\ZstdDec.h
2319# End Source File
2256# End Group 2320# End Group
2257# Begin Group "Archive" 2321# Begin Group "Archive"
2258 2322
@@ -2995,6 +3059,10 @@ SOURCE=..\..\Archive\XzHandler.h
2995 3059
2996SOURCE=..\..\Archive\ZHandler.cpp 3060SOURCE=..\..\Archive\ZHandler.cpp
2997# End Source File 3061# End Source File
3062# Begin Source File
3063
3064SOURCE=..\..\Archive\ZstdHandler.cpp
3065# End Source File
2998# End Group 3066# End Group
2999# Begin Group "7zip" 3067# Begin Group "7zip"
3000 3068
diff --git a/CPP/7zip/Bundles/Format7zF/makefile b/CPP/7zip/Bundles/Format7zF/makefile
index 3487596..521c8cf 100644
--- a/CPP/7zip/Bundles/Format7zF/makefile
+++ b/CPP/7zip/Bundles/Format7zF/makefile
@@ -5,7 +5,7 @@ CFLAGS = $(CFLAGS) \
5 -DZ7_EXTERNAL_CODECS \ 5 -DZ7_EXTERNAL_CODECS \
6 6
7!IFNDEF UNDER_CE 7!IFNDEF UNDER_CE
8CFLAGS = $(CFLAGS) -DZ7_LARGE_PAGES 8# CFLAGS = $(CFLAGS) -DZ7_LARGE_PAGES
9!ENDIF 9!ENDIF
10 10
11!include "Arc.mak" 11!include "Arc.mak"
diff --git a/CPP/7zip/Bundles/Format7zF/makefile.gcc b/CPP/7zip/Bundles/Format7zF/makefile.gcc
index fc65795..cc23d0b 100644
--- a/CPP/7zip/Bundles/Format7zF/makefile.gcc
+++ b/CPP/7zip/Bundles/Format7zF/makefile.gcc
@@ -16,13 +16,15 @@ IS_MINGW = 1
16endif 16endif
17endif 17endif
18 18
19LOCAL_FLAGS_SYS =
19 20
20ifdef IS_MINGW 21ifdef IS_MINGW
21 22
22LOCAL_FLAGS_WIN = \ 23LOCAL_FLAGS_SYS = \
23 -DZ7_LARGE_PAGES \
24 $(LOCAL_FLAGS_ST) \ 24 $(LOCAL_FLAGS_ST) \
25 25
26# -DZ7_LARGE_PAGES \
27
26SYS_OBJS = \ 28SYS_OBJS = \
27 $O/resource.o \ 29 $O/resource.o \
28 30
@@ -35,7 +37,7 @@ endif
35 37
36LOCAL_FLAGS = \ 38LOCAL_FLAGS = \
37 -DZ7_EXTERNAL_CODECS \ 39 -DZ7_EXTERNAL_CODECS \
38 $(LOCAL_FLAGS_WIN) \ 40 $(LOCAL_FLAGS_SYS) \
39 $(LOCAL_FLAGS_ST) \ 41 $(LOCAL_FLAGS_ST) \
40 42
41 43
diff --git a/CPP/7zip/Bundles/Format7zF/resource.rc b/CPP/7zip/Bundles/Format7zF/resource.rc
index 9c797c1..f2950c0 100644
--- a/CPP/7zip/Bundles/Format7zF/resource.rc
+++ b/CPP/7zip/Bundles/Format7zF/resource.rc
@@ -29,10 +29,11 @@ MY_VERSION_INFO_DLL("7z Plugin" , "7z")
2923 ICON "../../Archive/Icons/xz.ico" 2923 ICON "../../Archive/Icons/xz.ico"
3024 ICON "../../Archive/Icons/squashfs.ico" 3024 ICON "../../Archive/Icons/squashfs.ico"
3125 ICON "../../Archive/Icons/apfs.ico" 3125 ICON "../../Archive/Icons/apfs.ico"
3226 ICON "../../Archive/Icons/zst.ico"
32 33
33 34
34 35
35STRINGTABLE 36STRINGTABLE
36BEGIN 37BEGIN
37 100 "7z:0 zip:1 rar:3 001:9 cab:7 iso:8 xz:23 txz:23 lzma:16 tar:13 cpio:12 bz2:2 bzip2:2 tbz2:2 tbz:2 gz:14 gzip:14 tgz:14 tpz:14 z:5 taz:5 lzh:6 lha:6 rpm:10 deb:11 arj:4 vhd:20 vhdx:20 wim:15 swm:15 esd:15 fat:21 ntfs:22 dmg:17 hfs:18 xar:19 squashfs:24 apfs:25" 38 100 "7z:0 zip:1 rar:3 001:9 cab:7 iso:8 xz:23 txz:23 lzma:16 tar:13 cpio:12 bz2:2 bzip2:2 tbz2:2 tbz:2 gz:14 gzip:14 tgz:14 tpz:14 zst:26 tzst:26 z:5 taz:5 lzh:6 lha:6 rpm:10 deb:11 arj:4 vhd:20 vhdx:20 wim:15 swm:15 esd:15 fat:21 ntfs:22 dmg:17 hfs:18 xar:19 squashfs:24 apfs:25"
38END 39END
diff --git a/CPP/7zip/Bundles/Format7zR/makefile b/CPP/7zip/Bundles/Format7zR/makefile
index 2449755..326d043 100644
--- a/CPP/7zip/Bundles/Format7zR/makefile
+++ b/CPP/7zip/Bundles/Format7zR/makefile
@@ -23,6 +23,7 @@ WIN_OBJS = \
23 $O\PropVariant.obj \ 23 $O\PropVariant.obj \
24 $O\Synchronization.obj \ 24 $O\Synchronization.obj \
25 $O\System.obj \ 25 $O\System.obj \
26 $O\TimeUtils.obj \
26 27
277ZIP_COMMON_OBJS = \ 287ZIP_COMMON_OBJS = \
28 $O\CreateCoder.obj \ 29 $O\CreateCoder.obj \
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
index ac1334f..b4bd2de 100644
--- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
@@ -501,7 +501,7 @@ static int main2(int numArgs, const char *args[])
501 const UString &outputName = params[paramIndex++]; 501 const UString &outputName = params[paramIndex++];
502 outStreamSpec = new COutFileStream; 502 outStreamSpec = new COutFileStream;
503 outStream = outStreamSpec; 503 outStream = outStreamSpec;
504 if (!outStreamSpec->Create(us2fs(outputName), true)) 504 if (!outStreamSpec->Create_ALWAYS(us2fs(outputName)))
505 { 505 {
506 PrintError2("Cannot open output file", outputName); 506 PrintError2("Cannot open output file", outputName);
507 return 1; 507 return 1;
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
index 5a8911b..258bb6d 100644
--- a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
@@ -42,7 +42,7 @@ RSC=rc.exe
42# PROP Ignore_Export_Lib 0 42# PROP Ignore_Export_Lib 0
43# PROP Target_Dir "" 43# PROP Target_Dir ""
44# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 44# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
45# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c 45# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "Z7_NO_LONG_PATH" /Yu"StdAfx.h" /FD /c
46# ADD BASE RSC /l 0x419 /d "NDEBUG" 46# ADD BASE RSC /l 0x419 /d "NDEBUG"
47# ADD RSC /l 0x419 /d "NDEBUG" 47# ADD RSC /l 0x419 /d "NDEBUG"
48BSC32=bscmake.exe 48BSC32=bscmake.exe
@@ -66,7 +66,7 @@ LINK32=link.exe
66# PROP Ignore_Export_Lib 0 66# PROP Ignore_Export_Lib 0
67# PROP Target_Dir "" 67# PROP Target_Dir ""
68# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 68# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
69# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c 69# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "Z7_NO_LONG_PATH" /Yu"StdAfx.h" /FD /GZ /c
70# ADD BASE RSC /l 0x419 /d "_DEBUG" 70# ADD BASE RSC /l 0x419 /d "_DEBUG"
71# ADD RSC /l 0x419 /d "_DEBUG" 71# ADD RSC /l 0x419 /d "_DEBUG"
72BSC32=bscmake.exe 72BSC32=bscmake.exe
diff --git a/CPP/7zip/Bundles/LzmaCon/makefile b/CPP/7zip/Bundles/LzmaCon/makefile
index f303c31..4aef252 100644
--- a/CPP/7zip/Bundles/LzmaCon/makefile
+++ b/CPP/7zip/Bundles/LzmaCon/makefile
@@ -1,6 +1,7 @@
1PROG = lzma.exe 1PROG = lzma.exe
2MY_CONSOLE = 1 2MY_CONSOLE = 1
3 3
4CFLAGS = $(CFLAGS) -DZ7_NO_LONG_PATH
4# CFLAGS = $(CFLAGS) -DZ7_ST 5# CFLAGS = $(CFLAGS) -DZ7_ST
5 6
6 7
diff --git a/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/CPP/7zip/Bundles/LzmaCon/makefile.gcc
index dd19a0e..67c7892 100644
--- a/CPP/7zip/Bundles/LzmaCon/makefile.gcc
+++ b/CPP/7zip/Bundles/LzmaCon/makefile.gcc
@@ -4,12 +4,6 @@ PROG = lzma
4# USE_ASM = 1 4# USE_ASM = 1
5# ST_MODE = 1 5# ST_MODE = 1
6 6
7include ../../LzmaDec_gcc.mak
8
9LOCAL_FLAGS_ST =
10MT_OBJS =
11
12
13ifdef SystemDrive 7ifdef SystemDrive
14IS_MINGW = 1 8IS_MINGW = 1
15else 9else
@@ -19,6 +13,13 @@ IS_MINGW = 1
19endif 13endif
20endif 14endif
21 15
16include ../../LzmaDec_gcc.mak
17
18
19LOCAL_FLAGS_ST =
20MT_OBJS =
21
22
22ifdef ST_MODE 23ifdef ST_MODE
23 24
24LOCAL_FLAGS_ST = -DZ7_ST 25LOCAL_FLAGS_ST = -DZ7_ST
@@ -28,8 +29,8 @@ else
28MT_OBJS = \ 29MT_OBJS = \
29 $O/LzFindMt.o \ 30 $O/LzFindMt.o \
30 $O/LzFindOpt.o \ 31 $O/LzFindOpt.o \
31 $O/Synchronization.o \
32 $O/Threads.o \ 32 $O/Threads.o \
33 $O/Synchronization.o \
33 34
34 35
35 36
@@ -45,6 +46,9 @@ SYS_OBJS = \
45 $O/Registry.o \ 46 $O/Registry.o \
46 $O/resource.o \ 47 $O/resource.o \
47 48
49LOCAL_FLAGS_SYS = \
50 -DZ7_NO_LONG_PATH \
51
48else 52else
49 53
50SYS_OBJS = \ 54SYS_OBJS = \
@@ -58,6 +62,7 @@ endif
58 62
59LOCAL_FLAGS = \ 63LOCAL_FLAGS = \
60 $(LOCAL_FLAGS_ST) \ 64 $(LOCAL_FLAGS_ST) \
65 $(LOCAL_FLAGS_SYS) \
61 66
62 67
63COMMON_OBJS = \ 68COMMON_OBJS = \
diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
index 1bb063d..d490932 100644
--- a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
+++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
@@ -42,7 +42,7 @@ RSC=rc.exe
42# PROP Ignore_Export_Lib 0 42# PROP Ignore_Export_Lib 0
43# PROP Target_Dir "" 43# PROP Target_Dir ""
44# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 44# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
45# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_SFX" /D "Z7_NO_READ_FROM_CODER" /FAcs /Yu"StdAfx.h" /FD /c 45# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_SFX" /D "Z7_NO_READ_FROM_CODER" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /FAcs /Yu"StdAfx.h" /FD /c
46# ADD BASE RSC /l 0x419 /d "NDEBUG" 46# ADD BASE RSC /l 0x419 /d "NDEBUG"
47# ADD RSC /l 0x419 /d "NDEBUG" 47# ADD RSC /l 0x419 /d "NDEBUG"
48BSC32=bscmake.exe 48BSC32=bscmake.exe
@@ -67,7 +67,7 @@ LINK32=link.exe
67# PROP Ignore_Export_Lib 0 67# PROP Ignore_Export_Lib 0
68# PROP Target_Dir "" 68# PROP Target_Dir ""
69# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 69# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
70# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_SFX" /D "Z7_NO_READ_FROM_CODER" /Yu"StdAfx.h" /FD /GZ /c 70# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_SFX" /D "Z7_NO_READ_FROM_CODER" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c
71# ADD BASE RSC /l 0x419 /d "_DEBUG" 71# ADD BASE RSC /l 0x419 /d "_DEBUG"
72# ADD RSC /l 0x419 /d "_DEBUG" 72# ADD RSC /l 0x419 /d "_DEBUG"
73BSC32=bscmake.exe 73BSC32=bscmake.exe
@@ -447,6 +447,14 @@ SOURCE=..\..\..\Windows\System.cpp
447 447
448SOURCE=..\..\..\Windows\System.h 448SOURCE=..\..\..\Windows\System.h
449# End Source File 449# End Source File
450# Begin Source File
451
452SOURCE=..\..\..\Windows\TimeUtils.cpp
453# End Source File
454# Begin Source File
455
456SOURCE=..\..\..\Windows\TimeUtils.h
457# End Source File
450# End Group 458# End Group
451# Begin Group "Common" 459# Begin Group "Common"
452 460
diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile
index 51aaf51..a72e3f8 100644
--- a/CPP/7zip/Bundles/SFXCon/makefile
+++ b/CPP/7zip/Bundles/SFXCon/makefile
@@ -6,6 +6,8 @@ CFLAGS = $(CFLAGS) \
6 -DZ7_EXTRACT_ONLY \ 6 -DZ7_EXTRACT_ONLY \
7 -DZ7_NO_READ_FROM_CODER \ 7 -DZ7_NO_READ_FROM_CODER \
8 -DZ7_SFX \ 8 -DZ7_SFX \
9 -DZ7_NO_LONG_PATH \
10 -DZ7_NO_LARGE_PAGES \
9 11
10CURRENT_OBJS = \ 12CURRENT_OBJS = \
11 $O\SfxCon.obj \ 13 $O\SfxCon.obj \
@@ -43,6 +45,7 @@ WIN_OBJS = \
43 $O\PropVariantConv.obj \ 45 $O\PropVariantConv.obj \
44 $O\Synchronization.obj \ 46 $O\Synchronization.obj \
45 $O\System.obj \ 47 $O\System.obj \
48 $O\TimeUtils.obj \
46 49
477ZIP_COMMON_OBJS = \ 507ZIP_COMMON_OBJS = \
48 $O\CreateCoder.obj \ 51 $O\CreateCoder.obj \
diff --git a/CPP/7zip/Bundles/SFXCon/makefile.gcc b/CPP/7zip/Bundles/SFXCon/makefile.gcc
index 9278502..87d78a9 100644
--- a/CPP/7zip/Bundles/SFXCon/makefile.gcc
+++ b/CPP/7zip/Bundles/SFXCon/makefile.gcc
@@ -47,6 +47,8 @@ LOCAL_FLAGS_SYS =
47ifdef IS_MINGW 47ifdef IS_MINGW
48 48
49LOCAL_FLAGS_SYS = \ 49LOCAL_FLAGS_SYS = \
50 -DZ7_NO_LONG_PATH \
51 -DZ7_NO_LARGE_PAGES \
50 52
51SYS_OBJS = \ 53SYS_OBJS = \
52 $O/DLL.o \ 54 $O/DLL.o \
@@ -61,11 +63,11 @@ SYS_OBJS = \
61endif 63endif
62 64
63LOCAL_FLAGS = \ 65LOCAL_FLAGS = \
64 $(LOCAL_FLAGS_ST) \
65 $(LOCAL_FLAGS_SYS) \
66 -DZ7_EXTRACT_ONLY \ 66 -DZ7_EXTRACT_ONLY \
67 -DZ7_NO_READ_FROM_CODER \ 67 -DZ7_NO_READ_FROM_CODER \
68 -DZ7_SFX \ 68 -DZ7_SFX \
69 $(LOCAL_FLAGS_ST) \
70 $(LOCAL_FLAGS_SYS) \
69 71
70 72
71CURRENT_OBJS = \ 73CURRENT_OBJS = \
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
index 9d632ee..14dd2ec 100644
--- a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
@@ -190,7 +190,7 @@ Z7_COM7F_IMF(CExtractCallbackImp::GetStream(UInt32 index,
190 { 190 {
191 _outFileStreamSpec = new COutFileStream; 191 _outFileStreamSpec = new COutFileStream;
192 CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); 192 CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
193 if (!_outFileStreamSpec->Create(fullProcessedPath, true)) 193 if (!_outFileStreamSpec->Create_ALWAYS(fullProcessedPath))
194 { 194 {
195 _message = kCantOpenFile; 195 _message = kCantOpenFile;
196 return E_FAIL; 196 return E_FAIL;
diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
index cf96460..09683e2 100644
--- a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
+++ b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
@@ -44,7 +44,7 @@ RSC=rc.exe
44# PROP Ignore_Export_Lib 0 44# PROP Ignore_Export_Lib 0
45# PROP Target_Dir "" 45# PROP Target_Dir ""
46# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c 46# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
47# ADD CPP /nologo /Gz /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /D "Z7_NO_CRYPTO" /Yu"StdAfx.h" /FD /c 47# ADD CPP /nologo /Gz /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /D "Z7_NO_CRYPTO" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /c
48# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 48# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
49# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 49# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
50# ADD BASE RSC /l 0x419 /d "NDEBUG" 50# ADD BASE RSC /l 0x419 /d "NDEBUG"
@@ -71,7 +71,7 @@ LINK32=link.exe
71# PROP Ignore_Export_Lib 0 71# PROP Ignore_Export_Lib 0
72# PROP Target_Dir "" 72# PROP Target_Dir ""
73# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c 73# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
74# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /D "Z7_NO_CRYPTO" /Yu"StdAfx.h" /FD /GZ /c 74# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /D "Z7_NO_CRYPTO" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c
75# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 75# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
76# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 76# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
77# ADD BASE RSC /l 0x419 /d "_DEBUG" 77# ADD BASE RSC /l 0x419 /d "_DEBUG"
@@ -98,7 +98,7 @@ LINK32=link.exe
98# PROP Ignore_Export_Lib 0 98# PROP Ignore_Export_Lib 0
99# PROP Target_Dir "" 99# PROP Target_Dir ""
100# ADD BASE CPP /nologo /MD /W3 /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /Yu"StdAfx.h" /FD /c 100# ADD BASE CPP /nologo /MD /W3 /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /Yu"StdAfx.h" /FD /c
101# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /D "Z7_NO_CRYPTO" /Yu"StdAfx.h" /FD /c 101# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /D "Z7_NO_CRYPTO" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /c
102# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 102# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
103# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 103# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
104# ADD BASE RSC /l 0x419 /d "NDEBUG" 104# ADD BASE RSC /l 0x419 /d "NDEBUG"
@@ -477,6 +477,14 @@ SOURCE=..\..\..\Windows\System.h
477# End Source File 477# End Source File
478# Begin Source File 478# Begin Source File
479 479
480SOURCE=..\..\..\Windows\TimeUtils.cpp
481# End Source File
482# Begin Source File
483
484SOURCE=..\..\..\Windows\TimeUtils.h
485# End Source File
486# Begin Source File
487
480SOURCE=..\..\..\Windows\Window.cpp 488SOURCE=..\..\..\Windows\Window.cpp
481# End Source File 489# End Source File
482# Begin Source File 490# Begin Source File
diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
index 47d7966..eb28f5d 100644
--- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
@@ -33,6 +33,9 @@ using namespace NDir;
33extern 33extern
34HINSTANCE g_hInstance; 34HINSTANCE g_hInstance;
35HINSTANCE g_hInstance; 35HINSTANCE g_hInstance;
36extern
37bool g_DisableUserQuestions;
38bool g_DisableUserQuestions;
36 39
37static CFSTR const kTempDirPrefix = FTEXT("7zS"); 40static CFSTR const kTempDirPrefix = FTEXT("7zS");
38 41
diff --git a/CPP/7zip/Bundles/SFXSetup/makefile b/CPP/7zip/Bundles/SFXSetup/makefile
index ea0ece2..4f6c5fc 100644
--- a/CPP/7zip/Bundles/SFXSetup/makefile
+++ b/CPP/7zip/Bundles/SFXSetup/makefile
@@ -7,6 +7,8 @@ CFLAGS = $(CFLAGS) \
7 -DZ7_NO_READ_FROM_CODER \ 7 -DZ7_NO_READ_FROM_CODER \
8 -DZ7_SFX \ 8 -DZ7_SFX \
9 -DZ7_NO_CRYPTO \ 9 -DZ7_NO_CRYPTO \
10 -DZ7_NO_LONG_PATH \
11 -DZ7_NO_LARGE_PAGES \
10 12
11CURRENT_OBJS = \ 13CURRENT_OBJS = \
12 $O\SfxSetup.obj \ 14 $O\SfxSetup.obj \
@@ -36,6 +38,7 @@ WIN_OBJS = \
36 $O\ResourceString.obj \ 38 $O\ResourceString.obj \
37 $O\Synchronization.obj \ 39 $O\Synchronization.obj \
38 $O\System.obj \ 40 $O\System.obj \
41 $O\TimeUtils.obj \
39 $O\Window.obj \ 42 $O\Window.obj \
40 43
41WIN_CTRL_OBJS = \ 44WIN_CTRL_OBJS = \
diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
index 65cf0bf..18db7f8 100644
--- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
+++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
@@ -44,7 +44,7 @@ RSC=rc.exe
44# PROP Ignore_Export_Lib 0 44# PROP Ignore_Export_Lib 0
45# PROP Target_Dir "" 45# PROP Target_Dir ""
46# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c 46# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
47# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_NO_READ_FROM_CODER" /D "Z7_SFX" /Yu"StdAfx.h" /FD /c 47# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_NO_READ_FROM_CODER" /D "Z7_SFX" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /c
48# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 48# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
49# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 49# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
50# ADD BASE RSC /l 0x419 /d "NDEBUG" 50# ADD BASE RSC /l 0x419 /d "NDEBUG"
@@ -71,7 +71,7 @@ LINK32=link.exe
71# PROP Ignore_Export_Lib 0 71# PROP Ignore_Export_Lib 0
72# PROP Target_Dir "" 72# PROP Target_Dir ""
73# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c 73# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
74# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_NO_READ_FROM_CODER" /D "Z7_SFX" /Yu"StdAfx.h" /FD /GZ /c 74# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_NO_READ_FROM_CODER" /D "Z7_SFX" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c
75# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 75# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
76# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 76# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
77# ADD BASE RSC /l 0x419 /d "_DEBUG" 77# ADD BASE RSC /l 0x419 /d "_DEBUG"
@@ -98,7 +98,7 @@ LINK32=link.exe
98# PROP Ignore_Export_Lib 0 98# PROP Ignore_Export_Lib 0
99# PROP Target_Dir "" 99# PROP Target_Dir ""
100# ADD BASE CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /Yu"StdAfx.h" /FD /c 100# ADD BASE CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_SFX" /Yu"StdAfx.h" /FD /c
101# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_NO_READ_FROM_CODER" /D "Z7_SFX" /Yu"StdAfx.h" /FD /c 101# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "Z7_EXTRACT_ONLY" /D "Z7_NO_REGISTRY" /D "Z7_NO_READ_FROM_CODER" /D "Z7_SFX" /D "Z7_NO_LONG_PATH" /D "Z7_NO_LARGE_PAGES" /Yu"StdAfx.h" /FD /c
102# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 102# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
103# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 103# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
104# ADD BASE RSC /l 0x419 /d "NDEBUG" 104# ADD BASE RSC /l 0x419 /d "NDEBUG"
@@ -673,6 +673,14 @@ SOURCE=..\..\..\Windows\System.h
673# End Source File 673# End Source File
674# Begin Source File 674# Begin Source File
675 675
676SOURCE=..\..\..\Windows\TimeUtils.cpp
677# End Source File
678# Begin Source File
679
680SOURCE=..\..\..\Windows\TimeUtils.h
681# End Source File
682# Begin Source File
683
676SOURCE=..\..\..\Windows\Window.cpp 684SOURCE=..\..\..\Windows\Window.cpp
677# End Source File 685# End Source File
678# Begin Source File 686# Begin Source File
diff --git a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
index 3e1880e..de2ffa4 100644
--- a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
+++ b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
@@ -41,11 +41,18 @@ using namespace NDir;
41extern 41extern
42HINSTANCE g_hInstance; 42HINSTANCE g_hInstance;
43HINSTANCE g_hInstance; 43HINSTANCE g_hInstance;
44extern
45bool g_DisableUserQuestions;
46bool g_DisableUserQuestions;
44 47
45#ifndef UNDER_CE 48#ifndef UNDER_CE
46 49
47static 50#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // win2000
48DWORD g_ComCtl32Version; 51#define Z7_USE_DYN_ComCtl32Version
52#endif
53
54#ifdef Z7_USE_DYN_ComCtl32Version
55Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
49 56
50static DWORD GetDllVersion(LPCTSTR dllName) 57static DWORD GetDllVersion(LPCTSTR dllName)
51{ 58{
@@ -71,6 +78,7 @@ static DWORD GetDllVersion(LPCTSTR dllName)
71} 78}
72 79
73#endif 80#endif
81#endif
74 82
75extern 83extern
76bool g_LVN_ITEMACTIVATE_Support; 84bool g_LVN_ITEMACTIVATE_Support;
@@ -86,14 +94,18 @@ static void ErrorMessageForHRESULT(HRESULT res)
86static int APIENTRY WinMain2() 94static int APIENTRY WinMain2()
87{ 95{
88 // OleInitialize is required for ProgressBar in TaskBar. 96 // OleInitialize is required for ProgressBar in TaskBar.
89 #ifndef UNDER_CE 97#ifndef UNDER_CE
90 OleInitialize(NULL); 98 OleInitialize(NULL);
91 #endif 99#endif
92 100
93 #ifndef UNDER_CE 101#ifndef UNDER_CE
94 g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll")); 102#ifdef Z7_USE_DYN_ComCtl32Version
95 g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4)); 103 {
96 #endif 104 const DWORD g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll"));
105 g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4));
106 }
107#endif
108#endif
97 109
98 UString password; 110 UString password;
99 bool assumeYes = false; 111 bool assumeYes = false;
@@ -135,6 +147,8 @@ static int APIENTRY WinMain2()
135 } 147 }
136 } 148 }
137 149
150 g_DisableUserQuestions = assumeYes;
151
138 FString path; 152 FString path;
139 NDLL::MyGetModuleFileName(path); 153 NDLL::MyGetModuleFileName(path);
140 154
diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile
index 69a8553..806bd07 100644
--- a/CPP/7zip/Bundles/SFXWin/makefile
+++ b/CPP/7zip/Bundles/SFXWin/makefile
@@ -6,6 +6,8 @@ CFLAGS = $(CFLAGS) \
6 -DZ7_EXTRACT_ONLY \ 6 -DZ7_EXTRACT_ONLY \
7 -DZ7_NO_READ_FROM_CODER \ 7 -DZ7_NO_READ_FROM_CODER \
8 -DZ7_SFX \ 8 -DZ7_SFX \
9 -DZ7_NO_LONG_PATH \
10 -DZ7_NO_LARGE_PAGES \
9 11
10!IFDEF UNDER_CE 12!IFDEF UNDER_CE
11LIBS = $(LIBS) ceshell.lib Commctrl.lib 13LIBS = $(LIBS) ceshell.lib Commctrl.lib
@@ -46,6 +48,7 @@ WIN_OBJS = \
46 $O\Shell.obj \ 48 $O\Shell.obj \
47 $O\Synchronization.obj \ 49 $O\Synchronization.obj \
48 $O\System.obj \ 50 $O\System.obj \
51 $O\TimeUtils.obj \
49 $O\Window.obj \ 52 $O\Window.obj \
50 53
51WIN_CTRL_OBJS = \ 54WIN_CTRL_OBJS = \
diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp
index 346774e..d3676b7 100644
--- a/CPP/7zip/Common/CWrappers.cpp
+++ b/CPP/7zip/Common/CWrappers.cpp
@@ -18,6 +18,7 @@ SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw()
18 case E_ABORT: return SZ_ERROR_PROGRESS; 18 case E_ABORT: return SZ_ERROR_PROGRESS;
19 case S_FALSE: return SZ_ERROR_DATA; 19 case S_FALSE: return SZ_ERROR_DATA;
20 case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED; 20 case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED;
21 default: break;
21 } 22 }
22 return defaultRes; 23 return defaultRes;
23} 24}
@@ -32,6 +33,8 @@ HRESULT SResToHRESULT(SRes res) throw()
32 case SZ_ERROR_DATA: 33 case SZ_ERROR_DATA:
33 case SZ_ERROR_CRC: 34 case SZ_ERROR_CRC:
34 case SZ_ERROR_INPUT_EOF: 35 case SZ_ERROR_INPUT_EOF:
36 case SZ_ERROR_ARCHIVE:
37 case SZ_ERROR_NO_ARCHIVE:
35 return S_FALSE; 38 return S_FALSE;
36 39
37 case SZ_ERROR_MEM: return E_OUTOFMEMORY; 40 case SZ_ERROR_MEM: return E_OUTOFMEMORY;
@@ -45,6 +48,7 @@ HRESULT SResToHRESULT(SRes res) throw()
45 // case SZ_ERROR_ARCHIVE: 48 // case SZ_ERROR_ARCHIVE:
46 // case SZ_ERROR_NO_ARCHIVE: 49 // case SZ_ERROR_NO_ARCHIVE:
47 // return E_FAIL; 50 // return E_FAIL;
51 default: break;
48 } 52 }
49 if (res < 0) 53 if (res < 0)
50 return res; 54 return res;
diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp
index 1ebfd72..81172d5 100644
--- a/CPP/7zip/Common/FilePathAutoRename.cpp
+++ b/CPP/7zip/Common/FilePathAutoRename.cpp
@@ -19,8 +19,8 @@ static bool MakeAutoName(const FString &name,
19 19
20bool AutoRenamePath(FString &path) 20bool AutoRenamePath(FString &path)
21{ 21{
22 int dotPos = path.ReverseFind_Dot(); 22 const int dotPos = path.ReverseFind_Dot();
23 int slashPos = path.ReverseFind_PathSepar(); 23 const int slashPos = path.ReverseFind_PathSepar();
24 24
25 FString name = path; 25 FString name = path;
26 FString extension; 26 FString extension;
@@ -29,14 +29,14 @@ bool AutoRenamePath(FString &path)
29 name.DeleteFrom((unsigned)dotPos); 29 name.DeleteFrom((unsigned)dotPos);
30 extension = path.Ptr((unsigned)dotPos); 30 extension = path.Ptr((unsigned)dotPos);
31 } 31 }
32 name += '_'; 32 name.Add_Char('_');
33 33
34 FString temp; 34 FString temp;
35 35
36 UInt32 left = 1, right = ((UInt32)1 << 30); 36 UInt32 left = 1, right = (UInt32)1 << 30;
37 while (left != right) 37 while (left != right)
38 { 38 {
39 UInt32 mid = (left + right) / 2; 39 const UInt32 mid = (left + right) / 2;
40 if (MakeAutoName(name, extension, mid, temp)) 40 if (MakeAutoName(name, extension, mid, temp))
41 left = mid + 1; 41 left = mid + 1;
42 else 42 else
diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp
index 4298636..f90e280 100644
--- a/CPP/7zip/Common/FileStreams.cpp
+++ b/CPP/7zip/Common/FileStreams.cpp
@@ -11,14 +11,26 @@
11#include <grp.h> 11#include <grp.h>
12#include <pwd.h> 12#include <pwd.h>
13 13
14/*
15inclusion of <sys/sysmacros.h> by <sys/types.h> is deprecated since glibc 2.25.
16Since glibc 2.3.3, macros have been aliases for three GNU-specific
17functions: gnu_dev_makedev(), gnu_dev_major(), and gnu_dev_minor()
18
19Warning in GCC:
20In the GNU C Library, "major" is defined by <sys/sysmacros.h>.
21For historical compatibility, it is currently defined by
22<sys/types.h> as well, but we plan to remove this soon.
23To use "major", include <sys/sysmacros.h> directly.
24If you did not intend to use a system-defined macro "major",
25you should undefine it after including <sys/types.h>
26*/
14// for major()/minor(): 27// for major()/minor():
28#if defined(__APPLE__) || defined(__DragonFly__) || \
29 defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
15#include <sys/types.h> 30#include <sys/types.h>
16#if defined(__FreeBSD__) || defined(BSD) || defined(__APPLE__)
17#else 31#else
18#ifndef major
19#include <sys/sysmacros.h> 32#include <sys/sysmacros.h>
20#endif 33#endif
21#endif
22 34
23#endif // _WIN32 35#endif // _WIN32
24 36
@@ -85,6 +97,8 @@ CInFileStream::~CInFileStream()
85 97
86Z7_COM7F_IMF(CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)) 98Z7_COM7F_IMF(CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize))
87{ 99{
100 // printf("\nCInFileStream::Read size=%d, VirtPos=%8d\n", (unsigned)size, (int)VirtPos);
101
88 #ifdef Z7_FILE_STREAMS_USE_WIN_FILE 102 #ifdef Z7_FILE_STREAMS_USE_WIN_FILE
89 103
90 #ifdef Z7_DEVICE_FILE 104 #ifdef Z7_DEVICE_FILE
@@ -205,6 +219,10 @@ Z7_COM7F_IMF(CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
205 219
206 { 220 {
207 const DWORD error = ::GetLastError(); 221 const DWORD error = ::GetLastError();
222#if 0
223 if (File.IsStdStream && error == ERROR_BROKEN_PIPE)
224 return S_OK; // end of stream
225#endif
208 if (Callback) 226 if (Callback)
209 return Callback->InFileStream_On_Error(CallbackRef, error); 227 return Callback->InFileStream_On_Error(CallbackRef, error);
210 if (error == 0) 228 if (error == 0)
@@ -227,13 +245,35 @@ Z7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi
227#else 245#else
228Z7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)) 246Z7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize))
229{ 247{
248 // printf("\nCStdInFileStream::Read size = %d\n", (unsigned)size);
230 #ifdef _WIN32 249 #ifdef _WIN32
231 250
232 DWORD realProcessedSize; 251 DWORD realProcessedSize;
233 UInt32 sizeTemp = (1 << 20); 252 UInt32 sizeTemp = (1 << 20);
234 if (sizeTemp > size) 253 if (sizeTemp > size)
235 sizeTemp = size; 254 sizeTemp = size;
255 /* in GUI mode : GetStdHandle(STD_INPUT_HANDLE) returns NULL,
256 and it doesn't set LastError. */
257 /*
258 SetLastError(0);
259 const HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
260 if (!h || h == INVALID_HANDLE_VALUE)
261 {
262 if (processedSize)
263 *processedSize = 0;
264 if (GetLastError() == 0)
265 SetLastError(ERROR_INVALID_HANDLE);
266 return GetLastError_noZero_HRESULT();
267 }
268 */
236 BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL); 269 BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL);
270
271 /*
272 printf("\nCInFileStream::Read: size=%d, processed=%8d res=%d 4rror=%3d\n",
273 (unsigned)size, (int)realProcessedSize,
274 (int)res, GetLastError());
275 */
276
237 if (processedSize) 277 if (processedSize)
238 *processedSize = realProcessedSize; 278 *processedSize = realProcessedSize;
239 if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) 279 if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)
@@ -261,8 +301,62 @@ Z7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi
261 301
262#endif 302#endif
263 303
304
305/*
306bool CreateStdInStream(CMyComPtr<ISequentialInStream> &str)
307{
308#if 0
309 CInFileStream *inStreamSpec = new CInFileStream;
310 CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);;
311 if (!inStreamSpec->OpenStdIn())
312 return false;
313 if (!inStreamSpec->File.IsStdPipeStream)
314 str = inStreamLoc.Detach();
315 else
316#endif
317 str = new CStdInFileStream;
318 return true;
319}
320*/
321
322#if 0
323bool CInFileStream::OpenStdIn()
324{
325 _info_WasLoaded = false;
326 // Sleep(100);
327 bool res = File.AttachStdIn();
328 if (!res)
329 return false;
330#if 1
331 CStreamFileProps props;
332 if (GetProps2(&props) != S_OK)
333 {
334 // we can ignore that error
335 return false;
336 }
337 // we can't use Size, because Size can be set for pipe streams for some value.
338 // Seek() sees only current chunk in pipe buffer.
339 // So Seek() can move across only current unread chunk.
340 // But after reading that chunk. it can't move position back.
341 // We need safe check that shows that we can use seek (non-pipe mode)
342 // Is it safe check that shows that pipe mode was used?
343 File.IsStdPipeStream = (props.VolID == 0);
344 // && FILETIME_IsZero(props.CTime)
345 // && FILETIME_IsZero(props.ATime)
346 // && FILETIME_IsZero(props.MTime);
347#endif
348 // printf("\n######## pipe=%d", (unsigned)File.IsStdPipeStream);
349 return true;
350}
351#endif
352
353
264Z7_COM7F_IMF(CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) 354Z7_COM7F_IMF(CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
265{ 355{
356 /*
357 printf("\nCInFileStream::Seek seekOrigin=%d, offset=%8d, VirtPos=%8d\n",
358 (unsigned)seekOrigin, (int)offset, (int)VirtPos);
359 */
266 if (seekOrigin >= 3) 360 if (seekOrigin >= 3)
267 return STG_E_INVALIDFUNCTION; 361 return STG_E_INVALIDFUNCTION;
268 362
@@ -463,6 +557,31 @@ Z7_COM7F_IMF(CInFileStream::ReloadProps())
463 _info_WasLoaded = File.GetFileInformation(&_info); 557 _info_WasLoaded = File.GetFileInformation(&_info);
464 if (!_info_WasLoaded) 558 if (!_info_WasLoaded)
465 return GetLastError_HRESULT(); 559 return GetLastError_HRESULT();
560#ifdef _WIN32
561#if 0
562 printf(
563 "\ndwFileAttributes = %8x"
564 "\nftCreationTime = %8x"
565 "\nftLastAccessTime = %8x"
566 "\nftLastWriteTime = %8x"
567 "\ndwVolumeSerialNumber = %8x"
568 "\nnFileSizeHigh = %8x"
569 "\nnFileSizeLow = %8x"
570 "\nnNumberOfLinks = %8x"
571 "\nnFileIndexHigh = %8x"
572 "\nnFileIndexLow = %8x \n",
573 (unsigned)_info.dwFileAttributes,
574 (unsigned)_info.ftCreationTime.dwHighDateTime,
575 (unsigned)_info.ftLastAccessTime.dwHighDateTime,
576 (unsigned)_info.ftLastWriteTime.dwHighDateTime,
577 (unsigned)_info.dwVolumeSerialNumber,
578 (unsigned)_info.nFileSizeHigh,
579 (unsigned)_info.nFileSizeLow,
580 (unsigned)_info.nNumberOfLinks,
581 (unsigned)_info.nFileIndexHigh,
582 (unsigned)_info.nFileIndexLow);
583#endif
584#endif
466 return S_OK; 585 return S_OK;
467} 586}
468 587
@@ -471,6 +590,7 @@ Z7_COM7F_IMF(CInFileStream::ReloadProps())
471 590
472Z7_COM7F_IMF(CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)) 591Z7_COM7F_IMF(CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib))
473{ 592{
593 // printf("\nCInFileStream::GetProps VirtPos = %8d\n", (int)VirtPos);
474 if (!_info_WasLoaded) 594 if (!_info_WasLoaded)
475 { 595 {
476 RINOK(ReloadProps()) 596 RINOK(ReloadProps())
@@ -495,6 +615,7 @@ Z7_COM7F_IMF(CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aT
495 615
496Z7_COM7F_IMF(CInFileStream::GetProps2(CStreamFileProps *props)) 616Z7_COM7F_IMF(CInFileStream::GetProps2(CStreamFileProps *props))
497{ 617{
618 // printf("\nCInFileStream::GetProps2 VirtPos = %8d\n", (int)VirtPos);
498 if (!_info_WasLoaded) 619 if (!_info_WasLoaded)
499 { 620 {
500 RINOK(ReloadProps()) 621 RINOK(ReloadProps())
@@ -535,6 +656,7 @@ Z7_COM7F_IMF(CInFileStream::GetProps2(CStreamFileProps *props))
535 656
536Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)) 657Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value))
537{ 658{
659 // printf("\nCInFileStream::GetProperty VirtPos = %8d propID = %3d\n", (int)VirtPos, propID);
538 if (!_info_WasLoaded) 660 if (!_info_WasLoaded)
539 { 661 {
540 RINOK(ReloadProps()) 662 RINOK(ReloadProps())
@@ -648,6 +770,7 @@ Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value))
648 } 770 }
649 break; 771 break;
650 } 772 }
773 default: break;
651 } 774 }
652 } 775 }
653 prop.Detach(value); 776 prop.Detach(value);
diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h
index 7e1b086..212d4f0 100644
--- a/CPP/7zip/Common/FileStreams.h
+++ b/CPP/7zip/Common/FileStreams.h
@@ -46,8 +46,9 @@ Z7_class_final(CInFileStream) :
46 public IStreamGetProp, 46 public IStreamGetProp,
47 public CMyUnknownImp 47 public CMyUnknownImp
48{ 48{
49 Z7_COM_UNKNOWN_IMP_5( 49 Z7_COM_UNKNOWN_IMP_6(
50 IInStream, 50 IInStream,
51 ISequentialInStream,
51 IStreamGetSize, 52 IStreamGetSize,
52 IStreamGetProps, 53 IStreamGetProps,
53 IStreamGetProps2, 54 IStreamGetProps2,
@@ -108,6 +109,10 @@ public:
108 { 109 {
109 return File.GetLength(length); 110 return File.GetLength(length);
110 } 111 }
112
113#if 0
114 bool OpenStdIn();
115#endif
111 116
112 bool Open(CFSTR fileName) 117 bool Open(CFSTR fileName)
113 { 118 {
@@ -122,6 +127,7 @@ public:
122 } 127 }
123}; 128};
124 129
130// bool CreateStdInStream(CMyComPtr<ISequentialInStream> &str);
125 131
126Z7_CLASS_IMP_NOQIB_1( 132Z7_CLASS_IMP_NOQIB_1(
127 CStdInFileStream 133 CStdInFileStream
@@ -139,15 +145,28 @@ public:
139 145
140 NWindows::NFile::NIO::COutFile File; 146 NWindows::NFile::NIO::COutFile File;
141 147
142 bool Create(CFSTR fileName, bool createAlways) 148 bool Create_NEW(CFSTR fileName)
149 {
150 ProcessedSize = 0;
151 return File.Create_NEW(fileName);
152 }
153
154 bool Create_ALWAYS(CFSTR fileName)
143 { 155 {
144 ProcessedSize = 0; 156 ProcessedSize = 0;
145 return File.Create(fileName, createAlways); 157 return File.Create_ALWAYS(fileName);
146 } 158 }
147 bool Open(CFSTR fileName, DWORD creationDisposition) 159
160 bool Open_EXISTING(CFSTR fileName)
161 {
162 ProcessedSize = 0;
163 return File.Open_EXISTING(fileName);
164 }
165
166 bool Create_ALWAYS_or_Open_ALWAYS(CFSTR fileName, bool createAlways)
148 { 167 {
149 ProcessedSize = 0; 168 ProcessedSize = 0;
150 return File.Open(fileName, creationDisposition); 169 return File.Create_ALWAYS_or_Open_ALWAYS(fileName, createAlways);
151 } 170 }
152 171
153 HRESULT Close(); 172 HRESULT Close();
diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp
index b0f222c..ae004fb 100644
--- a/CPP/7zip/Common/InBuffer.cpp
+++ b/CPP/7zip/Common/InBuffer.cpp
@@ -96,6 +96,24 @@ Byte CInBufferBase::ReadByte_FromNewBlock()
96 return *_buf++; 96 return *_buf++;
97} 97}
98 98
99size_t CInBufferBase::ReadBytesPart(Byte *buf, size_t size)
100{
101 if (size == 0)
102 return 0;
103 size_t rem = (size_t)(_bufLim - _buf);
104 if (rem == 0)
105 {
106 if (!ReadBlock())
107 return 0;
108 rem = (size_t)(_bufLim - _buf);
109 }
110 if (size > rem)
111 size = rem;
112 memcpy(buf, _buf, size);
113 _buf += size;
114 return size;
115}
116
99size_t CInBufferBase::ReadBytes(Byte *buf, size_t size) 117size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
100{ 118{
101 size_t num = 0; 119 size_t num = 0;
diff --git a/CPP/7zip/Common/InBuffer.h b/CPP/7zip/Common/InBuffer.h
index 3aaf797..a8ccb40 100644
--- a/CPP/7zip/Common/InBuffer.h
+++ b/CPP/7zip/Common/InBuffer.h
@@ -51,6 +51,7 @@ public:
51 bool WasFinished() const { return _wasFinished; } 51 bool WasFinished() const { return _wasFinished; }
52 52
53 void SetStream(ISequentialInStream *stream) { _stream = stream; } 53 void SetStream(ISequentialInStream *stream) { _stream = stream; }
54 void ClearStreamPtr() { _stream = NULL; }
54 55
55 void SetBuf(Byte *buf, size_t bufSize, size_t end, size_t pos) 56 void SetBuf(Byte *buf, size_t bufSize, size_t end, size_t pos)
56 { 57 {
@@ -94,6 +95,7 @@ public:
94 return *_buf++; 95 return *_buf++;
95 } 96 }
96 97
98 size_t ReadBytesPart(Byte *buf, size_t size);
97 size_t ReadBytes(Byte *buf, size_t size); 99 size_t ReadBytes(Byte *buf, size_t size);
98 size_t Skip(size_t size); 100 size_t Skip(size_t size);
99}; 101};
diff --git a/CPP/7zip/Common/MemBlocks.cpp b/CPP/7zip/Common/MemBlocks.cpp
index aa68244..6165c7e 100644
--- a/CPP/7zip/Common/MemBlocks.cpp
+++ b/CPP/7zip/Common/MemBlocks.cpp
@@ -57,7 +57,7 @@ void CMemBlockManager::FreeBlock(void *p)
57 57
58// #include <stdio.h> 58// #include <stdio.h>
59 59
60HRes CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks) 60HRESULT CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks)
61{ 61{
62 if (numNoLockBlocks > numBlocks) 62 if (numNoLockBlocks > numBlocks)
63 return E_INVALIDARG; 63 return E_INVALIDARG;
@@ -87,7 +87,7 @@ HRes CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks)
87} 87}
88 88
89 89
90HRes CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks) 90HRESULT CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks)
91{ 91{
92 // desiredNumberOfBlocks = 0; // for debug 92 // desiredNumberOfBlocks = 0; // for debug
93 if (numNoLockBlocks > desiredNumberOfBlocks) 93 if (numNoLockBlocks > desiredNumberOfBlocks)
@@ -95,7 +95,7 @@ HRes CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_
95 for (;;) 95 for (;;)
96 { 96 {
97 // if (desiredNumberOfBlocks == 0) return E_OUTOFMEMORY; 97 // if (desiredNumberOfBlocks == 0) return E_OUTOFMEMORY;
98 HRes hres = AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks); 98 const HRESULT hres = AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks);
99 if (hres != E_OUTOFMEMORY) 99 if (hres != E_OUTOFMEMORY)
100 return hres; 100 return hres;
101 if (desiredNumberOfBlocks == numNoLockBlocks) 101 if (desiredNumberOfBlocks == numNoLockBlocks)
diff --git a/CPP/7zip/Common/MemBlocks.h b/CPP/7zip/Common/MemBlocks.h
index 7c34f21..201f3bc 100644
--- a/CPP/7zip/Common/MemBlocks.h
+++ b/CPP/7zip/Common/MemBlocks.h
@@ -36,8 +36,8 @@ public:
36 CMemBlockManagerMt(size_t blockSize = (1 << 20)): CMemBlockManager(blockSize) {} 36 CMemBlockManagerMt(size_t blockSize = (1 << 20)): CMemBlockManager(blockSize) {}
37 ~CMemBlockManagerMt() { FreeSpace(); } 37 ~CMemBlockManagerMt() { FreeSpace(); }
38 38
39 HRes AllocateSpace(size_t numBlocks, size_t numNoLockBlocks); 39 HRESULT AllocateSpace(size_t numBlocks, size_t numNoLockBlocks);
40 HRes AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks = 0); 40 HRESULT AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks = 0);
41 void FreeSpace(); 41 void FreeSpace();
42 void *AllocateBlock(); 42 void *AllocateBlock();
43 void FreeBlock(void *p, bool lockMode = true); 43 void FreeBlock(void *p, bool lockMode = true);
@@ -65,7 +65,7 @@ struct CMemLockBlocks: public CMemBlocks
65 CMemLockBlocks(): LockMode(true) {} 65 CMemLockBlocks(): LockMode(true) {}
66 void Free(CMemBlockManagerMt *memManager); 66 void Free(CMemBlockManagerMt *memManager);
67 void FreeBlock(unsigned index, CMemBlockManagerMt *memManager); 67 void FreeBlock(unsigned index, CMemBlockManagerMt *memManager);
68 // HRes SwitchToNoLockMode(CMemBlockManagerMt *memManager); 68 // HRESULT SwitchToNoLockMode(CMemBlockManagerMt *memManager);
69 void Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager); 69 void Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager);
70}; 70};
71 71
diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp
index fe60f61..d87884c 100644
--- a/CPP/7zip/Common/MethodProps.cpp
+++ b/CPP/7zip/Common/MethodProps.cpp
@@ -60,6 +60,7 @@ HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest)
60 case VT_EMPTY: dest = true; return S_OK; 60 case VT_EMPTY: dest = true; return S_OK;
61 case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK; 61 case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK;
62 case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG; 62 case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG;
63 default: break;
63 } 64 }
64 return E_INVALIDARG; 65 return E_INVALIDARG;
65} 66}
@@ -541,6 +542,7 @@ static bool IsLogSizeProp(PROPID propid)
541 */ 542 */
542 // case NCoderPropID::kReduceSize: 543 // case NCoderPropID::kReduceSize:
543 return true; 544 return true;
545 default: break;
544 } 546 }
545 return false; 547 return false;
546} 548}
diff --git a/CPP/7zip/Common/MultiOutStream.cpp b/CPP/7zip/Common/MultiOutStream.cpp
index 8efb977..1954311 100644
--- a/CPP/7zip/Common/MultiOutStream.cpp
+++ b/CPP/7zip/Common/MultiOutStream.cpp
@@ -183,7 +183,7 @@ bool CMultiOutStream::IsRestricted_for_Close(unsigned index) const
183FString CMultiOutStream::GetFilePath(unsigned index) 183FString CMultiOutStream::GetFilePath(unsigned index)
184{ 184{
185 FString name; 185 FString name;
186 name.Add_UInt32(index + 1); 186 name.Add_UInt32((UInt32)(index + 1));
187 while (name.Len() < 3) 187 while (name.Len() < 3)
188 name.InsertAtFront(FTEXT('0')); 188 name.InsertAtFront(FTEXT('0'));
189 name.Insert(0, Prefix); 189 name.Insert(0, Prefix);
@@ -209,7 +209,7 @@ HRESULT CMultiOutStream::CloseStream(unsigned index)
209// we close stream and delete file, but we still keep item in Streams[] vector 209// we close stream and delete file, but we still keep item in Streams[] vector
210HRESULT CMultiOutStream::CloseStream_and_DeleteFile(unsigned index) 210HRESULT CMultiOutStream::CloseStream_and_DeleteFile(unsigned index)
211{ 211{
212 PRF(printf("\n====== %u, CloseStream_AndDelete \n", index)); 212 PRF(printf("\n====== %u, CloseStream_AndDelete \n", index))
213 RINOK(CloseStream(index)) 213 RINOK(CloseStream(index))
214 FString path = GetFilePath(index); 214 FString path = GetFilePath(index);
215 path += Streams[index].Postfix; 215 path += Streams[index].Postfix;
@@ -223,7 +223,7 @@ HRESULT CMultiOutStream::CloseStream_and_DeleteFile(unsigned index)
223 223
224HRESULT CMultiOutStream::CloseStream_and_FinalRename(unsigned index) 224HRESULT CMultiOutStream::CloseStream_and_FinalRename(unsigned index)
225{ 225{
226 PRF(printf("\n====== %u, CloseStream_and_FinalRename \n", index)); 226 PRF(printf("\n====== %u, CloseStream_and_FinalRename \n", index))
227 CVolStream &s = Streams[index]; 227 CVolStream &s = Streams[index];
228 // HRESULT res = S_OK; 228 // HRESULT res = S_OK;
229 bool mtime_WasSet = false; 229 bool mtime_WasSet = false;
@@ -261,6 +261,8 @@ HRESULT CMultiOutStream::CloseStream_and_FinalRename(unsigned index)
261 261
262HRESULT CMultiOutStream::PrepareToOpenNew() 262HRESULT CMultiOutStream::PrepareToOpenNew()
263{ 263{
264 PRF(printf("PrepareToOpenNew NumListItems =%u, NumOpenFiles_AllowedMax = %u \n", NumListItems, NumOpenFiles_AllowedMax))
265
264 if (NumListItems < NumOpenFiles_AllowedMax) 266 if (NumListItems < NumOpenFiles_AllowedMax)
265 return S_OK; 267 return S_OK;
266 /* when we create zip archive: in most cases we need only starting 268 /* when we create zip archive: in most cases we need only starting
@@ -270,7 +272,7 @@ HRESULT CMultiOutStream::PrepareToOpenNew()
270 const int index = Head; 272 const int index = Head;
271 if (index == -1) 273 if (index == -1)
272 return E_FAIL; 274 return E_FAIL;
273 PRF(printf("\n== %u, PrepareToOpenNew::CloseStream, NumListItems =%u \n", index, NumListItems)); 275 PRF(printf("\n== %u, PrepareToOpenNew::CloseStream, NumListItems =%u \n", index, NumListItems))
274 /* we don't expect non-restricted stream here in normal cases (if _restrict_Global was not changed). 276 /* we don't expect non-restricted stream here in normal cases (if _restrict_Global was not changed).
275 if there was non-restricted stream, it should be closed before */ 277 if there was non-restricted stream, it should be closed before */
276 // if (!IsRestricted_for_Close(index)) return CloseStream_and_FinalRename(index); 278 // if (!IsRestricted_for_Close(index)) return CloseStream_and_FinalRename(index);
@@ -280,7 +282,7 @@ HRESULT CMultiOutStream::PrepareToOpenNew()
280 282
281HRESULT CMultiOutStream::CreateNewStream(UInt64 newSize) 283HRESULT CMultiOutStream::CreateNewStream(UInt64 newSize)
282{ 284{
283 PRF(printf("\n== %u, CreateNewStream, size =%u \n", Streams.Size(), (unsigned)newSize)); 285 PRF(printf("\n== %u, CreateNewStream, size =%u \n", Streams.Size(), (unsigned)newSize))
284 286
285 if (Streams.Size() >= k_NumVols_MAX) 287 if (Streams.Size() >= k_NumVols_MAX)
286 return E_INVALIDARG; // E_OUTOFMEMORY 288 return E_INVALIDARG; // E_OUTOFMEMORY
@@ -358,7 +360,7 @@ HRESULT CMultiOutStream::CreateStreams_If_Required(unsigned streamIndex)
358 360
359HRESULT CMultiOutStream::ReOpenStream(unsigned streamIndex) 361HRESULT CMultiOutStream::ReOpenStream(unsigned streamIndex)
360{ 362{
361 PRF(printf("\n====== %u, ReOpenStream \n", streamIndex)); 363 PRF(printf("\n====== %u, ReOpenStream \n", streamIndex))
362 RINOK(PrepareToOpenNew()) 364 RINOK(PrepareToOpenNew())
363 CVolStream &s = Streams[streamIndex]; 365 CVolStream &s = Streams[streamIndex];
364 366
@@ -370,7 +372,7 @@ HRESULT CMultiOutStream::ReOpenStream(unsigned streamIndex)
370 s.Pos = 0; 372 s.Pos = 0;
371 373
372 HRESULT hres; 374 HRESULT hres;
373 if (s.StreamSpec->Open(path, OPEN_EXISTING)) 375 if (s.StreamSpec->Open_EXISTING(path))
374 { 376 {
375 if (s.Postfix.IsEmpty()) 377 if (s.Postfix.IsEmpty())
376 { 378 {
@@ -384,6 +386,7 @@ HRESULT CMultiOutStream::ReOpenStream(unsigned streamIndex)
384 { 386 {
385 if (realSize == s.RealSize) 387 if (realSize == s.RealSize)
386 { 388 {
389 PRF(printf("\n ReOpenStream OK realSize = %u\n", (unsigned)realSize))
387 InsertToLinkedList(streamIndex); 390 InsertToLinkedList(streamIndex);
388 return S_OK; 391 return S_OK;
389 } 392 }
@@ -412,7 +415,7 @@ HRESULT CMultiOutStream::OptReOpen_and_SetSize(unsigned index, UInt64 size)
412 { 415 {
413 RINOK(ReOpenStream(index)) 416 RINOK(ReOpenStream(index))
414 } 417 }
415 PRF(printf("\n== %u, OptReOpen_and_SetSize, size =%u RealSize = %u\n", index, (unsigned)size, (unsigned)s.RealSize)); 418 PRF(printf("\n== %u, OptReOpen_and_SetSize, size =%u RealSize = %u\n", index, (unsigned)size, (unsigned)s.RealSize))
416 // comment it to debug tail after data 419 // comment it to debug tail after data
417 return s.SetSize2(size); 420 return s.SetSize2(size);
418} 421}
@@ -440,7 +443,7 @@ Note: we don't remove zero sized first volume, if (_length == 0)
440 443
441HRESULT CMultiOutStream::Normalize_finalMode(bool finalMode) 444HRESULT CMultiOutStream::Normalize_finalMode(bool finalMode)
442{ 445{
443 PRF(printf("\n== Normalize_finalMode: _length =%d \n", (unsigned)_length)); 446 PRF(printf("\n== Normalize_finalMode: _length =%d \n", (unsigned)_length))
444 447
445 unsigned i = Streams.Size(); 448 unsigned i = Streams.Size();
446 449
@@ -579,7 +582,7 @@ Z7_COM7F_IMF(CMultiOutStream::SetSize(UInt64 newSize))
579 else if (newSize < _restrict_Global) 582 else if (newSize < _restrict_Global)
580 _restrict_Global = newSize; 583 _restrict_Global = newSize;
581 584
582 PRF(printf("\n== SetSize, size =%u \n", (unsigned)newSize)); 585 PRF(printf("\n== CMultiOutStream::SetSize, size =%u \n", (unsigned)newSize))
583 586
584 _length = newSize; 587 _length = newSize;
585 return Normalize_finalMode(false); 588 return Normalize_finalMode(false);
@@ -596,6 +599,9 @@ Z7_COM7F_IMF(CMultiOutStream::Write(const void *data, UInt32 size, UInt32 *proce
596 if (size == 0) 599 if (size == 0)
597 return S_OK; 600 return S_OK;
598 601
602 PRF(printf("\n -- CMultiOutStream::Write() : _absPos = %6u, size =%6u \n",
603 (unsigned)_absPos, (unsigned)size))
604
599 if (_absPos > _length) 605 if (_absPos > _length)
600 { 606 {
601 // it create data only up to _absPos. 607 // it create data only up to _absPos.
@@ -648,7 +654,7 @@ Z7_COM7F_IMF(CMultiOutStream::Write(const void *data, UInt32 size, UInt32 *proce
648 CVolStream &s = Streams[_streamIndex]; 654 CVolStream &s = Streams[_streamIndex];
649 655
650 PRF(printf("\n%d, == Write : Pos = %u, RealSize = %u size =%u \n", 656 PRF(printf("\n%d, == Write : Pos = %u, RealSize = %u size =%u \n",
651 _streamIndex, (unsigned)s.Pos, (unsigned)s.RealSize, size)); 657 _streamIndex, (unsigned)s.Pos, (unsigned)s.RealSize, size))
652 658
653 if (!s.Stream) 659 if (!s.Stream)
654 { 660 {
@@ -712,7 +718,7 @@ Z7_COM7F_IMF(CMultiOutStream::Write(const void *data, UInt32 size, UInt32 *proce
712 718
713Z7_COM7F_IMF(CMultiOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) 719Z7_COM7F_IMF(CMultiOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
714{ 720{
715 PRF(printf("\n-- Seek seekOrigin=%u Seek =%u\n", seekOrigin, (unsigned)offset)); 721 PRF(printf("\n-- CMultiOutStream::Seek seekOrigin=%u Seek =%u\n", seekOrigin, (unsigned)offset))
716 722
717 switch (seekOrigin) 723 switch (seekOrigin)
718 { 724 {
@@ -753,7 +759,7 @@ unsigned CMultiOutStream::GetStreamIndex_for_Offset(UInt64 offset, UInt64 &relOf
753 const UInt64 size = Sizes[last]; 759 const UInt64 size = Sizes[last];
754 const UInt64 v = offset / size; 760 const UInt64 v = offset / size;
755 if (v >= ((UInt32)(Int32)-1) - last) 761 if (v >= ((UInt32)(Int32)-1) - last)
756 return (UInt32)(Int32)-1; // saturation 762 return (unsigned)(int)-1; // saturation
757 relOffset = offset - (unsigned)v * size; 763 relOffset = offset - (unsigned)v * size;
758 return last + (unsigned)(v); 764 return last + (unsigned)(v);
759} 765}
@@ -765,7 +771,7 @@ Z7_COM7F_IMF(CMultiOutStream::SetRestriction(UInt64 begin, UInt64 end))
765 771
766 // begin = end = 0; // for debug 772 // begin = end = 0; // for debug
767 773
768 PRF(printf("\n==================== CMultiOutStream::SetRestriction %u, %u\n", (unsigned)begin, (unsigned)end)); 774 PRF(printf("\n==================== CMultiOutStream::SetRestriction %u, %u\n", (unsigned)begin, (unsigned)end))
769 if (begin > end) 775 if (begin > end)
770 { 776 {
771 // these value are FAILED values. 777 // these value are FAILED values.
diff --git a/CPP/7zip/Common/OutBuffer.h b/CPP/7zip/Common/OutBuffer.h
index cef7d50..88f5787 100644
--- a/CPP/7zip/Common/OutBuffer.h
+++ b/CPP/7zip/Common/OutBuffer.h
@@ -60,6 +60,48 @@ public:
60 WriteByte(((const Byte *)data)[i]); 60 WriteByte(((const Byte *)data)[i]);
61 } 61 }
62 62
63 Byte *GetOutBuffer(size_t &avail)
64 {
65 const UInt32 pos = _pos;
66 avail = (size_t)(_limitPos - pos);
67 return _buf + pos;
68 }
69
70 void SkipWrittenBytes(size_t num)
71 {
72 const UInt32 pos = _pos;
73 const UInt32 rem = _limitPos - pos;
74 if (rem > num)
75 {
76 _pos = pos + (UInt32)num;
77 return;
78 }
79 // (rem <= num)
80 // the caller must not call it with (rem < num)
81 // so (rem == num)
82 _pos = _limitPos;
83 FlushWithCheck();
84 }
85 /*
86 void WriteBytesBig(const void *data, size_t size)
87 {
88 while (size)
89 {
90 UInt32 pos = _pos;
91 UInt32 rem = _limitPos - pos;
92 if (rem > size)
93 {
94 _pos = pos + size;
95 memcpy(_buf + pos, data, size);
96 return;
97 }
98 memcpy(_buf + pos, data, rem);
99 _pos = pos + rem;
100 FlushWithCheck();
101 }
102 }
103 */
104
63 UInt64 GetProcessedSize() const throw(); 105 UInt64 GetProcessedSize() const throw();
64}; 106};
65 107
diff --git a/CPP/7zip/Common/OutMemStream.h b/CPP/7zip/Common/OutMemStream.h
index 7fc2dbd..a58fb91 100644
--- a/CPP/7zip/Common/OutMemStream.h
+++ b/CPP/7zip/Common/OutMemStream.h
@@ -33,7 +33,7 @@ Z7_CLASS_IMP_NOQIB_1(
33 33
34public: 34public:
35 35
36 HRes CreateEvents(SYNC_PARAM_DECL(synchro)) 36 HRESULT CreateEvents(SYNC_PARAM_DECL(synchro))
37 { 37 {
38 WRes wres = StopWritingEvent.CreateIfNotCreated_Reset(SYNC_WFMO(synchro)); 38 WRes wres = StopWritingEvent.CreateIfNotCreated_Reset(SYNC_WFMO(synchro));
39 if (wres == 0) 39 if (wres == 0)
diff --git a/CPP/7zip/Compress/BZip2Crc.cpp b/CPP/7zip/Compress/BZip2Crc.cpp
index 9639c7b..1c62253 100644
--- a/CPP/7zip/Compress/BZip2Crc.cpp
+++ b/CPP/7zip/Compress/BZip2Crc.cpp
@@ -4,6 +4,7 @@
4 4
5#include "BZip2Crc.h" 5#include "BZip2Crc.h"
6 6
7MY_ALIGN(64)
7UInt32 CBZip2Crc::Table[256]; 8UInt32 CBZip2Crc::Table[256];
8 9
9static const UInt32 kBZip2CrcPoly = 0x04c11db7; /* AUTODIN II, Ethernet, & FDDI */ 10static const UInt32 kBZip2CrcPoly = 0x04c11db7; /* AUTODIN II, Ethernet, & FDDI */
@@ -12,7 +13,7 @@ void CBZip2Crc::InitTable()
12{ 13{
13 for (UInt32 i = 0; i < 256; i++) 14 for (UInt32 i = 0; i < 256; i++)
14 { 15 {
15 UInt32 r = (i << 24); 16 UInt32 r = i << 24;
16 for (unsigned j = 0; j < 8; j++) 17 for (unsigned j = 0; j < 8; j++)
17 r = (r << 1) ^ (kBZip2CrcPoly & ((UInt32)0 - (r >> 31))); 18 r = (r << 1) ^ (kBZip2CrcPoly & ((UInt32)0 - (r >> 31)));
18 Table[i] = r; 19 Table[i] = r;
diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp
index b28da5f..f44faa2 100644
--- a/CPP/7zip/Compress/BZip2Decoder.cpp
+++ b/CPP/7zip/Compress/BZip2Decoder.cpp
@@ -42,7 +42,7 @@ static const size_t kOutBufSize = (size_t)1 << 20;
42 42
43static const UInt32 kProgressStep = (UInt32)1 << 16; 43static const UInt32 kProgressStep = (UInt32)1 << 16;
44 44
45 45MY_ALIGN(64)
46static const UInt16 kRandNums[512] = { 46static const UInt16 kRandNums[512] = {
47 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 47 619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
48 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 48 985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
@@ -120,18 +120,18 @@ enum EState
120}; 120};
121 121
122 122
123#define UPDATE_VAL_2(val) { \ 123#define UPDATE_VAL_2(val, num_bits) { \
124 val |= (UInt32)(*_buf) << (24 - _numBits); \ 124 val |= (UInt32)(*_buf) << (24 - num_bits); \
125 _numBits += 8; \ 125 num_bits += 8; \
126 _buf++; \ 126 _buf++; \
127} 127}
128 128
129#define UPDATE_VAL UPDATE_VAL_2(VAL) 129#define UPDATE_VAL UPDATE_VAL_2(VAL, NUM_BITS)
130 130
131#define READ_BITS(res, num) { \ 131#define READ_BITS(res, num) { \
132 while (_numBits < num) { \ 132 while (_numBits < num) { \
133 if (_buf == _lim) return SZ_OK; \ 133 if (_buf == _lim) return SZ_OK; \
134 UPDATE_VAL_2(_value) } \ 134 UPDATE_VAL_2(_value, _numBits) } \
135 res = _value >> (32 - num); \ 135 res = _value >> (32 - num); \
136 _value <<= num; \ 136 _value <<= num; \
137 _numBits -= num; \ 137 _numBits -= num; \
@@ -140,7 +140,7 @@ enum EState
140#define READ_BITS_8(res, num) { \ 140#define READ_BITS_8(res, num) { \
141 if (_numBits < num) { \ 141 if (_numBits < num) { \
142 if (_buf == _lim) return SZ_OK; \ 142 if (_buf == _lim) return SZ_OK; \
143 UPDATE_VAL_2(_value) } \ 143 UPDATE_VAL_2(_value, _numBits) } \
144 res = _value >> (32 - num); \ 144 res = _value >> (32 - num); \
145 _value <<= num; \ 145 _value <<= num; \
146 _numBits -= num; \ 146 _numBits -= num; \
@@ -151,16 +151,20 @@ enum EState
151 151
152 152
153#define VAL _value2 153#define VAL _value2
154// #define NUM_BITS _numBits2
155#define NUM_BITS _numBits
154#define BLOCK_SIZE blockSize2 156#define BLOCK_SIZE blockSize2
155#define RUN_COUNTER runCounter2 157#define RUN_COUNTER runCounter2
156 158
157#define LOAD_LOCAL \ 159#define LOAD_LOCAL \
158 UInt32 VAL = this->_value; \ 160 UInt32 VAL = this->_value; \
161 /* unsigned NUM_BITS = this->_numBits; */ \
159 UInt32 BLOCK_SIZE = this->blockSize; \ 162 UInt32 BLOCK_SIZE = this->blockSize; \
160 UInt32 RUN_COUNTER = this->runCounter; \ 163 UInt32 RUN_COUNTER = this->runCounter; \
161 164
162#define SAVE_LOCAL \ 165#define SAVE_LOCAL \
163 this->_value = VAL; \ 166 this->_value = VAL; \
167 /* this->_numBits = NUM_BITS; */ \
164 this->blockSize = BLOCK_SIZE; \ 168 this->blockSize = BLOCK_SIZE; \
165 this->runCounter = RUN_COUNTER; \ 169 this->runCounter = RUN_COUNTER; \
166 170
@@ -364,8 +368,8 @@ SRes CBase::ReadBlock2()
364 if (++state4 >= numTables) 368 if (++state4 >= numTables)
365 return SZ_ERROR_DATA; 369 return SZ_ERROR_DATA;
366 } 370 }
367 UInt32 tmp = (state2 >> (kMtfBits * state4)) & kMtfMask; 371 const UInt32 tmp = (state2 >> (kMtfBits * state4)) & kMtfMask;
368 UInt32 mask = ((UInt32)1 << ((state4 + 1) * kMtfBits)) - 1; 372 const UInt32 mask = ((UInt32)1 << ((state4 + 1) * kMtfBits)) - 1;
369 state4 = 0; 373 state4 = 0;
370 state2 = ((state2 << kMtfBits) & mask) | (state2 & ~mask) | tmp; 374 state2 = ((state2 << kMtfBits) & mask) | (state2 & ~mask) | tmp;
371 // 20.01: here we keep compatibility with bzip2-1.0.8 decoder: 375 // 20.01: here we keep compatibility with bzip2-1.0.8 decoder:
@@ -424,15 +428,11 @@ SRes CBase::ReadBlock2()
424 state5 = 0; 428 state5 = 0;
425 } 429 }
426 430
427 // 19.03: we use Build() instead of BuildFull() to support lbzip2 archives 431 // 19.03: we use non-full Build() to support lbzip2 archives.
428 // lbzip2 2.5 can produce dummy tree, where lens[i] = kMaxHuffmanLen 432 // lbzip2 2.5 can produce dummy tree, where lens[i] = kMaxHuffmanLen
429 // BuildFull() returns error for such tree
430 for (unsigned i = state4; i < kMaxAlphaSize; i++) 433 for (unsigned i = state4; i < kMaxAlphaSize; i++)
431 lens[i] = 0; 434 lens[i] = 0;
432 if (!huffs[state2].Build(lens)) 435 if (!huffs[state2].Build(lens)) // k_BuildMode_Partial
433 /*
434 if (!huffs[state2].BuildFull(lens, state4))
435 */
436 return SZ_ERROR_DATA; 436 return SZ_ERROR_DATA;
437 state3 = 0; 437 state3 = 0;
438 } 438 }
@@ -462,7 +462,7 @@ SRes CBase::ReadBlock2()
462 462
463 { 463 {
464 LOAD_LOCAL 464 LOAD_LOCAL
465 const CHuffmanDecoder *huff = &huffs[selectors[groupIndex]]; 465 const CHuffmanDecoder *huf = &huffs[selectors[groupIndex]];
466 466
467 for (;;) 467 for (;;)
468 { 468 {
@@ -470,58 +470,38 @@ SRes CBase::ReadBlock2()
470 { 470 {
471 if (++groupIndex >= numSelectors) 471 if (++groupIndex >= numSelectors)
472 return SZ_ERROR_DATA; 472 return SZ_ERROR_DATA;
473 huff = &huffs[selectors[groupIndex]]; 473 huf = &huffs[selectors[groupIndex]];
474 groupSize = kGroupSize; 474 groupSize = kGroupSize;
475 } 475 }
476 476
477 if (_numBits <= 8 && 477 if (NUM_BITS < kMaxHuffmanLen && _buf != _lim) { UPDATE_VAL
478 _buf != _lim) { UPDATE_VAL 478 if (NUM_BITS < kMaxHuffmanLen && _buf != _lim) { UPDATE_VAL
479 if (_buf != _lim) { UPDATE_VAL 479 if (NUM_BITS < kMaxHuffmanLen && _buf != _lim) { UPDATE_VAL }}}
480 if (_buf != _lim) { UPDATE_VAL }}} 480
481 481 unsigned sym;
482 UInt32 sym; 482
483 UInt32 val = VAL >> (32 - kMaxHuffmanLen); 483 #define MOV_POS(bs, len) \
484 if (val >= huff->_limits[kNumTableBits]) 484 { \
485 { 485 if (NUM_BITS < len) \
486 if (_numBits <= kMaxHuffmanLen && _buf != _lim) { UPDATE_VAL 486 { \
487 if (_numBits <= kMaxHuffmanLen && _buf != _lim) { UPDATE_VAL }} 487 SAVE_LOCAL \
488 488 return SZ_OK; \
489 val = VAL >> (32 - kMaxHuffmanLen); 489 } \
490 unsigned len; 490 VAL <<= len; \
491 for (len = kNumTableBits + 1; val >= huff->_limits[len]; len++); 491 NUM_BITS -= (unsigned)len; \
492
493 // 19.03: we use that check to support partial trees created Build() for lbzip2 archives
494 if (len > kNumBitsMax)
495 return SZ_ERROR_DATA; // that check is required, if NHuffman::Build() was used instead of BuildFull()
496
497 if (_numBits < len)
498 {
499 SAVE_LOCAL
500 return SZ_OK;
501 }
502 sym = huff->_symbols[huff->_poses[len] + ((val - huff->_limits[(size_t)len - 1]) >> (kNumBitsMax - len))];
503 VAL <<= len;
504 _numBits -= len;
505 }
506 else
507 {
508 sym = huff->_lens[val >> (kMaxHuffmanLen - kNumTableBits)];
509 unsigned len = (sym & NHuffman::kPairLenMask);
510 sym >>= NHuffman::kNumPairLenBits;
511 if (_numBits < len)
512 {
513 SAVE_LOCAL
514 return SZ_OK;
515 }
516 VAL <<= len;
517 _numBits -= len;
518 } 492 }
519 493
494 Z7_HUFF_DECODE_VAL_IN_HIGH32(sym, huf, kMaxHuffmanLen, kNumTableBits,
495 VAL,
496 Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES,
497 { return SZ_ERROR_DATA; },
498 MOV_POS, {}, bs)
499
520 groupSize--; 500 groupSize--;
521 501
522 if (sym < 2) 502 if (sym < 2)
523 { 503 {
524 RUN_COUNTER += ((UInt32)(sym + 1) << runPower); 504 RUN_COUNTER += (UInt32)(sym + 1) << runPower;
525 runPower++; 505 runPower++;
526 if (blockSizeMax - BLOCK_SIZE < RUN_COUNTER) 506 if (blockSizeMax - BLOCK_SIZE < RUN_COUNTER)
527 return SZ_ERROR_DATA; 507 return SZ_ERROR_DATA;
diff --git a/CPP/7zip/Compress/BZip2Decoder.h b/CPP/7zip/Compress/BZip2Decoder.h
index a8ef700..4adc564 100644
--- a/CPP/7zip/Compress/BZip2Decoder.h
+++ b/CPP/7zip/Compress/BZip2Decoder.h
@@ -27,7 +27,6 @@ bool IsEndSig(const Byte *p) throw();
27bool IsBlockSig(const Byte *p) throw(); 27bool IsBlockSig(const Byte *p) throw();
28 28
29const unsigned kNumTableBits = 9; 29const unsigned kNumTableBits = 9;
30const unsigned kNumBitsMax = kMaxHuffmanLen;
31 30
32typedef NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize, kNumTableBits> CHuffmanDecoder; 31typedef NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize, kNumTableBits> CHuffmanDecoder;
33 32
@@ -99,7 +98,7 @@ struct CBase: public CBitDecoder
99 UInt32 blockSizeMax; 98 UInt32 blockSizeMax;
100 99
101 unsigned state; 100 unsigned state;
102 unsigned state2; 101 UInt32 state2;
103 unsigned state3; 102 unsigned state3;
104 unsigned state4; 103 unsigned state4;
105 unsigned state5; 104 unsigned state5;
diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp
index 27e78b0..4fa42a5 100644
--- a/CPP/7zip/Compress/Bcj2Coder.cpp
+++ b/CPP/7zip/Compress/Bcj2Coder.cpp
@@ -506,7 +506,7 @@ void CBaseDecoder::ReadInStream(ISequentialInStream *inStream)
506 506
507 if (BCJ2_IS_32BIT_STREAM(state)) 507 if (BCJ2_IS_32BIT_STREAM(state))
508 { 508 {
509 const unsigned extra = ((unsigned)total & 3); 509 const unsigned extra = (unsigned)total & 3;
510 _extraSizes[state] = extra; 510 _extraSizes[state] = extra;
511 if (total < 4) 511 if (total < 4)
512 { 512 {
@@ -514,7 +514,7 @@ void CBaseDecoder::ReadInStream(ISequentialInStream *inStream)
514 _readRes[state] = S_FALSE; // actually it's stream error. So maybe we need another error code. 514 _readRes[state] = S_FALSE; // actually it's stream error. So maybe we need another error code.
515 return; 515 return;
516 } 516 }
517 total -= extra; 517 total -= (UInt32)extra;
518 } 518 }
519 519
520 dec.lims[state] += total; // = _bufs[state] + total; 520 dec.lims[state] += total; // = _bufs[state] + total;
@@ -655,6 +655,20 @@ Z7_COM7F_IMF(CDecoder::Code(
655 return S_FALSE; 655 return S_FALSE;
656 } 656 }
657 } 657 }
658
659 /* v23.02: we call Read(0) for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP streams,
660 if there were no Read() calls for such stream.
661 So the handlers of these input streams objects can do
662 Init/Flushing even for case when stream is empty:
663 */
664 for (unsigned i = BCJ2_STREAM_CALL; i < BCJ2_STREAM_CALL + 2; i++)
665 {
666 if (_readSizes[i])
667 continue;
668 Byte b;
669 UInt32 processed;
670 RINOK(inStreams[i]->Read(&b, 0, &processed))
671 }
658 } 672 }
659 673
660 return S_OK; 674 return S_OK;
diff --git a/CPP/7zip/Compress/BitlDecoder.cpp b/CPP/7zip/Compress/BitlDecoder.cpp
index 876e649..bf1e5ba 100644
--- a/CPP/7zip/Compress/BitlDecoder.cpp
+++ b/CPP/7zip/Compress/BitlDecoder.cpp
@@ -6,20 +6,27 @@
6 6
7namespace NBitl { 7namespace NBitl {
8 8
9Byte kInvertTable[256]; 9#if defined(Z7_BITL_USE_REVERSE_BITS_TABLE)
10
11MY_ALIGN(64)
12Byte kReverseTable[256];
10 13
11static 14static
12struct CInverterTableInitializer 15struct CReverseerTableInitializer
13{ 16{
14 CInverterTableInitializer() 17 CReverseerTableInitializer()
15 { 18 {
16 for (unsigned i = 0; i < 256; i++) 19 for (unsigned i = 0; i < 256; i++)
17 { 20 {
18 unsigned x = ((i & 0x55) << 1) | ((i & 0xAA) >> 1); 21 unsigned
19 x = ((x & 0x33) << 2) | ((x & 0xCC) >> 2); 22 x = ((i & 0x55) << 1) | ((i >> 1) & 0x55);
20 kInvertTable[i] = (Byte)(((x & 0x0F) << 4) | ((x & 0xF0) >> 4)); 23 x = ((x & 0x33) << 2) | ((x >> 2) & 0x33);
24 kReverseTable[i] = (Byte)((x << 4) | (x >> 4));
21 } 25 }
22 } 26 }
23} g_InverterTableInitializer; 27} g_ReverseerTableInitializer;
24 28
29#elif 0
30unsigned ReverseBits8test(unsigned i) { return ReverseBits8(i); }
31#endif
25} 32}
diff --git a/CPP/7zip/Compress/BitlDecoder.h b/CPP/7zip/Compress/BitlDecoder.h
index 789ad1f..465c4d3 100644
--- a/CPP/7zip/Compress/BitlDecoder.h
+++ b/CPP/7zip/Compress/BitlDecoder.h
@@ -3,6 +3,8 @@
3#ifndef ZIP7_INC_BITL_DECODER_H 3#ifndef ZIP7_INC_BITL_DECODER_H
4#define ZIP7_INC_BITL_DECODER_H 4#define ZIP7_INC_BITL_DECODER_H
5 5
6#include "../../../C/CpuArch.h"
7
6#include "../IStream.h" 8#include "../IStream.h"
7 9
8namespace NBitl { 10namespace NBitl {
@@ -10,10 +12,50 @@ namespace NBitl {
10const unsigned kNumBigValueBits = 8 * 4; 12const unsigned kNumBigValueBits = 8 * 4;
11const unsigned kNumValueBytes = 3; 13const unsigned kNumValueBytes = 3;
12const unsigned kNumValueBits = 8 * kNumValueBytes; 14const unsigned kNumValueBits = 8 * kNumValueBytes;
13
14const UInt32 kMask = (1 << kNumValueBits) - 1; 15const UInt32 kMask = (1 << kNumValueBits) - 1;
15 16
16extern Byte kInvertTable[256]; 17#if !defined(Z7_BITL_USE_REVERSE_BITS_TABLE)
18#if 1 && defined(MY_CPU_ARM_OR_ARM64) \
19 && (defined(MY_CPU_ARM64) || defined(__ARM_ARCH_6T2__) \
20 || defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) \
21 && (defined(__GNUC__) && (__GNUC__ >= 4) \
22 || defined(__clang__) && (__clang_major__ >= 4))
23 #define Z7_BITL_USE_REVERSE_BITS_INSTRUCTION
24#elif 1
25 #define Z7_BITL_USE_REVERSE_BITS_TABLE
26#endif
27#endif
28
29#if defined(Z7_BITL_USE_REVERSE_BITS_TABLE)
30extern Byte kReverseTable[256];
31#endif
32
33inline unsigned ReverseBits8(unsigned i)
34{
35#if defined(Z7_BITL_USE_REVERSE_BITS_TABLE)
36 return kReverseTable[i];
37#elif defined(Z7_BITL_USE_REVERSE_BITS_INSTRUCTION)
38 // rbit is available in ARMv6T2 and above
39 asm ("rbit "
40#if defined(MY_CPU_ARM)
41 "%0,%0" // it uses default register size,
42 // but we need 32-bit register here.
43 // we must use it only if default register size is 32-bit.
44 // it will work incorrectly for ARM64.
45#else
46 "%w0,%w0" // it uses 32-bit registers in ARM64.
47 // compiler for (MY_CPU_ARM) can't compile it.
48#endif
49 : "+r" (i));
50 return i >> 24;
51#else
52 unsigned
53 x = ((i & 0x55) << 1) | ((i >> 1) & 0x55);
54 x = ((x & 0x33) << 2) | ((x >> 2) & 0x33);
55 return ((x & 0x0f) << 4) | (x >> 4);
56#endif
57}
58
17 59
18/* TInByte must support "Extra Bytes" (bytes that can be read after the end of stream 60/* TInByte must support "Extra Bytes" (bytes that can be read after the end of stream
19 TInByte::ReadByte() returns 0xFF after the end of stream 61 TInByte::ReadByte() returns 0xFF after the end of stream
@@ -31,6 +73,7 @@ protected:
31public: 73public:
32 bool Create(UInt32 bufSize) { return _stream.Create(bufSize); } 74 bool Create(UInt32 bufSize) { return _stream.Create(bufSize); }
33 void SetStream(ISequentialInStream *inStream) { _stream.SetStream(inStream); } 75 void SetStream(ISequentialInStream *inStream) { _stream.SetStream(inStream); }
76 void ClearStreamPtr() { _stream.ClearStreamPtr(); }
34 void Init() 77 void Init()
35 { 78 {
36 _stream.Init(); 79 _stream.Init();
@@ -107,9 +150,9 @@ public:
107 { 150 {
108 for (; this->_bitPos >= 8; this->_bitPos -= 8) 151 for (; this->_bitPos >= 8; this->_bitPos -= 8)
109 { 152 {
110 Byte b = this->_stream.ReadByte(); 153 const unsigned b = this->_stream.ReadByte();
111 _normalValue = ((UInt32)b << (kNumBigValueBits - this->_bitPos)) | _normalValue; 154 _normalValue = ((UInt32)b << (kNumBigValueBits - this->_bitPos)) | _normalValue;
112 this->_value = (this->_value << 8) | kInvertTable[b]; 155 this->_value = (this->_value << 8) | ReverseBits8(b);
113 } 156 }
114 } 157 }
115 158
@@ -119,11 +162,18 @@ public:
119 Normalize(); 162 Normalize();
120 return ((this->_value >> (8 - this->_bitPos)) & kMask) >> (kNumValueBits - numBits); 163 return ((this->_value >> (8 - this->_bitPos)) & kMask) >> (kNumValueBits - numBits);
121 } 164 }
165
166 Z7_FORCE_INLINE
167 UInt32 GetValue_InHigh32bits()
168 {
169 Normalize();
170 return this->_value << this->_bitPos;
171 }
122 172
123 Z7_FORCE_INLINE 173 Z7_FORCE_INLINE
124 void MovePos(unsigned numBits) 174 void MovePos(size_t numBits)
125 { 175 {
126 this->_bitPos += numBits; 176 this->_bitPos += (unsigned)numBits;
127 _normalValue >>= numBits; 177 _normalValue >>= numBits;
128 } 178 }
129 179
@@ -140,6 +190,9 @@ public:
140 190
141 Z7_FORCE_INLINE 191 Z7_FORCE_INLINE
142 Byte ReadDirectByte() { return this->_stream.ReadByte(); } 192 Byte ReadDirectByte() { return this->_stream.ReadByte(); }
193
194 Z7_FORCE_INLINE
195 size_t ReadDirectBytesPart(Byte *buf, size_t size) { return this->_stream.ReadBytesPart(buf, size); }
143 196
144 Z7_FORCE_INLINE 197 Z7_FORCE_INLINE
145 Byte ReadAlignedByte() 198 Byte ReadAlignedByte()
diff --git a/CPP/7zip/Compress/BitmDecoder.h b/CPP/7zip/Compress/BitmDecoder.h
index 199a228..21c83db 100644
--- a/CPP/7zip/Compress/BitmDecoder.h
+++ b/CPP/7zip/Compress/BitmDecoder.h
@@ -62,6 +62,12 @@ public:
62 } 62 }
63 63
64 Z7_FORCE_INLINE 64 Z7_FORCE_INLINE
65 UInt32 GetValue_InHigh32bits() const
66 {
67 return this->_value << this->_bitPos;
68 }
69
70 Z7_FORCE_INLINE
65 void MovePos(unsigned numBits) 71 void MovePos(unsigned numBits)
66 { 72 {
67 _bitPos += numBits; 73 _bitPos += numBits;
diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp
index d9fec8c..2098beb 100644
--- a/CPP/7zip/Compress/BranchMisc.cpp
+++ b/CPP/7zip/Compress/BranchMisc.cpp
@@ -26,8 +26,6 @@ Z7_COM7F_IMF2(UInt32, CCoder::Filter(Byte *data, UInt32 size))
26} 26}
27 27
28 28
29namespace NArm64 {
30
31#ifndef Z7_EXTRACT_ONLY 29#ifndef Z7_EXTRACT_ONLY
32 30
33Z7_COM7F_IMF(CEncoder::Init()) 31Z7_COM7F_IMF(CEncoder::Init())
@@ -38,7 +36,7 @@ Z7_COM7F_IMF(CEncoder::Init())
38 36
39Z7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size)) 37Z7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size))
40{ 38{
41 const UInt32 processed = (UInt32)(size_t)(Z7_BRANCH_CONV_ENC(ARM64)(data, size, _pc) - data); 39 const UInt32 processed = (UInt32)(size_t)(BraFunc(data, size, _pc) - data);
42 _pc += processed; 40 _pc += processed;
43 return processed; 41 return processed;
44} 42}
@@ -56,7 +54,7 @@ Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIA
56 if (prop.vt != VT_UI4) 54 if (prop.vt != VT_UI4)
57 return E_INVALIDARG; 55 return E_INVALIDARG;
58 pc = prop.ulVal; 56 pc = prop.ulVal;
59 if ((pc & 3) != 0) 57 if (pc & _alignment)
60 return E_INVALIDARG; 58 return E_INVALIDARG;
61 } 59 }
62 } 60 }
@@ -69,9 +67,9 @@ Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream))
69{ 67{
70 if (_pc_Init == 0) 68 if (_pc_Init == 0)
71 return S_OK; 69 return S_OK;
72 Byte buf[4]; 70 UInt32 buf32[1];
73 SetUi32(buf, _pc_Init) 71 SetUi32(buf32, _pc_Init)
74 return WriteStream(outStream, buf, 4); 72 return WriteStream(outStream, buf32, 4);
75} 73}
76 74
77#endif 75#endif
@@ -85,7 +83,7 @@ Z7_COM7F_IMF(CDecoder::Init())
85 83
86Z7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size)) 84Z7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size))
87{ 85{
88 const UInt32 processed = (UInt32)(size_t)(Z7_BRANCH_CONV_DEC(ARM64)(data, size, _pc) - data); 86 const UInt32 processed = (UInt32)(size_t)(BraFunc(data, size, _pc) - data);
89 _pc += processed; 87 _pc += processed;
90 return processed; 88 return processed;
91} 89}
@@ -98,13 +96,11 @@ Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size))
98 if (size != 4) 96 if (size != 4)
99 return E_NOTIMPL; 97 return E_NOTIMPL;
100 val = GetUi32(props); 98 val = GetUi32(props);
101 if ((val & 3) != 0) 99 if (val & _alignment)
102 return E_NOTIMPL; 100 return E_NOTIMPL;
103 } 101 }
104 _pc_Init = val; 102 _pc_Init = val;
105 return S_OK; 103 return S_OK;
106} 104}
107 105
108}
109
110}} 106}}
diff --git a/CPP/7zip/Compress/BranchMisc.h b/CPP/7zip/Compress/BranchMisc.h
index a5793f7..2b5cc42 100644
--- a/CPP/7zip/Compress/BranchMisc.h
+++ b/CPP/7zip/Compress/BranchMisc.h
@@ -21,8 +21,6 @@ public:
21 CCoder(z7_Func_BranchConv bra): _pc(0), BraFunc(bra) {} 21 CCoder(z7_Func_BranchConv bra): _pc(0), BraFunc(bra) {}
22}; 22};
23 23
24namespace NArm64 {
25
26#ifndef Z7_EXTRACT_ONLY 24#ifndef Z7_EXTRACT_ONLY
27 25
28Z7_CLASS_IMP_COM_3( 26Z7_CLASS_IMP_COM_3(
@@ -33,8 +31,11 @@ Z7_CLASS_IMP_COM_3(
33) 31)
34 UInt32 _pc; 32 UInt32 _pc;
35 UInt32 _pc_Init; 33 UInt32 _pc_Init;
34 UInt32 _alignment;
35 z7_Func_BranchConv BraFunc;
36public: 36public:
37 CEncoder(): _pc(0), _pc_Init(0) {} 37 CEncoder(z7_Func_BranchConv bra, UInt32 alignment):
38 _pc(0), _pc_Init(0), _alignment(alignment), BraFunc(bra) {}
38}; 39};
39 40
40#endif 41#endif
@@ -46,12 +47,13 @@ Z7_CLASS_IMP_COM_2(
46) 47)
47 UInt32 _pc; 48 UInt32 _pc;
48 UInt32 _pc_Init; 49 UInt32 _pc_Init;
50 UInt32 _alignment;
51 z7_Func_BranchConv BraFunc;
49public: 52public:
50 CDecoder(): _pc(0), _pc_Init(0) {} 53 CDecoder(z7_Func_BranchConv bra, UInt32 alignment):
54 _pc(0), _pc_Init(0), _alignment(alignment), BraFunc(bra) {}
51}; 55};
52 56
53}
54
55}} 57}}
56 58
57#endif 59#endif
diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp
index 80fbf60..20385ff 100644
--- a/CPP/7zip/Compress/BranchRegister.cpp
+++ b/CPP/7zip/Compress/BranchRegister.cpp
@@ -15,18 +15,18 @@ namespace NBranch {
15#else 15#else
16#define GET_CREATE_FUNC(x) x 16#define GET_CREATE_FUNC(x) x
17#define CREATE_BRA_E(n) \ 17#define CREATE_BRA_E(n) \
18 REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CCoder(Z7_BRANCH_CONV_ENC(n))) 18 REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CCoder(Z7_BRANCH_CONV_ENC_2(n)))
19#endif 19#endif
20 20
21#define CREATE_BRA(n) \ 21#define CREATE_BRA(n) \
22 REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CCoder(Z7_BRANCH_CONV_DEC(n))) \ 22 REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CCoder(Z7_BRANCH_CONV_DEC_2(n))) \
23 CREATE_BRA_E(n) 23 CREATE_BRA_E(n)
24 24
25CREATE_BRA(PPC) 25CREATE_BRA(BranchConv_PPC)
26CREATE_BRA(IA64) 26CREATE_BRA(BranchConv_IA64)
27CREATE_BRA(ARM) 27CREATE_BRA(BranchConv_ARM)
28CREATE_BRA(ARMT) 28CREATE_BRA(BranchConv_ARMT)
29CREATE_BRA(SPARC) 29CREATE_BRA(BranchConv_SPARC)
30 30
31#define METHOD_ITEM(n, id, name) \ 31#define METHOD_ITEM(n, id, name) \
32 REGISTER_FILTER_ITEM( \ 32 REGISTER_FILTER_ITEM( \
@@ -36,20 +36,23 @@ CREATE_BRA(SPARC)
36 36
37REGISTER_CODECS_VAR 37REGISTER_CODECS_VAR
38{ 38{
39 METHOD_ITEM(PPC, 0x205, "PPC"), 39 METHOD_ITEM(BranchConv_PPC, 0x205, "PPC"),
40 METHOD_ITEM(IA64, 0x401, "IA64"), 40 METHOD_ITEM(BranchConv_IA64, 0x401, "IA64"),
41 METHOD_ITEM(ARM, 0x501, "ARM"), 41 METHOD_ITEM(BranchConv_ARM, 0x501, "ARM"),
42 METHOD_ITEM(ARMT, 0x701, "ARMT"), 42 METHOD_ITEM(BranchConv_ARMT, 0x701, "ARMT"),
43 METHOD_ITEM(SPARC, 0x805, "SPARC") 43 METHOD_ITEM(BranchConv_SPARC, 0x805, "SPARC")
44}; 44};
45 45
46REGISTER_CODECS(Branch) 46REGISTER_CODECS(Branch)
47 47
48namespace NArm64 { 48
49REGISTER_FILTER_E(ARM64, 49#define REGISTER_FILTER_E_BRANCH(id, n, name, alignment) \
50 CDecoder(), 50 REGISTER_FILTER_E(n, \
51 CEncoder(), 51 CDecoder(Z7_BRANCH_CONV_DEC(n), alignment), \
52 0xa, "ARM64") 52 CEncoder(Z7_BRANCH_CONV_ENC(n), alignment), \
53} 53 id, name)
54
55REGISTER_FILTER_E_BRANCH(0xa, ARM64, "ARM64", 3)
56REGISTER_FILTER_E_BRANCH(0xb, RISCV, "RISCV", 1)
54 57
55}} 58}}
diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp
index 017b694..73895fe 100644
--- a/CPP/7zip/Compress/DeflateDecoder.cpp
+++ b/CPP/7zip/Compress/DeflateDecoder.cpp
@@ -15,8 +15,8 @@ CCoder::CCoder(bool deflate64Mode):
15 _needFinishInput(false), 15 _needFinishInput(false),
16 _needInitInStream(true), 16 _needInitInStream(true),
17 _outSizeDefined(false), 17 _outSizeDefined(false),
18 _outStartPos(0), 18 _outStartPos(0)
19 ZlibMode(false) {} 19 {}
20 20
21UInt32 CCoder::ReadBits(unsigned numBits) 21UInt32 CCoder::ReadBits(unsigned numBits)
22{ 22{
@@ -34,7 +34,7 @@ bool CCoder::DecodeLevels(Byte *levels, unsigned numSymbols)
34 34
35 do 35 do
36 { 36 {
37 UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream); 37 unsigned sym = m_LevelDecoder.Decode(&m_InBitStream);
38 if (sym < kTableDirectLevels) 38 if (sym < kTableDirectLevels)
39 levels[i++] = (Byte)sym; 39 levels[i++] = (Byte)sym;
40 else 40 else
@@ -110,7 +110,7 @@ bool CCoder::ReadTables(void)
110 else 110 else
111 { 111 {
112 const unsigned numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin; 112 const unsigned numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin;
113 _numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin; 113 _numDistLevels = (unsigned)ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin;
114 const unsigned numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin; 114 const unsigned numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin;
115 115
116 if (!_deflate64Mode) 116 if (!_deflate64Mode)
@@ -130,7 +130,7 @@ bool CCoder::ReadTables(void)
130 if (m_InBitStream.ExtraBitsWereRead()) 130 if (m_InBitStream.ExtraBitsWereRead())
131 return false; 131 return false;
132 132
133 RIF(m_LevelDecoder.Build(levelLevels)) 133 RIF(m_LevelDecoder.Build(levelLevels, false)) // full
134 134
135 Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize]; 135 Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize];
136 if (!DecodeLevels(tmpLevels, numLitLenLevels + _numDistLevels)) 136 if (!DecodeLevels(tmpLevels, numLitLenLevels + _numDistLevels))
@@ -182,7 +182,8 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputPro
182 _needReadTable = true; 182 _needReadTable = true;
183 } 183 }
184 184
185 while (_remainLen > 0 && curSize > 0) 185 // _remainLen >= 0
186 while (_remainLen && curSize)
186 { 187 {
187 _remainLen--; 188 _remainLen--;
188 const Byte b = m_OutWindowStream.GetByte(_rep0); 189 const Byte b = m_OutWindowStream.GetByte(_rep0);
@@ -194,7 +195,7 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputPro
194 if (inputProgressLimit != 0) 195 if (inputProgressLimit != 0)
195 inputStart = m_InBitStream.GetProcessedSize(); 196 inputStart = m_InBitStream.GetProcessedSize();
196 197
197 while (curSize > 0 || finishInputStream) 198 while (curSize || finishInputStream)
198 { 199 {
199 if (m_InBitStream.ExtraBitsWereRead()) 200 if (m_InBitStream.ExtraBitsWereRead())
200 return S_FALSE; 201 return S_FALSE;
@@ -224,20 +225,53 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputPro
224 return S_FALSE; 225 return S_FALSE;
225 /* NSIS version contains some bits in bitl bits buffer. 226 /* NSIS version contains some bits in bitl bits buffer.
226 So we must read some first bytes via ReadAlignedByte */ 227 So we must read some first bytes via ReadAlignedByte */
227 for (; m_StoredBlockSize > 0 && curSize > 0 && m_InBitStream.ThereAreDataInBitsBuffer(); m_StoredBlockSize--, curSize--) 228 UInt32 num = m_StoredBlockSize;
229 if (num > curSize)
230 num = curSize;
231 m_StoredBlockSize -= num;
232 curSize -= num;
233 for (; num && m_InBitStream.ThereAreDataInBitsBuffer(); num--)
228 m_OutWindowStream.PutByte(ReadAlignedByte()); 234 m_OutWindowStream.PutByte(ReadAlignedByte());
229 for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--) 235 if (num)
230 m_OutWindowStream.PutByte(m_InBitStream.ReadDirectByte()); 236 {
237#if 1
238 // fast code
239 do
240 {
241 size_t a;
242 Byte *buf = m_OutWindowStream.GetOutBuffer(a);
243 // a != 0
244 if (a > num)
245 a = num;
246 // a != 0
247 a = m_InBitStream.ReadDirectBytesPart(buf, a);
248 if (a == 0)
249 return S_FALSE;
250 m_OutWindowStream.SkipWrittenBytes(a);
251 num -= (UInt32)a;
252 }
253 while (num);
254#else
255 // slow code:
256 do
257 m_OutWindowStream.PutByte(m_InBitStream.ReadDirectByte());
258 while (--num);
259#endif
260 }
231 _needReadTable = (m_StoredBlockSize == 0); 261 _needReadTable = (m_StoredBlockSize == 0);
232 continue; 262 continue;
233 } 263 }
234 264
235 while (curSize > 0) 265 while (curSize)
236 { 266 {
237 if (m_InBitStream.ExtraBitsWereRead_Fast()) 267 if (m_InBitStream.ExtraBitsWereRead_Fast())
238 return S_FALSE; 268 return S_FALSE;
239 269 unsigned sym;
240 UInt32 sym = m_MainDecoder.Decode(&m_InBitStream); 270#if 0
271 sym = m_MainDecoder.Decode(&m_InBitStream);
272#else
273 Z7_HUFF_DECODE_CHECK(sym, &m_MainDecoder, kNumHuffmanBits, kNumTableBits_Main, &m_InBitStream, { return S_FALSE; })
274#endif
241 275
242 if (sym < 0x100) 276 if (sym < 0x100)
243 { 277 {
@@ -245,12 +279,15 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputPro
245 curSize--; 279 curSize--;
246 continue; 280 continue;
247 } 281 }
248 else if (sym == kSymbolEndOfBlock) 282 if (sym == kSymbolEndOfBlock)
249 { 283 {
250 _needReadTable = true; 284 _needReadTable = true;
251 break; 285 break;
252 } 286 }
253 else if (sym < kMainTableSize) 287#if 0
288 if (sym >= kMainTableSize)
289 return S_FALSE;
290#endif
254 { 291 {
255 sym -= kSymbolMatch; 292 sym -= kSymbolMatch;
256 UInt32 len; 293 UInt32 len;
@@ -268,22 +305,29 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputPro
268 } 305 }
269 len += kMatchMinLen + m_InBitStream.ReadBits(numBits); 306 len += kMatchMinLen + m_InBitStream.ReadBits(numBits);
270 } 307 }
271 UInt32 locLen = len; 308
272 if (locLen > curSize) 309#if 0
273 locLen = (UInt32)curSize;
274 sym = m_DistDecoder.Decode(&m_InBitStream); 310 sym = m_DistDecoder.Decode(&m_InBitStream);
275 if (sym >= _numDistLevels) 311 if (sym >= _numDistLevels)
276 return S_FALSE; 312 return S_FALSE;
313#else
314 Z7_HUFF_DECODE_CHECK(sym, &m_DistDecoder, kNumHuffmanBits, kNumTableBits_Dist, &m_InBitStream, { return S_FALSE; })
315#endif
316
317#if 1
277 sym = kDistStart[sym] + m_InBitStream.ReadBits(kDistDirectBits[sym]); 318 sym = kDistStart[sym] + m_InBitStream.ReadBits(kDistDirectBits[sym]);
278 /* 319#else
279 if (sym >= 4) 320 if (sym >= 4)
280 { 321 {
281 // sym &= 31; 322 // sym &= 31;
282 const unsigned numDirectBits = (unsigned)(((sym >> 1) - 1)); 323 const unsigned numDirectBits = (sym - 2) >> 1;
283 sym = (2 | (sym & 1)) << numDirectBits; 324 sym = (2u | (sym & 1)) << numDirectBits;
284 sym += m_InBitStream.ReadBits(numDirectBits); 325 sym += m_InBitStream.ReadBits(numDirectBits);
285 } 326 }
286 */ 327#endif
328 UInt32 locLen = len;
329 if (locLen > curSize)
330 locLen = (UInt32)curSize;
287 if (!m_OutWindowStream.CopyBlock(sym, locLen)) 331 if (!m_OutWindowStream.CopyBlock(sym, locLen))
288 return S_FALSE; 332 return S_FALSE;
289 curSize -= locLen; 333 curSize -= locLen;
@@ -295,8 +339,6 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputPro
295 break; 339 break;
296 } 340 }
297 } 341 }
298 else
299 return S_FALSE;
300 } 342 }
301 343
302 if (finishInputStream && curSize == 0) 344 if (finishInputStream && curSize == 0)
@@ -354,12 +396,12 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, ICompressProgressInfo
354 if (curSize >= rem) 396 if (curSize >= rem)
355 { 397 {
356 curSize = (UInt32)rem; 398 curSize = (UInt32)rem;
357 if (ZlibMode || _needFinishInput) 399 if (_needFinishInput)
358 finishInputStream = true; 400 finishInputStream = true;
401 else if (curSize == 0)
402 break;
359 } 403 }
360 } 404 }
361 if (!finishInputStream && curSize == 0)
362 break;
363 405
364 RINOK(CodeSpec(curSize, finishInputStream, progress ? kInputProgressLimit : 0)) 406 RINOK(CodeSpec(curSize, finishInputStream, progress ? kInputProgressLimit : 0))
365 407
@@ -374,13 +416,6 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, ICompressProgressInfo
374 } 416 }
375 } 417 }
376 418
377 if (_remainLen == kLenIdFinished && ZlibMode)
378 {
379 m_InBitStream.AlignToByte();
380 for (unsigned i = 0; i < 4; i++)
381 ZlibFooter[i] = ReadAlignedByte();
382 }
383
384 flusher.NeedFlush = false; 419 flusher.NeedFlush = false;
385 res = Flush(); 420 res = Flush();
386 if (res == S_OK && _remainLen != kLenIdNeedInit && InputEofError()) 421 if (res == S_OK && _remainLen != kLenIdNeedInit && InputEofError())
@@ -450,6 +485,7 @@ Z7_COM7F_IMF(CCoder::SetInStream(ISequentialInStream *inStream))
450Z7_COM7F_IMF(CCoder::ReleaseInStream()) 485Z7_COM7F_IMF(CCoder::ReleaseInStream())
451{ 486{
452 m_InStreamRef.Release(); 487 m_InStreamRef.Release();
488 m_InBitStream.ClearStreamPtr();
453 return S_OK; 489 return S_OK;
454} 490}
455 491
@@ -460,10 +496,8 @@ void CCoder::SetOutStreamSizeResume(const UInt64 *outSize)
460 _outSize = 0; 496 _outSize = 0;
461 if (_outSizeDefined) 497 if (_outSizeDefined)
462 _outSize = *outSize; 498 _outSize = *outSize;
463
464 m_OutWindowStream.Init(_keepHistory); 499 m_OutWindowStream.Init(_keepHistory);
465 _outStartPos = m_OutWindowStream.GetProcessedSize(); 500 _outStartPos = m_OutWindowStream.GetProcessedSize();
466
467 _remainLen = kLenIdNeedInit; 501 _remainLen = kLenIdNeedInit;
468} 502}
469 503
@@ -488,8 +522,6 @@ Z7_COM7F_IMF(CCoder::SetOutStreamSize(const UInt64 *outSize))
488 522
489Z7_COM7F_IMF(CCoder::Read(void *data, UInt32 size, UInt32 *processedSize)) 523Z7_COM7F_IMF(CCoder::Read(void *data, UInt32 size, UInt32 *processedSize))
490{ 524{
491 HRESULT res;
492
493 if (processedSize) 525 if (processedSize)
494 *processedSize = 0; 526 *processedSize = 0;
495 const UInt64 outPos = GetOutProcessedCur(); 527 const UInt64 outPos = GetOutProcessedCur();
@@ -501,30 +533,25 @@ Z7_COM7F_IMF(CCoder::Read(void *data, UInt32 size, UInt32 *processedSize))
501 if (size >= rem) 533 if (size >= rem)
502 { 534 {
503 size = (UInt32)rem; 535 size = (UInt32)rem;
504 if (ZlibMode || _needFinishInput) 536 if (_needFinishInput)
505 finishInputStream = true; 537 finishInputStream = true;
506 } 538 }
507 } 539 }
508 if (!finishInputStream && size == 0) 540 if (!finishInputStream && size == 0)
509 return S_OK; 541 return S_OK;
510 542
543 HRESULT res;
511 DEFLATE_TRY_BEGIN 544 DEFLATE_TRY_BEGIN
512
513 m_OutWindowStream.SetMemStream((Byte *)data); 545 m_OutWindowStream.SetMemStream((Byte *)data);
514
515 res = CodeSpec(size, finishInputStream); 546 res = CodeSpec(size, finishInputStream);
516
517 DEFLATE_TRY_END(res) 547 DEFLATE_TRY_END(res)
518
519 { 548 {
520 const HRESULT res2 = Flush(); 549 const HRESULT res2 = Flush();
521 if (res2 != S_OK) 550 if (res2 != S_OK)
522 res = res2; 551 res = res2;
523 } 552 }
524
525 if (processedSize) 553 if (processedSize)
526 *processedSize = (UInt32)(GetOutProcessedCur() - outPos); 554 *processedSize = (UInt32)(GetOutProcessedCur() - outPos);
527
528 m_OutWindowStream.SetMemStream(NULL); 555 m_OutWindowStream.SetMemStream(NULL);
529 return res; 556 return res;
530} 557}
diff --git a/CPP/7zip/Compress/DeflateDecoder.h b/CPP/7zip/Compress/DeflateDecoder.h
index d31f299..4e0ae61 100644
--- a/CPP/7zip/Compress/DeflateDecoder.h
+++ b/CPP/7zip/Compress/DeflateDecoder.h
@@ -21,6 +21,9 @@ namespace NDecoder {
21const int kLenIdFinished = -1; 21const int kLenIdFinished = -1;
22const int kLenIdNeedInit = -2; 22const int kLenIdNeedInit = -2;
23 23
24const unsigned kNumTableBits_Main = 10;
25const unsigned kNumTableBits_Dist = 6;
26
24class CCoder: 27class CCoder:
25 public ICompressCoder, 28 public ICompressCoder,
26 public ICompressSetFinishMode, 29 public ICompressSetFinishMode,
@@ -28,9 +31,9 @@ class CCoder:
28 public ICompressReadUnusedFromInBuf, 31 public ICompressReadUnusedFromInBuf,
29 public ICompressSetInStream, 32 public ICompressSetInStream,
30 public ICompressSetOutStreamSize, 33 public ICompressSetOutStreamSize,
31 #ifndef Z7_NO_READ_FROM_CODER 34#ifndef Z7_NO_READ_FROM_CODER
32 public ISequentialInStream, 35 public ISequentialInStream,
33 #endif 36#endif
34 public CMyUnknownImp 37 public CMyUnknownImp
35{ 38{
36 Z7_COM_QI_BEGIN2(ICompressCoder) 39 Z7_COM_QI_BEGIN2(ICompressCoder)
@@ -39,34 +42,33 @@ class CCoder:
39 Z7_COM_QI_ENTRY(ICompressReadUnusedFromInBuf) 42 Z7_COM_QI_ENTRY(ICompressReadUnusedFromInBuf)
40 Z7_COM_QI_ENTRY(ICompressSetInStream) 43 Z7_COM_QI_ENTRY(ICompressSetInStream)
41 Z7_COM_QI_ENTRY(ICompressSetOutStreamSize) 44 Z7_COM_QI_ENTRY(ICompressSetOutStreamSize)
42 #ifndef Z7_NO_READ_FROM_CODER 45#ifndef Z7_NO_READ_FROM_CODER
43 Z7_COM_QI_ENTRY(ISequentialInStream) 46 Z7_COM_QI_ENTRY(ISequentialInStream)
44 #endif 47#endif
45 Z7_COM_QI_END 48 Z7_COM_QI_END
46 Z7_COM_ADDREF_RELEASE 49 Z7_COM_ADDREF_RELEASE
47 50
48 Z7_IFACE_COM7_IMP(ICompressCoder) 51 Z7_IFACE_COM7_IMP(ICompressCoder)
49 Z7_IFACE_COM7_IMP(ICompressSetFinishMode) 52 Z7_IFACE_COM7_IMP(ICompressSetFinishMode)
50 Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize) 53 Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize)
51 Z7_IFACE_COM7_IMP(ICompressReadUnusedFromInBuf)
52public: 54public:
55 Z7_IFACE_COM7_IMP(ICompressReadUnusedFromInBuf)
53 Z7_IFACE_COM7_IMP(ICompressSetInStream) 56 Z7_IFACE_COM7_IMP(ICompressSetInStream)
54private: 57private:
55 Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize) 58 Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize)
56 #ifndef Z7_NO_READ_FROM_CODER 59#ifndef Z7_NO_READ_FROM_CODER
57 Z7_IFACE_COM7_IMP(ISequentialInStream) 60 Z7_IFACE_COM7_IMP(ISequentialInStream)
58 #endif 61#endif
59 62
60 CLzOutWindow m_OutWindowStream; 63 CLzOutWindow m_OutWindowStream;
61 CMyComPtr<ISequentialInStream> m_InStreamRef;
62 NBitl::CDecoder<CInBuffer> m_InBitStream; 64 NBitl::CDecoder<CInBuffer> m_InBitStream;
63 NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedMainTableSize> m_MainDecoder; 65 NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedMainTableSize, kNumTableBits_Main> m_MainDecoder;
64 NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedDistTableSize> m_DistDecoder; 66 NCompress::NHuffman::CDecoder256<kNumHuffmanBits, kFixedDistTableSize, kNumTableBits_Dist> m_DistDecoder;
65 NCompress::NHuffman::CDecoder7b<kLevelTableSize> m_LevelDecoder; 67 NCompress::NHuffman::CDecoder7b<kLevelTableSize> m_LevelDecoder;
66 68
67 UInt32 m_StoredBlockSize; 69 UInt32 m_StoredBlockSize;
68 70
69 UInt32 _numDistLevels; 71 unsigned _numDistLevels;
70 bool m_FinalBlock; 72 bool m_FinalBlock;
71 bool m_StoredMode; 73 bool m_StoredMode;
72 74
@@ -81,6 +83,7 @@ private:
81 UInt32 _rep0; 83 UInt32 _rep0;
82 84
83 bool _outSizeDefined; 85 bool _outSizeDefined;
86 CMyComPtr<ISequentialInStream> m_InStreamRef;
84 UInt64 _outSize; 87 UInt64 _outSize;
85 UInt64 _outStartPos; 88 UInt64 _outStartPos;
86 89
@@ -109,8 +112,6 @@ private:
109 112
110 HRESULT CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputProgressLimit = 0); 113 HRESULT CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputProgressLimit = 0);
111public: 114public:
112 bool ZlibMode;
113 Byte ZlibFooter[4];
114 115
115 CCoder(bool deflate64Mode); 116 CCoder(bool deflate64Mode);
116 virtual ~CCoder() {} 117 virtual ~CCoder() {}
@@ -133,7 +134,7 @@ public:
133 Byte ReadAlignedByte(); 134 Byte ReadAlignedByte();
134 UInt32 ReadAligned_UInt16() // aligned for Byte range 135 UInt32 ReadAligned_UInt16() // aligned for Byte range
135 { 136 {
136 UInt32 v = m_InBitStream.ReadAlignedByte(); 137 const UInt32 v = m_InBitStream.ReadAlignedByte();
137 return v | ((UInt32)m_InBitStream.ReadAlignedByte() << 8); 138 return v | ((UInt32)m_InBitStream.ReadAlignedByte() << 8);
138 } 139 }
139 bool InputEofError() const { return m_InBitStream.ExtraBitsWereRead(); } 140 bool InputEofError() const { return m_InBitStream.ExtraBitsWereRead(); }
diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp
index e277ad6..87b4f83 100644
--- a/CPP/7zip/Compress/DeflateEncoder.cpp
+++ b/CPP/7zip/Compress/DeflateEncoder.cpp
@@ -43,9 +43,11 @@ static const Byte kNoLiteralStatPrice = 11;
43static const Byte kNoLenStatPrice = 11; 43static const Byte kNoLenStatPrice = 11;
44static const Byte kNoPosStatPrice = 6; 44static const Byte kNoPosStatPrice = 6;
45 45
46MY_ALIGN(64)
46static Byte g_LenSlots[kNumLenSymbolsMax]; 47static Byte g_LenSlots[kNumLenSymbolsMax];
47 48
48#define kNumLogBits 9 // do not change it 49#define kNumLogBits 9 // do not change it
50MY_ALIGN(64)
49static Byte g_FastPos[1 << kNumLogBits]; 51static Byte g_FastPos[1 << kNumLogBits];
50 52
51class CFastPosInit 53class CFastPosInit
@@ -57,7 +59,7 @@ public:
57 for (i = 0; i < kNumLenSlots; i++) 59 for (i = 0; i < kNumLenSlots; i++)
58 { 60 {
59 unsigned c = kLenStart32[i]; 61 unsigned c = kLenStart32[i];
60 unsigned j = 1 << kLenDirectBits32[i]; 62 const unsigned j = 1u << kLenDirectBits32[i];
61 for (unsigned k = 0; k < j; k++, c++) 63 for (unsigned k = 0; k < j; k++, c++)
62 g_LenSlots[c] = (Byte)i; 64 g_LenSlots[c] = (Byte)i;
63 } 65 }
@@ -66,8 +68,8 @@ public:
66 unsigned c = 0; 68 unsigned c = 0;
67 for (Byte slotFast = 0; slotFast < kFastSlots; slotFast++) 69 for (Byte slotFast = 0; slotFast < kFastSlots; slotFast++)
68 { 70 {
69 UInt32 k = (1 << kDistDirectBits[slotFast]); 71 const unsigned k = 1u << kDistDirectBits[slotFast];
70 for (UInt32 j = 0; j < k; j++, c++) 72 for (unsigned j = 0; j < k; j++, c++)
71 g_FastPos[c] = slotFast; 73 g_FastPos[c] = slotFast;
72 } 74 }
73 } 75 }
diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp
index 35b77ba..c234b7a 100644
--- a/CPP/7zip/Compress/DeltaFilter.cpp
+++ b/CPP/7zip/Compress/DeltaFilter.cpp
@@ -52,7 +52,7 @@ Z7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size))
52 52
53Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)) 53Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))
54{ 54{
55 UInt32 delta = _delta; 55 unsigned delta = _delta;
56 for (UInt32 i = 0; i < numProps; i++) 56 for (UInt32 i = 0; i < numProps; i++)
57 { 57 {
58 const PROPVARIANT &prop = props[i]; 58 const PROPVARIANT &prop = props[i];
@@ -64,9 +64,9 @@ Z7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIA
64 switch (propID) 64 switch (propID)
65 { 65 {
66 case NCoderPropID::kDefaultProp: 66 case NCoderPropID::kDefaultProp:
67 delta = (UInt32)prop.ulVal; 67 if (prop.ulVal < 1 || prop.ulVal > 256)
68 if (delta < 1 || delta > 256)
69 return E_INVALIDARG; 68 return E_INVALIDARG;
69 delta = prop.ulVal;
70 break; 70 break;
71 case NCoderPropID::kNumThreads: break; 71 case NCoderPropID::kNumThreads: break;
72 case NCoderPropID::kLevel: break; 72 case NCoderPropID::kLevel: break;
diff --git a/CPP/7zip/Compress/HuffmanDecoder.h b/CPP/7zip/Compress/HuffmanDecoder.h
index 4b8169f..318190d 100644
--- a/CPP/7zip/Compress/HuffmanDecoder.h
+++ b/CPP/7zip/Compress/HuffmanDecoder.h
@@ -3,178 +3,401 @@
3#ifndef ZIP7_INC_COMPRESS_HUFFMAN_DECODER_H 3#ifndef ZIP7_INC_COMPRESS_HUFFMAN_DECODER_H
4#define ZIP7_INC_COMPRESS_HUFFMAN_DECODER_H 4#define ZIP7_INC_COMPRESS_HUFFMAN_DECODER_H
5 5
6#include "../../../C/CpuArch.h"
6#include "../../Common/MyTypes.h" 7#include "../../Common/MyTypes.h"
7 8
8namespace NCompress { 9namespace NCompress {
9namespace NHuffman { 10namespace NHuffman {
10 11
11const unsigned kNumPairLenBits = 4; 12// const unsigned kNumTableBits_Default = 9;
12const unsigned kPairLenMask = (1 << kNumPairLenBits) - 1; 13
14#if 0 || 0 && defined(MY_CPU_64BIT)
15// for debug or optimization:
16// 64-BIT limit array can be faster for some compilers.
17// for debug or optimization:
18#define Z7_HUFF_USE_64BIT_LIMIT
19#else
20// sizet value variable allows to eliminate some move operation in some compilers.
21// for debug or optimization:
22// #define Z7_HUFF_USE_SIZET_VALUE
23#endif
24
25// v0 must normalized to (32 bits) : (v0 < ((UInt64)1 << 32))
26
27#ifdef Z7_HUFF_USE_64BIT_LIMIT
28 typedef UInt64 CLimitInt;
29 typedef UInt64 CValueInt;
30 // all _limits[*] are normalized and limited by ((UInt64)1 << 32).
31 // we don't use (v1) in this branch
32 #define Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) 32
33 #define Z7_HUFF_TABLE_COMPARE(huf, kNumTableBits, v0, v1) \
34 ((NCompress::NHuffman::CLimitInt)v0 >= (huf)->_limits[0])
35 #define Z7_HUFF_GET_VAL_FOR_LIMITS(v0, v1, kNumBitsMax, kNumTableBits) (v0)
36 #define Z7_HUFF_GET_VAL_FOR_TABLE( v0, v1, kNumBitsMax, kNumTableBits) ((v0) >> (32 - kNumTableBits))
37 #define Z7_HUFF_PRECALC_V1(kNumTableBits, v0, v1)
38#else
39 typedef UInt32 CLimitInt;
40 typedef
41 #ifdef Z7_HUFF_USE_SIZET_VALUE
42 size_t
43 #else
44 UInt32
45 #endif
46 CValueInt;
47 // v1 must be precalculated from v0 in this branch
48 // _limits[0] and (v1) are normalized and limited by (1 << kNumTableBits).
49 // _limits[non_0] are normalized and limited by (1 << kNumBitsMax).
50 #define Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) (kNumBitsMax)
51 #define Z7_HUFF_TABLE_COMPARE(huf, kNumTableBits, v0, v1) \
52 ((NCompress::NHuffman::CLimitInt)v1 >= (huf)->_limits[0])
53 #define Z7_HUFF_GET_VAL_FOR_LIMITS(v0, v1, kNumBitsMax, kNumTableBits) ((v0) >> (32 - kNumBitsMax))
54 #define Z7_HUFF_GET_VAL_FOR_TABLE( v0, v1, kNumBitsMax, kNumTableBits) (v1)
55 #define Z7_HUFF_PRECALC_V1(kNumTableBits, v0, v1) const UInt32 v1 = ((v0) >> (32 - kNumTableBits));
56#endif
13 57
14template <unsigned kNumBitsMax, UInt32 m_NumSymbols, unsigned kNumTableBits = 9> 58
15class CDecoder 59enum enum_BuildMode
16{ 60{
17public: 61 k_BuildMode_Partial = 0,
18 UInt32 _limits[kNumBitsMax + 2]; 62 k_BuildMode_Full = 1,
19 UInt32 _poses[kNumBitsMax + 1]; 63 k_BuildMode_Full_or_Empty = 2
20 UInt16 _lens[1 << kNumTableBits]; 64};
21 UInt16 _symbols[m_NumSymbols]; 65
22 66
23 bool Build(const Byte *lens) throw() 67template <class symType, class symType2, class symType4, unsigned kNumBitsMax, unsigned m_NumSymbols, unsigned kNumTableBits /* = kNumTableBits_Default */>
68struct CDecoderBase
69{
70 CLimitInt _limits[kNumBitsMax + 2 - kNumTableBits];
71 UInt32 _poses[kNumBitsMax - kNumTableBits]; // unsigned
72union
73{
74 // if defined(MY_CPU_64BIT), we need 64-bit alignment for _symbols.
75 // if !defined(MY_CPU_64BIT), we need 32-bit alignment for _symbols
76 // but we provide alignment for _lens.
77 // _symbols also will be aligned, if _lens are aligned
78 #if defined(MY_CPU_64BIT)
79 UInt64
80 #else
81 UInt32
82 #endif
83 _pad_align[m_NumSymbols < (1u << sizeof(symType) * 8) ? 1 : -1];
84 /* if symType is Byte, we use 16-bytes padding to avoid cache
85 bank conflict between _lens and _symbols: */
86 Byte _lens[(1 << kNumTableBits) + (sizeof(symType) == 1 ? 16 : 0)];
87} _u;
88 symType _symbols[(1 << kNumTableBits) + m_NumSymbols - (kNumTableBits + 1)];
89
90 /*
91 Z7_FORCE_INLINE
92 bool IsFull() const
24 { 93 {
25 UInt32 counts[kNumBitsMax + 1]; 94 return _limits[kNumBitsMax - kNumTableBits] ==
26 95 (CLimitInt)1u << Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax);
27 unsigned i; 96 }
97 Z7_FORCE_INLINE
98 bool IsEmpty() const
99 {
100 return _limits[kNumBitsMax - kNumTableBits] == 0;
101 }
102 Z7_FORCE_INLINE
103 bool Is_Full_or_Empty() const
104 {
105 return 0 == (_limits[kNumBitsMax - kNumTableBits] &
106 ~((CLimitInt)1 << Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax)));
107 }
108 */
109
110 Z7_FORCE_INLINE
111 bool Build(const Byte *lens, enum_BuildMode buidMode = k_BuildMode_Partial) throw()
112 {
113 unsigned counts[kNumBitsMax + 1];
114 size_t i;
28 for (i = 0; i <= kNumBitsMax; i++) 115 for (i = 0; i <= kNumBitsMax; i++)
29 counts[i] = 0; 116 counts[i] = 0;
117 for (i = 0; i < m_NumSymbols; i++)
118 counts[lens[i]]++;
30 119
31 UInt32 sym;
32
33 for (sym = 0; sym < m_NumSymbols; sym++)
34 counts[lens[sym]]++;
35
36 const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax;
37
38 _limits[0] = 0;
39
40 UInt32 startPos = 0;
41 UInt32 sum = 0; 120 UInt32 sum = 0;
42 121 for (i = 1; i <= kNumTableBits; i++)
43 for (i = 1; i <= kNumBitsMax; i++)
44 { 122 {
45 const UInt32 cnt = counts[i]; 123 sum <<= 1;
46 startPos += cnt << (kNumBitsMax - i); 124 sum += counts[i];
47 if (startPos > kMaxValue) 125 }
48 return false; 126
49 _limits[i] = startPos; 127 CLimitInt startPos = (CLimitInt)sum;
128 _limits[0] =
129 #ifdef Z7_HUFF_USE_64BIT_LIMIT
130 startPos << (Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - kNumTableBits);
131 #else
132 startPos;
133 #endif
134
135 for (i = kNumTableBits + 1; i <= kNumBitsMax; i++)
136 {
137 startPos <<= 1;
138 _poses[i - (kNumTableBits + 1)] = (UInt32)(startPos - sum);
139 const unsigned cnt = counts[i];
50 counts[i] = sum; 140 counts[i] = sum;
51 _poses[i] = sum;
52 sum += cnt; 141 sum += cnt;
142 startPos += cnt;
143 _limits[i - kNumTableBits] = startPos << (Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - i);
53 } 144 }
54 145
55 counts[0] = sum; 146 _limits[kNumBitsMax + 1 - kNumTableBits] =
56 _poses[0] = sum; 147 (CLimitInt)1 << Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax);
57 _limits[kNumBitsMax + 1] = kMaxValue; 148
149 if (buidMode == k_BuildMode_Partial)
150 {
151 if (startPos > (1u << kNumBitsMax)) return false;
152 }
153 else
154 {
155 if (buidMode != k_BuildMode_Full && startPos == 0) return true;
156 if (startPos != (1u << kNumBitsMax)) return false;
157 }
158 size_t sum2 = 0;
159 for (i = 1; i <= kNumTableBits; i++)
160 {
161 const unsigned cnt = counts[i] << (kNumTableBits - i);
162 counts[i] = (unsigned)sum2 >> (kNumTableBits - i);
163 memset(_u._lens + sum2, (int)i, cnt);
164 sum2 += cnt;
165 }
58 166
59 for (sym = 0; sym < m_NumSymbols; sym++) 167#ifdef MY_CPU_64BIT
168 symType4
169 // UInt64 // for symType = UInt16
170 // UInt32 // for symType = Byte
171#else
172 UInt32
173#endif
174 v = 0;
175 for (i = 0; i < m_NumSymbols; i++,
176 v +=
177 1
178 + ( (UInt32)1 << (sizeof(symType) * 8 * 1))
179 // 0x00010001 // for symType = UInt16
180 // 0x00000101 // for symType = Byte
181#ifdef MY_CPU_64BIT
182 + ((symType4)1 << (sizeof(symType) * 8 * 2))
183 + ((symType4)1 << (sizeof(symType) * 8 * 3))
184 // 0x0001000100010001 // for symType = UInt16
185 // 0x0000000001010101 // for symType = Byte
186#endif
187 )
60 { 188 {
61 unsigned len = lens[sym]; 189 const unsigned len = lens[i];
62 if (len == 0) 190 if (len == 0)
63 continue; 191 continue;
64 192 const size_t offset = counts[len];
65 unsigned offset = counts[len]++; 193 counts[len] = (unsigned)offset + 1;
66 _symbols[offset] = (UInt16)sym; 194 if (len >= kNumTableBits)
67 195 _symbols[offset] = (symType)v;
68 if (len <= kNumTableBits) 196 else
69 { 197 {
70 offset -= _poses[len]; 198 Byte *s2 = (Byte *)(void *)_symbols + (offset <<
71 UInt32 num = (UInt32)1 << (kNumTableBits - len); 199 (kNumTableBits + sizeof(symType) / 2 - len));
72 UInt16 val = (UInt16)((sym << kNumPairLenBits) | len); 200 Byte *lim = s2 + ((size_t)1 <<
73 UInt16 *dest = _lens + (_limits[(size_t)len - 1] >> (kNumBitsMax - kNumTableBits)) + (offset << (kNumTableBits - len)); 201 (kNumTableBits + sizeof(symType) / 2 - len));
74 for (UInt32 k = 0; k < num; k++) 202 if (len >= kNumTableBits - 2)
75 dest[k] = val; 203 {
204 *(symType2 *)(void *)(s2 ) = (symType2)v;
205 *(symType2 *)(void *)(lim - sizeof(symType) * 2) = (symType2)v;
206 }
207 else
208 {
209#ifdef MY_CPU_64BIT
210 symType4 *s = (symType4 *)(void *)s2;
211 do
212 {
213 s[0] = v; s[1] = v; s += 2;
214 }
215 while (s != (const symType4 *)(const void *)lim);
216#else
217 symType2 *s = (symType2 *)(void *)s2;
218 do
219 {
220 s[0] = (symType2)v; s[1] = (symType2)v; s += 2;
221 s[0] = (symType2)v; s[1] = (symType2)v; s += 2;
222 }
223 while (s != (const symType2 *)(const void *)lim);
224#endif
225 }
76 } 226 }
77 } 227 }
78
79 return true; 228 return true;
80 } 229 }
81 230
82 231
83 bool BuildFull(const Byte *lens, UInt32 numSymbols = m_NumSymbols) throw() 232#define Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES(_numBits_, kNumBitsMax, error_op) if (_numBits_ > kNumBitsMax) { error_op }
84 { 233#define Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO( _numBits_, kNumBitsMax, error_op)
85 UInt32 counts[kNumBitsMax + 1];
86
87 unsigned i;
88 for (i = 0; i <= kNumBitsMax; i++)
89 counts[i] = 0;
90
91 UInt32 sym;
92
93 for (sym = 0; sym < numSymbols; sym++)
94 counts[lens[sym]]++;
95
96 const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax;
97 234
98 _limits[0] = 0; 235
99 236#define Z7_HUFF_DECODE_BASE_TREE_BRANCH(sym, huf, kNumBitsMax, kNumTableBits, \
100 UInt32 startPos = 0; 237 v0, v1, \
101 UInt32 sum = 0; 238 get_val_for_limits, \
102 239 check_op, error_op, _numBits_) \
103 for (i = 1; i <= kNumBitsMax; i++) 240{ \
104 { 241 const NHuffman::CValueInt _val = get_val_for_limits(v0, v1, kNumBitsMax, kNumTableBits); \
105 const UInt32 cnt = counts[i]; 242 _numBits_ = kNumTableBits + 1; \
106 startPos += cnt << (kNumBitsMax - i); 243 if ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[1]) \
107 if (startPos > kMaxValue) 244 do { _numBits_++; } \
108 return false; 245 while ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[_numBits_ - kNumTableBits]); \
109 _limits[i] = startPos; 246 check_op(_numBits_, kNumBitsMax, error_op) \
110 counts[i] = sum; 247 sym = (huf)->_symbols[(/* (UInt32) */ (_val >> ((Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - (unsigned)_numBits_)))) \
111 _poses[i] = sum; 248 - (huf)->_poses[_numBits_ - (kNumTableBits + 1)]]; \
112 sum += cnt; 249}
113 } 250
251/*
252 Z7_HUFF_DECODE_BASE_TREE_BRANCH(sym, huf, kNumBitsMax, kNumTableBits, \
253 v0, v1, \
254 get_val_for_limits, \
255 check_op, error_op, _numBits_) \
256
257*/
258
259#define Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits, \
260 v0, v1, \
261 get_val_for_table, get_val_for_limits, \
262 check_op, error_op, move_pos_op, after_op, bs) \
263{ \
264 if (Z7_HUFF_TABLE_COMPARE(huf, kNumTableBits, v0, v1)) \
265 { \
266 const NHuffman::CValueInt _val = get_val_for_limits(v0, v1, kNumBitsMax, kNumTableBits); \
267 size_t _numBits_ = kNumTableBits + 1; \
268 if ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[1]) \
269 do { _numBits_++; } \
270 while ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[_numBits_ - kNumTableBits]); \
271 check_op(_numBits_, kNumBitsMax, error_op) \
272 sym = (huf)->_symbols[(/* (UInt32) */ (_val >> ((Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - (unsigned)_numBits_)))) \
273 - (huf)->_poses[_numBits_ - (kNumTableBits + 1)]]; \
274 move_pos_op(bs, _numBits_); \
275 } \
276 else \
277 { \
278 const size_t _val = get_val_for_table(v0, v1, kNumBitsMax, kNumTableBits); \
279 const size_t _numBits_ = (huf)->_u._lens[_val]; \
280 sym = (huf)->_symbols[_val]; \
281 move_pos_op(bs, _numBits_); \
282 } \
283 after_op \
284}
285
286#define Z7_HUFF_DECODE_10(sym, huf, kNumBitsMax, kNumTableBits, \
287 v0, v1, \
288 check_op, error_op, move_pos_op, after_op, bs) \
289 Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits, \
290 v0, v1, \
291 Z7_HUFF_GET_VAL_FOR_TABLE, \
292 Z7_HUFF_GET_VAL_FOR_LIMITS, \
293 check_op, error_op, move_pos_op, after_op, bs) \
294
295
296#define Z7_HUFF_DECODE_VAL_IN_HIGH32(sym, huf, kNumBitsMax, kNumTableBits, \
297 v0, \
298 check_op, error_op, move_pos_op, after_op, bs) \
299{ \
300 Z7_HUFF_PRECALC_V1(kNumTableBits, v0, _v1_temp) \
301 Z7_HUFF_DECODE_10(sym, huf, kNumBitsMax, kNumTableBits, \
302 v0, _v1_temp, \
303 check_op, error_op, move_pos_op, after_op, bs) \
304}
305
306#if 0 || defined(Z7_HUFF_USE_64BIT_LIMIT)
307// this branch uses bitStream->GetValue_InHigh32bits().
308#define Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, \
309 check_op, error_op, move_pos_op) \
310{ \
311 const UInt32 v0 = (bitStream)->GetValue_InHigh32bits(); \
312 Z7_HUFF_PRECALC_V1(kNumTableBits, v0, v1); \
313 Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits, \
314 v0, v1, \
315 Z7_HUFF_GET_VAL_FOR_TABLE, \
316 Z7_HUFF_GET_VAL_FOR_LIMITS, \
317 check_op, error_op, move_pos_op, {}, bitStream) \
318}
319#else
320/*
321this branch uses bitStream->GetValue().
322So we use SIMPLE versions for v0, v1 calculation:
323 v0 is normalized for kNumBitsMax
324 v1 is normalized for kNumTableBits
325*/
326#define Z7_HUFF_GET_VAL_FOR_LIMITS_SIMPLE(v0, v1, kNumBitsMax, kNumTableBits) v0
327#define Z7_HUFF_GET_VAL_FOR_TABLE_SIMPLE( v0, v1, kNumBitsMax, kNumTableBits) v1
328#define Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op, move_pos_op) \
329{ \
330 const UInt32 v0 = (bitStream)->GetValue(kNumBitsMax); \
331 const UInt32 v1 = v0 >> (kNumBitsMax - kNumTableBits); \
332 Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits, \
333 v0, v1, \
334 Z7_HUFF_GET_VAL_FOR_TABLE_SIMPLE, \
335 Z7_HUFF_GET_VAL_FOR_LIMITS_SIMPLE, \
336 check_op, error_op, move_pos_op, {}, bitStream) \
337}
338#endif
114 339
115 counts[0] = sum; 340#define Z7_HUFF_bitStream_MovePos(bitStream, numBits) (bitStream)->MovePos((unsigned)(numBits))
116 _poses[0] = sum;
117 _limits[kNumBitsMax + 1] = kMaxValue;
118
119 for (sym = 0; sym < numSymbols; sym++)
120 {
121 unsigned len = lens[sym];
122 if (len == 0)
123 continue;
124 341
125 unsigned offset = counts[len]++; 342#define Z7_HUFF_DECODE_1(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op) \
126 _symbols[offset] = (UInt16)sym; 343 Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op, \
344 Z7_HUFF_bitStream_MovePos)
127 345
128 if (len <= kNumTableBits) 346// MovePosCheck
129 { 347
130 offset -= _poses[len]; 348#define Z7_HUFF_DECODE_2(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op) \
131 UInt32 num = (UInt32)1 << (kNumTableBits - len); 349 Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op, \
132 UInt16 val = (UInt16)((sym << kNumPairLenBits) | len); 350 Z7_HUFF_bitStream_MovePos)
133 UInt16 *dest = _lens + (_limits[(size_t)len - 1] >> (kNumBitsMax - kNumTableBits)) + (offset << (kNumTableBits - len)); 351
134 for (UInt32 k = 0; k < num; k++) 352// MovePosCheck
135 dest[k] = val; 353
136 } 354#define Z7_HUFF_DECODE_CHECK(sym, huf, kNumBitsMax, kNumTableBits, bitStream, error_op) \
137 } 355 Z7_HUFF_DECODE_1( sym, huf, kNumBitsMax, kNumTableBits, bitStream, \
138 356 Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES, error_op)
139 return startPos == kMaxValue;
140 }
141 357
142
143 template <class TBitDecoder> 358 template <class TBitDecoder>
144 Z7_FORCE_INLINE 359 Z7_FORCE_INLINE
145 UInt32 Decode(TBitDecoder *bitStream) const 360 bool Decode2(TBitDecoder *bitStream, unsigned &sym) const
146 { 361 {
147 UInt32 val = bitStream->GetValue(kNumBitsMax); 362 Z7_HUFF_DECODE_CHECK(sym, this, kNumBitsMax, kNumTableBits, bitStream,
148 363 { return false; }
149 if (val < _limits[kNumTableBits]) 364 )
150 { 365 return true;
151 UInt32 pair = _lens[val >> (kNumBitsMax - kNumTableBits)]; 366 }
152 bitStream->MovePos((unsigned)(pair & kPairLenMask));
153 return pair >> kNumPairLenBits;
154 }
155 367
156 unsigned numBits; 368 template <class TBitDecoder>
157 for (numBits = kNumTableBits + 1; val >= _limits[numBits]; numBits++); 369 Z7_FORCE_INLINE
158 370 bool Decode_SymCheck_MovePosCheck(TBitDecoder *bitStream, unsigned &sym) const
159 if (numBits > kNumBitsMax) 371 {
160 return 0xFFFFFFFF; 372 Z7_HUFF_DECODE_0(sym, this, kNumBitsMax, kNumTableBits, bitStream,
373 Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES,
374 { return false; },
375 { return (bitStream)->MovePosCheck; }
376 )
377 }
161 378
162 bitStream->MovePos(numBits); 379 template <class TBitDecoder>
163 UInt32 index = _poses[numBits] + ((val - _limits[(size_t)numBits - 1]) >> (kNumBitsMax - numBits)); 380 Z7_FORCE_INLINE
164 return _symbols[index]; 381 unsigned Decode(TBitDecoder *bitStream) const
382 {
383 unsigned sym;
384 Z7_HUFF_DECODE_CHECK(sym, this, kNumBitsMax, kNumTableBits, bitStream,
385 { return (unsigned)(int)(Int32)0xffffffff; }
386 )
387 return sym;
165 } 388 }
166 389
167 390
168 template <class TBitDecoder> 391 template <class TBitDecoder>
169 Z7_FORCE_INLINE 392 Z7_FORCE_INLINE
170 UInt32 DecodeFull(TBitDecoder *bitStream) const 393 unsigned DecodeFull(TBitDecoder *bitStream) const
171 { 394 {
172 UInt32 val = bitStream->GetValue(kNumBitsMax); 395 /*
173 396 const UInt32 val = bitStream->GetValue(kNumBitsMax);
174 if (val < _limits[kNumTableBits]) 397 if (val < _limits[kNumTableBits])
175 { 398 {
176 UInt32 pair = _lens[val >> (kNumBitsMax - kNumTableBits)]; 399 const unsigned pair = _u._lens[(size_t)(val >> (kNumBitsMax - kNumTableBits))];
177 bitStream->MovePos((unsigned)(pair & kPairLenMask)); 400 bitStream->MovePos(pair & kPairLenMask);
178 return pair >> kNumPairLenBits; 401 return pair >> kNumPairLenBits;
179 } 402 }
180 403
@@ -182,49 +405,55 @@ public:
182 for (numBits = kNumTableBits + 1; val >= _limits[numBits]; numBits++); 405 for (numBits = kNumTableBits + 1; val >= _limits[numBits]; numBits++);
183 406
184 bitStream->MovePos(numBits); 407 bitStream->MovePos(numBits);
185 UInt32 index = _poses[numBits] + ((val - _limits[(size_t)numBits - 1]) >> (kNumBitsMax - numBits)); 408 return _symbols[_poses[numBits] + (unsigned)
186 return _symbols[index]; 409 ((val - _limits[(size_t)numBits - 1]) >> (kNumBitsMax - numBits))];
410 */
411 unsigned sym;
412 Z7_HUFF_DECODE_2(sym, this, kNumBitsMax, kNumTableBits, bitStream,
413 Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO, {}
414 )
415 return sym;
187 } 416 }
188}; 417};
189 418
190 419
420template <unsigned kNumBitsMax, unsigned m_NumSymbols, unsigned kNumTableBits /* = kNumTableBits_Default */>
421struct CDecoder: public CDecoderBase
422 <UInt16, UInt32, UInt64, kNumBitsMax, m_NumSymbols, kNumTableBits> {};
191 423
192template <UInt32 m_NumSymbols> 424template <unsigned kNumBitsMax, unsigned m_NumSymbols, unsigned kNumTableBits /* = 7 */>
425struct CDecoder256: public CDecoderBase
426 <Byte, UInt16, UInt32, kNumBitsMax, m_NumSymbols, kNumTableBits> {};
427
428
429template <unsigned numSymbols>
193class CDecoder7b 430class CDecoder7b
194{ 431{
195 Byte _lens[1 << 7];
196public: 432public:
433 Byte _lens[1 << 7];
197 434
198 bool Build(const Byte *lens) throw() 435 bool Build(const Byte *lens, bool full) throw()
199 { 436 {
200 const unsigned kNumBitsMax = 7; 437 const unsigned kNumBitsMax = 7;
201 438
202 UInt32 counts[kNumBitsMax + 1]; 439 unsigned counts[kNumBitsMax + 1];
203 UInt32 _poses[kNumBitsMax + 1]; 440 unsigned _poses[kNumBitsMax + 1];
204 UInt32 _limits[kNumBitsMax + 1]; 441 unsigned _limits[kNumBitsMax + 1];
205
206 unsigned i; 442 unsigned i;
207 for (i = 0; i <= kNumBitsMax; i++) 443 for (i = 0; i <= kNumBitsMax; i++)
208 counts[i] = 0; 444 counts[i] = 0;
445 for (i = 0; i < numSymbols; i++)
446 counts[lens[i]]++;
209 447
210 UInt32 sym;
211
212 for (sym = 0; sym < m_NumSymbols; sym++)
213 counts[lens[sym]]++;
214
215 const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax;
216
217 _limits[0] = 0; 448 _limits[0] = 0;
218 449 const unsigned kMaxValue = 1u << kNumBitsMax;
219 UInt32 startPos = 0; 450 unsigned startPos = 0;
220 UInt32 sum = 0; 451 unsigned sum = 0;
221 452
222 for (i = 1; i <= kNumBitsMax; i++) 453 for (i = 1; i <= kNumBitsMax; i++)
223 { 454 {
224 const UInt32 cnt = counts[i]; 455 const unsigned cnt = counts[i];
225 startPos += cnt << (kNumBitsMax - i); 456 startPos += cnt << (kNumBitsMax - i);
226 if (startPos > kMaxValue)
227 return false;
228 _limits[i] = startPos; 457 _limits[i] = startPos;
229 counts[i] = sum; 458 counts[i] = sum;
230 _poses[i] = sum; 459 _poses[i] = sum;
@@ -234,41 +463,61 @@ public:
234 counts[0] = sum; 463 counts[0] = sum;
235 _poses[0] = sum; 464 _poses[0] = sum;
236 465
237 for (sym = 0; sym < m_NumSymbols; sym++) 466 if (full)
238 { 467 {
239 unsigned len = lens[sym]; 468 if (startPos != kMaxValue)
240 if (len == 0) 469 return false;
241 continue; 470 }
471 else
472 {
473 if (startPos > kMaxValue)
474 return false;
475 }
242 476
243 unsigned offset = counts[len]++;
244 477
478 for (i = 0; i < numSymbols; i++)
479 {
480 const unsigned len = lens[i];
481 if (len == 0)
482 continue;
483 const unsigned offset = counts[len]++;
245 { 484 {
246 offset -= _poses[len]; 485 Byte *dest = _lens + _limits[(size_t)len - 1]
247 UInt32 num = (UInt32)1 << (kNumBitsMax - len); 486 + ((offset - _poses[len]) << (kNumBitsMax - len));
248 Byte val = (Byte)((sym << 3) | len); 487 const unsigned num = (unsigned)1 << (kNumBitsMax - len);
249 Byte *dest = _lens + (_limits[(size_t)len - 1]) + (offset << (kNumBitsMax - len)); 488 const unsigned val = (i << 3) + len;
250 for (UInt32 k = 0; k < num; k++) 489 for (unsigned k = 0; k < num; k++)
251 dest[k] = val; 490 dest[k] = (Byte)val;
252 } 491 }
253 } 492 }
254 493
494 if (!full)
255 { 495 {
256 UInt32 limit = _limits[kNumBitsMax]; 496 const unsigned limit = _limits[kNumBitsMax];
257 UInt32 num = ((UInt32)1 << kNumBitsMax) - limit; 497 const unsigned num = ((unsigned)1 << kNumBitsMax) - limit;
258 Byte *dest = _lens + limit; 498 Byte *dest = _lens + limit;
259 for (UInt32 k = 0; k < num; k++) 499 for (unsigned k = 0; k < num; k++)
260 dest[k] = (Byte)(0x1F << 3); 500 dest[k] = (Byte)
501 // (0x1f << 3);
502 ((0x1f << 3) + 0x7);
261 } 503 }
262 504
263 return true; 505 return true;
264 } 506 }
265 507
508#define Z7_HUFF_DECODER_7B_DECODE(dest, huf, get_val, move_pos, bs) \
509 { \
510 const unsigned pair = huf->_lens[(size_t)get_val(7)]; \
511 const unsigned numBits = pair & 0x7; \
512 move_pos(bs, numBits); \
513 dest = pair >> 3; \
514 }
515
266 template <class TBitDecoder> 516 template <class TBitDecoder>
267 UInt32 Decode(TBitDecoder *bitStream) const 517 unsigned Decode(TBitDecoder *bitStream) const
268 { 518 {
269 UInt32 val = bitStream->GetValue(7); 519 const unsigned pair = _lens[(size_t)bitStream->GetValue(7)];
270 UInt32 pair = _lens[val]; 520 bitStream->MovePos(pair & 0x7);
271 bitStream->MovePos((unsigned)(pair & 0x7));
272 return pair >> 3; 521 return pair >> 3;
273 } 522 }
274}; 523};
diff --git a/CPP/7zip/Compress/ImplodeDecoder.cpp b/CPP/7zip/Compress/ImplodeDecoder.cpp
index 12f2dce..bcf5d4f 100644
--- a/CPP/7zip/Compress/ImplodeDecoder.cpp
+++ b/CPP/7zip/Compress/ImplodeDecoder.cpp
@@ -13,26 +13,21 @@ namespace NDecoder {
13bool CHuffmanDecoder::Build(const Byte *lens, unsigned numSymbols) throw() 13bool CHuffmanDecoder::Build(const Byte *lens, unsigned numSymbols) throw()
14{ 14{
15 unsigned counts[kNumHuffmanBits + 1]; 15 unsigned counts[kNumHuffmanBits + 1];
16
17 unsigned i; 16 unsigned i;
18 for (i = 0; i <= kNumHuffmanBits; i++) 17 for (i = 0; i <= kNumHuffmanBits; i++)
19 counts[i] = 0; 18 counts[i] = 0;
20 19 for (i = 0; i < numSymbols; i++)
21 unsigned sym; 20 counts[lens[i]]++;
22 for (sym = 0; sym < numSymbols; sym++)
23 counts[lens[sym]]++;
24 21
25 const UInt32 kMaxValue = (UInt32)1 << kNumHuffmanBits; 22 const UInt32 kMaxValue = (UInt32)1 << kNumHuffmanBits;
26
27 // _limits[0] = kMaxValue; 23 // _limits[0] = kMaxValue;
28
29 UInt32 startPos = kMaxValue; 24 UInt32 startPos = kMaxValue;
30 UInt32 sum = 0; 25 unsigned sum = 0;
31 26
32 for (i = 1; i <= kNumHuffmanBits; i++) 27 for (i = 1; i <= kNumHuffmanBits; i++)
33 { 28 {
34 const UInt32 cnt = counts[i]; 29 const unsigned cnt = counts[i];
35 const UInt32 range = cnt << (kNumHuffmanBits - i); 30 const UInt32 range = (UInt32)cnt << (kNumHuffmanBits - i);
36 if (startPos < range) 31 if (startPos < range)
37 return false; 32 return false;
38 startPos -= range; 33 startPos -= range;
@@ -41,29 +36,26 @@ bool CHuffmanDecoder::Build(const Byte *lens, unsigned numSymbols) throw()
41 sum += cnt; 36 sum += cnt;
42 counts[i] = sum; 37 counts[i] = sum;
43 } 38 }
44
45 // counts[0] += sum; 39 // counts[0] += sum;
46
47 if (startPos != 0) 40 if (startPos != 0)
48 return false; 41 return false;
49 42 for (i = 0; i < numSymbols; i++)
50 for (sym = 0; sym < numSymbols; sym++)
51 { 43 {
52 const unsigned len = lens[sym]; 44 const unsigned len = lens[i];
53 if (len != 0) 45 if (len != 0)
54 _symbols[--counts[len]] = (Byte)sym; 46 _symbols[--counts[len]] = (Byte)i;
55 } 47 }
56
57 return true; 48 return true;
58} 49}
59 50
60 51
61UInt32 CHuffmanDecoder::Decode(CInBit *inStream) const throw() 52unsigned CHuffmanDecoder::Decode(CInBit *inStream) const throw()
62{ 53{
63 const UInt32 val = inStream->GetValue(kNumHuffmanBits); 54 const UInt32 val = inStream->GetValue(kNumHuffmanBits);
64 unsigned numBits; 55 size_t numBits;
65 for (numBits = 1; val < _limits[numBits]; numBits++); 56 for (numBits = 1; val < _limits[numBits]; numBits++);
66 const UInt32 sym = _symbols[_poses[numBits] + ((val - _limits[numBits]) >> (kNumHuffmanBits - numBits))]; 57 const unsigned sym = _symbols[_poses[numBits]
58 + (unsigned)((val - _limits[numBits]) >> (kNumHuffmanBits - numBits))];
67 inStream->MovePos(numBits); 59 inStream->MovePos(numBits);
68 return sym; 60 return sym;
69} 61}
@@ -96,12 +88,12 @@ bool CCoder::BuildHuff(CHuffmanDecoder &decoder, unsigned numSymbols)
96 do 88 do
97 { 89 {
98 const unsigned b = (unsigned)_inBitStream.ReadAlignedByte(); 90 const unsigned b = (unsigned)_inBitStream.ReadAlignedByte();
99 const Byte level = (Byte)((b & 0xF) + 1); 91 const unsigned level = (b & 0xF) + 1;
100 const unsigned rep = ((unsigned)b >> 4) + 1; 92 const unsigned rep = ((unsigned)b >> 4) + 1;
101 if (index + rep > numSymbols) 93 if (index + rep > numSymbols)
102 return false; 94 return false;
103 for (unsigned j = 0; j < rep; j++) 95 for (unsigned j = 0; j < rep; j++)
104 levels[index++] = level; 96 levels[index++] = (Byte)level;
105 } 97 }
106 while (--numRecords); 98 while (--numRecords);
107 99
@@ -146,11 +138,11 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou
146 138
147 while (pos < unPackSize) 139 while (pos < unPackSize)
148 { 140 {
149 if (progress && (pos - prevProgress) >= (1 << 18)) 141 if (pos - prevProgress >= (1u << 18) && progress)
150 { 142 {
143 prevProgress = pos;
151 const UInt64 packSize = _inBitStream.GetProcessedSize(); 144 const UInt64 packSize = _inBitStream.GetProcessedSize();
152 RINOK(progress->SetRatioInfo(&packSize, &pos)) 145 RINOK(progress->SetRatioInfo(&packSize, &pos))
153 prevProgress = pos;
154 } 146 }
155 147
156 if (_inBitStream.ReadBits(1) != 0) 148 if (_inBitStream.ReadBits(1) != 0)
@@ -158,7 +150,7 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou
158 Byte b; 150 Byte b;
159 if (literalsOn) 151 if (literalsOn)
160 { 152 {
161 const UInt32 sym = _litDecoder.Decode(&_inBitStream); 153 const unsigned sym = _litDecoder.Decode(&_inBitStream);
162 // if (sym >= kLitTableSize) break; 154 // if (sym >= kLitTableSize) break;
163 b = (Byte)sym; 155 b = (Byte)sym;
164 } 156 }
@@ -170,36 +162,36 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou
170 else 162 else
171 { 163 {
172 const UInt32 lowDistBits = _inBitStream.ReadBits(numDistDirectBits); 164 const UInt32 lowDistBits = _inBitStream.ReadBits(numDistDirectBits);
173 UInt32 dist = _distDecoder.Decode(&_inBitStream); 165 UInt32 dist = (UInt32)_distDecoder.Decode(&_inBitStream);
174 // if (dist >= kDistTableSize) break; 166 // if (dist >= kDistTableSize) break;
175 dist = (dist << numDistDirectBits) + lowDistBits; 167 dist = (dist << numDistDirectBits) + lowDistBits;
176 UInt32 len = _lenDecoder.Decode(&_inBitStream); 168 unsigned len = _lenDecoder.Decode(&_inBitStream);
177 // if (len >= kLenTableSize) break; 169 // if (len >= kLenTableSize) break;
178 if (len == kLenTableSize - 1) 170 if (len == kLenTableSize - 1)
179 len += _inBitStream.ReadBits(kNumLenDirectBits); 171 len += _inBitStream.ReadBits(kNumLenDirectBits);
180 len += minMatchLen; 172 len += minMatchLen;
181
182 { 173 {
183 const UInt64 limit = unPackSize - pos; 174 const UInt64 limit = unPackSize - pos;
175 // limit != 0
184 if (len > limit) 176 if (len > limit)
185 { 177 {
186 moreOut = true; 178 moreOut = true;
187 len = (UInt32)limit; 179 len = (UInt32)limit;
188 } 180 }
189 } 181 }
190 182 do
191 while (dist >= pos && len != 0)
192 { 183 {
184 // len != 0
185 if (dist < pos)
186 {
187 _outWindowStream.CopyBlock(dist, len);
188 pos += len;
189 break;
190 }
193 _outWindowStream.PutByte(0); 191 _outWindowStream.PutByte(0);
194 pos++; 192 pos++;
195 len--;
196 }
197
198 if (len != 0)
199 {
200 _outWindowStream.CopyBlock(dist, len);
201 pos += len;
202 } 193 }
194 while (--len);
203 } 195 }
204 } 196 }
205 197
diff --git a/CPP/7zip/Compress/ImplodeDecoder.h b/CPP/7zip/Compress/ImplodeDecoder.h
index ec70045..6032515 100644
--- a/CPP/7zip/Compress/ImplodeDecoder.h
+++ b/CPP/7zip/Compress/ImplodeDecoder.h
@@ -28,7 +28,7 @@ class CHuffmanDecoder
28 Byte _symbols[kMaxHuffTableSize]; 28 Byte _symbols[kMaxHuffTableSize];
29public: 29public:
30 bool Build(const Byte *lens, unsigned numSymbols) throw(); 30 bool Build(const Byte *lens, unsigned numSymbols) throw();
31 UInt32 Decode(CInBit *inStream) const throw(); 31 unsigned Decode(CInBit *inStream) const throw();
32}; 32};
33 33
34 34
@@ -39,6 +39,9 @@ Z7_CLASS_IMP_NOQIB_4(
39 , ICompressSetFinishMode 39 , ICompressSetFinishMode
40 , ICompressGetInStreamProcessedSize 40 , ICompressGetInStreamProcessedSize
41) 41)
42 Byte _flags;
43 bool _fullStreamMode;
44
42 CLzOutWindow _outWindowStream; 45 CLzOutWindow _outWindowStream;
43 CInBit _inBitStream; 46 CInBit _inBitStream;
44 47
@@ -46,9 +49,6 @@ Z7_CLASS_IMP_NOQIB_4(
46 CHuffmanDecoder _lenDecoder; 49 CHuffmanDecoder _lenDecoder;
47 CHuffmanDecoder _distDecoder; 50 CHuffmanDecoder _distDecoder;
48 51
49 Byte _flags;
50 bool _fullStreamMode;
51
52 bool BuildHuff(CHuffmanDecoder &table, unsigned numSymbols); 52 bool BuildHuff(CHuffmanDecoder &table, unsigned numSymbols);
53 HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, 53 HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
54 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); 54 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
diff --git a/CPP/7zip/Compress/LzfseDecoder.cpp b/CPP/7zip/Compress/LzfseDecoder.cpp
index 236d5bd..b224a33 100644
--- a/CPP/7zip/Compress/LzfseDecoder.cpp
+++ b/CPP/7zip/Compress/LzfseDecoder.cpp
@@ -80,7 +80,7 @@ HRESULT CDecoder::DecodeUncompressed(UInt32 unpackSize)
80 UInt32 cur = unpackSize; 80 UInt32 cur = unpackSize;
81 if (cur > kBufSize) 81 if (cur > kBufSize)
82 cur = kBufSize; 82 cur = kBufSize;
83 UInt32 cur2 = (UInt32)m_InStream.ReadBytes(buf, cur); 83 const UInt32 cur2 = (UInt32)m_InStream.ReadBytes(buf, cur);
84 m_OutWindowStream.PutBytes(buf, cur2); 84 m_OutWindowStream.PutBytes(buf, cur2);
85 if (cur != cur2) 85 if (cur != cur2)
86 return S_FALSE; 86 return S_FALSE;
@@ -91,7 +91,7 @@ HRESULT CDecoder::DecodeUncompressed(UInt32 unpackSize)
91 91
92HRESULT CDecoder::DecodeLzvn(UInt32 unpackSize, UInt32 packSize) 92HRESULT CDecoder::DecodeLzvn(UInt32 unpackSize, UInt32 packSize)
93{ 93{
94 PRF(printf("\nLZVN %7u %7u", unpackSize, packSize)); 94 PRF(printf("\nLZVN 0x%07x 0x%07x\n", unpackSize, packSize));
95 95
96 UInt32 D = 0; 96 UInt32 D = 0;
97 97
@@ -241,19 +241,27 @@ HRESULT CDecoder::DecodeLzvn(UInt32 unpackSize, UInt32 packSize)
241 return S_FALSE; 241 return S_FALSE;
242 242
243 // LZVN encoder writes 7 additional zero bytes 243 // LZVN encoder writes 7 additional zero bytes
244 if (packSize != 7) 244 if (packSize < 7)
245 return S_FALSE; 245 return S_FALSE;
246 do 246 for (unsigned i = 0; i < 7; i++)
247 { 247 {
248 Byte b; 248 Byte b;
249 if (!m_InStream.ReadByte(b)) 249 if (!m_InStream.ReadByte(b))
250 return S_FALSE; 250 return S_FALSE;
251 packSize--;
252 if (b != 0) 251 if (b != 0)
253 return S_FALSE; 252 return S_FALSE;
254 } 253 }
255 while (packSize != 0); 254 packSize -= 7;
256 255 if (packSize)
256 {
257 PRF(printf("packSize after unused = %u\n", packSize));
258 // if (packSize <= 0x100) { Byte buf[0x100]; m_InStream.ReadBytes(buf, packSize); }
259 /* Lzvn block that is used in HFS can contain junk data
260 (at least 256 bytes) after payload data. Why?
261 We ignore that junk data, if it's HFS (LzvnMode) mode. */
262 if (!LzvnMode)
263 return S_FALSE;
264 }
257 return S_OK; 265 return S_OK;
258} 266}
259 267
@@ -479,7 +487,7 @@ static Z7_FORCE_INLINE int FseInStream_Init(CBitStream *s,
479static Z7_FORCE_INLINE UInt32 BitStream_Pull(CBitStream *s, unsigned numBits) 487static Z7_FORCE_INLINE UInt32 BitStream_Pull(CBitStream *s, unsigned numBits)
480{ 488{
481 s->numBits -= numBits; 489 s->numBits -= numBits;
482 UInt32 v = s->accum >> s->numBits; 490 const UInt32 v = s->accum >> s->numBits;
483 s->accum = mask31(s->accum, s->numBits); 491 s->accum = mask31(s->accum, s->numBits);
484 return v; 492 return v;
485} 493}
@@ -922,7 +930,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
922 coderReleaser.NeedFlush = false; 930 coderReleaser.NeedFlush = false;
923 HRESULT res = m_OutWindowStream.Flush(); 931 HRESULT res = m_OutWindowStream.Flush();
924 if (res == S_OK) 932 if (res == S_OK)
925 if ((inSize && *inSize != m_InStream.GetProcessedSize()) 933 if ((!LzvnMode && inSize && *inSize != m_InStream.GetProcessedSize())
926 || (outSize && *outSize != m_OutWindowStream.GetProcessedSize())) 934 || (outSize && *outSize != m_OutWindowStream.GetProcessedSize()))
927 res = S_FALSE; 935 res = S_FALSE;
928 return res; 936 return res;
diff --git a/CPP/7zip/Compress/LzhDecoder.cpp b/CPP/7zip/Compress/LzhDecoder.cpp
index 064bc55..fb115da 100644
--- a/CPP/7zip/Compress/LzhDecoder.cpp
+++ b/CPP/7zip/Compress/LzhDecoder.cpp
@@ -10,30 +10,17 @@ namespace NDecoder {
10 10
11static const UInt32 kWindowSizeMin = 1 << 16; 11static const UInt32 kWindowSizeMin = 1 << 16;
12 12
13static bool CheckCodeLens(const Byte *lens, unsigned num)
14{
15 UInt32 sum = 0;
16 for (unsigned i = 0; i < num; i++)
17 {
18 const unsigned len = lens[i];
19 if (len != 0)
20 sum += ((UInt32)1 << (NUM_CODE_BITS - len));
21 }
22 return sum == ((UInt32)1 << NUM_CODE_BITS);
23}
24
25bool CCoder::ReadTP(unsigned num, unsigned numBits, int spec) 13bool CCoder::ReadTP(unsigned num, unsigned numBits, int spec)
26{ 14{
27 _symbolT = -1; 15 _symbolT = -1;
28 16
29 const UInt32 n = _inBitStream.ReadBits(numBits); 17 const unsigned n = (unsigned)_inBitStream.ReadBits(numBits);
30 if (n == 0) 18 if (n == 0)
31 { 19 {
32 const unsigned s = _inBitStream.ReadBits(numBits); 20 const unsigned s = (unsigned)_inBitStream.ReadBits(numBits);
33 _symbolT = (int)s; 21 _symbolT = (int)s;
34 return (s < num); 22 return (s < num);
35 } 23 }
36
37 if (n > num) 24 if (n > num)
38 return false; 25 return false;
39 26
@@ -42,37 +29,31 @@ bool CCoder::ReadTP(unsigned num, unsigned numBits, int spec)
42 unsigned i; 29 unsigned i;
43 for (i = 0; i < NPT; i++) 30 for (i = 0; i < NPT; i++)
44 lens[i] = 0; 31 lens[i] = 0;
45
46 i = 0; 32 i = 0;
47
48 do 33 do
49 { 34 {
50 const UInt32 val = _inBitStream.GetValue(16); 35 unsigned val = (unsigned)_inBitStream.GetValue(16);
51 unsigned c = val >> 13; 36 unsigned c = val >> 13;
52 37 unsigned mov = 3;
53 if (c == 7) 38 if (c == 7)
54 { 39 {
55 UInt32 mask = 1 << 12; 40 while (val & (1 << 12))
56 while (mask & val)
57 { 41 {
58 mask >>= 1; 42 val += val;
59 c++; 43 c++;
60 } 44 }
61 if (c > 16) 45 if (c > 16)
62 return false; 46 return false;
47 mov = c - 3;
63 } 48 }
64
65 _inBitStream.MovePos(c < 7 ? 3 : c - 3);
66 lens[i++] = (Byte)c; 49 lens[i++] = (Byte)c;
67 50 _inBitStream.MovePos(mov);
68 if (i == (unsigned)spec) 51 if ((int)i == spec)
69 i += _inBitStream.ReadBits(2); 52 i += _inBitStream.ReadBits(2);
70 } 53 }
71 while (i < n); 54 while (i < n);
72 55
73 if (!CheckCodeLens(lens, NPT)) 56 return _decoderT.Build(lens, NHuffman::k_BuildMode_Full);
74 return false;
75 return _decoderT.Build(lens);
76 } 57 }
77} 58}
78 59
@@ -82,28 +63,24 @@ bool CCoder::ReadC()
82{ 63{
83 _symbolC = -1; 64 _symbolC = -1;
84 65
85 unsigned n = _inBitStream.ReadBits(NUM_C_BITS); 66 const unsigned n = (unsigned)_inBitStream.ReadBits(NUM_C_BITS);
86
87 if (n == 0) 67 if (n == 0)
88 { 68 {
89 const unsigned s = _inBitStream.ReadBits(NUM_C_BITS); 69 const unsigned s = (unsigned)_inBitStream.ReadBits(NUM_C_BITS);
90 _symbolC = (int)s; 70 _symbolC = (int)s;
91 return (s < NC); 71 return (s < NC);
92 } 72 }
93
94 if (n > NC) 73 if (n > NC)
95 return false; 74 return false;
96 75
97 { 76 {
98 Byte lens[NC]; 77 Byte lens[NC];
99
100 unsigned i = 0; 78 unsigned i = 0;
101
102 do 79 do
103 { 80 {
104 UInt32 c = (unsigned)_symbolT; 81 unsigned c = (unsigned)_symbolT;
105 if (_symbolT < 0) 82 if (_symbolT < 0)
106 c = _decoderT.Decode(&_inBitStream); 83 c = _decoderT.DecodeFull(&_inBitStream);
107 84
108 if (c <= 2) 85 if (c <= 2)
109 { 86 {
@@ -126,19 +103,13 @@ bool CCoder::ReadC()
126 } 103 }
127 while (i < n); 104 while (i < n);
128 105
129 while (i < NC) 106 while (i < NC) lens[i++] = 0;
130 lens[i++] = 0; 107 return _decoderC.Build(lens, /* n, */ NHuffman::k_BuildMode_Full);
131
132 if (!CheckCodeLens(lens, NC))
133 return false;
134 return _decoderC.Build(lens);
135 } 108 }
136} 109}
137 110
138HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress) 111HRESULT CCoder::CodeReal(UInt32 rem, ICompressProgressInfo *progress)
139{ 112{
140 const unsigned pbit = (DictSize <= (1 << 14) ? 4 : 5);
141
142 UInt32 blockSize = 0; 113 UInt32 blockSize = 0;
143 114
144 while (rem != 0) 115 while (rem != 0)
@@ -147,7 +118,6 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
147 { 118 {
148 if (_inBitStream.ExtraBitsWereRead()) 119 if (_inBitStream.ExtraBitsWereRead())
149 return S_FALSE; 120 return S_FALSE;
150
151 if (progress) 121 if (progress)
152 { 122 {
153 const UInt64 packSize = _inBitStream.GetProcessedSize(); 123 const UInt64 packSize = _inBitStream.GetProcessedSize();
@@ -163,15 +133,16 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
163 return S_FALSE; 133 return S_FALSE;
164 if (!ReadC()) 134 if (!ReadC())
165 return S_FALSE; 135 return S_FALSE;
136 const unsigned pbit = (DictSize <= (1 << 14) ? 4 : 5);
166 if (!ReadTP(NP, pbit, -1)) 137 if (!ReadTP(NP, pbit, -1))
167 return S_FALSE; 138 return S_FALSE;
168 } 139 }
169 140
170 blockSize--; 141 blockSize--;
171 142
172 UInt32 number = (unsigned)_symbolC; 143 unsigned number = (unsigned)_symbolC;
173 if (_symbolC < 0) 144 if (_symbolC < 0)
174 number = _decoderC.Decode(&_inBitStream); 145 number = _decoderC.DecodeFull(&_inBitStream);
175 146
176 if (number < 256) 147 if (number < 256)
177 { 148 {
@@ -180,11 +151,11 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
180 } 151 }
181 else 152 else
182 { 153 {
183 UInt32 len = number - 256 + kMatchMinLen; 154 const unsigned len = number - 256 + kMatchMinLen;
184 155
185 UInt32 dist = (unsigned)_symbolT; 156 UInt32 dist = (UInt32)(unsigned)_symbolT;
186 if (_symbolT < 0) 157 if (_symbolT < 0)
187 dist = _decoderT.Decode(&_inBitStream); 158 dist = (UInt32)_decoderT.DecodeFull(&_inBitStream);
188 159
189 if (dist > 1) 160 if (dist > 1)
190 { 161 {
@@ -196,7 +167,11 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
196 return S_FALSE; 167 return S_FALSE;
197 168
198 if (len > rem) 169 if (len > rem)
199 len = (UInt32)rem; 170 {
171 // if (FinishMode)
172 return S_FALSE;
173 // len = (unsigned)rem;
174 }
200 175
201 if (!_outWindow.CopyBlock(dist, len)) 176 if (!_outWindow.CopyBlock(dist, len))
202 return S_FALSE; 177 return S_FALSE;
@@ -204,44 +179,37 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
204 } 179 }
205 } 180 }
206 181
207 if (FinishMode) 182 // if (FinishMode)
208 { 183 {
209 if (blockSize != 0) 184 if (blockSize != 0)
210 return S_FALSE; 185 return S_FALSE;
211 if (_inBitStream.ReadAlignBits() != 0) 186 if (_inBitStream.ReadAlignBits() != 0)
212 return S_FALSE; 187 return S_FALSE;
213 } 188 }
214
215 if (_inBitStream.ExtraBitsWereRead()) 189 if (_inBitStream.ExtraBitsWereRead())
216 return S_FALSE; 190 return S_FALSE;
217
218 return S_OK; 191 return S_OK;
219} 192}
220 193
221 194
222Z7_COM7F_IMF(CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 195HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
223 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)) 196 const UInt32 outSize, ICompressProgressInfo *progress)
224{ 197{
225 try 198 try
226 { 199 {
227 if (!outSize)
228 return E_INVALIDARG;
229
230 if (!_outWindow.Create(DictSize > kWindowSizeMin ? DictSize : kWindowSizeMin)) 200 if (!_outWindow.Create(DictSize > kWindowSizeMin ? DictSize : kWindowSizeMin))
231 return E_OUTOFMEMORY; 201 return E_OUTOFMEMORY;
232 if (!_inBitStream.Create(1 << 17)) 202 if (!_inBitStream.Create(1 << 17))
233 return E_OUTOFMEMORY; 203 return E_OUTOFMEMORY;
234
235 _outWindow.SetStream(outStream); 204 _outWindow.SetStream(outStream);
236 _outWindow.Init(false); 205 _outWindow.Init(false);
237 _inBitStream.SetStream(inStream); 206 _inBitStream.SetStream(inStream);
238 _inBitStream.Init(); 207 _inBitStream.Init();
239 208 {
240 CCoderReleaser coderReleaser(this); 209 CCoderReleaser coderReleaser(this);
241 210 RINOK(CodeReal(outSize, progress))
242 RINOK(CodeReal(*outSize, progress)) 211 coderReleaser.Disable();
243 212 }
244 coderReleaser.Disable();
245 return _outWindow.Flush(); 213 return _outWindow.Flush();
246 } 214 }
247 catch(const CInBufferException &e) { return e.ErrorCode; } 215 catch(const CInBufferException &e) { return e.ErrorCode; }
diff --git a/CPP/7zip/Compress/LzhDecoder.h b/CPP/7zip/Compress/LzhDecoder.h
index 491212e..204c52c 100644
--- a/CPP/7zip/Compress/LzhDecoder.h
+++ b/CPP/7zip/Compress/LzhDecoder.h
@@ -19,25 +19,25 @@ namespace NDecoder {
19 19
20const unsigned kMatchMinLen = 3; 20const unsigned kMatchMinLen = 3;
21const unsigned kMatchMaxLen = 256; 21const unsigned kMatchMaxLen = 256;
22const unsigned NC = (256 + kMatchMaxLen - kMatchMinLen + 1); 22const unsigned NC = 256 + kMatchMaxLen - kMatchMinLen + 1;
23const unsigned NUM_CODE_BITS = 16; 23const unsigned NUM_CODE_BITS = 16;
24const unsigned NUM_DIC_BITS_MAX = 25; 24const unsigned NUM_DIC_BITS_MAX = 25;
25const unsigned NT = (NUM_CODE_BITS + 3); 25const unsigned NT = NUM_CODE_BITS + 3;
26const unsigned NP = (NUM_DIC_BITS_MAX + 1); 26const unsigned NP = NUM_DIC_BITS_MAX + 1;
27const unsigned NPT = NP; // Max(NT, NP) 27const unsigned NPT = NP; // Max(NT, NP)
28 28
29Z7_CLASS_IMP_NOQIB_1( 29class CCoder
30 CCoder 30{
31 , ICompressCoder
32)
33 CLzOutWindow _outWindow; 31 CLzOutWindow _outWindow;
34 NBitm::CDecoder<CInBuffer> _inBitStream; 32 NBitm::CDecoder<CInBuffer> _inBitStream;
35 33
36 int _symbolT; 34 int _symbolT;
37 int _symbolC; 35 int _symbolC;
36 UInt32 DictSize;
37 // bool FinishMode;
38 38
39 NHuffman::CDecoder<NUM_CODE_BITS, NPT> _decoderT; 39 NHuffman::CDecoder256<NUM_CODE_BITS, NPT, 7> _decoderT;
40 NHuffman::CDecoder<NUM_CODE_BITS, NC> _decoderC; 40 NHuffman::CDecoder<NUM_CODE_BITS, NC, 10> _decoderC;
41 41
42 class CCoderReleaser 42 class CCoderReleaser
43 { 43 {
@@ -52,16 +52,15 @@ Z7_CLASS_IMP_NOQIB_1(
52 bool ReadTP(unsigned num, unsigned numBits, int spec); 52 bool ReadTP(unsigned num, unsigned numBits, int spec);
53 bool ReadC(); 53 bool ReadC();
54 54
55 HRESULT CodeReal(UInt64 outSize, ICompressProgressInfo *progress); 55 HRESULT CodeReal(UInt32 outSize, ICompressProgressInfo *progress);
56public: 56public:
57 UInt32 DictSize; 57 CCoder(): DictSize(1 << 16)
58 bool FinishMode; 58 // , FinishMode(true)
59 59 {}
60 void SetDictSize(unsigned dictSize) { DictSize = dictSize; } 60 void SetDictSize(UInt32 dictSize) { DictSize = dictSize; }
61
62 CCoder(): DictSize(1 << 16), FinishMode(false) {}
63
64 UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); } 61 UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); }
62 HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
63 UInt32 outSize, ICompressProgressInfo *progress);
65}; 64};
66 65
67}}} 66}}}
diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp
index 4f05b48..4b67c8e 100644
--- a/CPP/7zip/Compress/LzmaDecoder.cpp
+++ b/CPP/7zip/Compress/LzmaDecoder.cpp
@@ -17,6 +17,7 @@ static HRESULT SResToHRESULT(SRes res)
17 case SZ_ERROR_PARAM: return E_INVALIDARG; 17 case SZ_ERROR_PARAM: return E_INVALIDARG;
18 case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; 18 case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
19 case SZ_ERROR_DATA: return S_FALSE; 19 case SZ_ERROR_DATA: return S_FALSE;
20 default: break;
20 } 21 }
21 return E_FAIL; 22 return E_FAIL;
22} 23}
diff --git a/CPP/7zip/Compress/LzmsDecoder.cpp b/CPP/7zip/Compress/LzmsDecoder.cpp
index 38c0408..0f6d475 100644
--- a/CPP/7zip/Compress/LzmsDecoder.cpp
+++ b/CPP/7zip/Compress/LzmsDecoder.cpp
@@ -10,6 +10,61 @@
10namespace NCompress { 10namespace NCompress {
11namespace NLzms { 11namespace NLzms {
12 12
13class CBitDecoder
14{
15public:
16 const Byte *_buf;
17 unsigned _bitPos;
18
19 void Init(const Byte *buf, size_t size) throw()
20 {
21 _buf = buf + size;
22 _bitPos = 0;
23 }
24
25 Z7_FORCE_INLINE
26 UInt32 GetValue(unsigned numBits) const
27 {
28 UInt32 v =
29 ((UInt32)_buf[-1] << 16) |
30 ((UInt32)_buf[-2] << 8) |
31 (UInt32)_buf[-3];
32 v >>= 24 - numBits - _bitPos;
33 return v & ((1u << numBits) - 1);
34 }
35
36 Z7_FORCE_INLINE
37 UInt32 GetValue_InHigh32bits()
38 {
39 return GetUi32(_buf - 4) << _bitPos;
40 }
41
42 void MovePos(unsigned numBits)
43 {
44 _bitPos += numBits;
45 _buf -= (_bitPos >> 3);
46 _bitPos &= 7;
47 }
48
49 UInt32 ReadBits32(unsigned numBits)
50 {
51 UInt32 mask = (((UInt32)1 << numBits) - 1);
52 numBits += _bitPos;
53 const Byte *buf = _buf;
54 UInt32 v = GetUi32(buf - 4);
55 if (numBits > 32)
56 {
57 v <<= (numBits - 32);
58 v |= (UInt32)buf[-5] >> (40 - numBits);
59 }
60 else
61 v >>= (32 - numBits);
62 _buf = buf - (numBits >> 3);
63 _bitPos = numBits & 7;
64 return v & mask;
65 }
66};
67
13static UInt32 g_PosBases[k_NumPosSyms /* + 1 */]; 68static UInt32 g_PosBases[k_NumPosSyms /* + 1 */];
14 69
15static Byte g_PosDirectBits[k_NumPosSyms]; 70static Byte g_PosDirectBits[k_NumPosSyms];
@@ -91,7 +146,7 @@ static unsigned GetNumPosSlots(size_t size)
91static const Int32 k_x86_WindowSize = 65535; 146static const Int32 k_x86_WindowSize = 65535;
92static const Int32 k_x86_TransOffset = 1023; 147static const Int32 k_x86_TransOffset = 1023;
93 148
94static const size_t k_x86_HistorySize = (1 << 16); 149static const size_t k_x86_HistorySize = 1 << 16;
95 150
96static void x86_Filter(Byte *data, UInt32 size, Int32 *history) 151static void x86_Filter(Byte *data, UInt32 size, Int32 *history)
97{ 152{
@@ -318,7 +373,7 @@ HRESULT CDecoder::CodeReal(const Byte *in, size_t inSize, Byte *_win, size_t out
318 { 373 {
319 if (_rc.Decode(&mainState, k_NumMainProbs, mainProbs) == 0) 374 if (_rc.Decode(&mainState, k_NumMainProbs, mainProbs) == 0)
320 { 375 {
321 UInt32 number; 376 unsigned number;
322 HUFF_DEC(number, m_LitDecoder) 377 HUFF_DEC(number, m_LitDecoder)
323 LIMIT_CHECK 378 LIMIT_CHECK
324 _win[_pos++] = (Byte)number; 379 _win[_pos++] = (Byte)number;
@@ -330,7 +385,7 @@ HRESULT CDecoder::CodeReal(const Byte *in, size_t inSize, Byte *_win, size_t out
330 385
331 if (_rc.Decode(&lzRepStates[0], k_NumRepProbs, lzRepProbs[0]) == 0) 386 if (_rc.Decode(&lzRepStates[0], k_NumRepProbs, lzRepProbs[0]) == 0)
332 { 387 {
333 UInt32 number; 388 unsigned number;
334 HUFF_DEC(number, m_PosDecoder) 389 HUFF_DEC(number, m_PosDecoder)
335 LIMIT_CHECK 390 LIMIT_CHECK
336 391
@@ -393,7 +448,7 @@ HRESULT CDecoder::CodeReal(const Byte *in, size_t inSize, Byte *_win, size_t out
393 } 448 }
394 } 449 }
395 450
396 UInt32 lenSlot; 451 unsigned lenSlot;
397 HUFF_DEC(lenSlot, m_LenDecoder) 452 HUFF_DEC(lenSlot, m_LenDecoder)
398 LIMIT_CHECK 453 LIMIT_CHECK
399 454
@@ -424,7 +479,7 @@ HRESULT CDecoder::CodeReal(const Byte *in, size_t inSize, Byte *_win, size_t out
424 { 479 {
425 UInt64 distance; 480 UInt64 distance;
426 481
427 UInt32 power; 482 unsigned power;
428 UInt32 distance32; 483 UInt32 distance32;
429 484
430 if (_rc.Decode(&deltaRepStates[0], k_NumRepProbs, deltaRepProbs[0]) == 0) 485 if (_rc.Decode(&deltaRepStates[0], k_NumRepProbs, deltaRepProbs[0]) == 0)
@@ -432,7 +487,7 @@ HRESULT CDecoder::CodeReal(const Byte *in, size_t inSize, Byte *_win, size_t out
432 HUFF_DEC(power, m_PowerDecoder) 487 HUFF_DEC(power, m_PowerDecoder)
433 LIMIT_CHECK 488 LIMIT_CHECK
434 489
435 UInt32 number; 490 unsigned number;
436 HUFF_DEC(number, m_DeltaDecoder) 491 HUFF_DEC(number, m_DeltaDecoder)
437 LIMIT_CHECK 492 LIMIT_CHECK
438 493
@@ -502,13 +557,13 @@ HRESULT CDecoder::CodeReal(const Byte *in, size_t inSize, Byte *_win, size_t out
502 557
503 const UInt32 dist = (distance32 << power); 558 const UInt32 dist = (distance32 << power);
504 559
505 UInt32 lenSlot; 560 unsigned lenSlot;
506 HUFF_DEC(lenSlot, m_LenDecoder) 561 HUFF_DEC(lenSlot, m_LenDecoder)
507 LIMIT_CHECK 562 LIMIT_CHECK
508 563
509 UInt32 len = g_LenBases[lenSlot]; 564 UInt32 len = g_LenBases[lenSlot];
510 { 565 {
511 unsigned numDirectBits = k_LenDirectBits[lenSlot]; 566 const unsigned numDirectBits = k_LenDirectBits[lenSlot];
512 READ_BITS_CHECK(numDirectBits) 567 READ_BITS_CHECK(numDirectBits)
513 len += _bs.ReadBits32(numDirectBits); 568 len += _bs.ReadBits32(numDirectBits);
514 } 569 }
diff --git a/CPP/7zip/Compress/LzmsDecoder.h b/CPP/7zip/Compress/LzmsDecoder.h
index e173c97..bb21262 100644
--- a/CPP/7zip/Compress/LzmsDecoder.h
+++ b/CPP/7zip/Compress/LzmsDecoder.h
@@ -4,74 +4,14 @@
4#ifndef ZIP7_INC_LZMS_DECODER_H 4#ifndef ZIP7_INC_LZMS_DECODER_H
5#define ZIP7_INC_LZMS_DECODER_H 5#define ZIP7_INC_LZMS_DECODER_H
6 6
7// #define SHOW_DEBUG_INFO
8
9#ifdef SHOW_DEBUG_INFO
10#include <stdio.h>
11#define PRF(x) x
12#else
13// #define PRF(x)
14#endif
15
16#include "../../../C/CpuArch.h" 7#include "../../../C/CpuArch.h"
17#include "../../../C/HuffEnc.h" 8#include "../../../C/HuffEnc.h"
18 9
19#include "../../Common/MyBuffer.h"
20#include "../../Common/MyCom.h"
21
22#include "../ICoder.h"
23
24#include "HuffmanDecoder.h" 10#include "HuffmanDecoder.h"
25 11
26namespace NCompress { 12namespace NCompress {
27namespace NLzms { 13namespace NLzms {
28 14
29class CBitDecoder
30{
31public:
32 const Byte *_buf;
33 unsigned _bitPos;
34
35 void Init(const Byte *buf, size_t size) throw()
36 {
37 _buf = buf + size;
38 _bitPos = 0;
39 }
40
41 UInt32 GetValue(unsigned numBits) const
42 {
43 UInt32 v = ((UInt32)_buf[-1] << 16) | ((UInt32)_buf[-2] << 8) | (UInt32)_buf[-3];
44 v >>= (24 - numBits - _bitPos);
45 return v & ((1 << numBits) - 1);
46 }
47
48 void MovePos(unsigned numBits)
49 {
50 _bitPos += numBits;
51 _buf -= (_bitPos >> 3);
52 _bitPos &= 7;
53 }
54
55 UInt32 ReadBits32(unsigned numBits)
56 {
57 UInt32 mask = (((UInt32)1 << numBits) - 1);
58 numBits += _bitPos;
59 const Byte *buf = _buf;
60 UInt32 v = GetUi32(buf - 4);
61 if (numBits > 32)
62 {
63 v <<= (numBits - 32);
64 v |= (UInt32)buf[-5] >> (40 - numBits);
65 }
66 else
67 v >>= (32 - numBits);
68 _buf = buf - (numBits >> 3);
69 _bitPos = numBits & 7;
70 return v & mask;
71 }
72};
73
74
75const unsigned k_NumLitSyms = 256; 15const unsigned k_NumLitSyms = 256;
76const unsigned k_NumLenSyms = 54; 16const unsigned k_NumLenSyms = 54;
77const unsigned k_NumPosSyms = 799; 17const unsigned k_NumPosSyms = 799;
@@ -106,18 +46,17 @@ public:
106 // We need to check that our algorithm is OK, when optimal Huffman tree uses more than 15 levels !!! 46 // We need to check that our algorithm is OK, when optimal Huffman tree uses more than 15 levels !!!
107 Huffman_Generate(Freqs, vals, levels, NumSyms, k_NumHuffmanBits); 47 Huffman_Generate(Freqs, vals, levels, NumSyms, k_NumHuffmanBits);
108 48
109 /*
110 for (UInt32 i = NumSyms; i < m_NumSyms; i++) 49 for (UInt32 i = NumSyms; i < m_NumSyms; i++)
111 levels[i] = 0; 50 levels[i] = 0;
112 */ 51
113 this->BuildFull(levels, NumSyms); 52 this->Build(levels, /* NumSyms, */ NHuffman::k_BuildMode_Full);
114 } 53 }
115 54
116 void Rebuild() throw() 55 void Rebuild() throw()
117 { 56 {
118 Generate(); 57 Generate();
119 RebuildRem = m_RebuildFreq; 58 RebuildRem = m_RebuildFreq;
120 UInt32 num = NumSyms; 59 const UInt32 num = NumSyms;
121 for (UInt32 i = 0; i < num; i++) 60 for (UInt32 i = 0; i < num; i++)
122 Freqs[i] = (Freqs[i] >> 1) + 1; 61 Freqs[i] = (Freqs[i] >> 1) + 1;
123 } 62 }
@@ -197,7 +136,7 @@ struct CRangeDecoder
197 CProbEntry *entry = &probs[st]; 136 CProbEntry *entry = &probs[st];
198 st = (st << 1) & (numStates - 1); 137 st = (st << 1) & (numStates - 1);
199 138
200 UInt32 prob = entry->GetProb(); 139 const UInt32 prob = entry->GetProb();
201 140
202 if (range <= 0xFFFF) 141 if (range <= 0xFFFF)
203 { 142 {
@@ -208,7 +147,7 @@ struct CRangeDecoder
208 cur += 2; 147 cur += 2;
209 } 148 }
210 149
211 UInt32 bound = (range >> k_NumProbBits) * prob; 150 const UInt32 bound = (range >> k_NumProbBits) * prob;
212 151
213 if (code < bound) 152 if (code < bound)
214 { 153 {
@@ -232,7 +171,6 @@ struct CRangeDecoder
232class CDecoder 171class CDecoder
233{ 172{
234 // CRangeDecoder _rc; 173 // CRangeDecoder _rc;
235 // CBitDecoder _bs;
236 size_t _pos; 174 size_t _pos;
237 175
238 UInt32 _reps[k_NumReps + 1]; 176 UInt32 _reps[k_NumReps + 1];
diff --git a/CPP/7zip/Compress/Lzx.h b/CPP/7zip/Compress/Lzx.h
index 2532088..39fca0c 100644
--- a/CPP/7zip/Compress/Lzx.h
+++ b/CPP/7zip/Compress/Lzx.h
@@ -52,7 +52,9 @@ const unsigned kNumDictBits_Max = 21;
52const UInt32 kDictSize_Max = (UInt32)1 << kNumDictBits_Max; 52const UInt32 kDictSize_Max = (UInt32)1 << kNumDictBits_Max;
53 53
54const unsigned kNumLinearPosSlotBits = 17; 54const unsigned kNumLinearPosSlotBits = 17;
55const unsigned kNumPowerPosSlots = 38; 55// const unsigned kNumPowerPosSlots = 38;
56// const unsigned kNumPowerPosSlots = (kNumLinearPosSlotBits + 1) * 2; // non-including two first linear slots.
57const unsigned kNumPowerPosSlots = (kNumLinearPosSlotBits + 2) * 2; // including two first linear slots.
56 58
57}} 59}}
58 60
diff --git a/CPP/7zip/Compress/LzxDecoder.cpp b/CPP/7zip/Compress/LzxDecoder.cpp
index b50d863..a7b9986 100644
--- a/CPP/7zip/Compress/LzxDecoder.cpp
+++ b/CPP/7zip/Compress/LzxDecoder.cpp
@@ -3,6 +3,7 @@
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include <string.h> 5#include <string.h>
6// #include <stdio.h>
6 7
7// #define SHOW_DEBUG_INFO 8// #define SHOW_DEBUG_INFO
8 9
@@ -14,448 +15,1433 @@
14#endif 15#endif
15 16
16#include "../../../C/Alloc.h" 17#include "../../../C/Alloc.h"
18#include "../../../C/RotateDefs.h"
19#include "../../../C/CpuArch.h"
17 20
18#include "LzxDecoder.h" 21#include "LzxDecoder.h"
19 22
23
24#ifdef MY_CPU_X86_OR_AMD64
25#if defined(MY_CPU_AMD64) \
26 || defined(__SSE2__) \
27 || defined(_M_IX86_FP) && (_M_IX86_FP >= 2) \
28 || 0 && defined(_MSC_VER) && (_MSC_VER >= 1400) // set (1 &&) for debug
29
30#if defined(__clang__) && (__clang_major__ >= 2) \
31 || defined(__GNUC__) && (__GNUC__ >= 4) \
32 || defined(_MSC_VER) && (_MSC_VER >= 1400)
33#define Z7_LZX_X86_FILTER_USE_SSE2
34#endif
35#endif
36#endif
37
38
39#ifdef Z7_LZX_X86_FILTER_USE_SSE2
40// #ifdef MY_CPU_X86_OR_AMD64
41#include <emmintrin.h> // SSE2
42// #endif
43 #if defined(__clang__) || defined(__GNUC__)
44 typedef int ctz_type;
45 #define MY_CTZ(dest, mask) dest = __builtin_ctz((UInt32)(mask))
46 #else // #if defined(_MSC_VER)
47 #if (_MSC_VER >= 1600)
48 // #include <intrin.h>
49 #endif
50 typedef unsigned long ctz_type;
51 #define MY_CTZ(dest, mask) _BitScanForward(&dest, (mask));
52 #endif // _MSC_VER
53#endif
54
55// when window buffer is filled, we must wrap position to zero,
56// and we want to wrap at same points where original-lzx must wrap.
57// But the wrapping is possible in point where chunk is finished.
58// Usually (chunk_size == 32KB), but (chunk_size != 32KB) also is allowed.
59// So we don't use additional buffer space over required (winSize).
60// And we can't use large overwrite after (len) in CopyLzMatch().
61// But we are allowed to write 3 bytes after (len), because
62// (delta <= _winSize - 3).
63
64// #define k_Lz_OverwriteSize 0 // for debug : to disable overwrite
65#define k_Lz_OverwriteSize 3 // = kNumReps
66#if k_Lz_OverwriteSize > 0
67// (k_Lz_OutBufSize_Add >= k_Lz_OverwriteSize) is required
68// we use value 4 to simplify memset() code.
69#define k_Lz_OutBufSize_Add (k_Lz_OverwriteSize + 1) // == 4
70#else
71#define k_Lz_OutBufSize_Add 0
72#endif
73
74// (len != 0)
75// (0 < delta <= _winSize - 3)
76Z7_FORCE_INLINE
77void CopyLzMatch(Byte *dest, const Byte *src, UInt32 len, UInt32 delta)
78{
79 if (delta >= 4)
80 {
81#if k_Lz_OverwriteSize >= 3
82 // optimized code with overwrite to reduce the number of branches
83 #ifdef MY_CPU_LE_UNALIGN
84 *(UInt32 *)(void *)(dest) = *(const UInt32 *)(const void *)(src);
85 #else
86 dest[0] = src[0];
87 dest[1] = src[1];
88 dest[2] = src[2];
89 dest[3] = src[3];
90 #endif
91 len--;
92 src++;
93 dest++;
94 {
95#else
96 // no overwrite in out buffer
97 dest[0] = src[0];
98 {
99 const unsigned m = (unsigned)len & 1;
100 src += m;
101 dest += m;
102 }
103 if (len &= ~(unsigned)1)
104 {
105 dest[0] = src[0];
106 dest[1] = src[1];
107#endif
108 // len == 0 is allowed here
109 {
110 const unsigned m = (unsigned)len & 3;
111 src += m;
112 dest += m;
113 }
114 if (len &= ~(unsigned)3)
115 {
116#ifdef MY_CPU_LE_UNALIGN
117 #if 1
118 *(UInt32 *)(void *)(dest) = *(const UInt32 *)(const void *)(src);
119 {
120 const unsigned m = (unsigned)len & 7;
121 dest += m;
122 src += m;
123 }
124 if (len &= ~(unsigned)7)
125 do
126 {
127 *(UInt32 *)(void *)(dest ) = *(const UInt32 *)(const void *)(src);
128 *(UInt32 *)(void *)(dest + 4) = *(const UInt32 *)(const void *)(src + 4);
129 src += 8;
130 dest += 8;
131 }
132 while (len -= 8);
133 #else
134 // gcc-11 -O3 for x64 generates incorrect code here
135 do
136 {
137 *(UInt32 *)(void *)(dest) = *(const UInt32 *)(const void *)(src);
138 src += 4;
139 dest += 4;
140 }
141 while (len -= 4);
142 #endif
143#else
144 do
145 {
146 const Byte b0 = src[0];
147 const Byte b1 = src[1];
148 dest[0] = b0;
149 dest[1] = b1;
150 const Byte b2 = src[2];
151 const Byte b3 = src[3];
152 dest[2] = b2;
153 dest[3] = b3;
154 src += 4;
155 dest += 4;
156 }
157 while (len -= 4);
158#endif
159 }
160 }
161 }
162 else // (delta < 4)
163 {
164 const unsigned b0 = *src;
165 *dest = (Byte)b0;
166 if (len >= 2)
167 {
168 if (delta < 2)
169 {
170 dest += (unsigned)len & 1;
171 dest[0] = (Byte)b0;
172 dest[1] = (Byte)b0;
173 dest += (unsigned)len & 2;
174 if (len &= ~(unsigned)3)
175 {
176#ifdef MY_CPU_LE_UNALIGN
177 #ifdef MY_CPU_64BIT
178 const UInt64 a = (UInt64)b0 * 0x101010101010101;
179 *(UInt32 *)(void *)dest = (UInt32)a;
180 dest += (unsigned)len & 7;
181 if (len &= ~(unsigned)7)
182 {
183 // *(UInt64 *)(void *)dest = a;
184 // dest += 8;
185 // len -= 8;
186 // if (len)
187 {
188 // const ptrdiff_t delta = (ptrdiff_t)dest & 7;
189 // dest -= delta;
190 do
191 {
192 *(UInt64 *)(void *)dest = a;
193 dest += 8;
194 }
195 while (len -= 8);
196 // dest += delta - 8;
197 // *(UInt64 *)(void *)dest = a;
198 }
199 }
200 #else
201 const UInt32 a = (UInt32)b0 * 0x1010101;
202 do
203 {
204 *(UInt32 *)(void *)dest = a;
205 dest += 4;
206 }
207 while (len -= 4);
208 #endif
209#else
210 do
211 {
212 dest[0] = (Byte)b0;
213 dest[1] = (Byte)b0;
214 dest[2] = (Byte)b0;
215 dest[3] = (Byte)b0;
216 dest += 4;
217 }
218 while (len -= 4);
219#endif
220 }
221 }
222 else if (delta == 2)
223 {
224 const unsigned m = (unsigned)len & 1;
225 len &= ~(unsigned)1;
226 src += m;
227 dest += m;
228 {
229 const Byte a0 = src[0];
230 const Byte a1 = src[1];
231 do
232 {
233 dest[0] = a0;
234 dest[1] = a1;
235 dest += 2;
236 }
237 while (len -= 2);
238 }
239 }
240 else /* if (delta == 3) */
241 {
242 const unsigned b1 = src[1];
243 dest[1] = (Byte)b1;
244 if (len -= 2)
245 {
246 const unsigned b2 = src[2];
247 dest += 2;
248 do
249 {
250 dest[0] = (Byte)b2; if (--len == 0) break;
251 dest[1] = (Byte)b0; if (--len == 0) break;
252 dest[2] = (Byte)b1;
253 dest += 3;
254 }
255 while (--len);
256 }
257 }
258 }
259 }
260}
261
262// #define Z7_LZX_SHOW_STAT
263#ifdef Z7_LZX_SHOW_STAT
264#include <stdio.h>
265#endif
266
20namespace NCompress { 267namespace NCompress {
21namespace NLzx { 268namespace NLzx {
22 269
23static void x86_Filter(Byte *data, UInt32 size, UInt32 processedSize, UInt32 translationSize) 270// #define Z7_LZX_SHOW_STAT
271#ifdef Z7_LZX_SHOW_STAT
272static UInt32 g_stats_Num_x86[3];
273static UInt32 g_stats_NumTables;
274static UInt32 g_stats_NumLits;
275static UInt32 g_stats_NumAlign;
276static UInt32 g_stats_main[kMainTableSize];
277static UInt32 g_stats_len[kNumLenSymbols];
278static UInt32 g_stats_main_levels[kNumHuffmanBits + 1];
279static UInt32 g_stats_len_levels[kNumHuffmanBits + 1];
280#define UPDATE_STAT(a) a
281static void PrintVal(UInt32 v)
282{
283 printf("\n : %9u", v);
284}
285static void PrintStat(const char *name, const UInt32 *a, size_t num)
286{
287 printf("\n\n==== %s:", name);
288 UInt32 sum = 0;
289 size_t i;
290 for (i = 0; i < num; i++)
291 sum += a[i];
292 PrintVal(sum);
293 if (sum != 0)
294 {
295 for (i = 0; i < num; i++)
296 {
297 if (i % 8 == 0)
298 printf("\n");
299 printf("\n%3x : %9u : %5.2f", (unsigned)i, (unsigned)a[i], (double)a[i] * 100 / sum);
300 }
301 }
302 printf("\n");
303}
304
305static struct CStat
24{ 306{
25 const UInt32 kResidue = 10; 307 ~CStat()
308 {
309 PrintStat("x86_filter", g_stats_Num_x86, Z7_ARRAY_SIZE(g_stats_Num_x86));
310 printf("\nTables:"); PrintVal(g_stats_NumTables);
311 printf("\nLits:"); PrintVal(g_stats_NumLits);
312 printf("\nAlign:"); PrintVal(g_stats_NumAlign);
313 PrintStat("Main", g_stats_main, Z7_ARRAY_SIZE(g_stats_main));
314 PrintStat("Len", g_stats_len, Z7_ARRAY_SIZE(g_stats_len));
315 PrintStat("Main Levels", g_stats_main_levels, Z7_ARRAY_SIZE(g_stats_main_levels));
316 PrintStat("Len Levels", g_stats_len_levels, Z7_ARRAY_SIZE(g_stats_len_levels));
317 }
318} g_stat;
319#else
320#define UPDATE_STAT(a)
321#endif
322
323
324
325/*
3263 p015 : ivb- : or r32,r32 / add r32,r32
3274 p0156 : hsw+
3285 p0156b: adl+
3292 p0_5 : ivb- : shl r32,i8
3302 p0__6 : hsw+
3311 p5 : ivb- : jb
3322 p0__6 : hsw+
3332 p0_5 : wsm- : SSE2 : pcmpeqb : _mm_cmpeq_epi8
3342 p_15 : snb-bdw
3352 p01 : skl+
3361 p0 : SSE2 : pmovmskb : _mm_movemask_epi8
337*/
338/*
339 v24.00: the code was fixed for more compatibility with original-ms-cab-decoder.
340 for ((Int32)translationSize >= 0) : LZX specification shows the code with signed Int32.
341 for ((Int32)translationSize < 0) : no specification for that case, but we support that case.
342 We suppose our code now is compatible with original-ms-cab-decoder.
343
344 Starting byte of data stream (real_pos == 0) is special corner case,
345 where we don't need any conversion (as in original-ms-cab-decoder).
346 Our optimization: we use unsigned (UInt32 pos) (pos = -1 - real_pos).
347 So (pos) is always negative: ((Int32)pos < 0).
348 It allows us to use simple comparison (v > pos) instead of more complex comparisons.
349*/
350// (p) will point 5 bytes after 0xe8 byte:
351// pos == -1 - (p - 5 - data_start) == 4 + data_start - p
352// (FILTER_PROCESSED_SIZE_DELTA == 4) is optimized value for better speed in some compilers:
353#define FILTER_PROCESSED_SIZE_DELTA 4
354
355#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_OR_ARM64)
356 // optimized branch:
357 // size_t must be at least 32-bit for this branch.
358 #if 1 // use 1 for simpler code
359 // use integer (low 32 bits of pointer) instead of pointer
360 #define X86_FILTER_PREPARE processedSize4 = (UInt32)(size_t)(ptrdiff_t)data + \
361 (UInt32)(4 - FILTER_PROCESSED_SIZE_DELTA) - processedSize4;
362 #define X86_FILTER_CALC_pos(p) const UInt32 pos = processedSize4 - (UInt32)(size_t)(ptrdiff_t)p;
363 #else
364 // note: (dataStart) pointer can point out of array ranges:
365 #define X86_FILTER_PREPARE const Byte *dataStart = data + \
366 (4 - FILTER_PROCESSED_SIZE_DELTA) - processedSize4;
367 #define X86_FILTER_CALC_pos(p) const UInt32 pos = (UInt32)(size_t)(dataStart - p);
368 #endif
369#else
370 // non-optimized branch for unusual platforms (16-bit size_t or unusual size_t):
371 #define X86_FILTER_PREPARE processedSize4 = \
372 (UInt32)(4 - FILTER_PROCESSED_SIZE_DELTA) - processedSize4;
373 #define X86_FILTER_CALC_pos(p) const UInt32 pos = processedSize4 - (UInt32)(size_t)(p - data);
374#endif
375
376#define X86_TRANSLATE_PRE(p) \
377 UInt32 v = GetUi32((p) - 4);
378
379#define X86_TRANSLATE_POST(p) \
380 { \
381 X86_FILTER_CALC_pos(p) \
382 if (v < translationSize) { \
383 UPDATE_STAT(g_stats_Num_x86[0]++;) \
384 v += pos + 1; \
385 SetUi32((p) - 4, v) \
386 } \
387 else if (v > pos) { \
388 UPDATE_STAT(g_stats_Num_x86[1]++;) \
389 v += translationSize; \
390 SetUi32((p) - 4, v) \
391 } else { UPDATE_STAT(g_stats_Num_x86[2]++;) } \
392 }
393
394
395/*
396 if ( defined(Z7_LZX_X86_FILTER_USE_SSE2)
397 && defined(Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED))
398 the function can read up to aligned_for_32_up_from(size) bytes in (data).
399*/
400// processedSize < (1 << 30)
401Z7_NO_INLINE
402static void x86_Filter4(Byte *data, size_t size, UInt32 processedSize4, UInt32 translationSize)
403{
404 const size_t kResidue = 10;
26 if (size <= kResidue) 405 if (size <= kResidue)
27 return; 406 return;
28 size -= kResidue; 407 Byte * const lim = data + size - kResidue + 4;
29 408 const Byte save = lim[0];
30 const Byte save = data[(size_t)size + 4]; 409 lim[0] = 0xe8;
31 data[(size_t)size + 4] = 0xE8; 410 X86_FILTER_PREPARE
32 411 Byte *p = data;
33 for (UInt32 i = 0;;) 412
413#define FILTER_RETURN_IF_LIM(_p_) if (_p_ > lim) { lim[0] = save; return; }
414
415#ifdef Z7_LZX_X86_FILTER_USE_SSE2
416
417// sse2-aligned/sse2-unaligned provide same speed on real data.
418// but the code is smaller for sse2-unaligned version.
419// for debug : define it to get alternative version with aligned 128-bit reads:
420// #define Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED
421
422#define FILTER_MASK_INT UInt32
423#define FILTER_NUM_VECTORS_IN_CHUNK 2
424#define FILTER_CHUNK_BYTES_OFFSET (16 * FILTER_NUM_VECTORS_IN_CHUNK - 5)
425
426#ifdef Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED
427 // aligned version doesn't uses additional space if buf size is aligned for 32
428 #define k_Filter_OutBufSize_Add 0
429 #define k_Filter_OutBufSize_AlignMask (16 * FILTER_NUM_VECTORS_IN_CHUNK - 1)
430 #define FILTER_LOAD_128(p) _mm_load_si128 ((const __m128i *)(const void *)(p))
431#else
432 #define k_Filter_OutBufSize_Add (16 * FILTER_NUM_VECTORS_IN_CHUNK)
433 #define k_Filter_OutBufSize_AlignMask 0
434 #define FILTER_LOAD_128(p) _mm_loadu_si128((const __m128i *)(const void *)(p))
435#endif
436
437#define GET_E8_MASK(dest, dest1, p) \
438{ \
439 __m128i v0 = FILTER_LOAD_128(p); \
440 __m128i v1 = FILTER_LOAD_128(p + 16); \
441 p += 16 * FILTER_NUM_VECTORS_IN_CHUNK; \
442 v0 = _mm_cmpeq_epi8(v0, k_e8_Vector); \
443 v1 = _mm_cmpeq_epi8(v1, k_e8_Vector); \
444 dest = (unsigned)_mm_movemask_epi8(v0); \
445 dest1 = (unsigned)_mm_movemask_epi8(v1); \
446}
447
448 const __m128i k_e8_Vector = _mm_set1_epi32((Int32)(UInt32)0xe8e8e8e8);
449 for (;;)
34 { 450 {
35 Byte *p = data + i; 451 // for debug: define it for smaller code:
452 // #define Z7_LZX_X86_FILTER_CALC_IN_LOOP
453 // without Z7_LZX_X86_FILTER_CALC_IN_LOOP, we can get faster and simpler loop
454 FILTER_MASK_INT mask;
455 {
456 FILTER_MASK_INT mask1;
457 do
458 {
459 GET_E8_MASK(mask, mask1, p)
460 #ifndef Z7_LZX_X86_FILTER_CALC_IN_LOOP
461 mask += mask1;
462 #else
463 mask |= mask1 << 16;
464 #endif
465 }
466 while (!mask);
467
468 #ifndef Z7_LZX_X86_FILTER_CALC_IN_LOOP
469 mask -= mask1;
470 mask |= mask1 << 16;
471 #endif
472 }
473
474#ifdef Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED
36 for (;;) 475 for (;;)
37 { 476 {
38 if (*p++ == 0xE8) break; 477 ctz_type index;
39 if (*p++ == 0xE8) break; 478 typedef
40 if (*p++ == 0xE8) break; 479 #ifdef MY_CPU_64BIT
41 if (*p++ == 0xE8) break; 480 UInt64
481 #else
482 UInt32
483 #endif
484 SUPER_MASK_INT;
485 SUPER_MASK_INT superMask;
486 {
487 MY_CTZ(index, mask);
488 Byte *p2 = p - FILTER_CHUNK_BYTES_OFFSET + (unsigned)index;
489 X86_TRANSLATE_PRE(p2)
490 superMask = ~(SUPER_MASK_INT)0x1f << index;
491 FILTER_RETURN_IF_LIM(p2)
492 X86_TRANSLATE_POST(p2)
493 mask &= (UInt32)superMask;
494 }
495 if (mask)
496 continue;
497 if (index <= FILTER_CHUNK_BYTES_OFFSET)
498 break;
499 {
500 FILTER_MASK_INT mask1;
501 GET_E8_MASK(mask, mask1, p)
502 mask &=
503 #ifdef MY_CPU_64BIT
504 (UInt32)(superMask >> 32);
505 #else
506 ((FILTER_MASK_INT)0 - 1) << ((int)index - FILTER_CHUNK_BYTES_OFFSET);
507 #endif
508 mask |= mask1 << 16;
509 }
510 if (!mask)
511 break;
42 } 512 }
43 513#else // ! Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED
44 i = (UInt32)(p - data);
45
46 if (i > size)
47 break;
48 { 514 {
49 Int32 v = (Int32)GetUi32(p); 515 // we use simplest version without loop:
50 Int32 pos = (Int32)((Int32)1 - (Int32)(processedSize + i)); 516 // for (;;)
51 i += 4;
52 if (v >= pos && v < (Int32)translationSize)
53 { 517 {
54 v += (v >= 0 ? pos : (Int32)translationSize); 518 ctz_type index;
55 SetUi32(p, (UInt32)v) 519 MY_CTZ(index, mask);
520 /*
521 printf("\np=%p, mask=%8x, index = %2d, p + index = %x\n",
522 (p - 16 * FILTER_NUM_VECTORS_IN_CHUNK), (unsigned)mask,
523 (unsigned)index, (unsigned)((unsigned)(ptrdiff_t)(p - 16 * FILTER_NUM_VECTORS_IN_CHUNK) + index));
524 */
525 p += (size_t)(unsigned)index - FILTER_CHUNK_BYTES_OFFSET;
526 FILTER_RETURN_IF_LIM(p)
527 // mask &= ~(FILTER_MASK_INT)0x1f << index; mask >>= index;
528 X86_TRANSLATE_PRE(p)
529 X86_TRANSLATE_POST(p)
530 // if (!mask) break; // p += 16 * FILTER_NUM_VECTORS_IN_CHUNK;
56 } 531 }
57 } 532 }
533#endif // ! Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED
58 } 534 }
59 535
60 data[(size_t)size + 4] = save; 536#else // ! Z7_LZX_X86_FILTER_USE_SSE2
537
538#define k_Filter_OutBufSize_Add 0
539#define k_Filter_OutBufSize_AlignMask 0
540
541
542 for (;;)
543 {
544 for (;;)
545 {
546 if (p[0] == 0xe8) { p += 5; break; }
547 if (p[1] == 0xe8) { p += 6; break; }
548 if (p[2] == 0xe8) { p += 7; break; }
549 p += 4;
550 if (p[-1] == 0xe8) { p += 4; break; }
551 }
552 FILTER_RETURN_IF_LIM(p)
553 X86_TRANSLATE_PRE(p)
554 X86_TRANSLATE_POST(p)
555 }
556
557#endif // ! Z7_LZX_X86_FILTER_USE_SSE2
61} 558}
62 559
63 560
64CDecoder::CDecoder(bool wimMode): 561CDecoder::CDecoder() throw():
65 _win(NULL), 562 _win(NULL),
563 _isUncompressedBlock(false),
66 _skipByte(false), 564 _skipByte(false),
67 _unpackBlockSize(0),
68 KeepHistoryForNext(true),
69 NeedAlloc(true),
70 _keepHistory(false), 565 _keepHistory(false),
71 _wimMode(wimMode), 566 _keepHistoryForNext(true),
567 _needAlloc(true),
568 _wimMode(false),
72 _numDictBits(15), 569 _numDictBits(15),
73 _x86_buf(NULL), 570 _unpackBlockSize(0),
74 _x86_translationSize(0), 571 _x86_translationSize(0),
572 _x86_buf(NULL),
75 _unpackedData(NULL) 573 _unpackedData(NULL)
76{ 574{
575 {
576 // it's better to get empty virtual entries, if mispredicted value can be used:
577 memset(_reps, 0, kPosSlotOffset * sizeof(_reps[0]));
578 memset(_extra, 0, kPosSlotOffset);
579#define SET_NUM_BITS(i) i // #define NUM_BITS_DELTA 31
580 _extra[kPosSlotOffset + 0] = SET_NUM_BITS(0);
581 _extra[kPosSlotOffset + 1] = SET_NUM_BITS(0);
582 // reps[0] = 0 - (kNumReps - 1);
583 // reps[1] = 1 - (kNumReps - 1);
584 UInt32 a = 2 - (kNumReps - 1);
585 UInt32 delta = 1;
586 unsigned i;
587 for (i = 0; i < kNumLinearPosSlotBits; i++)
588 {
589 _extra[(size_t)i * 2 + 2 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));
590 _extra[(size_t)i * 2 + 3 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));
591 _reps [(size_t)i * 2 + 2 + kPosSlotOffset] = a; a += delta;
592 _reps [(size_t)i * 2 + 3 + kPosSlotOffset] = a; a += delta;
593 delta += delta;
594 }
595 for (i = kNumLinearPosSlotBits * 2 + 2; i < kNumPosSlots; i++)
596 {
597 _extra[(size_t)i + kPosSlotOffset] = SET_NUM_BITS(kNumLinearPosSlotBits);
598 _reps [(size_t)i + kPosSlotOffset] = a;
599 a += (UInt32)1 << kNumLinearPosSlotBits;
600 }
601 }
77} 602}
78 603
79CDecoder::~CDecoder() 604CDecoder::~CDecoder() throw()
80{ 605{
81 if (NeedAlloc) 606 if (_needAlloc)
82 ::MidFree(_win); 607 // BigFree
83 ::MidFree(_x86_buf); 608 z7_AlignedFree
609 (_win);
610 z7_AlignedFree(_x86_buf);
84} 611}
85 612
86HRESULT CDecoder::Flush() 613HRESULT CDecoder::Flush() throw()
87{ 614{
615 // UInt32 t = _x86_processedSize; for (int y = 0; y < 50; y++) { _x86_processedSize = t; // benchmark: (branch predicted)
88 if (_x86_translationSize != 0) 616 if (_x86_translationSize != 0)
89 { 617 {
90 Byte *destData = _win + _writePos; 618 Byte *destData = _win + _writePos;
91 const UInt32 curSize = _pos - _writePos; 619 const UInt32 curSize = _pos - _writePos;
92 if (KeepHistoryForNext) 620 if (_keepHistoryForNext)
93 { 621 {
622 const size_t kChunkSize = (size_t)1 << 15;
623 if (curSize > kChunkSize)
624 return E_NOTIMPL;
94 if (!_x86_buf) 625 if (!_x86_buf)
95 { 626 {
96 // we must change it to support another chunk sizes 627 // (kChunkSize % 32 == 0) is required in some cases, because
97 const size_t kChunkSize = (size_t)1 << 15; 628 // the filter can read data by 32-bytes chunks in some cases.
98 if (curSize > kChunkSize) 629 // if (chunk_size > (1 << 15)) is possible, then we must the code:
99 return E_NOTIMPL; 630 const size_t kAllocSize = kChunkSize + k_Filter_OutBufSize_Add;
100 _x86_buf = (Byte *)::MidAlloc(kChunkSize); 631 _x86_buf = (Byte *)z7_AlignedAlloc(kAllocSize);
101 if (!_x86_buf) 632 if (!_x86_buf)
102 return E_OUTOFMEMORY; 633 return E_OUTOFMEMORY;
634 #if 0 != k_Filter_OutBufSize_Add || \
635 0 != k_Filter_OutBufSize_AlignMask
636 // x86_Filter4() can read after curSize.
637 // So we set all data to zero to prevent reading of uninitialized data:
638 memset(_x86_buf, 0, kAllocSize); // optional
639 #endif
103 } 640 }
641 // for (int yy = 0; yy < 1; yy++) // for debug
104 memcpy(_x86_buf, destData, curSize); 642 memcpy(_x86_buf, destData, curSize);
105 _unpackedData = _x86_buf; 643 _unpackedData = _x86_buf;
106 destData = _x86_buf; 644 destData = _x86_buf;
107 } 645 }
108 x86_Filter(destData, (UInt32)curSize, _x86_processedSize, _x86_translationSize); 646 else
647 {
648 // x86_Filter4() can overread after (curSize),
649 // so we can do memset() after (curSize):
650 // k_Filter_OutBufSize_AlignMask also can be used
651 // if (!_overDict) memset(destData + curSize, 0, k_Filter_OutBufSize_Add);
652 }
653 x86_Filter4(destData, curSize, _x86_processedSize - FILTER_PROCESSED_SIZE_DELTA, _x86_translationSize);
109 _x86_processedSize += (UInt32)curSize; 654 _x86_processedSize += (UInt32)curSize;
110 if (_x86_processedSize >= ((UInt32)1 << 30)) 655 if (_x86_processedSize >= ((UInt32)1 << 30))
111 _x86_translationSize = 0; 656 _x86_translationSize = 0;
112 } 657 }
113 658 // }
114 return S_OK; 659 return S_OK;
115} 660}
116 661
117 662
118UInt32 CDecoder::ReadBits(unsigned numBits) { return _bitStream.ReadBitsSmall(numBits); } 663
664// (NUM_DELTA_BYTES == 2) reduces the code in main loop.
665#if 1
666 #define NUM_DELTA_BYTES 2
667#else
668 #define NUM_DELTA_BYTES 0
669#endif
670
671#define NUM_DELTA_BIT_OFFSET_BITS (NUM_DELTA_BYTES * 8)
672
673#if NUM_DELTA_BIT_OFFSET_BITS > 0
674 #define DECODE_ERROR_CODE 0
675 #define IS_OVERFLOW_bitOffset(bo) ((bo) >= 0)
676 // ( >= 0) comparison after bitOffset change gives simpler commands than ( > 0) comparison
677#else
678 #define DECODE_ERROR_CODE 1
679 #define IS_OVERFLOW_bitOffset(bo) ((bo) > 0)
680#endif
681
682// (numBits != 0)
683#define GET_VAL_BASE(numBits) (_value >> (32 - (numBits)))
684
685#define Z7_LZX_HUFF_DECODE( sym, huff, kNumTableBits, move_pos_op, check_op, error_op) \
686 Z7_HUFF_DECODE_VAL_IN_HIGH32(sym, huff, kNumHuffmanBits, kNumTableBits, \
687 _value, check_op, error_op, move_pos_op, NORMALIZE, bs)
688
689#define Z7_LZX_HUFF_DECODE_CHECK_YES(sym, huff, kNumTableBits, move_pos_op) \
690 Z7_LZX_HUFF_DECODE( sym, huff, kNumTableBits, move_pos_op, \
691 Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES, { return DECODE_ERROR_CODE; })
692
693#define Z7_LZX_HUFF_DECODE_CHECK_NO( sym, huff, kNumTableBits, move_pos_op) \
694 Z7_LZX_HUFF_DECODE( sym, huff, kNumTableBits, move_pos_op, \
695 Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO, {})
696
697#define NORMALIZE \
698{ \
699 const Byte *ptr = _buf + (_bitOffset >> 4) * 2; \
700 /* _value = (((UInt32)GetUi16(ptr) << 16) | GetUi16(ptr + 2)) << (_bitOffset & 15); */ \
701 const UInt32 v = GetUi32(ptr); \
702 _value = rotlFixed (v, ((int)_bitOffset & 15) + 16); \
703}
704
705#define MOVE_POS(bs, numBits) \
706{ \
707 _bitOffset += numBits; \
708}
709
710#define MOVE_POS_STAT(bs, numBits) \
711{ \
712 UPDATE_STAT(g_stats_len_levels[numBits]++;) \
713 MOVE_POS(bs, numBits); \
714}
715
716#define MOVE_POS_CHECK(bs, numBits) \
717{ \
718 if (IS_OVERFLOW_bitOffset(_bitOffset += numBits)) return DECODE_ERROR_CODE; \
719}
720
721#define MOVE_POS_CHECK_STAT(bs, numBits) \
722{ \
723 UPDATE_STAT(g_stats_main_levels[numBits]++;) \
724 MOVE_POS_CHECK(bs, numBits) \
725}
726
727
728// (numBits == 0) is supported
729
730#ifdef Z7_HUFF_USE_64BIT_LIMIT
731
732#define MACRO_ReadBitsBig_pre(numBits) \
733{ \
734 _bitOffset += (numBits); \
735 _value >>= 32 - (numBits); \
736}
737
738#else
739
740#define MACRO_ReadBitsBig_pre(numBits) \
741{ \
742 _bitOffset += (numBits); \
743 _value = (UInt32)((UInt32)_value >> 1 >> (31 ^ (numBits))); \
744}
745
746#endif
747
748
749#define MACRO_ReadBitsBig_add(dest) \
750 { dest += (UInt32)_value; }
751
752#define MACRO_ReadBitsBig_add3(dest) \
753 { dest += (UInt32)(_value) << 3; }
754
755
756// (numBits != 0)
757#define MACRO_ReadBits_NonZero(val, numBits) \
758{ \
759 val = (UInt32)(_value >> (32 - (numBits))); \
760 MOVE_POS(bs, numBits); \
761 NORMALIZE \
762}
763
764
765struct CBitDecoder
766{
767 ptrdiff_t _bitOffset;
768 const Byte *_buf;
769
770 Z7_FORCE_INLINE
771 UInt32 GetVal() const
772 {
773 const Byte *ptr = _buf + (_bitOffset >> 4) * 2;
774 const UInt32 v = GetUi32(ptr);
775 return rotlFixed (v, ((int)_bitOffset & 15) + 16);
776 }
777
778 Z7_FORCE_INLINE
779 bool IsOverRead() const
780 {
781 return _bitOffset > (int)(0 - NUM_DELTA_BIT_OFFSET_BITS);
782 }
783
784
785 Z7_FORCE_INLINE
786 bool WasBitStreamFinishedOK() const
787 {
788 // we check that all 0-15 unused bits are zeros:
789 if (_bitOffset == 0 - NUM_DELTA_BIT_OFFSET_BITS)
790 return true;
791 if ((_bitOffset + NUM_DELTA_BIT_OFFSET_BITS + 15) & ~(ptrdiff_t)15)
792 return false;
793 const Byte *ptr = _buf - NUM_DELTA_BYTES - 2;
794 if ((UInt16)(GetUi16(ptr) << (_bitOffset & 15)))
795 return false;
796 return true;
797 }
798
799 // (numBits != 0)
800 Z7_FORCE_INLINE
801 UInt32 ReadBits_NonZero(unsigned numBits) throw()
802 {
803 const UInt32 val = GetVal() >> (32 - numBits);
804 _bitOffset += numBits;
805 return val;
806 }
807};
808
809
810class CBitByteDecoder: public CBitDecoder
811{
812 size_t _size;
813public:
814
815 Z7_FORCE_INLINE
816 void Init_ByteMode(const Byte *data, size_t size)
817 {
818 _buf = data;
819 _size = size;
820 }
821
822 Z7_FORCE_INLINE
823 void Init_BitMode(const Byte *data, size_t size)
824 {
825 _size = size & 1;
826 size &= ~(size_t)1;
827 _buf = data + size + NUM_DELTA_BYTES;
828 _bitOffset = 0 - (ptrdiff_t)(size * 8) - NUM_DELTA_BIT_OFFSET_BITS;
829 }
830
831 Z7_FORCE_INLINE
832 void Switch_To_BitMode()
833 {
834 Init_BitMode(_buf, _size);
835 }
836
837 Z7_FORCE_INLINE
838 bool Switch_To_ByteMode()
839 {
840 /* here we check that unused bits in high 16-bits word are zeros.
841 If high word is full (all 16-bits are unused),
842 we check that all 16-bits are zeros.
843 So we check and skip (1-16 bits) unused bits */
844 if ((GetVal() >> (16 + (_bitOffset & 15))) != 0)
845 return false;
846 _bitOffset += 16;
847 _bitOffset &= ~(ptrdiff_t)15;
848 if (_bitOffset > 0 - NUM_DELTA_BIT_OFFSET_BITS)
849 return false;
850 const ptrdiff_t delta = _bitOffset >> 3;
851 _size = (size_t)((ptrdiff_t)(_size) - delta - NUM_DELTA_BYTES);
852 _buf += delta;
853 // _bitOffset = 0; // optional
854 return true;
855 }
856
857 Z7_FORCE_INLINE
858 size_t GetRem() const { return _size; }
859
860 Z7_FORCE_INLINE
861 UInt32 ReadUInt32()
862 {
863 const Byte *ptr = _buf;
864 const UInt32 v = GetUi32(ptr);
865 _buf += 4;
866 _size -= 4;
867 return v;
868 }
869
870 Z7_FORCE_INLINE
871 void CopyTo(Byte *dest, size_t size)
872 {
873 memcpy(dest, _buf, size);
874 _buf += size;
875 _size -= size;
876 }
877
878 Z7_FORCE_INLINE
879 bool IsOneDirectByteLeft() const
880 {
881 return GetRem() == 1;
882 }
883
884 Z7_FORCE_INLINE
885 Byte DirectReadByte()
886 {
887 _size--;
888 return *_buf++;
889 }
890};
891
892
893// numBits != 0
894// Z7_FORCE_INLINE
895Z7_NO_INLINE
896static
897UInt32 ReadBits(CBitDecoder &_bitStream, unsigned numBits)
898{
899 return _bitStream.ReadBits_NonZero(numBits);
900}
119 901
120#define RIF(x) { if (!(x)) return false; } 902#define RIF(x) { if (!(x)) return false; }
121 903
122bool CDecoder::ReadTable(Byte *levels, unsigned numSymbols) 904
905/*
906MSVC compiler adds extra move operation,
907 if we access array with 32-bit index
908 array[calc_index_32_bit(32-bit_var)]
909 where calc_index_32_bit operations are: ((unsigned)a>>cnt), &, ^, |
910 clang is also affected for ((unsigned)a>>cnt) in byte array.
911*/
912
913// it can overread input buffer for 7-17 bytes.
914// (levels != levelsEnd)
915Z7_NO_INLINE
916static ptrdiff_t ReadTable(ptrdiff_t _bitOffset, const Byte *_buf, Byte *levels, const Byte *levelsEnd)
123{ 917{
918 const unsigned kNumTableBits_Level = 7;
919 NHuffman::CDecoder256<kNumHuffmanBits, kLevelTableSize, kNumTableBits_Level> _levelDecoder;
920 NHuffman::CValueInt _value;
921 // optional check to reduce size of overread zone:
922 if (_bitOffset > (int)0 - (int)NUM_DELTA_BIT_OFFSET_BITS - (int)(kLevelTableSize * kNumLevelBits))
923 return DECODE_ERROR_CODE;
924 NORMALIZE
124 { 925 {
125 Byte levels2[kLevelTableSize]; 926 Byte levels2[kLevelTableSize / 4 * 4];
126 for (unsigned i = 0; i < kLevelTableSize; i++) 927 for (size_t i = 0; i < kLevelTableSize / 4 * 4; i += 4)
127 levels2[i] = (Byte)ReadBits(kNumLevelBits); 928 {
128 RIF(_levelDecoder.Build(levels2)) 929 UInt32 val;
930 MACRO_ReadBits_NonZero(val, kNumLevelBits * 4)
931 levels2[i + 0] = (Byte)((val >> (3 * kNumLevelBits)));
932 levels2[i + 1] = (Byte)((val >> (2 * kNumLevelBits)) & ((1u << kNumLevelBits) - 1));
933 levels2[i + 2] = (Byte)((Byte)val >> (1 * kNumLevelBits));
934 levels2[i + 3] = (Byte)((val) & ((1u << kNumLevelBits) - 1));
935 }
936 RIF(_levelDecoder.Build(levels2, NHuffman::k_BuildMode_Full))
129 } 937 }
130 938
131 unsigned i = 0;
132 do 939 do
133 { 940 {
134 UInt32 sym = _levelDecoder.Decode(&_bitStream); 941 unsigned sym;
942 Z7_LZX_HUFF_DECODE_CHECK_NO(sym, &_levelDecoder, kNumTableBits_Level, MOVE_POS_CHECK)
943 // Z7_HUFF_DECODE_CHECK(sym, &_levelDecoder, kNumHuffmanBits, kNumTableBits_Level, &bitStream, return false)
944 // sym = _levelDecoder.Decode(&bitStream);
945 // if (!_levelDecoder.Decode_SymCheck_MovePosCheck(&bitStream, sym)) return false;
946
135 if (sym <= kNumHuffmanBits) 947 if (sym <= kNumHuffmanBits)
136 { 948 {
137 int delta = (int)levels[i] - (int)sym; 949 int delta = (int)*levels - (int)sym;
138 delta += (delta < 0) ? (kNumHuffmanBits + 1) : 0; 950 delta += delta < 0 ? kNumHuffmanBits + 1 : 0;
139 levels[i++] = (Byte)delta; 951 *levels++ = (Byte)delta;
140 continue; 952 continue;
141 } 953 }
142 954
143 unsigned num; 955 unsigned num;
144 Byte symbol; 956 int symbol;
145 957
146 if (sym < kLevelSym_Same) 958 if (sym < kLevelSym_Same)
147 { 959 {
148 sym -= kLevelSym_Zero1; 960 // sym -= kLevelSym_Zero1;
149 num = kLevelSym_Zero1_Start + ((unsigned)sym << kLevelSym_Zero1_NumBits) + 961 MACRO_ReadBits_NonZero(num, kLevelSym_Zero1_NumBits + (sym - kLevelSym_Zero1))
150 (unsigned)ReadBits(kLevelSym_Zero1_NumBits + sym); 962 num += (sym << kLevelSym_Zero1_NumBits) - (kLevelSym_Zero1 << kLevelSym_Zero1_NumBits) + kLevelSym_Zero1_Start;
151 symbol = 0; 963 symbol = 0;
152 } 964 }
153 else if (sym == kLevelSym_Same) 965 // else if (sym != kLevelSym_Same) return DECODE_ERROR_CODE;
966 else // (sym == kLevelSym_Same)
154 { 967 {
155 num = kLevelSym_Same_Start + (unsigned)ReadBits(kLevelSym_Same_NumBits); 968 MACRO_ReadBits_NonZero(num, kLevelSym_Same_NumBits)
156 sym = _levelDecoder.Decode(&_bitStream); 969 num += kLevelSym_Same_Start;
157 if (sym > kNumHuffmanBits) 970 // + (unsigned)bitStream.ReadBitsSmall(kLevelSym_Same_NumBits);
158 return false; 971 // Z7_HUFF_DECODE_CHECK(sym, &_levelDecoder, kNumHuffmanBits, kNumTableBits_Level, &bitStream, return DECODE_ERROR_CODE)
159 int delta = (int)levels[i] - (int)sym; 972 // if (!_levelDecoder.Decode2(&bitStream, sym)) return DECODE_ERROR_CODE;
160 delta += (delta < 0) ? (kNumHuffmanBits + 1) : 0; 973 // sym = _levelDecoder.Decode(&bitStream);
161 symbol = (Byte)delta; 974
975 Z7_LZX_HUFF_DECODE_CHECK_NO(sym, &_levelDecoder, kNumTableBits_Level, MOVE_POS)
976
977 if (sym > kNumHuffmanBits) return DECODE_ERROR_CODE;
978 symbol = *levels - (int)sym;
979 symbol += symbol < 0 ? kNumHuffmanBits + 1 : 0;
162 } 980 }
163 else
164 return false;
165 981
166 const unsigned limit = i + num; 982 if (num > (size_t)(levelsEnd - levels))
167 if (limit > numSymbols)
168 return false; 983 return false;
169 984 const Byte *limit = levels + num;
170 do 985 do
171 levels[i++] = symbol; 986 *levels++ = (Byte)symbol;
172 while (i < limit); 987 while (levels != limit);
173 } 988 }
174 while (i < numSymbols); 989 while (levels != levelsEnd);
175 990
176 return true; 991 return _bitOffset;
177} 992}
178 993
179 994
180bool CDecoder::ReadTables(void) 995static const unsigned kPosSlotDelta = 256 / kNumLenSlots - kPosSlotOffset;
181{ 996
182 {
183 if (_skipByte)
184 {
185 if (_bitStream.DirectReadByte() != 0)
186 return false;
187 }
188 997
189 _bitStream.NormalizeBig(); 998#define READ_TABLE(_bitStream, levels, levelsEnd) \
999{ \
1000 _bitStream._bitOffset = ReadTable(_bitStream._bitOffset, _bitStream._buf, levels, levelsEnd); \
1001 if (_bitStream.IsOverRead()) return false; \
1002}
190 1003
191 const unsigned blockType = (unsigned)ReadBits(kBlockType_NumBits); 1004// can over-read input buffer for less than 32 bytes
192 if (blockType > kBlockType_Uncompressed) 1005bool CDecoder::ReadTables(CBitByteDecoder &_bitStream) throw()
1006{
1007 UPDATE_STAT(g_stats_NumTables++;)
1008 {
1009 const unsigned blockType = (unsigned)ReadBits(_bitStream, kBlockType_NumBits);
1010 // if (blockType > kBlockType_Uncompressed || blockType == 0)
1011 if ((unsigned)(blockType - 1) > kBlockType_Uncompressed - 1)
193 return false; 1012 return false;
194 1013 _unpackBlockSize = 1u << 15;
195 _unpackBlockSize = (1 << 15); 1014 if (!_wimMode || ReadBits(_bitStream, 1) == 0)
196 if (!_wimMode || ReadBits(1) == 0)
197 { 1015 {
198 _unpackBlockSize = ReadBits(16); 1016 _unpackBlockSize = ReadBits(_bitStream, 16);
199 // wimlib supports chunks larger than 32KB (unsupported my MS wim). 1017 // wimlib supports chunks larger than 32KB (unsupported my MS wim).
200 if (!_wimMode || _numDictBits >= 16) 1018 if (!_wimMode || _numDictBits >= 16)
201 { 1019 {
202 _unpackBlockSize <<= 8; 1020 _unpackBlockSize <<= 8;
203 _unpackBlockSize |= ReadBits(8); 1021 _unpackBlockSize |= ReadBits(_bitStream, 8);
204 } 1022 }
205 } 1023 }
206 1024
207 PRF(printf("\nBlockSize = %6d %s ", _unpackBlockSize, (_pos & 1) ? "@@@" : " ")); 1025 PRF(printf("\nBlockSize = %6d %s ", _unpackBlockSize, (_pos & 1) ? "@@@" : " "));
208 1026
209 _isUncompressedBlock = (blockType == kBlockType_Uncompressed); 1027 _isUncompressedBlock = (blockType == kBlockType_Uncompressed);
210
211 _skipByte = false; 1028 _skipByte = false;
212 1029
213 if (_isUncompressedBlock) 1030 if (_isUncompressedBlock)
214 { 1031 {
215 _skipByte = ((_unpackBlockSize & 1) != 0); 1032 _skipByte = ((_unpackBlockSize & 1) != 0);
216 1033 // printf("\n UncompressedBlock %d", _unpackBlockSize);
217 PRF(printf(" UncompressedBlock ")); 1034 PRF(printf(" UncompressedBlock ");)
218 if (_unpackBlockSize & 1) 1035 // if (_unpackBlockSize & 1) { PRF(printf(" ######### ")); }
219 { 1036 if (!_bitStream.Switch_To_ByteMode())
220 PRF(printf(" ######### "));
221 }
222
223 if (!_bitStream.PrepareUncompressed())
224 return false; 1037 return false;
225 if (_bitStream.GetRem() < kNumReps * 4) 1038 if (_bitStream.GetRem() < kNumReps * 4)
226 return false; 1039 return false;
227
228 for (unsigned i = 0; i < kNumReps; i++) 1040 for (unsigned i = 0; i < kNumReps; i++)
229 { 1041 {
230 const UInt32 rep = _bitStream.ReadUInt32(); 1042 const UInt32 rep = _bitStream.ReadUInt32();
231 if (rep > _winSize) 1043 // here we allow only such values for (rep) that can be set also by LZ code:
1044 if (rep == 0 || rep > _winSize - kNumReps)
232 return false; 1045 return false;
233 _reps[i] = rep; 1046 _reps[(size_t)i + kPosSlotOffset] = rep;
234 } 1047 }
235 1048 // printf("\n");
236 return true; 1049 return true;
237 } 1050 }
238 1051
239 _numAlignBits = 64; 1052 // _numAlignBits = 64;
240 1053 // const UInt32 k_numAlignBits_PosSlots_MAX = 64 + kPosSlotDelta;
1054 // _numAlignBits_PosSlots = k_numAlignBits_PosSlots_MAX;
1055 const UInt32 k_numAlignBits_Dist_MAX = (UInt32)(Int32)-1;
1056 _numAlignBits_Dist = k_numAlignBits_Dist_MAX;
241 if (blockType == kBlockType_Aligned) 1057 if (blockType == kBlockType_Aligned)
242 { 1058 {
243 Byte levels[kAlignTableSize]; 1059 Byte levels[kAlignTableSize];
244 _numAlignBits = kNumAlignBits; 1060 // unsigned not0 = 0;
1061 unsigned not3 = 0;
245 for (unsigned i = 0; i < kAlignTableSize; i++) 1062 for (unsigned i = 0; i < kAlignTableSize; i++)
246 levels[i] = (Byte)ReadBits(kNumAlignLevelBits); 1063 {
247 RIF(_alignDecoder.Build(levels)) 1064 const unsigned val = ReadBits(_bitStream, kNumAlignLevelBits);
1065 levels[i] = (Byte)val;
1066 // not0 |= val;
1067 not3 |= (val ^ 3);
1068 }
1069 // static unsigned number = 0, all = 0; all++;
1070 // if (!not0) return false; // Build(true) will test this case
1071 if (not3)
1072 {
1073 // _numAlignBits_PosSlots = (kNumAlignBits + 1) * 2 + kPosSlotDelta;
1074 // _numAlignBits = kNumAlignBits;
1075 _numAlignBits_Dist = (1u << (kNumAlignBits + 1)) - (kNumReps - 1);
1076 RIF(_alignDecoder.Build(levels, true)) // full
1077 }
1078 // else { number++; if (number % 4 == 0) printf("\nnumber= %u : %u%%", number, number * 100 / all); }
1079 }
1080 // if (_numAlignBits_PosSlots == k_numAlignBits_PosSlots_MAX)
1081 if (_numAlignBits_Dist == k_numAlignBits_Dist_MAX)
1082 {
1083 size_t i;
1084 for (i = 3; i < kNumLinearPosSlotBits; i++)
1085 {
1086 _extra[i * 2 + 2 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));
1087 _extra[i * 2 + 3 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));
1088 }
1089 for (i = kNumLinearPosSlotBits * 2 + 2; i < kNumPosSlots; i++)
1090 _extra[i + kPosSlotOffset] = (Byte)SET_NUM_BITS(kNumLinearPosSlotBits);
1091 }
1092 else
1093 {
1094 size_t i;
1095 for (i = 3; i < kNumLinearPosSlotBits; i++)
1096 {
1097 _extra[i * 2 + 2 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i) - 3);
1098 _extra[i * 2 + 3 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i) - 3);
1099 }
1100 for (i = kNumLinearPosSlotBits * 2 + 2; i < kNumPosSlots; i++)
1101 _extra[i + kPosSlotOffset] = (Byte)(SET_NUM_BITS(kNumLinearPosSlotBits) - 3);
248 } 1102 }
249 } 1103 }
250 1104
251 RIF(ReadTable(_mainLevels, 256)) 1105 READ_TABLE(_bitStream, _mainLevels, _mainLevels + 256)
252 RIF(ReadTable(_mainLevels + 256, _numPosLenSlots)) 1106 READ_TABLE(_bitStream, _mainLevels + 256, _mainLevels + 256 + _numPosLenSlots)
253 unsigned end = 256 + _numPosLenSlots; 1107 const unsigned end = 256 + _numPosLenSlots;
254 memset(_mainLevels + end, 0, kMainTableSize - end); 1108 memset(_mainLevels + end, 0, kMainTableSize - end);
255 RIF(_mainDecoder.Build(_mainLevels)) 1109 // #define NUM_CYC 1
256 RIF(ReadTable(_lenLevels, kNumLenSymbols)) 1110 // unsigned j; for (j = 0; j < NUM_CYC; j++)
257 return _lenDecoder.Build(_lenLevels); 1111 RIF(_mainDecoder.Build(_mainLevels, NHuffman::k_BuildMode_Full))
1112 // if (kNumLenSymols_Big_Start)
1113 memset(_lenLevels, 0, kNumLenSymols_Big_Start);
1114 READ_TABLE(_bitStream,
1115 _lenLevels + kNumLenSymols_Big_Start,
1116 _lenLevels + kNumLenSymols_Big_Start + kNumLenSymbols)
1117 // for (j = 0; j < NUM_CYC; j++)
1118 RIF(_lenDecoder.Build(_lenLevels, NHuffman::k_BuildMode_Full_or_Empty))
1119 return true;
1120}
1121
1122
1123
1124static ptrdiff_t CodeLz(CDecoder *dec, size_t next, ptrdiff_t _bitOffset, const Byte *_buf) throw()
1125{
1126 {
1127 Byte *const win = dec->_win;
1128 const UInt32 winSize = dec->_winSize;
1129 Byte *pos = win + dec->_pos;
1130 const Byte * const posEnd = pos + next;
1131 NHuffman::CValueInt _value;
1132
1133 NORMALIZE
1134
1135#if 1
1136 #define HUFF_DEC_PREFIX dec->
1137#else
1138 const NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, kNumTableBits_Main> _mainDecoder = dec->_mainDecoder;
1139 const NHuffman::CDecoder256<kNumHuffmanBits, kNumLenSymbols, kNumTableBits_Len> _lenDecoder = dec->_lenDecoder;
1140 const NHuffman::CDecoder7b<kAlignTableSize> _alignDecoder = dec->_alignDecoder;
1141 #define HUFF_DEC_PREFIX
1142#endif
1143
1144 do
1145 {
1146 unsigned sym;
1147 // printf("\npos = %6u", pos - win);
1148 {
1149 const NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, kNumTableBits_Main>
1150 *mainDecoder = & HUFF_DEC_PREFIX _mainDecoder;
1151 Z7_LZX_HUFF_DECODE_CHECK_NO(sym, mainDecoder, kNumTableBits_Main, MOVE_POS_CHECK_STAT)
1152 }
1153 // if (!_mainDecoder.Decode_SymCheck_MovePosCheck(&bitStream, sym)) return DECODE_ERROR_CODE;
1154 // sym = _mainDecoder.Decode(&bitStream);
1155 // if (bitStream.WasExtraReadError_Fast()) return DECODE_ERROR_CODE;
1156
1157 // printf(" sym = %3x", sym);
1158 UPDATE_STAT(g_stats_main[sym]++;)
1159
1160 if (sym < 256)
1161 {
1162 UPDATE_STAT(g_stats_NumLits++;)
1163 *pos++ = (Byte)sym;
1164 }
1165 else
1166 {
1167 // sym -= 256;
1168 // if (sym >= _numPosLenSlots) return DECODE_ERROR_CODE;
1169 const unsigned posSlot = sym / kNumLenSlots;
1170 unsigned len = sym % kNumLenSlots + kMatchMinLen;
1171 if (len == kNumLenSlots - 1 + kMatchMinLen)
1172 {
1173 const NHuffman::CDecoder256<kNumHuffmanBits, kNumLenSymbols, kNumTableBits_Len>
1174 *lenDecoder = & HUFF_DEC_PREFIX _lenDecoder;
1175 Z7_LZX_HUFF_DECODE_CHECK_YES(len, lenDecoder, kNumTableBits_Len, MOVE_POS_STAT)
1176 // if (!_lenDecoder.Decode2(&bitStream, len)) return DECODE_ERROR_CODE;
1177 // len = _lenDecoder.Decode(&bitStream);
1178 // if (len >= kNumLenSymbols) return DECODE_ERROR_CODE;
1179 UPDATE_STAT(g_stats_len[len - kNumLenSymols_Big_Start]++;)
1180 len += kNumLenSlots - 1 + kMatchMinLen - kNumLenSymols_Big_Start;
1181 }
1182 /*
1183 if ((next -= len) < 0)
1184 return DECODE_ERROR_CODE;
1185 */
1186 UInt32 dist;
1187
1188 dist = dec->_reps[(size_t)posSlot - kPosSlotDelta];
1189 if (posSlot < kNumReps + 256 / kNumLenSlots)
1190 {
1191 // if (posSlot != kNumReps + kPosSlotDelta)
1192 // if (posSlot - (kNumReps + kPosSlotDelta + 1) < 2)
1193 dec->_reps[(size_t)posSlot - kPosSlotDelta] = dec->_reps[kPosSlotOffset];
1194 /*
1195 if (posSlot != kPosSlotDelta)
1196 {
1197 UInt32 temp = dist;
1198 if (posSlot == kPosSlotDelta + 1)
1199 {
1200 dist = reps[1];
1201 reps[1] = temp;
1202 }
1203 else
1204 {
1205 dist = reps[2];
1206 reps[2] = temp;
1207 }
1208 // dist = reps[(size_t)(posSlot) - kPosSlotDelta];
1209 // reps[(size_t)(posSlot) - kPosSlotDelta] = reps[0];
1210 // reps[(size_t)(posSlot) - kPosSlotDelta] = temp;
1211 }
1212 */
1213 }
1214 else // if (posSlot != kNumReps + kPosSlotDelta)
1215 {
1216 unsigned numDirectBits;
1217#if 0
1218 if (posSlot < kNumPowerPosSlots + kPosSlotDelta)
1219 {
1220 numDirectBits = (posSlot - 2 - kPosSlotDelta) >> 1;
1221 dist = (UInt32)(2 | (posSlot & 1)) << numDirectBits;
1222 }
1223 else
1224 {
1225 numDirectBits = kNumLinearPosSlotBits;
1226 dist = (UInt32)(posSlot - 0x22 - kPosSlotDelta) << kNumLinearPosSlotBits;
1227 }
1228 dist -= kNumReps - 1;
1229#else
1230 numDirectBits = dec->_extra[(size_t)posSlot - kPosSlotDelta];
1231 // dist = reps[(size_t)(posSlot) - kPosSlotDelta];
1232#endif
1233 dec->_reps[kPosSlotOffset + 2] =
1234 dec->_reps[kPosSlotOffset + 1];
1235 dec->_reps[kPosSlotOffset + 1] =
1236 dec->_reps[kPosSlotOffset + 0];
1237
1238 // dist += val; dist += bitStream.ReadBitsBig(numDirectBits);
1239 // if (posSlot >= _numAlignBits_PosSlots)
1240 // if (numDirectBits >= _numAlignBits)
1241 // if (val >= _numAlignBits_Dist)
1242 // UInt32 val; MACRO_ReadBitsBig(val , numDirectBits)
1243 // dist += val;
1244 // dist += (UInt32)((UInt32)_value >> 1 >> (/* 31 ^ */ (numDirectBits)));
1245 // MOVE_POS((numDirectBits ^ 31))
1246 MACRO_ReadBitsBig_pre(numDirectBits)
1247 // dist += (UInt32)_value;
1248 if (dist >= dec->_numAlignBits_Dist)
1249 {
1250 // if (numDirectBits != _numAlignBits)
1251 {
1252 // UInt32 val;
1253 // dist -= (UInt32)_value;
1254 MACRO_ReadBitsBig_add3(dist)
1255 NORMALIZE
1256 // dist += (val << kNumAlignBits);
1257 // dist += bitStream.ReadBitsSmall(numDirectBits - kNumAlignBits) << kNumAlignBits;
1258 }
1259 {
1260 // const unsigned alignTemp = _alignDecoder.Decode(&bitStream);
1261 const NHuffman::CDecoder7b<kAlignTableSize> *alignDecoder = & HUFF_DEC_PREFIX _alignDecoder;
1262 unsigned alignTemp;
1263 UPDATE_STAT(g_stats_NumAlign++;)
1264 Z7_HUFF_DECODER_7B_DECODE(alignTemp, alignDecoder, GET_VAL_BASE, MOVE_POS, bs)
1265 // NORMALIZE
1266 // if (alignTemp >= kAlignTableSize) return DECODE_ERROR_CODE;
1267 dist += alignTemp;
1268 }
1269 }
1270 else
1271 {
1272 {
1273 MACRO_ReadBitsBig_add(dist)
1274 // dist += bitStream.ReadBitsSmall(numDirectBits - kNumAlignBits) << kNumAlignBits;
1275 }
1276 }
1277 NORMALIZE
1278 /*
1279 else
1280 {
1281 UInt32 val;
1282 MACRO_ReadBitsBig(val, numDirectBits)
1283 dist += val;
1284 // dist += bitStream.ReadBitsBig(numDirectBits);
1285 }
1286 */
1287 }
1288 dec->_reps[kPosSlotOffset + 0] = dist;
1289
1290 Byte *dest = pos;
1291 if (len > (size_t)(posEnd - pos))
1292 return DECODE_ERROR_CODE;
1293 Int32 srcPos = (Int32)(pos - win);
1294 pos += len;
1295 srcPos -= (Int32)dist;
1296 if (srcPos < 0) // fast version
1297 {
1298 if (!dec->_overDict)
1299 return DECODE_ERROR_CODE;
1300 srcPos &= winSize - 1;
1301 UInt32 rem = winSize - (UInt32)srcPos;
1302 if (len > rem)
1303 {
1304 len -= rem;
1305 const Byte *src = win + (UInt32)srcPos;
1306 do
1307 *dest++ = *src++;
1308 while (--rem);
1309 srcPos = 0;
1310 }
1311 }
1312 CopyLzMatch(dest, win + (UInt32)srcPos, len, dist);
1313 }
1314 }
1315 while (pos != posEnd);
1316
1317 return _bitOffset;
1318 }
258} 1319}
259 1320
260 1321
261HRESULT CDecoder::CodeSpec(UInt32 curSize) 1322
1323
1324// inSize != 0
1325// outSize != 0 ???
1326HRESULT CDecoder::CodeSpec(const Byte *inData, size_t inSize, UInt32 outSize) throw()
262{ 1327{
263 if (!_keepHistory || !_isUncompressedBlock) 1328 // ((inSize & 1) != 0) case is possible, if current call will be finished with Uncompressed Block.
264 _bitStream.NormalizeBig(); 1329 CBitByteDecoder _bitStream;
1330 if (_keepHistory && _isUncompressedBlock)
1331 _bitStream.Init_ByteMode(inData, inSize);
1332 else
1333 _bitStream.Init_BitMode(inData, inSize);
265 1334
266 if (!_keepHistory) 1335 if (!_keepHistory)
267 { 1336 {
1337 _isUncompressedBlock = false;
268 _skipByte = false; 1338 _skipByte = false;
269 _unpackBlockSize = 0; 1339 _unpackBlockSize = 0;
270 1340 memset(_mainLevels, 0, sizeof(_mainLevels));
271 memset(_mainLevels, 0, kMainTableSize); 1341 memset(_lenLevels, 0, sizeof(_lenLevels));
272 memset(_lenLevels, 0, kNumLenSymbols);
273
274 { 1342 {
275 _x86_translationSize = 12000000; 1343 _x86_translationSize = 12000000;
276 if (!_wimMode) 1344 if (!_wimMode)
277 { 1345 {
278 _x86_translationSize = 0; 1346 _x86_translationSize = 0;
279 if (ReadBits(1) != 0) 1347 if (ReadBits(_bitStream, 1) != 0)
280 { 1348 {
281 UInt32 v = ReadBits(16) << 16; 1349 UInt32 v = ReadBits(_bitStream, 16) << 16;
282 v |= ReadBits(16); 1350 v |= ReadBits(_bitStream, 16);
283 _x86_translationSize = v; 1351 _x86_translationSize = v;
284 } 1352 }
285 } 1353 }
286
287 _x86_processedSize = 0; 1354 _x86_processedSize = 0;
288 } 1355 }
289 1356 _reps[0 + kPosSlotOffset] = 1;
290 _reps[0] = 1; 1357 _reps[1 + kPosSlotOffset] = 1;
291 _reps[1] = 1; 1358 _reps[2 + kPosSlotOffset] = 1;
292 _reps[2] = 1;
293 } 1359 }
294 1360
295 while (curSize > 0) 1361 while (outSize)
296 { 1362 {
1363 /*
1364 // check it for bit mode only:
297 if (_bitStream.WasExtraReadError_Fast()) 1365 if (_bitStream.WasExtraReadError_Fast())
298 return S_FALSE; 1366 return S_FALSE;
299 1367 */
300 if (_unpackBlockSize == 0) 1368 if (_unpackBlockSize == 0)
301 { 1369 {
302 if (!ReadTables()) 1370 if (_skipByte)
1371 {
1372 if (_bitStream.GetRem() < 1)
1373 return S_FALSE;
1374 if (_bitStream.DirectReadByte() != 0)
1375 return S_FALSE;
1376 }
1377 if (_isUncompressedBlock)
1378 _bitStream.Switch_To_BitMode();
1379 if (!ReadTables(_bitStream))
303 return S_FALSE; 1380 return S_FALSE;
304 continue; 1381 continue;
305 } 1382 }
306 1383
1384 // _unpackBlockSize != 0
307 UInt32 next = _unpackBlockSize; 1385 UInt32 next = _unpackBlockSize;
308 if (next > curSize) 1386 if (next > outSize)
309 next = curSize; 1387 next = outSize;
1388 // next != 0
1389
1390 // PRF(printf("\nnext = %d", (unsigned)next);)
310 1391
311 if (_isUncompressedBlock) 1392 if (_isUncompressedBlock)
312 { 1393 {
313 const size_t rem = _bitStream.GetRem(); 1394 if (_bitStream.GetRem() < next)
314 if (rem == 0)
315 return S_FALSE; 1395 return S_FALSE;
316 if (next > rem)
317 next = (UInt32)rem;
318 _bitStream.CopyTo(_win + _pos, next); 1396 _bitStream.CopyTo(_win + _pos, next);
319 _pos += next; 1397 _pos += next;
320 curSize -= next;
321 _unpackBlockSize -= next; 1398 _unpackBlockSize -= next;
322
323 /* we don't know where skipByte can be placed, if it's end of chunk:
324 1) in current chunk - there are such cab archives, if chunk is last
325 2) in next chunk - are there such archives ? */
326
327 if (_skipByte
328 && _unpackBlockSize == 0
329 && curSize == 0
330 && _bitStream.IsOneDirectByteLeft())
331 {
332 _skipByte = false;
333 if (_bitStream.DirectReadByte() != 0)
334 return S_FALSE;
335 }
336
337 continue;
338 } 1399 }
339 1400 else
340 curSize -= next;
341 _unpackBlockSize -= next;
342
343 Byte *win = _win;
344
345 while (next > 0)
346 { 1401 {
347 if (_bitStream.WasExtraReadError_Fast()) 1402 _unpackBlockSize -= next;
1403 _bitStream._bitOffset = CodeLz(this, next, _bitStream._bitOffset, _bitStream._buf);
1404 if (_bitStream.IsOverRead())
348 return S_FALSE; 1405 return S_FALSE;
1406 _pos += next;
1407 }
1408 outSize -= next;
1409 }
349 1410
350 UInt32 sym = _mainDecoder.Decode(&_bitStream); 1411 // outSize == 0
351
352 if (sym < 256)
353 {
354 win[_pos++] = (Byte)sym;
355 next--;
356 continue;
357 }
358 {
359 sym -= 256;
360 if (sym >= _numPosLenSlots)
361 return S_FALSE;
362 const UInt32 posSlot = sym / kNumLenSlots;
363 const UInt32 lenSlot = sym % kNumLenSlots;
364 UInt32 len = kMatchMinLen + lenSlot;
365
366 if (lenSlot == kNumLenSlots - 1)
367 {
368 UInt32 lenTemp = _lenDecoder.Decode(&_bitStream);
369 if (lenTemp >= kNumLenSymbols)
370 return S_FALSE;
371 len = kMatchMinLen + kNumLenSlots - 1 + lenTemp;
372 }
373
374 UInt32 dist;
375
376 if (posSlot < kNumReps)
377 {
378 dist = _reps[posSlot];
379 _reps[posSlot] = _reps[0];
380 _reps[0] = dist;
381 }
382 else
383 {
384 unsigned numDirectBits;
385
386 if (posSlot < kNumPowerPosSlots)
387 {
388 numDirectBits = (unsigned)(posSlot >> 1) - 1;
389 dist = ((2 | (posSlot & 1)) << numDirectBits);
390 }
391 else
392 {
393 numDirectBits = kNumLinearPosSlotBits;
394 dist = ((posSlot - 0x22) << kNumLinearPosSlotBits);
395 }
396
397 if (numDirectBits >= _numAlignBits)
398 {
399 dist += (_bitStream.ReadBitsSmall(numDirectBits - kNumAlignBits) << kNumAlignBits);
400 const UInt32 alignTemp = _alignDecoder.Decode(&_bitStream);
401 if (alignTemp >= kAlignTableSize)
402 return S_FALSE;
403 dist += alignTemp;
404 }
405 else
406 dist += _bitStream.ReadBitsBig(numDirectBits);
407
408 dist -= kNumReps - 1;
409 _reps[2] = _reps[1];
410 _reps[1] = _reps[0];
411 _reps[0] = dist;
412 }
413
414 if (len > next)
415 return S_FALSE;
416
417 if (dist > _pos && !_overDict)
418 return S_FALSE;
419
420 Byte *dest = win + _pos;
421 const UInt32 mask = (_winSize - 1);
422 UInt32 srcPos = (_pos - dist) & mask;
423 1412
424 next -= len; 1413 if (_isUncompressedBlock)
425 1414 {
426 if (len > _winSize - srcPos) 1415 /* we don't know where skipByte can be placed, if it's end of chunk:
427 { 1416 1) in current chunk - there are such cab archives, if chunk is last
428 _pos += len; 1417 2) in next chunk - are there such archives ? */
429 do 1418 if (_unpackBlockSize == 0
430 { 1419 && _skipByte
431 *dest++ = win[srcPos++]; 1420 // && outSize == 0
432 srcPos &= mask; 1421 && _bitStream.IsOneDirectByteLeft())
433 } 1422 {
434 while (--len); 1423 _skipByte = false;
435 } 1424 if (_bitStream.DirectReadByte() != 0)
436 else 1425 return S_FALSE;
437 {
438 const ptrdiff_t src = (ptrdiff_t)srcPos - (ptrdiff_t)_pos;
439 _pos += len;
440 const Byte *lim = dest + len;
441 *(dest) = *(dest + src);
442 dest++;
443 do
444 *(dest) = *(dest + src);
445 while (++dest != lim);
446 }
447 }
448 } 1426 }
449 } 1427 }
450 1428
451 if (!_bitStream.WasFinishedOK()) 1429 if (_bitStream.GetRem() != 0)
452 return S_FALSE; 1430 return S_FALSE;
453 1431 if (!_isUncompressedBlock)
1432 if (!_bitStream.WasBitStreamFinishedOK())
1433 return S_FALSE;
454 return S_OK; 1434 return S_OK;
455} 1435}
456 1436
457 1437
458HRESULT CDecoder::Code(const Byte *inData, size_t inSize, UInt32 outSize) 1438#if k_Filter_OutBufSize_Add > k_Lz_OutBufSize_Add
1439 #define k_OutBufSize_Add k_Filter_OutBufSize_Add
1440#else
1441 #define k_OutBufSize_Add k_Lz_OutBufSize_Add
1442#endif
1443
1444HRESULT CDecoder::Code_WithExceedReadWrite(const Byte *inData, size_t inSize, UInt32 outSize) throw()
459{ 1445{
460 if (!_keepHistory) 1446 if (!_keepHistory)
461 { 1447 {
@@ -466,63 +1452,65 @@ HRESULT CDecoder::Code(const Byte *inData, size_t inSize, UInt32 outSize)
466 { 1452 {
467 _pos = 0; 1453 _pos = 0;
468 _overDict = true; 1454 _overDict = true;
1455#if k_OutBufSize_Add > 0
1456 // data after (_winSize) can be used, because we can use overwrite.
1457 // memset(_win + _winSize, 0, k_OutBufSize_Add);
1458#endif
469 } 1459 }
470
471 _writePos = _pos; 1460 _writePos = _pos;
472 _unpackedData = _win + _pos; 1461 _unpackedData = _win + _pos;
473 1462
474 if (outSize > _winSize - _pos) 1463 if (outSize > _winSize - _pos)
475 return S_FALSE; 1464 return S_FALSE;
1465
1466 PRF(printf("\ninSize = %d", (unsigned)inSize);)
1467 PRF(if ((inSize & 1) != 0) printf("---------");)
476 1468
477 PRF(printf("\ninSize = %d", inSize)); 1469 if (inSize == 0)
478 if ((inSize & 1) != 0)
479 {
480 PRF(printf(" ---------"));
481 }
482
483 if (inSize < 1)
484 return S_FALSE; 1470 return S_FALSE;
485 1471 const HRESULT res = CodeSpec(inData, inSize, outSize);
486 _bitStream.Init(inData, inSize);
487
488 const HRESULT res = CodeSpec(outSize);
489 const HRESULT res2 = Flush(); 1472 const HRESULT res2 = Flush();
490 return (res == S_OK ? res2 : res); 1473 return (res == S_OK ? res2 : res);
491} 1474}
492 1475
493 1476
494HRESULT CDecoder::SetParams2(unsigned numDictBits) 1477HRESULT CDecoder::SetParams2(unsigned numDictBits) throw()
495{ 1478{
496 _numDictBits = numDictBits; 1479 if (numDictBits < kNumDictBits_Min ||
497 if (numDictBits < kNumDictBits_Min || numDictBits > kNumDictBits_Max) 1480 numDictBits > kNumDictBits_Max)
498 return E_INVALIDARG; 1481 return E_INVALIDARG;
499 const unsigned numPosSlots = (numDictBits < 20) ? 1482 _numDictBits = (Byte)numDictBits;
500 numDictBits * 2 : 1483 const unsigned numPosSlots2 = (numDictBits < 20) ?
501 34 + ((unsigned)1 << (numDictBits - 17)); 1484 numDictBits : 17 + (1u << (numDictBits - 18));
502 _numPosLenSlots = numPosSlots * kNumLenSlots; 1485 _numPosLenSlots = numPosSlots2 * (kNumLenSlots * 2);
503 return S_OK; 1486 return S_OK;
504} 1487}
505 1488
506 1489
507HRESULT CDecoder::SetParams_and_Alloc(unsigned numDictBits) 1490HRESULT CDecoder::Set_DictBits_and_Alloc(unsigned numDictBits) throw()
508{ 1491{
509 RINOK(SetParams2(numDictBits)) 1492 RINOK(SetParams2(numDictBits))
510
511 const UInt32 newWinSize = (UInt32)1 << numDictBits; 1493 const UInt32 newWinSize = (UInt32)1 << numDictBits;
512 1494 if (_needAlloc)
513 if (NeedAlloc)
514 { 1495 {
515 if (!_win || newWinSize != _winSize) 1496 if (!_win || newWinSize != _winSize)
516 { 1497 {
517 ::MidFree(_win); 1498 // BigFree
1499 z7_AlignedFree
1500 (_win);
518 _winSize = 0; 1501 _winSize = 0;
519 _win = (Byte *)::MidAlloc(newWinSize); 1502 const size_t alloc_size = newWinSize + k_OutBufSize_Add;
1503 _win = (Byte *)
1504 // BigAlloc
1505 z7_AlignedAlloc
1506 (alloc_size);
520 if (!_win) 1507 if (!_win)
521 return E_OUTOFMEMORY; 1508 return E_OUTOFMEMORY;
1509 // optional:
1510 memset(_win, 0, alloc_size);
522 } 1511 }
523 } 1512 }
524 1513 _winSize = newWinSize;
525 _winSize = (UInt32)newWinSize;
526 return S_OK; 1514 return S_OK;
527} 1515}
528 1516
diff --git a/CPP/7zip/Compress/LzxDecoder.h b/CPP/7zip/Compress/LzxDecoder.h
index ab114e5..b4556a6 100644
--- a/CPP/7zip/Compress/LzxDecoder.h
+++ b/CPP/7zip/Compress/LzxDecoder.h
@@ -3,239 +3,102 @@
3#ifndef ZIP7_INC_LZX_DECODER_H 3#ifndef ZIP7_INC_LZX_DECODER_H
4#define ZIP7_INC_LZX_DECODER_H 4#define ZIP7_INC_LZX_DECODER_H
5 5
6#include "../../../C/CpuArch.h"
7
8#include "../../Common/MyCom.h"
9
10#include "HuffmanDecoder.h" 6#include "HuffmanDecoder.h"
11#include "Lzx.h" 7#include "Lzx.h"
12 8
13namespace NCompress { 9namespace NCompress {
14namespace NLzx { 10namespace NLzx {
15 11
16class CBitDecoder 12const unsigned kAdditionalOutputBufSize = 32 * 2;
17{
18 unsigned _bitPos;
19 UInt32 _value;
20 const Byte *_buf;
21 const Byte *_bufLim;
22 UInt32 _extraSize;
23public:
24
25 void Init(const Byte *data, size_t size)
26 {
27 _buf = data;
28 _bufLim = data + size - 1;
29 _bitPos = 0;
30 _extraSize = 0;
31 }
32
33 size_t GetRem() const { return (size_t)(_bufLim + 1 - _buf); }
34 bool WasExtraReadError_Fast() const { return _extraSize > 4; }
35
36 bool WasFinishedOK() const
37 {
38 if (_buf != _bufLim + 1)
39 return false;
40 if ((_bitPos >> 4) * 2 != _extraSize)
41 return false;
42 unsigned numBits = _bitPos & 15;
43 return (((_value >> (_bitPos - numBits)) & (((UInt32)1 << numBits) - 1)) == 0);
44 }
45
46 void NormalizeSmall()
47 {
48 if (_bitPos <= 16)
49 {
50 UInt32 val;
51 if (_buf >= _bufLim)
52 {
53 val = 0xFFFF;
54 _extraSize += 2;
55 }
56 else
57 {
58 val = GetUi16(_buf);
59 _buf += 2;
60 }
61 _value = (_value << 16) | val;
62 _bitPos += 16;
63 }
64 }
65
66 void NormalizeBig()
67 {
68 if (_bitPos <= 16)
69 {
70 {
71 UInt32 val;
72 if (_buf >= _bufLim)
73 {
74 val = 0xFFFF;
75 _extraSize += 2;
76 }
77 else
78 {
79 val = GetUi16(_buf);
80 _buf += 2;
81 }
82 _value = (_value << 16) | val;
83 _bitPos += 16;
84 }
85 if (_bitPos <= 16)
86 {
87 UInt32 val;
88 if (_buf >= _bufLim)
89 {
90 val = 0xFFFF;
91 _extraSize += 2;
92 }
93 else
94 {
95 val = GetUi16(_buf);
96 _buf += 2;
97 }
98 _value = (_value << 16) | val;
99 _bitPos += 16;
100 }
101 }
102 }
103
104 UInt32 GetValue(unsigned numBits) const
105 {
106 return (_value >> (_bitPos - numBits)) & (((UInt32)1 << numBits) - 1);
107 }
108
109 void MovePos(unsigned numBits)
110 {
111 _bitPos -= numBits;
112 NormalizeSmall();
113 }
114
115 UInt32 ReadBitsSmall(unsigned numBits)
116 {
117 _bitPos -= numBits;
118 UInt32 val = (_value >> _bitPos) & (((UInt32)1 << numBits) - 1);
119 NormalizeSmall();
120 return val;
121 }
122 13
123 UInt32 ReadBitsBig(unsigned numBits) 14const unsigned kNumTableBits_Main = 11;
124 { 15const unsigned kNumTableBits_Len = 8;
125 _bitPos -= numBits;
126 UInt32 val = (_value >> _bitPos) & (((UInt32)1 << numBits) - 1);
127 NormalizeBig();
128 return val;
129 }
130 16
131 bool PrepareUncompressed() 17// if (kNumLenSymols_Big <= 256) we can use NHuffman::CDecoder256
132 { 18// if (kNumLenSymols_Big > 256) we must use NHuffman::CDecoder
133 if (_extraSize != 0) 19// const unsigned kNumLenSymols_Big_Start = kNumLenSlots - 1 + kMatchMinLen; // 8 - 1 + 2
134 return false; 20const unsigned kNumLenSymols_Big_Start = 0;
135 unsigned numBits = _bitPos - 16; 21// const unsigned kNumLenSymols_Big_Start = 0;
136 if (((_value >> 16) & (((UInt32)1 << numBits) - 1)) != 0) 22const unsigned kNumLenSymols_Big = kNumLenSymols_Big_Start + kNumLenSymbols;
137 return false;
138 _buf -= 2;
139 _bitPos = 0;
140 return true;
141 }
142 23
143 UInt32 ReadUInt32() 24#if 1
144 { 25 // for smallest structure size:
145 UInt32 v = GetUi32(_buf); 26 const unsigned kPosSlotOffset = 0;
146 _buf += 4; 27#else
147 return v; 28 // use virtual entries for mispredicted branches:
148 } 29 const unsigned kPosSlotOffset = 256 / kNumLenSlots;
149 30#endif
150 void CopyTo(Byte *dest, size_t size)
151 {
152 memcpy(dest, _buf, size);
153 _buf += size;
154 }
155
156 bool IsOneDirectByteLeft() const { return _buf == _bufLim && _extraSize == 0; }
157
158 Byte DirectReadByte()
159 {
160 if (_buf > _bufLim)
161 {
162 _extraSize++;
163 return 0xFF;
164 }
165 return *_buf++;
166 }
167};
168 31
32class CBitByteDecoder;
169 33
170Z7_CLASS_IMP_COM_0( 34class CDecoder
171 CDecoder 35{
172) 36public:
173 CBitDecoder _bitStream;
174 Byte *_win;
175 UInt32 _pos; 37 UInt32 _pos;
176 UInt32 _winSize; 38 UInt32 _winSize;
39 Byte *_win;
177 40
178 bool _overDict; 41 bool _overDict;
179 bool _isUncompressedBlock; 42 bool _isUncompressedBlock;
180 bool _skipByte; 43 bool _skipByte;
181 unsigned _numAlignBits; 44 bool _keepHistory;
45 bool _keepHistoryForNext;
46 bool _needAlloc;
47 bool _wimMode;
48 Byte _numDictBits;
182 49
183 UInt32 _reps[kNumReps]; 50 // unsigned _numAlignBits_PosSlots;
184 UInt32 _numPosLenSlots; 51 // unsigned _numAlignBits;
52 UInt32 _numAlignBits_Dist;
53private:
54 unsigned _numPosLenSlots;
185 UInt32 _unpackBlockSize; 55 UInt32 _unpackBlockSize;
186 56
187public:
188 bool KeepHistoryForNext;
189 bool NeedAlloc;
190private:
191 bool _keepHistory;
192 bool _wimMode;
193 unsigned _numDictBits;
194 UInt32 _writePos; 57 UInt32 _writePos;
195 58
196 Byte *_x86_buf;
197 UInt32 _x86_translationSize; 59 UInt32 _x86_translationSize;
198 UInt32 _x86_processedSize; 60 UInt32 _x86_processedSize;
61 Byte *_x86_buf;
199 62
200 Byte *_unpackedData; 63 Byte *_unpackedData;
201 64public:
202 NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> _mainDecoder; 65 Byte _extra[kPosSlotOffset + kNumPosSlots];
203 NHuffman::CDecoder<kNumHuffmanBits, kNumLenSymbols> _lenDecoder; 66 UInt32 _reps[kPosSlotOffset + kNumPosSlots];
204 NHuffman::CDecoder7b<kAlignTableSize> _alignDecoder;
205 NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize, 7> _levelDecoder;
206 67
68 NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, kNumTableBits_Main> _mainDecoder;
69 NHuffman::CDecoder256<kNumHuffmanBits, kNumLenSymols_Big, kNumTableBits_Len> _lenDecoder;
70 NHuffman::CDecoder7b<kAlignTableSize> _alignDecoder;
71private:
207 Byte _mainLevels[kMainTableSize]; 72 Byte _mainLevels[kMainTableSize];
208 Byte _lenLevels[kNumLenSymbols]; 73 Byte _lenLevels[kNumLenSymols_Big];
209
210 HRESULT Flush();
211 74
212 UInt32 ReadBits(unsigned numBits); 75 HRESULT Flush() throw();
213 bool ReadTable(Byte *levels, unsigned numSymbols); 76 bool ReadTables(CBitByteDecoder &_bitStream) throw();
214 bool ReadTables();
215 77
216 HRESULT CodeSpec(UInt32 size); 78 HRESULT CodeSpec(const Byte *inData, size_t inSize, UInt32 outSize) throw();
217 HRESULT SetParams2(unsigned numDictBits); 79 HRESULT SetParams2(unsigned numDictBits) throw();
218public: 80public:
219 CDecoder(bool wimMode = false); 81 CDecoder() throw();
220 ~CDecoder(); 82 ~CDecoder() throw();
83
84 void Set_WimMode(bool wimMode) { _wimMode = wimMode; }
85 void Set_KeepHistory(bool keepHistory) { _keepHistory = keepHistory; }
86 void Set_KeepHistoryForNext(bool keepHistoryForNext) { _keepHistoryForNext = keepHistoryForNext; }
221 87
222 HRESULT SetExternalWindow(Byte *win, unsigned numDictBits) 88 HRESULT Set_ExternalWindow_DictBits(Byte *win, unsigned numDictBits)
223 { 89 {
224 NeedAlloc = false; 90 _needAlloc = false;
225 _win = win; 91 _win = win;
226 _winSize = (UInt32)1 << numDictBits; 92 _winSize = (UInt32)1 << numDictBits;
227 return SetParams2(numDictBits); 93 return SetParams2(numDictBits);
228 } 94 }
95 HRESULT Set_DictBits_and_Alloc(unsigned numDictBits) throw();
229 96
230 void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; } 97 HRESULT Code_WithExceedReadWrite(const Byte *inData, size_t inSize, UInt32 outSize) throw();
231
232 HRESULT SetParams_and_Alloc(unsigned numDictBits);
233
234 HRESULT Code(const Byte *inData, size_t inSize, UInt32 outSize);
235 98
236 bool WasBlockFinished() const { return _unpackBlockSize == 0; } 99 bool WasBlockFinished() const { return _unpackBlockSize == 0; }
237 const Byte *GetUnpackData() const { return _unpackedData; } 100 const Byte *GetUnpackData() const { return _unpackedData; }
238 UInt32 GetUnpackSize() const { return _pos - _writePos; } 101 UInt32 GetUnpackSize() const { return _pos - _writePos; }
239}; 102};
240 103
241}} 104}}
diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp
index 1238df6..3dbde75 100644
--- a/CPP/7zip/Compress/PpmdDecoder.cpp
+++ b/CPP/7zip/Compress/PpmdDecoder.cpp
@@ -74,6 +74,7 @@ HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)
74 _status = kStatus_Normal; 74 _status = kStatus_Normal;
75 Ppmd7_Init(&_ppmd, _order); 75 Ppmd7_Init(&_ppmd, _order);
76 break; 76 break;
77 default: break;
77 } 78 }
78 79
79 if (_outSizeDefined) 80 if (_outSizeDefined)
diff --git a/CPP/7zip/Compress/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp
index 5039131..e59e52f 100644
--- a/CPP/7zip/Compress/PpmdZip.cpp
+++ b/CPP/7zip/Compress/PpmdZip.cpp
@@ -12,6 +12,15 @@
12namespace NCompress { 12namespace NCompress {
13namespace NPpmdZip { 13namespace NPpmdZip {
14 14
15static const UInt32 kBufSize = 1 << 20;
16
17bool CBuf::Alloc()
18{
19 if (!Buf)
20 Buf = (Byte *)::MidAlloc(kBufSize);
21 return (Buf != NULL);
22}
23
15CDecoder::CDecoder(bool fullFileMode): 24CDecoder::CDecoder(bool fullFileMode):
16 _fullFileMode(fullFileMode) 25 _fullFileMode(fullFileMode)
17{ 26{
@@ -255,7 +264,10 @@ Z7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream
255 Ppmd8_Init(&_ppmd, (unsigned)_props.Order, (unsigned)_props.Restor); 264 Ppmd8_Init(&_ppmd, (unsigned)_props.Order, (unsigned)_props.Restor);
256 265
257 { 266 {
258 const UInt32 val = (UInt32)(((unsigned)_props.Order - 1) + ((_props.MemSizeMB - 1) << 4) + ((unsigned)_props.Restor << 12)); 267 const unsigned val =
268 ((unsigned)_props.Order - 1)
269 + (((unsigned)_props.MemSizeMB - 1) << 4)
270 + ((unsigned)_props.Restor << 12);
259 _outStream.WriteByte((Byte)(val & 0xFF)); 271 _outStream.WriteByte((Byte)(val & 0xFF));
260 _outStream.WriteByte((Byte)(val >> 8)); 272 _outStream.WriteByte((Byte)(val >> 8));
261 } 273 }
@@ -294,7 +306,4 @@ Z7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream
294 } 306 }
295} 307}
296 308
297
298
299
300}} 309}}
diff --git a/CPP/7zip/Compress/PpmdZip.h b/CPP/7zip/Compress/PpmdZip.h
index a23d008..6cc6af1 100644
--- a/CPP/7zip/Compress/PpmdZip.h
+++ b/CPP/7zip/Compress/PpmdZip.h
@@ -15,20 +15,13 @@
15namespace NCompress { 15namespace NCompress {
16namespace NPpmdZip { 16namespace NPpmdZip {
17 17
18static const UInt32 kBufSize = (1 << 20);
19
20struct CBuf 18struct CBuf
21{ 19{
22 Byte *Buf; 20 Byte *Buf;
23 21
24 CBuf(): Buf(NULL) {} 22 CBuf(): Buf(NULL) {}
25 ~CBuf() { ::MidFree(Buf); } 23 ~CBuf() { ::MidFree(Buf); }
26 bool Alloc() 24 bool Alloc();
27 {
28 if (!Buf)
29 Buf = (Byte *)::MidAlloc(kBufSize);
30 return (Buf != NULL);
31 }
32}; 25};
33 26
34 27
@@ -38,10 +31,10 @@ Z7_CLASS_IMP_NOQIB_3(
38 , ICompressSetFinishMode 31 , ICompressSetFinishMode
39 , ICompressGetInStreamProcessedSize 32 , ICompressGetInStreamProcessedSize
40) 33)
34 bool _fullFileMode;
41 CByteInBufWrap _inStream; 35 CByteInBufWrap _inStream;
42 CBuf _outStream; 36 CBuf _outStream;
43 CPpmd8 _ppmd; 37 CPpmd8 _ppmd;
44 bool _fullFileMode;
45public: 38public:
46 CDecoder(bool fullFileMode = true); 39 CDecoder(bool fullFileMode = true);
47 ~CDecoder(); 40 ~CDecoder();
diff --git a/CPP/7zip/Compress/QuantumDecoder.cpp b/CPP/7zip/Compress/QuantumDecoder.cpp
index 16ef0fc..98817a4 100644
--- a/CPP/7zip/Compress/QuantumDecoder.cpp
+++ b/CPP/7zip/Compress/QuantumDecoder.cpp
@@ -2,6 +2,11 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5// #include <stdio.h>
6
7#include "../../../C/Alloc.h"
8#include "../../../C/CpuArch.h"
9
5#include "../../Common/Defs.h" 10#include "../../Common/Defs.h"
6 11
7#include "QuantumDecoder.h" 12#include "QuantumDecoder.h"
@@ -11,184 +16,339 @@ namespace NQuantum {
11 16
12static const unsigned kNumLenSymbols = 27; 17static const unsigned kNumLenSymbols = 27;
13static const unsigned kMatchMinLen = 3; 18static const unsigned kMatchMinLen = 3;
14static const unsigned kNumSimplePosSlots = 4;
15static const unsigned kNumSimpleLenSlots = 6; 19static const unsigned kNumSimpleLenSlots = 6;
16 20
17static const UInt16 kUpdateStep = 8; 21static const unsigned kUpdateStep = 8;
18static const UInt16 kFreqSumMax = 3800; 22static const unsigned kFreqSumMax = 3800;
19static const unsigned kReorderCountStart = 4; 23static const unsigned kReorderCount_Start = 4;
20static const unsigned kReorderCount = 50; 24static const unsigned kReorderCount = 50;
21 25
22void CModelDecoder::Init(unsigned numItems) 26
27class CRangeDecoder
23{ 28{
24 NumItems = numItems; 29 UInt32 Low;
25 ReorderCount = kReorderCountStart; 30 UInt32 Range;
26 for (unsigned i = 0; i < numItems; i++) 31 UInt32 Code;
32
33 unsigned _bitOffset;
34 const Byte *_buf;
35 const Byte *_bufLim;
36
37public:
38
39 Z7_FORCE_INLINE
40 void Init(const Byte *inData, size_t inSize)
27 { 41 {
28 Freqs[i] = (UInt16)(numItems - i); 42 Code = ((UInt32)*inData << 8) | inData[1];
29 Vals[i] = (Byte)i; 43 _buf = inData + 2;
44 _bufLim = inData + inSize;
45 _bitOffset = 0;
46 Low = 0;
47 Range = 0x10000;
30 } 48 }
31 Freqs[numItems] = 0;
32}
33 49
50 Z7_FORCE_INLINE
51 bool WasExtraRead() const
52 {
53 return _buf > _bufLim;
54 }
55
56 Z7_FORCE_INLINE
57 UInt32 ReadBits(unsigned numBits) // numBits > 0
58 {
59 unsigned bitOffset = _bitOffset;
60 const Byte *buf = _buf;
61 const UInt32 res = GetBe32(buf) << bitOffset;
62 bitOffset += numBits;
63 _buf = buf + (bitOffset >> 3);
64 _bitOffset = bitOffset & 7;
65 return res >> (32 - numBits);
66 }
67
68 // ---------- Range Decoder functions ----------
69
70 Z7_FORCE_INLINE
71 bool Finish()
72 {
73 const unsigned numBits = 2 + ((16 - 2 - _bitOffset) & 7);
74 if (ReadBits(numBits) != 0)
75 return false;
76 return _buf == _bufLim;
77 }
78
79 Z7_FORCE_INLINE
80 UInt32 GetThreshold(UInt32 total) const
81 {
82 return ((Code + 1) * total - 1) / Range; // & 0xFFFF is not required;
83 }
84
85 Z7_FORCE_INLINE
86 void Decode(UInt32 start, UInt32 end, UInt32 total)
87 {
88 // UInt32 hi = ~(Low + end * Range / total - 1);
89 UInt32 hi = 0 - (Low + end * Range / total);
90 const UInt32 offset = start * Range / total;
91 UInt32 lo = Low + offset;
92 Code -= offset;
93 UInt32 numBits = 0;
94 lo ^= hi;
95 while (lo & (1u << 15))
96 {
97 lo <<= 1;
98 hi <<= 1;
99 numBits++;
100 }
101 lo ^= hi;
102 UInt32 an = lo & hi;
103 while (an & (1u << 14))
104 {
105 an <<= 1;
106 lo <<= 1;
107 hi <<= 1;
108 numBits++;
109 }
110 Low = lo;
111 Range = ((~hi - lo) & 0xffff) + 1;
112 if (numBits)
113 Code = (Code << numBits) + ReadBits(numBits);
114 }
115};
116
117
118// Z7_FORCE_INLINE
119Z7_NO_INLINE
34unsigned CModelDecoder::Decode(CRangeDecoder *rc) 120unsigned CModelDecoder::Decode(CRangeDecoder *rc)
121// Z7_NO_INLINE void CModelDecoder::Normalize()
35{ 122{
36 const UInt32 threshold = rc->GetThreshold(Freqs[0]);
37 unsigned i;
38 for (i = 1; Freqs[i] > threshold; i++);
39
40 rc->Decode(Freqs[i], Freqs[(size_t)i - 1], Freqs[0]);
41 const unsigned res = Vals[--i];
42
43 do
44 Freqs[i] = (UInt16)(Freqs[i] + kUpdateStep);
45 while (i--);
46
47 if (Freqs[0] > kFreqSumMax) 123 if (Freqs[0] > kFreqSumMax)
48 { 124 {
49 if (--ReorderCount == 0) 125 if (--ReorderCount == 0)
50 { 126 {
51 ReorderCount = kReorderCount; 127 ReorderCount = kReorderCount;
52 for (i = 0; i < NumItems; i++) 128 {
53 Freqs[i] = (UInt16)(((Freqs[i] - Freqs[(size_t)i + 1]) + 1) >> 1); 129 unsigned i = NumItems;
54 for (i = 0; i < NumItems - 1; i++) 130 unsigned next = 0;
55 for (unsigned j = i + 1; j < NumItems; j++) 131 UInt16 *freqs = &Freqs[i];
56 if (Freqs[i] < Freqs[j]) 132 do
57 { 133 {
58 const UInt16 tmpFreq = Freqs[i]; 134 const unsigned freq = *--freqs;
59 const Byte tmpVal = Vals[i]; 135 *freqs = (UInt16)((freq - next + 1) >> 1);
60 Freqs[i] = Freqs[j]; 136 next = freq;
61 Vals[i] = Vals[j]; 137 }
62 Freqs[j] = tmpFreq; 138 while (--i);
63 Vals[j] = tmpVal; 139 }
64 } 140 {
65 141 for (unsigned i = 0; i < NumItems - 1; i++)
142 {
143 UInt16 freq = Freqs[i];
144 for (unsigned k = i + 1; k < NumItems; k++)
145 if (freq < Freqs[k])
146 {
147 const UInt16 freq2 = Freqs[k];
148 Freqs[k] = freq;
149 Freqs[i] = freq2;
150 freq = freq2;
151 const Byte val = Vals[i];
152 Vals[i] = Vals[k];
153 Vals[k] = val;
154 }
155 }
156 }
157 unsigned i = NumItems;
158 unsigned freq = 0;
159 UInt16 *freqs = &Freqs[i];
66 do 160 do
67 Freqs[i] = (UInt16)(Freqs[i] + Freqs[(size_t)i + 1]); 161 {
68 while (i--); 162 freq += *--freqs;
163 *freqs = (UInt16)freq;
164 }
165 while (--i);
69 } 166 }
70 else 167 else
71 { 168 {
72 i = NumItems - 1; 169 unsigned i = NumItems;
170 unsigned next = 1;
171 UInt16 *freqs = &Freqs[i];
73 do 172 do
74 { 173 {
75 Freqs[i] = (UInt16)(Freqs[i] >> 1); 174 unsigned freq = *--freqs >> 1;
76 if (Freqs[i] <= Freqs[(size_t)i + 1]) 175 if (freq < next)
77 Freqs[i] = (UInt16)(Freqs[(size_t)i + 1] + 1); 176 freq = next;
177 *freqs = (UInt16)freq;
178 next = freq + 1;
78 } 179 }
79 while (i--); 180 while (--i);
80 } 181 }
81 } 182 }
82 183 unsigned res;
184 {
185 const unsigned freq0 = Freqs[0];
186 Freqs[0] = (UInt16)(freq0 + kUpdateStep);
187 const unsigned threshold = rc->GetThreshold(freq0);
188 UInt16 *freqs = &Freqs[1];
189 unsigned freq = *freqs;
190 while (freq > threshold)
191 {
192 *freqs++ = (UInt16)(freq + kUpdateStep);
193 freq = *freqs;
194 }
195 res = Vals[freqs - Freqs - 1];
196 rc->Decode(freq, freqs[-1] - kUpdateStep, freq0);
197 }
83 return res; 198 return res;
84} 199}
85 200
86 201
87void CDecoder::Init() 202Z7_NO_INLINE
203void CModelDecoder::Init(unsigned numItems, unsigned startVal)
88{ 204{
89 m_Selector.Init(kNumSelectors); 205 NumItems = numItems;
90 unsigned i; 206 ReorderCount = kReorderCount_Start;
91 for (i = 0; i < kNumLitSelectors; i++) 207 UInt16 *freqs = Freqs;
92 m_Literals[i].Init(kNumLitSymbols); 208 freqs[numItems] = 0;
93 const unsigned numItems = (_numDictBits == 0 ? 1 : (_numDictBits << 1)); 209 Byte *vals = Vals;
94 const unsigned kNumPosSymbolsMax[kNumMatchSelectors] = { 24, 36, 42 }; 210 do
95 for (i = 0; i < kNumMatchSelectors; i++) 211 {
96 m_PosSlot[i].Init(MyMin(numItems, kNumPosSymbolsMax[i])); 212 *freqs++ = (UInt16)numItems;
97 m_LenSlot.Init(kNumLenSymbols); 213 *vals++ = (Byte)startVal;
214 startVal++;
215 }
216 while (--numItems);
98} 217}
99 218
100 219
101HRESULT CDecoder::CodeSpec(const Byte *inData, size_t inSize, UInt32 outSize) 220HRESULT CDecoder::Code(const Byte *inData, size_t inSize, UInt32 outSize, bool keepHistory)
102{ 221{
103 if (inSize < 2) 222 if (inSize < 2)
104 return S_FALSE; 223 return S_FALSE;
224 if (!keepHistory)
225 {
226 _winPos = 0;
227 m_Selector.Init(kNumSelectors, 0);
228 unsigned i;
229 for (i = 0; i < kNumLitSelectors; i++)
230 m_Literals[i].Init(kNumLitSymbols, i * kNumLitSymbols);
231 const unsigned numItems = (_numDictBits == 0 ? 1 : (_numDictBits << 1));
232 // const unsigned kNumPosSymbolsMax[kNumMatchSelectors] = { 24, 36, 42 };
233 for (i = 0; i < kNumMatchSelectors; i++)
234 {
235 const unsigned num = 24 + i * 6 + ((i + 1) & 2) * 3;
236 m_PosSlot[i].Init(MyMin(numItems, num), 0);
237 }
238 m_LenSlot.Init(kNumLenSymbols, kMatchMinLen + kNumMatchSelectors - 1);
239 }
105 240
106 CRangeDecoder rc; 241 CRangeDecoder rc;
107 rc.Stream.SetStreamAndInit(inData, inSize); 242 rc.Init(inData, inSize);
108 rc.Init(); 243 const UInt32 winSize = _winSize;
244 Byte *pos;
245 {
246 UInt32 winPos = _winPos;
247 if (winPos == winSize)
248 {
249 winPos = 0;
250 _winPos = winPos;
251 _overWin = true;
252 }
253 if (outSize > winSize - winPos)
254 return S_FALSE;
255 pos = _win + winPos;
256 }
109 257
110 while (outSize != 0) 258 while (outSize != 0)
111 { 259 {
112 if (rc.Stream.WasExtraRead()) 260 if (rc.WasExtraRead())
113 return S_FALSE; 261 return S_FALSE;
114 262
115 unsigned selector = m_Selector.Decode(&rc); 263 const unsigned selector = m_Selector.Decode(&rc);
116 264
117 if (selector < kNumLitSelectors) 265 if (selector < kNumLitSelectors)
118 { 266 {
119 const Byte b = (Byte)((selector << (8 - kNumLitSelectorBits)) + m_Literals[selector].Decode(&rc)); 267 const unsigned b = m_Literals[selector].Decode(&rc);
120 _outWindow.PutByte(b); 268 *pos++ = (Byte)b;
121 outSize--; 269 --outSize;
270 // if (--outSize == 0) break;
122 } 271 }
123 else 272 else
124 { 273 {
125 selector -= kNumLitSelectors; 274 unsigned len = selector - kNumLitSelectors + kMatchMinLen;
126 unsigned len = selector + kMatchMinLen;
127 275
128 if (selector == 2) 276 if (selector == kNumLitSelectors + kNumMatchSelectors - 1)
129 { 277 {
130 unsigned lenSlot = m_LenSlot.Decode(&rc); 278 len = m_LenSlot.Decode(&rc);
131 if (lenSlot >= kNumSimpleLenSlots) 279 if (len >= kNumSimpleLenSlots + kMatchMinLen + kNumMatchSelectors - 1)
132 { 280 {
133 lenSlot -= 2; 281 len -= kNumSimpleLenSlots - 4 + kMatchMinLen + kNumMatchSelectors - 1;
134 const unsigned numDirectBits = (unsigned)(lenSlot >> 2); 282 const unsigned numDirectBits = (unsigned)(len >> 2);
135 len += ((4 | (lenSlot & 3)) << numDirectBits) - 2; 283 len = ((4 | (len & 3)) << numDirectBits) - (4 << 1)
284 + kNumSimpleLenSlots
285 + kMatchMinLen + kNumMatchSelectors - 1;
136 if (numDirectBits < 6) 286 if (numDirectBits < 6)
137 len += rc.Stream.ReadBits(numDirectBits); 287 len += rc.ReadBits(numDirectBits);
138 } 288 }
139 else
140 len += lenSlot;
141 } 289 }
142 290
143 UInt32 dist = m_PosSlot[selector].Decode(&rc); 291 UInt32 dist = m_PosSlot[(size_t)selector - kNumLitSelectors].Decode(&rc);
144 292
145 if (dist >= kNumSimplePosSlots) 293 if (dist >= 4)
146 { 294 {
147 unsigned numDirectBits = (unsigned)((dist >> 1) - 1); 295 const unsigned numDirectBits = (unsigned)((dist >> 1) - 1);
148 dist = ((2 | (dist & 1)) << numDirectBits) + rc.Stream.ReadBits(numDirectBits); 296 dist = ((2 | (dist & 1)) << numDirectBits) + rc.ReadBits(numDirectBits);
149 } 297 }
150 298
151 unsigned locLen = len; 299 if ((Int32)(outSize -= len) < 0)
152 if (len > outSize)
153 locLen = (unsigned)outSize;
154 if (!_outWindow.CopyBlock(dist, locLen))
155 return S_FALSE;
156 outSize -= locLen;
157 len -= locLen;
158 if (len != 0)
159 return S_FALSE; 300 return S_FALSE;
301
302 ptrdiff_t srcPos = (ptrdiff_t)(Int32)((pos - _win) - (ptrdiff_t)dist - 1);
303 if (srcPos < 0)
304 {
305 if (!_overWin)
306 return S_FALSE;
307 UInt32 rem = (UInt32)-srcPos;
308 srcPos += winSize;
309 if (rem < len)
310 {
311 const Byte *src = _win + srcPos;
312 len -= rem;
313 do
314 *pos++ = *src++;
315 while (--rem);
316 srcPos = 0;
317 }
318 }
319 const Byte *src = _win + srcPos;
320 do
321 *pos++ = *src++;
322 while (--len);
323 // if (outSize == 0) break;
160 } 324 }
161 } 325 }
162 326
327 _winPos = (UInt32)(size_t)(pos - _win);
163 return rc.Finish() ? S_OK : S_FALSE; 328 return rc.Finish() ? S_OK : S_FALSE;
164} 329}
165 330
166HRESULT CDecoder::Code(const Byte *inData, size_t inSize,
167 ISequentialOutStream *outStream, UInt32 outSize,
168 bool keepHistory)
169{
170 try
171 {
172 _outWindow.SetStream(outStream);
173 _outWindow.Init(keepHistory);
174 if (!keepHistory)
175 Init();
176
177 const HRESULT res = CodeSpec(inData, inSize, outSize);
178 const HRESULT res2 = _outWindow.Flush();
179 return res != S_OK ? res : res2;
180 }
181 catch(const CLzOutWindowException &e) { return e.ErrorCode; }
182 catch(...) { return S_FALSE; }
183}
184 331
185HRESULT CDecoder::SetParams(unsigned numDictBits) 332HRESULT CDecoder::SetParams(unsigned numDictBits)
186{ 333{
187 if (numDictBits > 21) 334 if (numDictBits > 21)
188 return E_INVALIDARG; 335 return E_INVALIDARG;
189 _numDictBits = numDictBits; 336 _numDictBits = numDictBits;
190 if (!_outWindow.Create((UInt32)1 << _numDictBits)) 337 _winPos = 0;
191 return E_OUTOFMEMORY; 338 _overWin = false;
339
340 if (numDictBits < 15)
341 numDictBits = 15;
342 _winSize = (UInt32)1 << numDictBits;
343 if (!_win || _winSize > _winSize_allocated)
344 {
345 MidFree(_win);
346 _win = NULL;
347 _win = (Byte *)MidAlloc(_winSize);
348 if (!_win)
349 return E_OUTOFMEMORY;
350 _winSize_allocated = _winSize;
351 }
192 return S_OK; 352 return S_OK;
193} 353}
194 354
diff --git a/CPP/7zip/Compress/QuantumDecoder.h b/CPP/7zip/Compress/QuantumDecoder.h
index 925989a..fd5baea 100644
--- a/CPP/7zip/Compress/QuantumDecoder.h
+++ b/CPP/7zip/Compress/QuantumDecoder.h
@@ -3,149 +3,41 @@
3#ifndef ZIP7_INC_COMPRESS_QUANTUM_DECODER_H 3#ifndef ZIP7_INC_COMPRESS_QUANTUM_DECODER_H
4#define ZIP7_INC_COMPRESS_QUANTUM_DECODER_H 4#define ZIP7_INC_COMPRESS_QUANTUM_DECODER_H
5 5
6#include "../../Common/MyCom.h" 6#include "../../Common/MyTypes.h"
7
8#include "LzOutWindow.h"
9 7
10namespace NCompress { 8namespace NCompress {
11namespace NQuantum { 9namespace NQuantum {
12 10
13class CBitDecoder
14{
15 UInt32 Value;
16 bool _extra;
17 const Byte *_buf;
18 const Byte *_bufLim;
19public:
20 void SetStreamAndInit(const Byte *inData, size_t inSize)
21 {
22 _buf = inData;
23 _bufLim = inData + inSize;
24 Value = 0x10000;
25 _extra = false;
26 }
27
28 bool WasExtraRead() const { return _extra; }
29
30 bool WasFinishedOK() const
31 {
32 return !_extra && _buf == _bufLim;
33 }
34
35 UInt32 ReadBit()
36 {
37 if (Value >= 0x10000)
38 {
39 Byte b;
40 if (_buf >= _bufLim)
41 {
42 b = 0xFF;
43 _extra = true;
44 }
45 else
46 b = *_buf++;
47 Value = 0x100 | b;
48 }
49 UInt32 res = (Value >> 7) & 1;
50 Value <<= 1;
51 return res;
52 }
53
54 UInt32 ReadStart16Bits()
55 {
56 // we use check for extra read in another code.
57 UInt32 val = ((UInt32)*_buf << 8) | _buf[1];
58 _buf += 2;
59 return val;
60 }
61
62 UInt32 ReadBits(unsigned numBits) // numBits > 0
63 {
64 UInt32 res = 0;
65 do
66 res = (res << 1) | ReadBit();
67 while (--numBits);
68 return res;
69 }
70};
71
72
73class CRangeDecoder
74{
75 UInt32 Low;
76 UInt32 Range;
77 UInt32 Code;
78public:
79 CBitDecoder Stream;
80
81 void Init()
82 {
83 Low = 0;
84 Range = 0x10000;
85 Code = Stream.ReadStart16Bits();
86 }
87
88 bool Finish()
89 {
90 // do all streams use these two bits at end?
91 if (Stream.ReadBit() != 0) return false;
92 if (Stream.ReadBit() != 0) return false;
93 return Stream.WasFinishedOK();
94 }
95
96 UInt32 GetThreshold(UInt32 total) const
97 {
98 return ((Code + 1) * total - 1) / Range; // & 0xFFFF is not required;
99 }
100
101 void Decode(UInt32 start, UInt32 end, UInt32 total)
102 {
103 UInt32 high = Low + end * Range / total - 1;
104 UInt32 offset = start * Range / total;
105 Code -= offset;
106 Low += offset;
107 for (;;)
108 {
109 if ((Low & 0x8000) != (high & 0x8000))
110 {
111 if ((Low & 0x4000) == 0 || (high & 0x4000) != 0)
112 break;
113 Low &= 0x3FFF;
114 high |= 0x4000;
115 }
116 Low = (Low << 1) & 0xFFFF;
117 high = ((high << 1) | 1) & 0xFFFF;
118 Code = ((Code << 1) | Stream.ReadBit());
119 }
120 Range = high - Low + 1;
121 }
122};
123
124
125const unsigned kNumLitSelectorBits = 2; 11const unsigned kNumLitSelectorBits = 2;
126const unsigned kNumLitSelectors = (1 << kNumLitSelectorBits); 12const unsigned kNumLitSelectors = 1 << kNumLitSelectorBits;
127const unsigned kNumLitSymbols = 1 << (8 - kNumLitSelectorBits); 13const unsigned kNumLitSymbols = 1 << (8 - kNumLitSelectorBits);
128const unsigned kNumMatchSelectors = 3; 14const unsigned kNumMatchSelectors = 3;
129const unsigned kNumSelectors = kNumLitSelectors + kNumMatchSelectors; 15const unsigned kNumSelectors = kNumLitSelectors + kNumMatchSelectors;
130const unsigned kNumSymbolsMax = kNumLitSymbols; // 64 16const unsigned kNumSymbolsMax = kNumLitSymbols; // 64
131 17
18class CRangeDecoder;
132 19
133class CModelDecoder 20class CModelDecoder
134{ 21{
135 unsigned NumItems; 22 unsigned NumItems;
136 unsigned ReorderCount; 23 unsigned ReorderCount;
137 UInt16 Freqs[kNumSymbolsMax + 1];
138 Byte Vals[kNumSymbolsMax]; 24 Byte Vals[kNumSymbolsMax];
25 UInt16 Freqs[kNumSymbolsMax + 1];
139public: 26public:
140 void Init(unsigned numItems); 27 Byte _pad[64 - 10]; // for structure size alignment
28
29 void Init(unsigned numItems, unsigned startVal);
141 unsigned Decode(CRangeDecoder *rc); 30 unsigned Decode(CRangeDecoder *rc);
142}; 31};
143 32
144 33
145Z7_CLASS_IMP_COM_0( 34class CDecoder
146 CDecoder 35{
147) 36 UInt32 _winSize;
148 CLzOutWindow _outWindow; 37 UInt32 _winPos;
38 UInt32 _winSize_allocated;
39 bool _overWin;
40 Byte *_win;
149 unsigned _numDictBits; 41 unsigned _numDictBits;
150 42
151 CModelDecoder m_Selector; 43 CModelDecoder m_Selector;
@@ -156,12 +48,11 @@ Z7_CLASS_IMP_COM_0(
156 void Init(); 48 void Init();
157 HRESULT CodeSpec(const Byte *inData, size_t inSize, UInt32 outSize); 49 HRESULT CodeSpec(const Byte *inData, size_t inSize, UInt32 outSize);
158public: 50public:
159 HRESULT Code(const Byte *inData, size_t inSize, 51 HRESULT Code(const Byte *inData, size_t inSize, UInt32 outSize, bool keepHistory);
160 ISequentialOutStream *outStream, UInt32 outSize,
161 bool keepHistory);
162 HRESULT SetParams(unsigned numDictBits); 52 HRESULT SetParams(unsigned numDictBits);
163 53
164 CDecoder(): _numDictBits(0) {} 54 CDecoder(): _win(NULL), _numDictBits(0) {}
55 const Byte * GetDataPtr() const { return _win + _winPos; }
165}; 56};
166 57
167}} 58}}
diff --git a/CPP/7zip/Compress/Rar1Decoder.h b/CPP/7zip/Compress/Rar1Decoder.h
index 6d0e31d..e1e22e2 100644
--- a/CPP/7zip/Compress/Rar1Decoder.h
+++ b/CPP/7zip/Compress/Rar1Decoder.h
@@ -12,19 +12,22 @@
12#include "../Common/InBuffer.h" 12#include "../Common/InBuffer.h"
13 13
14#include "BitmDecoder.h" 14#include "BitmDecoder.h"
15#include "HuffmanDecoder.h"
16#include "LzOutWindow.h" 15#include "LzOutWindow.h"
17 16
18namespace NCompress { 17namespace NCompress {
19namespace NRar1 { 18namespace NRar1 {
20 19
21const UInt32 kNumRepDists = 4; 20const unsigned kNumRepDists = 4;
22 21
23Z7_CLASS_IMP_COM_2( 22Z7_CLASS_IMP_COM_2(
24 CDecoder 23 CDecoder
25 , ICompressCoder 24 , ICompressCoder
26 , ICompressSetDecoderProperties2 25 , ICompressSetDecoderProperties2
27) 26)
27 bool _isSolid;
28 bool _solidAllowed;
29 bool StMode;
30
28 CLzOutWindow m_OutWindowStream; 31 CLzOutWindow m_OutWindowStream;
29 NBitm::CDecoder<CInBuffer> m_InBitStream; 32 NBitm::CDecoder<CInBuffer> m_InBitStream;
30 33
@@ -36,10 +39,6 @@ Z7_CLASS_IMP_COM_2(
36 UInt32 m_RepDistPtr; 39 UInt32 m_RepDistPtr;
37 UInt32 m_RepDists[kNumRepDists]; 40 UInt32 m_RepDists[kNumRepDists];
38 41
39 bool _isSolid;
40 bool _solidAllowed;
41
42 bool StMode;
43 int FlagsCnt; 42 int FlagsCnt;
44 UInt32 FlagBuf, AvrPlc, AvrPlcB, AvrLn1, AvrLn2, AvrLn3; 43 UInt32 FlagBuf, AvrPlc, AvrPlcB, AvrLn1, AvrLn2, AvrLn3;
45 unsigned Buf60, NumHuf, LCount; 44 unsigned Buf60, NumHuf, LCount;
diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp
index 92404b6..63c04a1 100644
--- a/CPP/7zip/Compress/Rar2Decoder.cpp
+++ b/CPP/7zip/Compress/Rar2Decoder.cpp
@@ -93,7 +93,7 @@ CDecoder::CDecoder():
93void CDecoder::InitStructures() 93void CDecoder::InitStructures()
94{ 94{
95 m_MmFilter.Init(); 95 m_MmFilter.Init();
96 for (unsigned i = 0; i < kNumRepDists; i++) 96 for (unsigned i = 0; i < kNumReps; i++)
97 m_RepDists[i] = 0; 97 m_RepDists[i] = 0;
98 m_RepDistPtr = 0; 98 m_RepDistPtr = 0;
99 m_LastLength = 0; 99 m_LastLength = 0;
@@ -104,10 +104,34 @@ UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.ReadBits(numB
104 104
105#define RIF(x) { if (!(x)) return false; } 105#define RIF(x) { if (!(x)) return false; }
106 106
107static const unsigned kRepBothNumber = 256;
108static const unsigned kRepNumber = kRepBothNumber + 1;
109static const unsigned kLen2Number = kRepNumber + kNumReps;
110static const unsigned kReadTableNumber = kLen2Number + kNumLen2Symbols;
111static const unsigned kMatchNumber = kReadTableNumber + 1;
112
113// static const unsigned kDistTableStart = kMainTableSize;
114// static const unsigned kLenTableStart = kDistTableStart + kDistTableSize;
115
116static const UInt32 kDistStart [kDistTableSize] = {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};
117static const Byte kDistDirectBits[kDistTableSize] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
118
119static const Byte kLen2DistStarts [kNumLen2Symbols]={0,4,8,16,32,64,128,192};
120static const Byte kLen2DistDirectBits[kNumLen2Symbols]={2,2,3, 4, 5, 6, 6, 6};
121
122static const UInt32 kDistLimit2 = 0x101 - 1;
123static const UInt32 kDistLimit3 = 0x2000 - 1;
124static const UInt32 kDistLimit4 = 0x40000 - 1;
125
126// static const UInt32 kMatchMaxLen = 255 + 2;
127// static const UInt32 kMatchMaxLenMax = 255 + 5;
128
129
107bool CDecoder::ReadTables(void) 130bool CDecoder::ReadTables(void)
108{ 131{
109 m_TablesOK = false; 132 m_TablesOK = false;
110 133
134 const unsigned kLevelTableSize = 19;
111 Byte levelLevels[kLevelTableSize]; 135 Byte levelLevels[kLevelTableSize];
112 Byte lens[kMaxTableSize]; 136 Byte lens[kMaxTableSize];
113 137
@@ -123,7 +147,7 @@ bool CDecoder::ReadTables(void)
123 m_NumChannels = ReadBits(2) + 1; 147 m_NumChannels = ReadBits(2) + 1;
124 if (m_MmFilter.CurrentChannel >= m_NumChannels) 148 if (m_MmFilter.CurrentChannel >= m_NumChannels)
125 m_MmFilter.CurrentChannel = 0; 149 m_MmFilter.CurrentChannel = 0;
126 numLevels = m_NumChannels * kMMTableSize; 150 numLevels = m_NumChannels * k_MM_TableSize;
127 } 151 }
128 else 152 else
129 numLevels = kHeapTablesSizesSum; 153 numLevels = kHeapTablesSizesSum;
@@ -131,55 +155,48 @@ bool CDecoder::ReadTables(void)
131 unsigned i; 155 unsigned i;
132 for (i = 0; i < kLevelTableSize; i++) 156 for (i = 0; i < kLevelTableSize; i++)
133 levelLevels[i] = (Byte)ReadBits(4); 157 levelLevels[i] = (Byte)ReadBits(4);
134 RIF(m_LevelDecoder.Build(levelLevels)) 158 NHuffman::CDecoder256<kNumHufBits, kLevelTableSize, 6> m_LevelDecoder;
159 RIF(m_LevelDecoder.Build(levelLevels, NHuffman::k_BuildMode_Full))
135 160
136 i = 0; 161 i = 0;
137
138 do 162 do
139 { 163 {
140 const UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream); 164 const unsigned sym = m_LevelDecoder.DecodeFull(&m_InBitStream);
141 if (sym < kTableDirectLevels) 165 if (sym < 16)
142 { 166 {
143 lens[i] = (Byte)((sym + m_LastLevels[i]) & kLevelMask); 167 lens[i] = (Byte)((sym + m_LastLevels[i]) & 15);
144 i++; 168 i++;
145 } 169 }
170#if 0
171 else if (sym >= kLevelTableSize)
172 return false;
173#endif
146 else 174 else
147 { 175 {
148 if (sym == kTableLevelRepNumber) 176 unsigned num;
177 Byte v;
178 if (sym == 16)
149 { 179 {
150 unsigned num = ReadBits(2) + 3;
151 if (i == 0) 180 if (i == 0)
152 return false; 181 return false;
153 num += i; 182 num = ReadBits(2) + 3;
154 if (num > numLevels) 183 v = lens[(size_t)i - 1];
155 {
156 // return false;
157 num = numLevels; // original unRAR
158 }
159 const Byte v = lens[(size_t)i - 1];
160 do
161 lens[i++] = v;
162 while (i < num);
163 } 184 }
164 else 185 else
165 { 186 {
166 unsigned num; 187 num = (sym - 17) * 4;
167 if (sym == kTableLevel0Number) 188 num += num + 3 + ReadBits(3 + num);
168 num = ReadBits(3) + 3; 189 v = 0;
169 else if (sym == kTableLevel0Number2) 190 }
170 num = ReadBits(7) + 11; 191 num += i;
171 else 192 if (num > numLevels)
172 return false; 193 {
173 num += i; 194 // return false;
174 if (num > numLevels) 195 num = numLevels; // original unRAR
175 {
176 // return false;
177 num = numLevels; // original unRAR
178 }
179 do
180 lens[i++] = 0;
181 while (i < num);
182 } 196 }
197 do
198 lens[i++] = v;
199 while (i < num);
183 } 200 }
184 } 201 }
185 while (i < numLevels); 202 while (i < numLevels);
@@ -190,7 +207,7 @@ bool CDecoder::ReadTables(void)
190 if (m_AudioMode) 207 if (m_AudioMode)
191 for (i = 0; i < m_NumChannels; i++) 208 for (i = 0; i < m_NumChannels; i++)
192 { 209 {
193 RIF(m_MMDecoders[i].Build(&lens[i * kMMTableSize])) 210 RIF(m_MMDecoders[i].Build(&lens[(size_t)i * k_MM_TableSize]))
194 } 211 }
195 else 212 else
196 { 213 {
@@ -202,10 +219,10 @@ bool CDecoder::ReadTables(void)
202 memcpy(m_LastLevels, lens, kMaxTableSize); 219 memcpy(m_LastLevels, lens, kMaxTableSize);
203 220
204 m_TablesOK = true; 221 m_TablesOK = true;
205
206 return true; 222 return true;
207} 223}
208 224
225
209bool CDecoder::ReadLastTables() 226bool CDecoder::ReadLastTables()
210{ 227{
211 // it differs a little from pure RAR sources; 228 // it differs a little from pure RAR sources;
@@ -216,15 +233,15 @@ bool CDecoder::ReadLastTables()
216 { 233 {
217 if (m_AudioMode) 234 if (m_AudioMode)
218 { 235 {
219 const UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream); 236 const unsigned symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream);
220 if (symbol == 256) 237 if (symbol == 256)
221 return ReadTables(); 238 return ReadTables();
222 if (symbol >= kMMTableSize) 239 if (symbol >= k_MM_TableSize)
223 return false; 240 return false;
224 } 241 }
225 else 242 else
226 { 243 {
227 const UInt32 sym = m_MainDecoder.Decode(&m_InBitStream); 244 const unsigned sym = m_MainDecoder.Decode(&m_InBitStream);
228 if (sym == kReadTableNumber) 245 if (sym == kReadTableNumber)
229 return ReadTables(); 246 return ReadTables();
230 if (sym >= kMainTableSize) 247 if (sym >= kMainTableSize)
@@ -239,7 +256,7 @@ bool CDecoder::DecodeMm(UInt32 pos)
239{ 256{
240 while (pos-- != 0) 257 while (pos-- != 0)
241 { 258 {
242 const UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream); 259 const unsigned symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream);
243 if (m_InBitStream.ExtraBitsWereRead()) 260 if (m_InBitStream.ExtraBitsWereRead())
244 return false; 261 return false;
245 if (symbol >= 256) 262 if (symbol >= 256)
@@ -257,14 +274,23 @@ bool CDecoder::DecodeMm(UInt32 pos)
257 return true; 274 return true;
258} 275}
259 276
277
278typedef unsigned CLenType;
279
280static inline CLenType SlotToLen(CBitDecoder &_bitStream, CLenType slot)
281{
282 const unsigned numBits = ((unsigned)slot >> 2) - 1;
283 return ((4 | (slot & 3)) << numBits) + (CLenType)_bitStream.ReadBits(numBits);
284}
285
260bool CDecoder::DecodeLz(Int32 pos) 286bool CDecoder::DecodeLz(Int32 pos)
261{ 287{
262 while (pos > 0) 288 while (pos > 0)
263 { 289 {
264 UInt32 sym = m_MainDecoder.Decode(&m_InBitStream); 290 unsigned sym = m_MainDecoder.Decode(&m_InBitStream);
265 if (m_InBitStream.ExtraBitsWereRead()) 291 if (m_InBitStream.ExtraBitsWereRead())
266 return false; 292 return false;
267 UInt32 length, distance; 293 UInt32 len, distance;
268 if (sym < 256) 294 if (sym < 256)
269 { 295 {
270 m_OutWindowStream.PutByte(Byte(sym)); 296 m_OutWindowStream.PutByte(Byte(sym));
@@ -275,44 +301,49 @@ bool CDecoder::DecodeLz(Int32 pos)
275 { 301 {
276 if (sym >= kMainTableSize) 302 if (sym >= kMainTableSize)
277 return false; 303 return false;
278 sym -= kMatchNumber; 304 len = sym - kMatchNumber;
279 length = kNormalMatchMinLen + UInt32(kLenStart[sym]) + 305 if (len >= 8)
280 m_InBitStream.ReadBits(kLenDirectBits[sym]); 306 len = SlotToLen(m_InBitStream, len);
307 len += 3;
308
281 sym = m_DistDecoder.Decode(&m_InBitStream); 309 sym = m_DistDecoder.Decode(&m_InBitStream);
282 if (sym >= kDistTableSize) 310 if (sym >= kDistTableSize)
283 return false; 311 return false;
284 distance = kDistStart[sym] + m_InBitStream.ReadBits(kDistDirectBits[sym]); 312 distance = kDistStart[sym] + m_InBitStream.ReadBits(kDistDirectBits[sym]);
285 if (distance >= kDistLimit3) 313 if (distance >= kDistLimit3)
286 { 314 {
287 length += 2 - ((distance - kDistLimit4) >> 31); 315 len += 2 - ((distance - kDistLimit4) >> 31);
288 // length++; 316 // len++;
289 // if (distance >= kDistLimit4) 317 // if (distance >= kDistLimit4)
290 // length++; 318 // len++;
291 } 319 }
292 } 320 }
293 else if (sym == kRepBothNumber) 321 else if (sym == kRepBothNumber)
294 { 322 {
295 length = m_LastLength; 323 len = m_LastLength;
296 if (length == 0) 324 if (len == 0)
297 return false; 325 return false;
298 distance = m_RepDists[(m_RepDistPtr + 4 - 1) & 3]; 326 distance = m_RepDists[(m_RepDistPtr + 4 - 1) & 3];
299 } 327 }
300 else if (sym < kLen2Number) 328 else if (sym < kLen2Number)
301 { 329 {
302 distance = m_RepDists[(m_RepDistPtr - (sym - kRepNumber + 1)) & 3]; 330 distance = m_RepDists[(m_RepDistPtr - (sym - kRepNumber + 1)) & 3];
303 sym = m_LenDecoder.Decode(&m_InBitStream); 331 len = m_LenDecoder.Decode(&m_InBitStream);
304 if (sym >= kLenTableSize) 332 if (len >= kLenTableSize)
305 return false; 333 return false;
306 length = 2 + kLenStart[sym] + m_InBitStream.ReadBits(kLenDirectBits[sym]); 334 if (len >= 8)
335 len = SlotToLen(m_InBitStream, len);
336 len += 2;
337
307 if (distance >= kDistLimit2) 338 if (distance >= kDistLimit2)
308 { 339 {
309 length++; 340 len++;
310 if (distance >= kDistLimit3) 341 if (distance >= kDistLimit3)
311 { 342 {
312 length += 2 - ((distance - kDistLimit4) >> 31); 343 len += 2 - ((distance - kDistLimit4) >> 31);
313 // length++; 344 // len++;
314 // if (distance >= kDistLimit4) 345 // if (distance >= kDistLimit4)
315 // length++; 346 // len++;
316 } 347 }
317 } 348 }
318 } 349 }
@@ -321,16 +352,16 @@ bool CDecoder::DecodeLz(Int32 pos)
321 sym -= kLen2Number; 352 sym -= kLen2Number;
322 distance = kLen2DistStarts[sym] + 353 distance = kLen2DistStarts[sym] +
323 m_InBitStream.ReadBits(kLen2DistDirectBits[sym]); 354 m_InBitStream.ReadBits(kLen2DistDirectBits[sym]);
324 length = 2; 355 len = 2;
325 } 356 }
326 else // (sym == kReadTableNumber) 357 else // (sym == kReadTableNumber)
327 return true; 358 return true;
328 359
329 m_RepDists[m_RepDistPtr++ & 3] = distance; 360 m_RepDists[m_RepDistPtr++ & 3] = distance;
330 m_LastLength = length; 361 m_LastLength = len;
331 if (!m_OutWindowStream.CopyBlock(distance, length)) 362 if (!m_OutWindowStream.CopyBlock(distance, len))
332 return false; 363 return false;
333 pos -= length; 364 pos -= len;
334 } 365 }
335 return true; 366 return true;
336} 367}
diff --git a/CPP/7zip/Compress/Rar2Decoder.h b/CPP/7zip/Compress/Rar2Decoder.h
index d77bfc1..c9ddedb 100644
--- a/CPP/7zip/Compress/Rar2Decoder.h
+++ b/CPP/7zip/Compress/Rar2Decoder.h
@@ -18,59 +18,16 @@
18namespace NCompress { 18namespace NCompress {
19namespace NRar2 { 19namespace NRar2 {
20 20
21const unsigned kNumRepDists = 4; 21const unsigned kNumReps = 4;
22const unsigned kDistTableSize = 48; 22const unsigned kDistTableSize = 48;
23 23const unsigned kNumLen2Symbols = 8;
24const unsigned kMMTableSize = 256 + 1; 24const unsigned kLenTableSize = 28;
25 25const unsigned kMainTableSize = 256 + 2 + kNumReps + kNumLen2Symbols + kLenTableSize;
26const UInt32 kMainTableSize = 298; 26const unsigned kHeapTablesSizesSum = kMainTableSize + kDistTableSize + kLenTableSize;
27const UInt32 kLenTableSize = 28; 27const unsigned k_MM_TableSize = 256 + 1;
28 28const unsigned k_MM_NumChanelsMax = 4;
29const UInt32 kDistTableStart = kMainTableSize; 29const unsigned k_MM_TablesSizesSum = k_MM_TableSize * k_MM_NumChanelsMax;
30const UInt32 kLenTableStart = kDistTableStart + kDistTableSize; 30const unsigned kMaxTableSize = k_MM_TablesSizesSum;
31
32const UInt32 kHeapTablesSizesSum = kMainTableSize + kDistTableSize + kLenTableSize;
33
34const UInt32 kLevelTableSize = 19;
35
36const UInt32 kMMTablesSizesSum = kMMTableSize * 4;
37
38const UInt32 kMaxTableSize = kMMTablesSizesSum;
39
40const UInt32 kTableDirectLevels = 16;
41const UInt32 kTableLevelRepNumber = kTableDirectLevels;
42const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1;
43const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1;
44
45const UInt32 kLevelMask = 0xF;
46
47
48const UInt32 kRepBothNumber = 256;
49const UInt32 kRepNumber = kRepBothNumber + 1;
50const UInt32 kLen2Number = kRepNumber + 4;
51
52const UInt32 kLen2NumNumbers = 8;
53const UInt32 kReadTableNumber = kLen2Number + kLen2NumNumbers;
54const UInt32 kMatchNumber = kReadTableNumber + 1;
55
56const Byte kLenStart [kLenTableSize] = {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
57const Byte kLenDirectBits[kLenTableSize] = {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
58
59const UInt32 kDistStart [kDistTableSize] = {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};
60const Byte kDistDirectBits[kDistTableSize] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
61
62const Byte kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7};
63
64const Byte kLen2DistStarts[kLen2NumNumbers]={0,4,8,16,32,64,128,192};
65const Byte kLen2DistDirectBits[kLen2NumNumbers]={2,2,3, 4, 5, 6, 6, 6};
66
67const UInt32 kDistLimit2 = 0x101 - 1;
68const UInt32 kDistLimit3 = 0x2000 - 1;
69const UInt32 kDistLimit4 = 0x40000 - 1;
70
71const UInt32 kMatchMaxLen = 255 + 2;
72const UInt32 kMatchMaxLenMax = 255 + 5;
73const UInt32 kNormalMatchMinLen = 3;
74 31
75namespace NMultimedia { 32namespace NMultimedia {
76 33
@@ -83,18 +40,13 @@ struct CFilter
83 UInt32 ByteCount; 40 UInt32 ByteCount;
84 int LastChar; 41 int LastChar;
85 42
86 Byte Decode(int &channelDelta, Byte delta);
87
88 void Init() { memset(this, 0, sizeof(*this)); } 43 void Init() { memset(this, 0, sizeof(*this)); }
89 44 Byte Decode(int &channelDelta, Byte delta);
90}; 45};
91 46
92const unsigned kNumChanelsMax = 4; 47struct CFilter2
93
94class CFilter2
95{ 48{
96public: 49 CFilter m_Filters[k_MM_NumChanelsMax];
97 CFilter m_Filters[kNumChanelsMax];
98 int m_ChannelDelta; 50 int m_ChannelDelta;
99 unsigned CurrentChannel; 51 unsigned CurrentChannel;
100 52
@@ -103,47 +55,42 @@ public:
103 { 55 {
104 return m_Filters[CurrentChannel].Decode(m_ChannelDelta, delta); 56 return m_Filters[CurrentChannel].Decode(m_ChannelDelta, delta);
105 } 57 }
106
107}; 58};
108 59
109} 60}
110 61
111typedef NBitm::CDecoder<CInBuffer> CBitDecoder; 62typedef NBitm::CDecoder<CInBuffer> CBitDecoder;
112 63
113const unsigned kNumHuffmanBits = 15; 64const unsigned kNumHufBits = 15;
114 65
115Z7_CLASS_IMP_NOQIB_2( 66Z7_CLASS_IMP_NOQIB_2(
116 CDecoder 67 CDecoder
117 , ICompressCoder 68 , ICompressCoder
118 , ICompressSetDecoderProperties2 69 , ICompressSetDecoderProperties2
119) 70)
71 bool _isSolid;
72 bool _solidAllowed;
73 bool m_TablesOK;
74 bool m_AudioMode;
75
120 CLzOutWindow m_OutWindowStream; 76 CLzOutWindow m_OutWindowStream;
121 CBitDecoder m_InBitStream; 77 CBitDecoder m_InBitStream;
122 78
123 UInt32 m_RepDistPtr; 79 UInt32 m_RepDistPtr;
124 UInt32 m_RepDists[kNumRepDists]; 80 UInt32 m_RepDists[kNumReps];
125
126 UInt32 m_LastLength; 81 UInt32 m_LastLength;
82 unsigned m_NumChannels;
127 83
128 bool _isSolid; 84 NHuffman::CDecoder<kNumHufBits, kMainTableSize, 9> m_MainDecoder;
129 bool _solidAllowed; 85 NHuffman::CDecoder256<kNumHufBits, kDistTableSize, 7> m_DistDecoder;
130 bool m_TablesOK; 86 NHuffman::CDecoder256<kNumHufBits, kLenTableSize, 7> m_LenDecoder;
131 bool m_AudioMode; 87 NHuffman::CDecoder<kNumHufBits, k_MM_TableSize, 9> m_MMDecoders[k_MM_NumChanelsMax];
132
133 NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
134 NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder;
135 NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder;
136 NHuffman::CDecoder<kNumHuffmanBits, kMMTableSize> m_MMDecoders[NMultimedia::kNumChanelsMax];
137 NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
138 88
139 UInt64 m_PackSize; 89 UInt64 m_PackSize;
140 90
141 unsigned m_NumChannels;
142 NMultimedia::CFilter2 m_MmFilter; 91 NMultimedia::CFilter2 m_MmFilter;
143
144 Byte m_LastLevels[kMaxTableSize]; 92 Byte m_LastLevels[kMaxTableSize];
145 93
146
147 void InitStructures(); 94 void InitStructures();
148 UInt32 ReadBits(unsigned numBits); 95 UInt32 ReadBits(unsigned numBits);
149 bool ReadTables(); 96 bool ReadTables();
diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp
index a4943ad..c17d46d 100644
--- a/CPP/7zip/Compress/Rar3Decoder.cpp
+++ b/CPP/7zip/Compress/Rar3Decoder.cpp
@@ -17,8 +17,8 @@ namespace NRar3 {
17 17
18static const UInt32 kNumAlignReps = 15; 18static const UInt32 kNumAlignReps = 15;
19 19
20static const UInt32 kSymbolReadTable = 256; 20static const unsigned kSymbolReadTable = 256;
21static const UInt32 kSymbolRep = 259; 21static const unsigned kSymbolRep = 259;
22 22
23static const Byte kDistDirectBits[kDistTableSize] = 23static const Byte kDistDirectBits[kDistTableSize] =
24 {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15, 24 {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,
@@ -54,15 +54,15 @@ static Byte Wrap_ReadBits8(IByteInPtr pp) throw()
54 54
55 55
56CDecoder::CDecoder(): 56CDecoder::CDecoder():
57 _isSolid(false),
58 _solidAllowed(false),
57 _window(NULL), 59 _window(NULL),
58 _winPos(0), 60 _winPos(0),
59 _wrPtr(0), 61 _wrPtr(0),
60 _lzSize(0), 62 _lzSize(0),
61 _writtenFileSize(0), 63 _writtenFileSize(0),
62 _vmData(NULL), 64 _vmData(NULL),
63 _vmCode(NULL), 65 _vmCode(NULL)
64 _isSolid(false),
65 _solidAllowed(false)
66{ 66{
67 Ppmd7_Construct(&_ppmd); 67 Ppmd7_Construct(&_ppmd);
68 68
@@ -252,8 +252,8 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
252 252
253 if (_numEmptyTempFilters != 0) 253 if (_numEmptyTempFilters != 0)
254 { 254 {
255 unsigned num = _tempFilters.Size(); 255 const unsigned num = _tempFilters.Size();
256 CTempFilter **tempFilters = &_tempFilters.Front(); 256 CTempFilter **tempFilters = _tempFilters.NonConstData();
257 257
258 unsigned w = 0; 258 unsigned w = 0;
259 for (unsigned i = 0; i < num; i++) 259 for (unsigned i = 0; i < num; i++)
@@ -542,6 +542,7 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing)
542 PrevAlignBits = 0; 542 PrevAlignBits = 0;
543 PrevAlignCount = 0; 543 PrevAlignCount = 0;
544 544
545 const unsigned kLevelTableSize = 20;
545 Byte levelLevels[kLevelTableSize]; 546 Byte levelLevels[kLevelTableSize];
546 Byte lens[kTablesSizesSum]; 547 Byte lens[kTablesSizesSum];
547 548
@@ -568,23 +569,26 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing)
568 levelLevels[i] = (Byte)len; 569 levelLevels[i] = (Byte)len;
569 } 570 }
570 571
571 RIF(m_LevelDecoder.Build(levelLevels)) 572 NHuffman::CDecoder256<kNumHuffmanBits, kLevelTableSize, 6> m_LevelDecoder;
573 RIF(m_LevelDecoder.Build(levelLevels, NHuffman::k_BuildMode_Full))
572 574
573 i = 0; 575 i = 0;
574 576
575 do 577 do
576 { 578 {
577 const UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream.BitDecoder); 579 const unsigned sym = m_LevelDecoder.DecodeFull(&m_InBitStream.BitDecoder);
578 if (sym < 16) 580 if (sym < 16)
579 { 581 {
580 lens[i] = Byte((sym + m_LastLevels[i]) & 15); 582 lens[i] = Byte((sym + m_LastLevels[i]) & 15);
581 i++; 583 i++;
582 } 584 }
585#if 0
583 else if (sym > kLevelTableSize) 586 else if (sym > kLevelTableSize)
584 return S_FALSE; 587 return S_FALSE;
588#endif
585 else 589 else
586 { 590 {
587 unsigned num = ((sym - 16) & 1) * 4; 591 unsigned num = ((sym /* - 16 */) & 1) * 4;
588 num += num + 3 + (unsigned)ReadBits(num + 3); 592 num += num + 3 + (unsigned)ReadBits(num + 3);
589 num += i; 593 num += i;
590 if (num > kTablesSizesSum) 594 if (num > kTablesSizesSum)
@@ -678,7 +682,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
678 if (InputEofError_Fast()) 682 if (InputEofError_Fast())
679 return S_FALSE; 683 return S_FALSE;
680 684
681 UInt32 sym = m_MainDecoder.Decode(&m_InBitStream.BitDecoder); 685 unsigned sym = m_MainDecoder.Decode(&m_InBitStream.BitDecoder);
682 if (sym < 256) 686 if (sym < 256)
683 { 687 {
684 PutByte((Byte)sym); 688 PutByte((Byte)sym);
@@ -722,14 +726,14 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
722 rep0 = dist; 726 rep0 = dist;
723 } 727 }
724 728
725 const UInt32 sym2 = m_LenDecoder.Decode(&m_InBitStream.BitDecoder); 729 const unsigned sym2 = m_LenDecoder.Decode(&m_InBitStream.BitDecoder);
726 if (sym2 >= kLenTableSize) 730 if (sym2 >= kLenTableSize)
727 return S_FALSE; 731 return S_FALSE;
728 len = 2 + sym2; 732 len = 2 + sym2;
729 if (sym2 >= 8) 733 if (sym2 >= 8)
730 { 734 {
731 unsigned num = (sym2 >> 2) - 1; 735 const unsigned num = (sym2 >> 2) - 1;
732 len = 2 + ((4 + (sym2 & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num); 736 len = 2 + (UInt32)((4 + (sym2 & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num);
733 } 737 }
734 } 738 }
735 else 739 else
@@ -750,9 +754,9 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
750 if (sym >= 8) 754 if (sym >= 8)
751 { 755 {
752 const unsigned num = (sym >> 2) - 1; 756 const unsigned num = (sym >> 2) - 1;
753 len = kNormalMatchMinLen + ((4 + (sym & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num); 757 len = kNormalMatchMinLen + (UInt32)((4 + (sym & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num);
754 } 758 }
755 const UInt32 sym2 = m_DistDecoder.Decode(&m_InBitStream.BitDecoder); 759 const unsigned sym2 = m_DistDecoder.Decode(&m_InBitStream.BitDecoder);
756 if (sym2 >= kDistTableSize) 760 if (sym2 >= kDistTableSize)
757 return S_FALSE; 761 return S_FALSE;
758 rep0 = kDistStart[sym2]; 762 rep0 = kDistStart[sym2];
@@ -768,7 +772,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
768 } 772 }
769 else 773 else
770 { 774 {
771 const UInt32 sym3 = m_AlignDecoder.Decode(&m_InBitStream.BitDecoder); 775 const unsigned sym3 = m_AlignDecoder.Decode(&m_InBitStream.BitDecoder);
772 if (sym3 < (1 << kNumAlignBits)) 776 if (sym3 < (1 << kNumAlignBits))
773 { 777 {
774 rep0 += sym3; 778 rep0 += sym3;
diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h
index 4711052..48fc212 100644
--- a/CPP/7zip/Compress/Rar3Decoder.h
+++ b/CPP/7zip/Compress/Rar3Decoder.h
@@ -22,21 +22,21 @@
22namespace NCompress { 22namespace NCompress {
23namespace NRar3 { 23namespace NRar3 {
24 24
25const unsigned kNumHuffmanBits = 15;
26
25const UInt32 kWindowSize = 1 << 22; 27const UInt32 kWindowSize = 1 << 22;
26const UInt32 kWindowMask = (kWindowSize - 1); 28const UInt32 kWindowMask = kWindowSize - 1;
27 29
28const UInt32 kNumReps = 4; 30const unsigned kNumReps = 4;
29const UInt32 kNumLen2Symbols = 8; 31const unsigned kNumLen2Symbols = 8;
30const UInt32 kLenTableSize = 28; 32const unsigned kLenTableSize = 28;
31const UInt32 kMainTableSize = 256 + 1 + 1 + 1 + kNumReps + kNumLen2Symbols + kLenTableSize; 33const unsigned kMainTableSize = 256 + 3 + kNumReps + kNumLen2Symbols + kLenTableSize;
32const UInt32 kDistTableSize = 60; 34const unsigned kDistTableSize = 60;
33 35
34const unsigned kNumAlignBits = 4; 36const unsigned kNumAlignBits = 4;
35const UInt32 kAlignTableSize = (1 << kNumAlignBits) + 1; 37const unsigned kAlignTableSize = (1 << kNumAlignBits) + 1;
36 38
37const UInt32 kLevelTableSize = 20; 39const unsigned kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;
38
39const UInt32 kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;
40 40
41class CBitDecoder 41class CBitDecoder
42{ 42{
@@ -68,6 +68,7 @@ public:
68 _value = _value & ((1 << _bitPos) - 1); 68 _value = _value & ((1 << _bitPos) - 1);
69 } 69 }
70 70
71 Z7_FORCE_INLINE
71 UInt32 GetValue(unsigned numBits) 72 UInt32 GetValue(unsigned numBits)
72 { 73 {
73 if (_bitPos < numBits) 74 if (_bitPos < numBits)
@@ -82,7 +83,15 @@ public:
82 } 83 }
83 return _value >> (_bitPos - numBits); 84 return _value >> (_bitPos - numBits);
84 } 85 }
86
87 Z7_FORCE_INLINE
88 UInt32 GetValue_InHigh32bits()
89 {
90 return GetValue(kNumHuffmanBits) << (32 - kNumHuffmanBits);
91 }
92
85 93
94 Z7_FORCE_INLINE
86 void MovePos(unsigned numBits) 95 void MovePos(unsigned numBits)
87 { 96 {
88 _bitPos -= numBits; 97 _bitPos -= numBits;
@@ -91,7 +100,7 @@ public:
91 100
92 UInt32 ReadBits(unsigned numBits) 101 UInt32 ReadBits(unsigned numBits)
93 { 102 {
94 UInt32 res = GetValue(numBits); 103 const UInt32 res = GetValue(numBits);
95 MovePos(numBits); 104 MovePos(numBits);
96 return res; 105 return res;
97 } 106 }
@@ -104,7 +113,7 @@ public:
104 _value = (_value << 8) | Stream.ReadByte(); 113 _value = (_value << 8) | Stream.ReadByte();
105 } 114 }
106 _bitPos -= numBits; 115 _bitPos -= numBits;
107 UInt32 res = _value >> _bitPos; 116 const UInt32 res = _value >> _bitPos;
108 _value = _value & ((1 << _bitPos) - 1); 117 _value = _value & ((1 << _bitPos) - 1);
109 return res; 118 return res;
110 } 119 }
@@ -113,8 +122,8 @@ public:
113 { 122 {
114 if (_bitPos == 0) 123 if (_bitPos == 0)
115 return Stream.ReadByte(); 124 return Stream.ReadByte();
116 unsigned bitsPos = _bitPos - 8; 125 const unsigned bitsPos = _bitPos - 8;
117 Byte b = (Byte)(_value >> bitsPos); 126 const Byte b = (Byte)(_value >> bitsPos);
118 _value = _value & ((1 << bitsPos) - 1); 127 _value = _value & ((1 << bitsPos) - 1);
119 _bitPos = bitsPos; 128 _bitPos = bitsPos;
120 return b; 129 return b;
@@ -154,13 +163,19 @@ struct CTempFilter: public NVm::CProgramInitState
154 } 163 }
155}; 164};
156 165
157const unsigned kNumHuffmanBits = 15;
158 166
159Z7_CLASS_IMP_NOQIB_2( 167Z7_CLASS_IMP_NOQIB_2(
160 CDecoder 168 CDecoder
161 , ICompressCoder 169 , ICompressCoder
162 , ICompressSetDecoderProperties2 170 , ICompressSetDecoderProperties2
163) 171)
172 bool _isSolid;
173 bool _solidAllowed;
174 // bool _errorMode;
175
176 bool _lzMode;
177 bool _unsupportedFilter;
178
164 CByteIn m_InBitStream; 179 CByteIn m_InBitStream;
165 Byte *_window; 180 Byte *_window;
166 UInt32 _winPos; 181 UInt32 _winPos;
@@ -169,12 +184,12 @@ Z7_CLASS_IMP_NOQIB_2(
169 UInt64 _unpackSize; 184 UInt64 _unpackSize;
170 UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written 185 UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written
171 ISequentialOutStream *_outStream; 186 ISequentialOutStream *_outStream;
172 NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder; 187
188 NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, 9> m_MainDecoder;
173 UInt32 kDistStart[kDistTableSize]; 189 UInt32 kDistStart[kDistTableSize];
174 NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder; 190 NHuffman::CDecoder256<kNumHuffmanBits, kDistTableSize, 7> m_DistDecoder;
175 NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder; 191 NHuffman::CDecoder256<kNumHuffmanBits, kAlignTableSize, 6> m_AlignDecoder;
176 NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder; 192 NHuffman::CDecoder256<kNumHuffmanBits, kLenTableSize, 7> m_LenDecoder;
177 NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
178 193
179 UInt32 _reps[kNumReps]; 194 UInt32 _reps[kNumReps];
180 UInt32 _lastLength; 195 UInt32 _lastLength;
@@ -189,22 +204,15 @@ Z7_CLASS_IMP_NOQIB_2(
189 unsigned _numEmptyTempFilters; 204 unsigned _numEmptyTempFilters;
190 UInt32 _lastFilter; 205 UInt32 _lastFilter;
191 206
192 bool _isSolid;
193 bool _solidAllowed;
194 // bool _errorMode;
195
196 bool _lzMode;
197 bool _unsupportedFilter;
198
199 UInt32 PrevAlignBits; 207 UInt32 PrevAlignBits;
200 UInt32 PrevAlignCount; 208 UInt32 PrevAlignCount;
201 209
202 bool TablesRead; 210 bool TablesRead;
203 bool TablesOK; 211 bool TablesOK;
212 bool PpmError;
204 213
205 CPpmd7 _ppmd;
206 int PpmEscChar; 214 int PpmEscChar;
207 bool PpmError; 215 CPpmd7 _ppmd;
208 216
209 HRESULT WriteDataToStream(const Byte *data, UInt32 size); 217 HRESULT WriteDataToStream(const Byte *data, UInt32 size);
210 HRESULT WriteData(const Byte *data, UInt32 size); 218 HRESULT WriteData(const Byte *data, UInt32 size);
diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp
index 9b728ef..f4ca500 100644
--- a/CPP/7zip/Compress/Rar3Vm.cpp
+++ b/CPP/7zip/Compress/Rar3Vm.cpp
@@ -967,13 +967,13 @@ static void RgbDecode(Byte *srcData, UInt32 dataSize, UInt32 width, UInt32 posR)
967 967
968 for (UInt32 i = curChannel; i < dataSize; i += kNumChannels) 968 for (UInt32 i = curChannel; i < dataSize; i += kNumChannels)
969 { 969 {
970 unsigned int predicted; 970 unsigned predicted;
971 if (i < width) 971 if (i < width)
972 predicted = prevByte; 972 predicted = prevByte;
973 else 973 else
974 { 974 {
975 const unsigned int upperLeftByte = destData[i - width]; 975 const unsigned upperLeftByte = destData[i - width];
976 const unsigned int upperByte = destData[i - width + 3]; 976 const unsigned upperByte = destData[i - width + 3];
977 predicted = prevByte + upperByte - upperLeftByte; 977 predicted = prevByte + upperByte - upperLeftByte;
978 const int pa = abs((int)(predicted - prevByte)); 978 const int pa = abs((int)(predicted - prevByte));
979 const int pb = abs((int)(predicted - upperByte)); 979 const int pb = abs((int)(predicted - upperByte));
diff --git a/CPP/7zip/Compress/Rar5Decoder.cpp b/CPP/7zip/Compress/Rar5Decoder.cpp
index e55d7de..8be24e2 100644
--- a/CPP/7zip/Compress/Rar5Decoder.cpp
+++ b/CPP/7zip/Compress/Rar5Decoder.cpp
@@ -4,20 +4,618 @@
4 4
5#include "StdAfx.h" 5#include "StdAfx.h"
6 6
7#define DICT_SIZE_MAX ((UInt64)1 << DICT_SIZE_BITS_MAX)
8
9// #include <emmintrin.h> // SSE2
10// #endif
11
12#include "../../../C/CpuArch.h"
13#if 0
14#include "../../../C/Bra.h"
15#endif
16
17#if defined(MY_CPU_ARM64)
18#include <arm_neon.h>
19#endif
20
21// #define Z7_RAR5_SHOW_STAT
7// #include <stdio.h> 22// #include <stdio.h>
23#ifdef Z7_RAR5_SHOW_STAT
24#include <stdio.h>
25#endif
8 26
9#include "../Common/StreamUtils.h" 27#include "../Common/StreamUtils.h"
10 28
11#include "Rar5Decoder.h" 29#include "Rar5Decoder.h"
12 30
31/*
32Note: original-unrar claims that encoder has limitation for Distance:
33 (Distance <= MaxWinSize - MAX_INC_LZ_MATCH)
34 MAX_INC_LZ_MATCH = 0x1001 + 3;
35*/
36
37#define LZ_ERROR_TYPE_NO 0
38#define LZ_ERROR_TYPE_HEADER 1
39// #define LZ_ERROR_TYPE_SYM 1
40#define LZ_ERROR_TYPE_DIST 2
41
42static
43void My_ZeroMemory(void *p, size_t size)
44{
45 #if defined(MY_CPU_AMD64) && !defined(_M_ARM64EC) \
46 && defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL <= 1400)
47 // __stosq((UInt64 *)(void *)win, 0, size / 8);
48 /*
49 printf("\n__stosb \n");
50 #define STEP_BIG (1 << 28)
51 for (size_t i = 0; i < ((UInt64)1 << 50); i += STEP_BIG)
52 {
53 printf("\n__stosb end %p\n", (void *)i);
54 __stosb((Byte *)p + i, 0, STEP_BIG);
55 }
56 */
57 // __stosb((Byte *)p, 0, 0);
58 __stosb((Byte *)p, 0, size);
59 #else
60 // SecureZeroMemory (win, STEP);
61 // ZeroMemory(win, STEP);
62 // memset(win, 0, STEP);
63 memset(p, 0, size);
64 #endif
65}
66
67
68
69#ifdef MY_CPU_LE_UNALIGN
70 #define Z7_RAR5_DEC_USE_UNALIGNED_COPY
71#endif
72
73#ifdef Z7_RAR5_DEC_USE_UNALIGNED_COPY
74
75 #define COPY_CHUNK_SIZE 16
76
77 #define COPY_CHUNK_4_2(dest, src) \
78 { \
79 ((UInt32 *)(void *)dest)[0] = ((const UInt32 *)(const void *)src)[0]; \
80 ((UInt32 *)(void *)dest)[1] = ((const UInt32 *)(const void *)src)[1]; \
81 src += 4 * 2; \
82 dest += 4 * 2; \
83 }
84
85 /* sse2 doesn't help here in GCC and CLANG.
86 so we disabled sse2 here */
87#if 0
88 #if defined(MY_CPU_AMD64)
89 #define Z7_RAR5_DEC_USE_SSE2
90 #elif defined(MY_CPU_X86)
91 #if defined(_MSC_VER) && _MSC_VER >= 1300 && defined(_M_IX86_FP) && (_M_IX86_FP >= 2) \
92 || defined(__SSE2__) \
93 // || 1 == 1 // for debug only
94 #define Z7_RAR5_DEC_USE_SSE2
95 #endif
96 #endif
97#endif
98
99 #if defined(MY_CPU_ARM64)
100
101 #define COPY_OFFSET_MIN 16
102 #define COPY_CHUNK1(dest, src) \
103 { \
104 vst1q_u8((uint8_t *)(void *)dest, \
105 vld1q_u8((const uint8_t *)(const void *)src)); \
106 src += 16; \
107 dest += 16; \
108 }
109
110 #define COPY_CHUNK(dest, src) \
111 { \
112 COPY_CHUNK1(dest, src) \
113 if (dest >= lim) break; \
114 COPY_CHUNK1(dest, src) \
115 }
116
117 #elif defined(Z7_RAR5_DEC_USE_SSE2)
118 #include <emmintrin.h> // sse2
119 #define COPY_OFFSET_MIN 16
120
121 #define COPY_CHUNK1(dest, src) \
122 { \
123 _mm_storeu_si128((__m128i *)(void *)dest, \
124 _mm_loadu_si128((const __m128i *)(const void *)src)); \
125 src += 16; \
126 dest += 16; \
127 }
128
129 #define COPY_CHUNK(dest, src) \
130 { \
131 COPY_CHUNK1(dest, src) \
132 if (dest >= lim) break; \
133 COPY_CHUNK1(dest, src) \
134 }
135
136 #elif defined(MY_CPU_64BIT)
137 #define COPY_OFFSET_MIN 8
138
139 #define COPY_CHUNK(dest, src) \
140 { \
141 ((UInt64 *)(void *)dest)[0] = ((const UInt64 *)(const void *)src)[0]; \
142 src += 8 * 1; dest += 8 * 1; \
143 ((UInt64 *)(void *)dest)[0] = ((const UInt64 *)(const void *)src)[0]; \
144 src += 8 * 1; dest += 8 * 1; \
145 }
146
147 #else
148 #define COPY_OFFSET_MIN 4
149
150 #define COPY_CHUNK(dest, src) \
151 { \
152 COPY_CHUNK_4_2(dest, src); \
153 COPY_CHUNK_4_2(dest, src); \
154 }
155
156 #endif
157#endif
158
159
160#ifndef COPY_CHUNK_SIZE
161 #define COPY_OFFSET_MIN 4
162 #define COPY_CHUNK_SIZE 8
163 #define COPY_CHUNK_2(dest, src) \
164 { \
165 const Byte a0 = src[0]; \
166 const Byte a1 = src[1]; \
167 dest[0] = a0; \
168 dest[1] = a1; \
169 src += 2; \
170 dest += 2; \
171 }
172 #define COPY_CHUNK(dest, src) \
173 { \
174 COPY_CHUNK_2(dest, src) \
175 COPY_CHUNK_2(dest, src) \
176 COPY_CHUNK_2(dest, src) \
177 COPY_CHUNK_2(dest, src) \
178 }
179#endif
180
181
182#define COPY_CHUNKS \
183{ \
184 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \
185 do { COPY_CHUNK(dest, src) } \
186 while (dest < lim); \
187}
188
13namespace NCompress { 189namespace NCompress {
14namespace NRar5 { 190namespace NRar5 {
15 191
192typedef
193#if 1
194 unsigned
195#else
196 size_t
197#endif
198 CLenType;
199
200// (len != 0)
201static
202Z7_FORCE_INLINE
203// Z7_ATTRIB_NO_VECTOR
204void CopyMatch(size_t offset, Byte *dest, const Byte *src, const Byte *lim)
205{
206 {
207 // (COPY_OFFSET_MIN >= 4)
208 if (offset >= COPY_OFFSET_MIN)
209 {
210 COPY_CHUNKS
211 // return;
212 }
213 else
214 #if (COPY_OFFSET_MIN > 4)
215 #if COPY_CHUNK_SIZE < 8
216 #error Stop_Compiling_Bad_COPY_CHUNK_SIZE
217 #endif
218 if (offset >= 4)
219 {
220 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
221 do
222 {
223 COPY_CHUNK_4_2(dest, src)
224 #if COPY_CHUNK_SIZE < 16
225 if (dest >= lim) break;
226 #endif
227 COPY_CHUNK_4_2(dest, src)
228 }
229 while (dest < lim);
230 // return;
231 }
232 else
233 #endif
234 {
235 // (offset < 4)
236 const unsigned b0 = src[0];
237 if (offset < 2)
238 {
239 #if defined(Z7_RAR5_DEC_USE_UNALIGNED_COPY) && (COPY_CHUNK_SIZE == 16)
240 #if defined(MY_CPU_64BIT)
241 {
242 const UInt64 v64 = (UInt64)b0 * 0x0101010101010101;
243 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
244 do
245 {
246 ((UInt64 *)(void *)dest)[0] = v64;
247 ((UInt64 *)(void *)dest)[1] = v64;
248 dest += 16;
249 }
250 while (dest < lim);
251 }
252 #else
253 {
254 UInt32 v = b0;
255 v |= v << 8;
256 v |= v << 16;
257 do
258 {
259 ((UInt32 *)(void *)dest)[0] = v;
260 ((UInt32 *)(void *)dest)[1] = v;
261 dest += 8;
262 ((UInt32 *)(void *)dest)[0] = v;
263 ((UInt32 *)(void *)dest)[1] = v;
264 dest += 8;
265 }
266 while (dest < lim);
267 }
268 #endif
269 #else
270 do
271 {
272 dest[0] = (Byte)b0;
273 dest[1] = (Byte)b0;
274 dest += 2;
275 dest[0] = (Byte)b0;
276 dest[1] = (Byte)b0;
277 dest += 2;
278 }
279 while (dest < lim);
280 #endif
281 }
282 else if (offset == 2)
283 {
284 const Byte b1 = src[1];
285 {
286 do
287 {
288 dest[0] = (Byte)b0;
289 dest[1] = b1;
290 dest += 2;
291 }
292 while (dest < lim);
293 }
294 }
295 else // (offset == 3)
296 {
297 const Byte b1 = src[1];
298 const Byte b2 = src[2];
299 do
300 {
301 dest[0] = (Byte)b0;
302 dest[1] = b1;
303 dest[2] = b2;
304 dest += 3;
305 }
306 while (dest < lim);
307 }
308 }
309 }
310}
311
16static const size_t kInputBufSize = 1 << 20; 312static const size_t kInputBufSize = 1 << 20;
17 313static const UInt32 k_Filter_BlockSize_MAX = 1 << 22;
314static const unsigned k_Filter_AfterPad_Size = 64;
315
316#ifdef Z7_RAR5_SHOW_STAT
317static const unsigned kNumStats1 = 10;
318static const unsigned kNumStats2 = (1 << 12) + 16;
319static UInt32 g_stats1[kNumStats1];
320static UInt32 g_stats2[kNumStats1][kNumStats2];
321#endif
322
323#if 1
324MY_ALIGN(32)
325// DICT_SIZE_BITS_MAX-1 are required
326static const Byte k_LenPlusTable[DICT_SIZE_BITS_MAX] =
327 { 0,0,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 };
328#endif
329
330
331
332class CBitDecoder
333{
334public:
335 const Byte *_buf;
336 const Byte *_bufCheck_Block; // min(ptr for _blockEnd, _bufCheck)
337 unsigned _bitPos; // = [0 ... 7]
338 bool _wasFinished;
339 bool _minorError;
340 unsigned _blockEndBits7; // = [0 ... 7] : the number of additional bits in (_blockEnd) poisition.
341 HRESULT _hres;
342 const Byte *_bufCheck; // relaxed limit (16 bytes before real end of input data in buffer)
343 Byte *_bufLim; // end if input data
344 Byte *_bufBase;
345 ISequentialInStream *_stream;
346
347 UInt64 _processedSize;
348 UInt64 _blockEnd; // absolute end of current block
349 // but it doesn't include additional _blockEndBits7 [0 ... 7] bits
350
351 Z7_FORCE_INLINE
352 void CopyFrom(const CBitDecoder &a)
353 {
354 _buf = a._buf;
355 _bufCheck_Block = a._bufCheck_Block;
356 _bitPos = a._bitPos;
357 _wasFinished = a._wasFinished;
358 _blockEndBits7 = a._blockEndBits7;
359 _bufCheck = a._bufCheck;
360 _bufLim = a._bufLim;
361 _bufBase = a._bufBase;
362
363 _processedSize = a._processedSize;
364 _blockEnd = a._blockEnd;
365 }
366
367 Z7_FORCE_INLINE
368 void RestoreFrom2(const CBitDecoder &a)
369 {
370 _buf = a._buf;
371 _bitPos = a._bitPos;
372 }
373
374 Z7_FORCE_INLINE
375 void SetCheck_forBlock()
376 {
377 _bufCheck_Block = _bufCheck;
378 if (_bufCheck > _buf)
379 {
380 const UInt64 processed = GetProcessedSize_Round();
381 if (_blockEnd < processed)
382 _bufCheck_Block = _buf;
383 else
384 {
385 const UInt64 delta = _blockEnd - processed;
386 if ((size_t)(_bufCheck - _buf) > delta)
387 _bufCheck_Block = _buf + (size_t)delta;
388 }
389 }
390 }
391
392 Z7_FORCE_INLINE
393 bool IsBlockOverRead() const
394 {
395 const UInt64 v = GetProcessedSize_Round();
396 if (v < _blockEnd) return false;
397 if (v > _blockEnd) return true;
398 return _bitPos > _blockEndBits7;
399 }
400
401 /*
402 CBitDecoder() throw():
403 _buf(0),
404 _bufLim(0),
405 _bufBase(0),
406 _stream(0),
407 _processedSize(0),
408 _wasFinished(false)
409 {}
410 */
411
412 Z7_FORCE_INLINE
413 void Init() throw()
414 {
415 _blockEnd = 0;
416 _blockEndBits7 = 0;
417
418 _bitPos = 0;
419 _processedSize = 0;
420 _buf = _bufBase;
421 _bufLim = _bufBase;
422 _bufCheck = _buf;
423 _bufCheck_Block = _buf;
424 _wasFinished = false;
425 _minorError = false;
426 }
427
428 void Prepare2() throw();
429
430 Z7_FORCE_INLINE
431 void Prepare() throw()
432 {
433 if (_buf >= _bufCheck)
434 Prepare2();
435 }
436
437 Z7_FORCE_INLINE
438 bool ExtraBitsWereRead() const
439 {
440 return _buf >= _bufLim && (_buf > _bufLim || _bitPos != 0);
441 }
442
443 Z7_FORCE_INLINE bool InputEofError() const { return ExtraBitsWereRead(); }
444
445 Z7_FORCE_INLINE unsigned GetProcessedBits7() const { return _bitPos; }
446 Z7_FORCE_INLINE UInt64 GetProcessedSize_Round() const { return _processedSize + (size_t)(_buf - _bufBase); }
447 Z7_FORCE_INLINE UInt64 GetProcessedSize() const { return _processedSize + (size_t)(_buf - _bufBase) + ((_bitPos + 7) >> 3); }
448
449 Z7_FORCE_INLINE
450 void AlignToByte()
451 {
452 if (_bitPos != 0)
453 {
454#if 1
455 // optional check of unused bits for strict checking:
456 // original-unrar doesn't check it:
457 const unsigned b = (unsigned)*_buf << _bitPos;
458 if (b & 0xff)
459 _minorError = true;
460#endif
461 _buf++;
462 _bitPos = 0;
463 }
464 // _buf += (_bitPos + 7) >> 3;
465 // _bitPos = 0;
466 }
467
468 Z7_FORCE_INLINE
469 Byte ReadByte_InAligned()
470 {
471 return *_buf++;
472 }
473
474 Z7_FORCE_INLINE
475 UInt32 GetValue(unsigned numBits) const
476 {
477 // 0 < numBits <= 17 : supported values
478#if defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE_UNALIGN)
479 UInt32 v = GetBe32(_buf);
480#if 1
481 return (v >> (32 - numBits - _bitPos)) & ((1u << numBits) - 1);
482#else
483 return (v << _bitPos) >> (32 - numBits);
484#endif
485#else
486 UInt32 v = ((UInt32)_buf[0] << 16) | ((UInt32)_buf[1] << 8) | (UInt32)_buf[2];
487 v >>= 24 - numBits - _bitPos;
488 return v & ((1 << numBits) - 1);
489#endif
490 }
491
492 Z7_FORCE_INLINE
493 UInt32 GetValue_InHigh32bits() const
494 {
495 // 0 < numBits <= 17 : supported vales
496#if defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE_UNALIGN)
497 return GetBe32(_buf) << _bitPos;
498#else
499 const UInt32 v = ((UInt32)_buf[0] << 16) | ((UInt32)_buf[1] << 8) | (UInt32)_buf[2];
500 return v << (_bitPos + 8);
501#endif
502 }
503
504
505 Z7_FORCE_INLINE
506 void MovePos(unsigned numBits)
507 {
508 numBits += _bitPos;
509 _buf += numBits >> 3;
510 _bitPos = numBits & 7;
511 }
512
513
514 Z7_FORCE_INLINE
515 UInt32 ReadBits9(unsigned numBits)
516 {
517 const Byte *buf = _buf;
518 UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];
519 v &= (UInt32)0xFFFF >> _bitPos;
520 numBits += _bitPos;
521 v >>= 16 - numBits;
522 _buf = buf + (numBits >> 3);
523 _bitPos = numBits & 7;
524 return v;
525 }
526
527 Z7_FORCE_INLINE
528 UInt32 ReadBits_9fix(unsigned numBits)
529 {
530 const Byte *buf = _buf;
531 UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];
532 const UInt32 mask = (1u << numBits) - 1;
533 numBits += _bitPos;
534 v >>= 16 - numBits;
535 _buf = buf + (numBits >> 3);
536 _bitPos = numBits & 7;
537 return v & mask;
538 }
539
540#if 1 && defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 8)
541#define Z7_RAR5_USE_64BIT
542#endif
543
544#ifdef Z7_RAR5_USE_64BIT
545#define MAX_DICT_LOG (sizeof(size_t) / 8 * 5 + 31)
546#else
547#define MAX_DICT_LOG 31
548#endif
549
550#ifdef Z7_RAR5_USE_64BIT
551
552 Z7_FORCE_INLINE
553 size_t ReadBits_Big(unsigned numBits, UInt64 v)
554 {
555 const UInt64 mask = ((UInt64)1 << numBits) - 1;
556 numBits += _bitPos;
557 const Byte *buf = _buf;
558 // UInt64 v = GetBe64(buf);
559 v >>= 64 - numBits;
560 _buf = buf + (numBits >> 3);
561 _bitPos = numBits & 7;
562 return (size_t)(v & mask);
563 }
564 #define ReadBits_Big25 ReadBits_Big
565
566#else
567
568 // (numBits <= 25) for 32-bit mode
569 Z7_FORCE_INLINE
570 size_t ReadBits_Big25(unsigned numBits, UInt32 v)
571 {
572 const UInt32 mask = ((UInt32)1 << numBits) - 1;
573 numBits += _bitPos;
574 v >>= 32 - numBits;
575 _buf += numBits >> 3;
576 _bitPos = numBits & 7;
577 return v & mask;
578 }
579
580 // numBits != 0
581 Z7_FORCE_INLINE
582 size_t ReadBits_Big(unsigned numBits, UInt32 v)
583 {
584 const Byte *buf = _buf;
585 // UInt32 v = GetBe32(buf);
586#if 0
587 const UInt32 mask = ((UInt32)1 << numBits) - 1;
588 numBits += _bitPos;
589 if (numBits > 32)
590 {
591 v <<= numBits - 32;
592 v |= (UInt32)buf[4] >> (40 - numBits);
593 }
594 else
595 v >>= 32 - numBits;
596 _buf = buf + (numBits >> 3);
597 _bitPos = numBits & 7;
598 return v & mask;
599#else
600 v <<= _bitPos;
601 v |= (UInt32)buf[4] >> (8 - _bitPos);
602 v >>= 32 - numBits;
603 numBits += _bitPos;
604 _buf = buf + (numBits >> 3);
605 _bitPos = numBits & 7;
606 return v;
607#endif
608 }
609#endif
610};
611
612
613static const unsigned kLookaheadSize = 16;
614static const unsigned kInputBufferPadZone = kLookaheadSize;
615
616Z7_NO_INLINE
18void CBitDecoder::Prepare2() throw() 617void CBitDecoder::Prepare2() throw()
19{ 618{
20 const unsigned kSize = 16;
21 if (_buf > _bufLim) 619 if (_buf > _bufLim)
22 return; 620 return;
23 621
@@ -29,27 +627,39 @@ void CBitDecoder::Prepare2() throw()
29 _processedSize += (size_t)(_buf - _bufBase); 627 _processedSize += (size_t)(_buf - _bufBase);
30 _buf = _bufBase; 628 _buf = _bufBase;
31 629
630 // we do not look ahead more than 16 bytes before limit checks.
631
32 if (!_wasFinished) 632 if (!_wasFinished)
33 { 633 {
34 UInt32 processed = (UInt32)(kInputBufSize - rem); 634 while (rem <= kLookaheadSize)
35 _hres = _stream->Read(_bufLim, (UInt32)processed, &processed);
36 _bufLim += processed;
37 _wasFinished = (processed == 0);
38 if (_hres != S_OK)
39 { 635 {
40 _wasFinished = true; 636 UInt32 processed = (UInt32)(kInputBufSize - rem);
41 // throw CInBufferException(result); 637 // processed = 33; // for debug
638 _hres = _stream->Read(_bufLim, processed, &processed);
639 _bufLim += processed;
640 rem += processed;
641 if (processed == 0 || _hres != S_OK)
642 {
643 _wasFinished = true;
644 // if (_hres != S_OK) throw CInBufferException(result);
645 break;
646 }
42 } 647 }
43 } 648 }
44 649
45 rem = (size_t)(_bufLim - _buf); 650 // we always fill pad zone here.
46 _bufCheck = _buf; 651 // so we don't need to call Prepare2() if (_wasFinished == true)
47 if (rem < kSize) 652 memset(_bufLim, 0xFF, kLookaheadSize);
48 memset(_bufLim, 0xFF, kSize - rem); 653
654 if (rem < kLookaheadSize)
655 {
656 _bufCheck = _buf;
657 // memset(_bufLim, 0xFF, kLookaheadSize - rem);
658 }
49 else 659 else
50 _bufCheck = _bufLim - kSize; 660 _bufCheck = _bufLim - kLookaheadSize;
51 661
52 SetCheck2(); 662 SetCheck_forBlock();
53} 663}
54 664
55 665
@@ -61,29 +671,79 @@ enum FilterType
61 FILTER_ARM 671 FILTER_ARM
62}; 672};
63 673
64static const size_t kWriteStep = (size_t)1 << 22; 674static const size_t kWriteStep = (size_t)1 << 18;
675 // (size_t)1 << 22; // original-unrar
676
677// Original unRAR claims that maximum possible filter block size is (1 << 16) now,
678// and (1 << 17) is minimum win size required to support filter.
679// Original unRAR uses (1u << 18) for "extra safety and possible filter area size expansion"
680// We can use any win size, but we use same (1u << 18) for compatibility
681// with WinRar
682
683// static const unsigned kWinSize_Log_Min = 17;
684static const size_t kWinSize_Min = 1u << 18;
65 685
66CDecoder::CDecoder(): 686CDecoder::CDecoder():
67 _isSolid(false), 687 _isSolid(false),
68 _solidAllowed(false), 688 _is_v7(false),
69 _wasInit(false), 689 _wasInit(false),
70 _dictSizeLog(0), 690 // _dictSizeLog(0),
691 _dictSize(kWinSize_Min),
71 _window(NULL), 692 _window(NULL),
72 _winPos(0), 693 _winPos(0),
694 _winSize(0),
695 _dictSize_forCheck(0),
73 _lzSize(0), 696 _lzSize(0),
74 _lzEnd(0), 697 _lzEnd(0),
75 _writtenFileSize(0), 698 _writtenFileSize(0),
76 _winSizeAllocated(0), 699 _filters(NULL),
700 _winSize_Allocated(0),
77 _inputBuf(NULL) 701 _inputBuf(NULL)
78{ 702{
703#if 1
704 memcpy(m_LenPlusTable, k_LenPlusTable, sizeof(k_LenPlusTable));
705#endif
706 // printf("\nsizeof(CDecoder) == %d\n", sizeof(CDecoder));
79} 707}
80 708
81CDecoder::~CDecoder() 709CDecoder::~CDecoder()
82{ 710{
83 ::MidFree(_window); 711#ifdef Z7_RAR5_SHOW_STAT
84 ::MidFree(_inputBuf); 712 printf("\n%4d :", 0);
713 for (unsigned k = 0; k < kNumStats1; k++)
714 printf(" %8u", (unsigned)g_stats1[k]);
715 printf("\n");
716 for (unsigned i = 0; i < kNumStats2; i++)
717 {
718 printf("\n%4d :", i);
719 for (unsigned k = 0; k < kNumStats1; k++)
720 printf(" %8u", (unsigned)g_stats2[k][i]);
721 }
722 printf("\n");
723#endif
724
725#define Z7_RAR_FREE_WINDOW ::BigFree(_window);
726
727 Z7_RAR_FREE_WINDOW
728 z7_AlignedFree(_inputBuf);
729 z7_AlignedFree(_filters);
85} 730}
86 731
732Z7_NO_INLINE
733void CDecoder::DeleteUnusedFilters()
734{
735 if (_numUnusedFilters != 0)
736 {
737 // printf("\nDeleteUnusedFilters _numFilters = %6u\n", _numFilters);
738 const unsigned n = _numFilters - _numUnusedFilters;
739 _numFilters = n;
740 memmove(_filters, _filters + _numUnusedFilters, n * sizeof(CFilter));
741 _numUnusedFilters = 0;
742 }
743}
744
745
746Z7_NO_INLINE
87HRESULT CDecoder::WriteData(const Byte *data, size_t size) 747HRESULT CDecoder::WriteData(const Byte *data, size_t size)
88{ 748{
89 HRESULT res = S_OK; 749 HRESULT res = S_OK;
@@ -104,107 +764,172 @@ HRESULT CDecoder::WriteData(const Byte *data, size_t size)
104 return res; 764 return res;
105} 765}
106 766
767
768#if defined(MY_CPU_SIZEOF_POINTER) \
769 && ( MY_CPU_SIZEOF_POINTER == 4 \
770 || MY_CPU_SIZEOF_POINTER == 8)
771 #define BR_CONV_USE_OPT_PC_PTR
772#endif
773
774#ifdef BR_CONV_USE_OPT_PC_PTR
775#define BR_PC_INIT(lim_back) pc -= (UInt32)(SizeT)data;
776#define BR_PC_GET (pc + (UInt32)(SizeT)data)
777#else
778#define BR_PC_INIT(lim_back) pc += (UInt32)dataSize - (lim_back);
779#define BR_PC_GET (pc - (UInt32)(SizeT)(data_lim - data))
780#endif
781
782#ifdef MY_CPU_LE_UNALIGN
783#define Z7_RAR5_FILTER_USE_LE_UNALIGN
784#endif
785
786#ifdef Z7_RAR5_FILTER_USE_LE_UNALIGN
787#define RAR_E8_FILT(mask) \
788{ \
789 for (;;) \
790 { UInt32 v; \
791 do { \
792 v = GetUi32(data) ^ (UInt32)0xe8e8e8e8; \
793 data += 4; \
794 if ((v & ((UInt32)(mask) << (8 * 0))) == 0) { data -= 3; break; } \
795 if ((v & ((UInt32)(mask) << (8 * 1))) == 0) { data -= 2; break; } \
796 if ((v & ((UInt32)(mask) << (8 * 2))) == 0) { data -= 1; break; } } \
797 while((v & ((UInt32)(mask) << (8 * 3)))); \
798 if (data > data_lim) break; \
799 const UInt32 offset = BR_PC_GET & (kFileSize - 1); \
800 const UInt32 addr = GetUi32(data); \
801 data += 4; \
802 if (addr < kFileSize) \
803 SetUi32(data - 4, addr - offset) \
804 else if (addr > ~offset) /* if (addr > ((UInt32)0xFFFFFFFF - offset)) */ \
805 SetUi32(data - 4, addr + kFileSize) \
806 } \
807}
808#else
809#define RAR_E8_FILT(get_byte) \
810{ \
811 for (;;) \
812 { \
813 if ((get_byte) != 0xe8) \
814 if ((get_byte) != 0xe8) \
815 if ((get_byte) != 0xe8) \
816 if ((get_byte) != 0xe8) \
817 continue; \
818 { if (data > data_lim) break; \
819 const UInt32 offset = BR_PC_GET & (kFileSize - 1); \
820 const UInt32 addr = GetUi32(data); \
821 data += 4; \
822 if (addr < kFileSize) \
823 SetUi32(data - 4, addr - offset) \
824 else if (addr > ~offset) /* if (addr > ((UInt32)0xFFFFFFFF - offset)) */ \
825 SetUi32(data - 4, addr + kFileSize) \
826 } \
827 } \
828}
829#endif
830
107HRESULT CDecoder::ExecuteFilter(const CFilter &f) 831HRESULT CDecoder::ExecuteFilter(const CFilter &f)
108{ 832{
109 bool useDest = false;
110
111 Byte *data = _filterSrc; 833 Byte *data = _filterSrc;
112 UInt32 dataSize = f.Size; 834 UInt32 dataSize = f.Size;
113
114 // printf("\nType = %d offset = %9d size = %5d", f.Type, (unsigned)(f.Start - _lzFileStart), dataSize); 835 // printf("\nType = %d offset = %9d size = %5d", f.Type, (unsigned)(f.Start - _lzFileStart), dataSize);
115 836
116 switch (f.Type) 837 if (f.Type == FILTER_DELTA)
117 { 838 {
118 case FILTER_E8: 839 // static unsigned g1 = 0, g2 = 0; g1 += dataSize;
119 case FILTER_E8E9: 840 // if (g2++ % 100 == 0) printf("DELTA num %8u, size %8u MiB, channels = %2u curSize=%8u\n", g2, (g1 >> 20), f.Channels, dataSize);
841 _filterDst.AllocAtLeast_max((size_t)dataSize, k_Filter_BlockSize_MAX);
842 if (!_filterDst.IsAllocated())
843 return E_OUTOFMEMORY;
844
845 Byte *dest = _filterDst;
846 const unsigned numChannels = f.Channels;
847 unsigned curChannel = 0;
848 do
120 { 849 {
121 // printf(" FILTER_E8"); 850 Byte prevByte = 0;
122 if (dataSize > 4) 851 Byte *dest2 = dest + curChannel;
123 { 852 const Byte *dest_lim = dest + dataSize;
124 dataSize -= 4; 853 for (; dest2 < dest_lim; dest2 += numChannels)
125 const UInt32 fileOffset = (UInt32)(f.Start - _lzFileStart); 854 *dest2 = (prevByte = (Byte)(prevByte - *data++));
126
127 const UInt32 kFileSize = (UInt32)1 << 24;
128 const Byte cmpMask = (Byte)(f.Type == FILTER_E8 ? 0xFF : 0xFE);
129
130 for (UInt32 curPos = 0; curPos < dataSize;)
131 {
132 curPos++;
133 if (((*data++) & cmpMask) == 0xE8)
134 {
135 const UInt32 offset = (curPos + fileOffset) & (kFileSize - 1);
136 const UInt32 addr = GetUi32(data);
137
138 if (addr < kFileSize)
139 {
140 SetUi32(data, addr - offset)
141 }
142 else if (addr > ((UInt32)0xFFFFFFFF - offset)) // (addr > ~(offset))
143 {
144 SetUi32(data, addr + kFileSize)
145 }
146
147 data += 4;
148 curPos += 4;
149 }
150 }
151 }
152 break;
153 } 855 }
154 856 while (++curChannel != numChannels);
155 case FILTER_ARM: 857 // return WriteData(dest, dataSize);
858 data = dest;
859 }
860 else if (f.Type < FILTER_ARM)
861 {
862 // FILTER_E8 or FILTER_E8E9
863 if (dataSize > 4)
156 { 864 {
157 if (dataSize >= 4) 865 UInt32 pc = (UInt32)(f.Start - _lzFileStart);
866 const UInt32 kFileSize = (UInt32)1 << 24;
867 const Byte *data_lim = data + dataSize - 4;
868 BR_PC_INIT(4) // because (data_lim) was moved back for 4 bytes
869 data[dataSize] = 0xe8;
870 if (f.Type == FILTER_E8)
158 { 871 {
159 dataSize -= 4; 872 // static unsigned g1 = 0; g1 += dataSize; printf("\n FILTER_E8 %u", (g1 >> 20));
160 const UInt32 fileOffset = (UInt32)(f.Start - _lzFileStart); 873#ifdef Z7_RAR5_FILTER_USE_LE_UNALIGN
161 874 RAR_E8_FILT (0xff)
162 for (UInt32 curPos = 0; curPos <= dataSize; curPos += 4) 875#else
163 { 876 RAR_E8_FILT (*data++)
164 Byte *d = data + curPos; 877#endif
165 if (d[3] == 0xEB) 878 }
166 { 879 else
167 UInt32 offset = d[0] | ((UInt32)d[1] << 8) | ((UInt32)d[2] << 16); 880 {
168 offset -= (fileOffset + curPos) >> 2; 881 // static unsigned g1 = 0; g1 += dataSize; printf("\n FILTER_E8_E9 %u", (g1 >> 20));
169 d[0] = (Byte)offset; 882#ifdef Z7_RAR5_FILTER_USE_LE_UNALIGN
170 d[1] = (Byte)(offset >> 8); 883 RAR_E8_FILT (0xfe)
171 d[2] = (Byte)(offset >> 16); 884#else
172 } 885 RAR_E8_FILT (*data++ & 0xfe)
173 } 886#endif
174 } 887 }
175 break;
176 } 888 }
177 889 data = _filterSrc;
178 case FILTER_DELTA: 890 }
891 else if (f.Type == FILTER_ARM)
892 {
893 UInt32 pc = (UInt32)(f.Start - _lzFileStart);
894#if 0
895 // z7_BranchConv_ARM_Dec expects that (fileOffset & 3) == 0;
896 // but even if (fileOffset & 3) then current code
897 // in z7_BranchConv_ARM_Dec works same way as unrar's code still.
898 z7_BranchConv_ARM_Dec(data, dataSize, pc - 8);
899#else
900 dataSize &= ~(UInt32)3;
901 if (dataSize)
179 { 902 {
180 // printf(" channels = %d", f.Channels); 903 Byte *data_lim = data + dataSize;
181 _filterDst.AllocAtLeast(dataSize); 904 data_lim[3] = 0xeb;
182 if (!_filterDst.IsAllocated()) 905 BR_PC_INIT(0)
183 return E_OUTOFMEMORY; 906 pc -= 4; // because (data) will point to next instruction
184 907 for (;;) // do
185 Byte *dest = _filterDst;
186 const UInt32 numChannels = f.Channels;
187
188 for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)
189 { 908 {
190 Byte prevByte = 0; 909 data += 4;
191 for (UInt32 destPos = curChannel; destPos < dataSize; destPos += numChannels) 910 if (data[-1] != 0xeb)
192 dest[destPos] = (prevByte = (Byte)(prevByte - *data++)); 911 continue;
912 if (data > data_lim)
913 break;
914 {
915 UInt32 v = GetUi32a(data - 4) - (BR_PC_GET >> 2);
916 v &= 0x00ffffff;
917 v |= 0xeb000000;
918 SetUi32a(data - 4, v)
919 }
193 } 920 }
194 useDest = true;
195 break;
196 } 921 }
197 922#endif
198 default: 923 data = _filterSrc;
199 _unsupportedFilter = true;
200 memset(_filterSrc, 0, f.Size);
201 // return S_OK; // unrar
202 } 924 }
203 925 else
204 return WriteData(useDest ? 926 {
205 (const Byte *)_filterDst : 927 _unsupportedFilter = true;
206 (const Byte *)_filterSrc, 928 My_ZeroMemory(data, dataSize);
207 f.Size); 929 // return S_OK; // unrar
930 }
931 // return WriteData(_filterSrc, (size_t)f.Size);
932 return WriteData(data, (size_t)f.Size);
208} 933}
209 934
210 935
@@ -212,13 +937,13 @@ HRESULT CDecoder::WriteBuf()
212{ 937{
213 DeleteUnusedFilters(); 938 DeleteUnusedFilters();
214 939
215 for (unsigned i = 0; i < _filters.Size();) 940 const UInt64 lzSize = _lzSize + _winPos;
941
942 for (unsigned i = 0; i < _numFilters;)
216 { 943 {
217 const CFilter &f = _filters[i]; 944 const CFilter &f = _filters[i];
218
219 const UInt64 blockStart = f.Start; 945 const UInt64 blockStart = f.Start;
220 946 const size_t lzAvail = (size_t)(lzSize - _lzWritten);
221 const size_t lzAvail = (size_t)(_lzSize - _lzWritten);
222 if (lzAvail == 0) 947 if (lzAvail == 0)
223 break; 948 break;
224 949
@@ -228,7 +953,7 @@ HRESULT CDecoder::WriteBuf()
228 size_t size = lzAvail; 953 size_t size = lzAvail;
229 if (size > rem) 954 if (size > rem)
230 size = (size_t)rem; 955 size = (size_t)rem;
231 if (size != 0) 956 if (size != 0) // is it true always ?
232 { 957 {
233 RINOK(WriteData(_window + _winPos - lzAvail, size)) 958 RINOK(WriteData(_window + _winPos - lzAvail, size))
234 _lzWritten += size; 959 _lzWritten += size;
@@ -240,7 +965,9 @@ HRESULT CDecoder::WriteBuf()
240 size_t offset = (size_t)(_lzWritten - blockStart); 965 size_t offset = (size_t)(_lzWritten - blockStart);
241 if (offset == 0) 966 if (offset == 0)
242 { 967 {
243 _filterSrc.AllocAtLeast(blockSize); 968 _filterSrc.AllocAtLeast_max(
969 (size_t)blockSize + k_Filter_AfterPad_Size,
970 k_Filter_BlockSize_MAX + k_Filter_AfterPad_Size);
244 if (!_filterSrc.IsAllocated()) 971 if (!_filterSrc.IsAllocated())
245 return E_OUTOFMEMORY; 972 return E_OUTOFMEMORY;
246 } 973 }
@@ -248,7 +975,7 @@ HRESULT CDecoder::WriteBuf()
248 const size_t blockRem = (size_t)blockSize - offset; 975 const size_t blockRem = (size_t)blockSize - offset;
249 size_t size = lzAvail; 976 size_t size = lzAvail;
250 if (size > blockRem) 977 if (size > blockRem)
251 size = blockRem; 978 size = blockRem;
252 memcpy(_filterSrc + offset, _window + _winPos - lzAvail, size); 979 memcpy(_filterSrc + offset, _window + _winPos - lzAvail, size);
253 _lzWritten += size; 980 _lzWritten += size;
254 offset += size; 981 offset += size;
@@ -261,22 +988,28 @@ HRESULT CDecoder::WriteBuf()
261 988
262 DeleteUnusedFilters(); 989 DeleteUnusedFilters();
263 990
264 if (!_filters.IsEmpty()) 991 if (_numFilters)
265 return S_OK; 992 return S_OK;
266 993
267 const size_t lzAvail = (size_t)(_lzSize - _lzWritten); 994 const size_t lzAvail = (size_t)(lzSize - _lzWritten);
268 RINOK(WriteData(_window + _winPos - lzAvail, lzAvail)) 995 RINOK(WriteData(_window + _winPos - lzAvail, lzAvail))
269 _lzWritten += lzAvail; 996 _lzWritten += lzAvail;
270 return S_OK; 997 return S_OK;
271} 998}
272 999
273 1000
1001Z7_NO_INLINE
274static UInt32 ReadUInt32(CBitDecoder &bi) 1002static UInt32 ReadUInt32(CBitDecoder &bi)
275{ 1003{
276 const unsigned numBytes = bi.ReadBits9fix(2) + 1; 1004 const unsigned numBits = (unsigned)bi.ReadBits_9fix(2) * 8 + 8;
277 UInt32 v = 0; 1005 UInt32 v = 0;
278 for (unsigned i = 0; i < numBytes; i++) 1006 unsigned i = 0;
279 v += ((UInt32)bi.ReadBits9fix(8) << (i * 8)); 1007 do
1008 {
1009 v += (UInt32)bi.ReadBits_9fix(8) << i;
1010 i += 8;
1011 }
1012 while (i != numBits);
280 return v; 1013 return v;
281} 1014}
282 1015
@@ -287,11 +1020,11 @@ HRESULT CDecoder::AddFilter(CBitDecoder &_bitStream)
287{ 1020{
288 DeleteUnusedFilters(); 1021 DeleteUnusedFilters();
289 1022
290 if (_filters.Size() >= MAX_UNPACK_FILTERS) 1023 if (_numFilters >= MAX_UNPACK_FILTERS)
291 { 1024 {
292 RINOK(WriteBuf()) 1025 RINOK(WriteBuf())
293 DeleteUnusedFilters(); 1026 DeleteUnusedFilters();
294 if (_filters.Size() >= MAX_UNPACK_FILTERS) 1027 if (_numFilters >= MAX_UNPACK_FILTERS)
295 { 1028 {
296 _unsupportedFilter = true; 1029 _unsupportedFilter = true;
297 InitFilters(); 1030 InitFilters();
@@ -304,17 +1037,24 @@ HRESULT CDecoder::AddFilter(CBitDecoder &_bitStream)
304 const UInt32 blockStart = ReadUInt32(_bitStream); 1037 const UInt32 blockStart = ReadUInt32(_bitStream);
305 f.Size = ReadUInt32(_bitStream); 1038 f.Size = ReadUInt32(_bitStream);
306 1039
307 if (f.Size > ((UInt32)1 << 22)) 1040 if (f.Size > k_Filter_BlockSize_MAX)
308 { 1041 {
309 _unsupportedFilter = true; 1042 _unsupportedFilter = true;
310 f.Size = 0; // unrar 5.5.5 1043 f.Size = 0; // unrar 5.5.5
311 } 1044 }
312 1045
313 f.Type = (Byte)_bitStream.ReadBits9fix(3); 1046 f.Type = (Byte)_bitStream.ReadBits_9fix(3);
314 f.Channels = 0; 1047 f.Channels = 0;
315 if (f.Type == FILTER_DELTA) 1048 if (f.Type == FILTER_DELTA)
316 f.Channels = (Byte)(_bitStream.ReadBits9fix(5) + 1); 1049 f.Channels = (Byte)(_bitStream.ReadBits_9fix(5) + 1);
317 f.Start = _lzSize + blockStart; 1050 f.Start = _lzSize + _winPos + blockStart;
1051
1052#if 0
1053 static unsigned z_cnt = 0; if (z_cnt++ % 100 == 0)
1054 printf ("\nFilter %7u : %4u : %8p, st=%8x, size=%8x, type=%u ch=%2u",
1055 z_cnt, (unsigned)_filters.Size(), (void *)(size_t)(_lzSize + _winPos),
1056 (unsigned)blockStart, (unsigned)f.Size, (unsigned)f.Type, (unsigned)f.Channels);
1057#endif
318 1058
319 if (f.Start < _filterEnd) 1059 if (f.Start < _filterEnd)
320 _unsupportedFilter = true; 1060 _unsupportedFilter = true;
@@ -322,7 +1062,17 @@ HRESULT CDecoder::AddFilter(CBitDecoder &_bitStream)
322 { 1062 {
323 _filterEnd = f.Start + f.Size; 1063 _filterEnd = f.Start + f.Size;
324 if (f.Size != 0) 1064 if (f.Size != 0)
325 _filters.Add(f); 1065 {
1066 if (!_filters)
1067 {
1068 _filters = (CFilter *)z7_AlignedAlloc(MAX_UNPACK_FILTERS * sizeof(CFilter));
1069 if (!_filters)
1070 return E_OUTOFMEMORY;
1071 }
1072 // printf("\n_numFilters = %6u\n", _numFilters);
1073 const unsigned i = _numFilters++;
1074 _filters[i] = f;
1075 }
326 } 1076 }
327 1077
328 return S_OK; 1078 return S_OK;
@@ -331,126 +1081,184 @@ HRESULT CDecoder::AddFilter(CBitDecoder &_bitStream)
331 1081
332#define RIF(x) { if (!(x)) return S_FALSE; } 1082#define RIF(x) { if (!(x)) return S_FALSE; }
333 1083
1084#if 1
1085#define PRINT_CNT(name, skip)
1086#else
1087#define PRINT_CNT(name, skip) \
1088 { static unsigned g_cnt = 0; if (g_cnt++ % skip == 0) printf("\n%16s: %8u", name, g_cnt); }
1089#endif
1090
334HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream) 1091HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)
335{ 1092{
336 if (_progress) 1093 if (_progress)
337 { 1094 {
338 const UInt64 packSize = _bitStream.GetProcessedSize(); 1095 const UInt64 packSize = _bitStream.GetProcessedSize();
339 RINOK(_progress->SetRatioInfo(&packSize, &_writtenFileSize)) 1096 if (packSize - _progress_Pack >= (1u << 24)
1097 || _writtenFileSize - _progress_Unpack >= (1u << 26))
1098 {
1099 _progress_Pack = packSize;
1100 _progress_Unpack = _writtenFileSize;
1101 RINOK(_progress->SetRatioInfo(&_progress_Pack, &_writtenFileSize))
1102 }
1103 // printf("\ntable read pos=%p packSize=%p _writtenFileSize = %p\n", (size_t)_winPos, (size_t)packSize, (size_t)_writtenFileSize);
340 } 1104 }
341 1105
342 _bitStream.AlignToByte(); 1106 // _bitStream is aligned already
343 _bitStream.Prepare(); 1107 _bitStream.Prepare();
344
345 { 1108 {
346 const unsigned flags = _bitStream.ReadByteInAligned(); 1109 const unsigned flags = _bitStream.ReadByte_InAligned();
347 unsigned checkSum = _bitStream.ReadByteInAligned(); 1110 /* ((flags & 20) == 0) in all rar archives now,
1111 but (flags & 20) flag can be used as some decoding hint in future versions of original rar.
1112 So we ignore that bit here. */
1113 unsigned checkSum = _bitStream.ReadByte_InAligned();
348 checkSum ^= flags; 1114 checkSum ^= flags;
349 const unsigned num = (flags >> 3) & 3; 1115 const unsigned num = (flags >> 3) & 3;
350 if (num == 3) 1116 if (num >= 3)
351 return S_FALSE; 1117 return S_FALSE;
352 UInt32 blockSize = _bitStream.ReadByteInAligned(); 1118 UInt32 blockSize = _bitStream.ReadByte_InAligned();
353 checkSum ^= blockSize; 1119 checkSum ^= blockSize;
354
355 if (num != 0) 1120 if (num != 0)
356 { 1121 {
357 unsigned b = _bitStream.ReadByteInAligned(); 1122 {
358 checkSum ^= b; 1123 const unsigned b = _bitStream.ReadByte_InAligned();
359 blockSize += (UInt32)b << 8; 1124 checkSum ^= b;
1125 blockSize += (UInt32)b << 8;
1126 }
360 if (num > 1) 1127 if (num > 1)
361 { 1128 {
362 b = _bitStream.ReadByteInAligned(); 1129 const unsigned b = _bitStream.ReadByte_InAligned();
363 checkSum ^= b; 1130 checkSum ^= b;
364 blockSize += (UInt32)b << 16; 1131 blockSize += (UInt32)b << 16;
365 } 1132 }
366 } 1133 }
367
368 if (checkSum != 0x5A) 1134 if (checkSum != 0x5A)
369 return S_FALSE; 1135 return S_FALSE;
370
371 unsigned blockSizeBits7 = (flags & 7) + 1; 1136 unsigned blockSizeBits7 = (flags & 7) + 1;
372 blockSize += (blockSizeBits7 >> 3); 1137 blockSize += (UInt32)(blockSizeBits7 >> 3);
373 if (blockSize == 0) 1138 if (blockSize == 0)
1139 {
1140 // it's error in data stream
1141 // but original-unrar ignores that error
1142 _bitStream._minorError = true;
1143#if 1
1144 // we ignore that error as original-unrar:
1145 blockSizeBits7 = 0;
1146 blockSize = 1;
1147#else
1148 // we can stop decoding:
374 return S_FALSE; 1149 return S_FALSE;
1150#endif
1151 }
375 blockSize--; 1152 blockSize--;
376 blockSizeBits7 &= 7; 1153 blockSizeBits7 &= 7;
377 1154 PRINT_CNT("Blocks", 100)
378 _bitStream._blockEndBits7 = (Byte)blockSizeBits7; 1155 /*
1156 {
1157 static unsigned g_prev = 0;
1158 static unsigned g_cnt = 0;
1159 unsigned proc = unsigned(_winPos);
1160 if (g_cnt++ % 100 == 0) printf(" c_size = %8u ", blockSize);
1161 if (g_cnt++ % 100 == 1) printf(" unp_size = %8u", proc - g_prev);
1162 g_prev = proc;
1163 }
1164 */
1165 _bitStream._blockEndBits7 = blockSizeBits7;
379 _bitStream._blockEnd = _bitStream.GetProcessedSize_Round() + blockSize; 1166 _bitStream._blockEnd = _bitStream.GetProcessedSize_Round() + blockSize;
380 1167 _bitStream.SetCheck_forBlock();
381 _bitStream.SetCheck2();
382
383 _isLastBlock = ((flags & 0x40) != 0); 1168 _isLastBlock = ((flags & 0x40) != 0);
384
385 if ((flags & 0x80) == 0) 1169 if ((flags & 0x80) == 0)
386 { 1170 {
387 if (!_tableWasFilled) 1171 if (!_tableWasFilled)
388 if (blockSize != 0 || blockSizeBits7 != 0) 1172 // if (blockSize != 0 || blockSizeBits7 != 0)
1173 if (blockSize + blockSizeBits7 != 0)
389 return S_FALSE; 1174 return S_FALSE;
390 return S_OK; 1175 return S_OK;
391 } 1176 }
392
393 _tableWasFilled = false; 1177 _tableWasFilled = false;
394 } 1178 }
395 1179
1180 PRINT_CNT("Tables", 100);
1181
1182 const unsigned kLevelTableSize = 20;
1183 const unsigned k_NumHufTableBits_Level = 6;
1184 NHuffman::CDecoder256<kNumHufBits, kLevelTableSize, k_NumHufTableBits_Level> m_LevelDecoder;
1185 const unsigned kTablesSizesSum_MAX = kMainTableSize + kDistTableSize_MAX + kAlignTableSize + kLenTableSize;
1186 Byte lens[kTablesSizesSum_MAX];
396 { 1187 {
397 Byte lens2[kLevelTableSize]; 1188 // (kLevelTableSize + 16 < kTablesSizesSum). So we use lens[] array for (Level) table
398 1189 // Byte lens2[kLevelTableSize + 16];
399 for (unsigned i = 0; i < kLevelTableSize;) 1190 unsigned i = 0;
1191 do
400 { 1192 {
401 _bitStream.Prepare(); 1193 if (_bitStream._buf >= _bitStream._bufCheck_Block)
402 const unsigned len = (unsigned)_bitStream.ReadBits9fix(4); 1194 {
1195 _bitStream.Prepare();
1196 if (_bitStream.IsBlockOverRead())
1197 return S_FALSE;
1198 }
1199 const unsigned len = (unsigned)_bitStream.ReadBits_9fix(4);
403 if (len == 15) 1200 if (len == 15)
404 { 1201 {
405 unsigned num = (unsigned)_bitStream.ReadBits9fix(4); 1202 unsigned num = (unsigned)_bitStream.ReadBits_9fix(4);
406 if (num != 0) 1203 if (num != 0)
407 { 1204 {
408 num += 2; 1205 num += 2;
409 num += i; 1206 num += i;
1207 // we are allowed to overwrite to lens[] for extra 16 bytes after kLevelTableSize
1208#if 0
410 if (num > kLevelTableSize) 1209 if (num > kLevelTableSize)
1210 {
1211 // we ignore this error as original-unrar
411 num = kLevelTableSize; 1212 num = kLevelTableSize;
1213 // return S_FALSE;
1214 }
1215#endif
412 do 1216 do
413 lens2[i++] = 0; 1217 lens[i++] = 0;
414 while (i < num); 1218 while (i < num);
415 continue; 1219 continue;
416 } 1220 }
417 } 1221 }
418 lens2[i++] = (Byte)len; 1222 lens[i++] = (Byte)len;
419 } 1223 }
420 1224 while (i < kLevelTableSize);
421 if (_bitStream.IsBlockOverRead()) 1225 if (_bitStream.IsBlockOverRead())
422 return S_FALSE; 1226 return S_FALSE;
423 1227 RIF(m_LevelDecoder.Build(lens, NHuffman::k_BuildMode_Full))
424 RIF(m_LevelDecoder.Build(lens2))
425 } 1228 }
426 1229
427 Byte lens[kTablesSizesSum];
428 unsigned i = 0; 1230 unsigned i = 0;
429 1231 const unsigned tableSize = _is_v7 ?
1232 kTablesSizesSum_MAX :
1233 kTablesSizesSum_MAX - kExtraDistSymbols_v7;
430 do 1234 do
431 { 1235 {
432 if (_bitStream._buf >= _bitStream._bufCheck2) 1236 if (_bitStream._buf >= _bitStream._bufCheck_Block)
433 { 1237 {
434 if (_bitStream._buf >= _bitStream._bufCheck) 1238 // if (_bitStream._buf >= _bitStream._bufCheck)
435 _bitStream.Prepare(); 1239 _bitStream.Prepare();
436 if (_bitStream.IsBlockOverRead()) 1240 if (_bitStream.IsBlockOverRead())
437 return S_FALSE; 1241 return S_FALSE;
438 } 1242 }
439 1243 const unsigned sym = m_LevelDecoder.DecodeFull(&_bitStream);
440 const UInt32 sym = m_LevelDecoder.Decode(&_bitStream);
441
442 if (sym < 16) 1244 if (sym < 16)
443 lens[i++] = (Byte)sym; 1245 lens[i++] = (Byte)sym;
1246#if 0
444 else if (sym > kLevelTableSize) 1247 else if (sym > kLevelTableSize)
445 return S_FALSE; 1248 return S_FALSE;
1249#endif
446 else 1250 else
447 { 1251 {
448 unsigned num = ((sym - 16) & 1) * 4; 1252 unsigned num = ((sym /* - 16 */) & 1) * 4;
449 num += num + 3 + (unsigned)_bitStream.ReadBits9(num + 3); 1253 num += num + 3 + (unsigned)_bitStream.ReadBits9(num + 3);
450 num += i; 1254 num += i;
451 if (num > kTablesSizesSum) 1255 if (num > tableSize)
452 num = kTablesSizesSum; 1256 {
453 Byte v = 0; 1257 // we ignore this error as original-unrar
1258 num = tableSize;
1259 // return S_FALSE;
1260 }
1261 unsigned v = 0;
454 if (sym < 16 + 2) 1262 if (sym < 16 + 2)
455 { 1263 {
456 if (i == 0) 1264 if (i == 0)
@@ -458,27 +1266,63 @@ HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)
458 v = lens[(size_t)i - 1]; 1266 v = lens[(size_t)i - 1];
459 } 1267 }
460 do 1268 do
461 lens[i++] = v; 1269 lens[i++] = (Byte)v;
462 while (i < num); 1270 while (i < num);
463 } 1271 }
464 } 1272 }
465 while (i < kTablesSizesSum); 1273 while (i < tableSize);
466 1274
467 if (_bitStream.IsBlockOverRead()) 1275 if (_bitStream.IsBlockOverRead())
468 return S_FALSE; 1276 return S_FALSE;
469 if (_bitStream.InputEofError()) 1277 if (_bitStream.InputEofError())
470 return S_FALSE; 1278 return S_FALSE;
471 1279
472 RIF(m_MainDecoder.Build(&lens[0])) 1280 /* We suppose that original-rar encoder can create only two cases for Huffman:
473 RIF(m_DistDecoder.Build(&lens[kMainTableSize])) 1281 1) Empty Huffman tree (if num_used_symbols == 0)
474 RIF(m_AlignDecoder.Build(&lens[kMainTableSize + kDistTableSize])) 1282 2) Full Huffman tree (if num_used_symbols != 0)
475 RIF(m_LenDecoder.Build(&lens[kMainTableSize + kDistTableSize + kAlignTableSize])) 1283 Usually the block contains at least one symbol for m_MainDecoder.
1284 So original-rar-encoder creates full Huffman tree for m_MainDecoder.
1285 But we suppose that (num_used_symbols == 0) is possible for m_MainDecoder,
1286 because file must be finished with (_isLastBlock) flag,
1287 even if there are no symbols in m_MainDecoder.
1288 So we use k_BuildMode_Full_or_Empty for m_MainDecoder.
1289 */
1290 const NHuffman::enum_BuildMode buildMode = NHuffman::
1291 k_BuildMode_Full_or_Empty; // strict check
1292 // k_BuildMode_Partial; // non-strict check (ignore errors)
1293
1294 RIF(m_MainDecoder.Build(&lens[0], buildMode))
1295 if (!_is_v7)
1296 {
1297#if 1
1298 /* we use this manual loop to avoid compiler BUG.
1299 GCC 4.9.2 compiler has BUG with overlapping memmove() to right in local array. */
1300 Byte *dest = lens + kMainTableSize + kDistTableSize_v6 +
1301 kAlignTableSize + kLenTableSize - 1;
1302 unsigned num = kAlignTableSize + kLenTableSize;
1303 do
1304 {
1305 dest[kExtraDistSymbols_v7] = dest[0];
1306 dest--;
1307 }
1308 while (--num);
1309#else
1310 memmove(lens + kMainTableSize + kDistTableSize_v6 + kExtraDistSymbols_v7,
1311 lens + kMainTableSize + kDistTableSize_v6,
1312 kAlignTableSize + kLenTableSize);
1313#endif
1314 memset(lens + kMainTableSize + kDistTableSize_v6, 0, kExtraDistSymbols_v7);
1315 }
1316
1317 RIF(m_DistDecoder.Build(&lens[kMainTableSize], buildMode))
1318 RIF( m_LenDecoder.Build(&lens[kMainTableSize
1319 + kDistTableSize_MAX + kAlignTableSize], buildMode))
476 1320
477 _useAlignBits = false; 1321 _useAlignBits = false;
478 // _useAlignBits = true;
479 for (i = 0; i < kAlignTableSize; i++) 1322 for (i = 0; i < kAlignTableSize; i++)
480 if (lens[kMainTableSize + kDistTableSize + (size_t)i] != kNumAlignBits) 1323 if (lens[kMainTableSize + kDistTableSize_MAX + (size_t)i] != kNumAlignBits)
481 { 1324 {
1325 RIF(m_AlignDecoder.Build(&lens[kMainTableSize + kDistTableSize_MAX], buildMode))
482 _useAlignBits = true; 1326 _useAlignBits = true;
483 break; 1327 break;
484 } 1328 }
@@ -487,139 +1331,108 @@ HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)
487 return S_OK; 1331 return S_OK;
488} 1332}
489 1333
1334static inline CLenType SlotToLen(CBitDecoder &_bitStream, CLenType slot)
1335{
1336 const unsigned numBits = ((unsigned)slot >> 2) - 1;
1337 return ((4 | (slot & 3)) << numBits) + (CLenType)_bitStream.ReadBits9(numBits);
1338}
1339
490 1340
491static inline unsigned SlotToLen(CBitDecoder &_bitStream, unsigned slot) 1341static const unsigned kSymbolRep = 258;
1342static const unsigned kMaxMatchLen = 0x1001 + 3;
1343
1344enum enum_exit_type
492{ 1345{
493 if (slot < 8) 1346 Z7_RAR_EXIT_TYPE_NONE,
494 return slot + 2; 1347 Z7_RAR_EXIT_TYPE_ADD_FILTER
495 const unsigned numBits = (slot >> 2) - 1; 1348};
496 return 2 + ((4 | (slot & 3)) << numBits) + _bitStream.ReadBits9(numBits); 1349
1350
1351#define LZ_RESTORE \
1352{ \
1353 _reps[0] = rep0; \
1354 _winPos = (size_t)(winPos - _window); \
1355 _buf_Res = _bitStream._buf; \
1356 _bitPos_Res = _bitStream._bitPos; \
497} 1357}
498 1358
1359#define LZ_LOOP_BREAK_OK { break; }
1360// #define LZ_LOOP_BREAK_ERROR { _lzError = LZ_ERROR_TYPE_SYM; break; }
1361// #define LZ_LOOP_BREAK_ERROR { LZ_RESTORE; return S_FALSE; }
1362#define LZ_LOOP_BREAK_ERROR { goto decode_error; }
1363// goto decode_error; }
1364// #define LZ_LOOP_BREAK_ERROR { break; }
499 1365
500static const UInt32 kSymbolRep = 258; 1366#define Z7_RAR_HUFF_DECODE_CHECK_break(sym, huf, kNumTableBits, bitStream) \
501// static const unsigned kMaxMatchLen = 0x1001 + 3; 1367 Z7_HUFF_DECODE_CHECK(sym, huf, kNumHufBits, kNumTableBits, bitStream, { LZ_LOOP_BREAK_ERROR })
502 1368
503HRESULT CDecoder::DecodeLZ() 1369
1370HRESULT CDecoder::DecodeLZ2(const CBitDecoder &bitStream) throw()
504{ 1371{
505 CBitDecoder _bitStream; 1372#if 0
506 _bitStream._stream = _inStream; 1373 Byte k_LenPlusTable_LOC[DICT_SIZE_BITS_MAX];
507 _bitStream._bufBase = _inputBuf; 1374 memcpy(k_LenPlusTable_LOC, k_LenPlusTable, sizeof(k_LenPlusTable));
508 _bitStream.Init(); 1375#endif
509 1376
510 UInt32 rep0 = _reps[0]; 1377 PRINT_CNT("DecodeLZ2", 2000);
511 1378
512 UInt32 remLen = 0; 1379 CBitDecoder _bitStream;
1380 _bitStream.CopyFrom(bitStream);
1381 // _bitStream._stream = _inStream;
1382 // _bitStream._bufBase = _inputBuf;
1383 // _bitStream.Init();
1384
1385 // _reps[*] can be larger than _winSize, if _winSize was reduced in solid stream.
1386 size_t rep0 = _reps[0];
1387 // size_t rep1 = _reps[1];
1388 // Byte *win = _window;
1389 Byte *winPos = _window + _winPos;
1390 const Byte *limit = _window + _limit;
1391 _exitType = Z7_RAR_EXIT_TYPE_NONE;
513 1392
514 size_t limit;
515 {
516 size_t rem = _winSize - _winPos;
517 if (rem > kWriteStep)
518 rem = kWriteStep;
519 limit = _winPos + rem;
520 }
521
522 for (;;) 1393 for (;;)
523 { 1394 {
524 if (_winPos >= limit) 1395 if (winPos >= limit)
525 { 1396 LZ_LOOP_BREAK_OK
526 RINOK(WriteBuf()) 1397 // (winPos < limit)
527 if (_unpackSize_Defined && _writtenFileSize > _unpackSize) 1398 if (_bitStream._buf >= _bitStream._bufCheck_Block)
528 break; // return S_FALSE;
529
530 {
531 size_t rem = _winSize - _winPos;
532
533 if (rem == 0)
534 {
535 _winPos = 0;
536 rem = _winSize;
537 }
538 if (rem > kWriteStep)
539 rem = kWriteStep;
540 limit = _winPos + rem;
541 }
542
543 if (remLen != 0)
544 {
545 size_t winPos = _winPos;
546 const size_t winMask = _winMask;
547 size_t pos = (winPos - (size_t)rep0 - 1) & winMask;
548
549 Byte *win = _window;
550 do
551 {
552 if (winPos >= limit)
553 break;
554 win[winPos] = win[pos];
555 winPos++;
556 pos = (pos + 1) & winMask;
557 }
558 while (--remLen != 0);
559
560 _lzSize += winPos - _winPos;
561 _winPos = winPos;
562 continue;
563 }
564 }
565
566 if (_bitStream._buf >= _bitStream._bufCheck2)
567 { 1399 {
568 if (_bitStream.InputEofError()) 1400 if (_bitStream.InputEofError())
569 break; // return S_FALSE; 1401 LZ_LOOP_BREAK_OK
570 if (_bitStream._buf >= _bitStream._bufCheck) 1402 if (_bitStream._buf >= _bitStream._bufCheck)
571 _bitStream.Prepare2();
572
573 const UInt64 processed = _bitStream.GetProcessedSize_Round();
574 if (processed >= _bitStream._blockEnd)
575 { 1403 {
576 if (processed > _bitStream._blockEnd) 1404 if (!_bitStream._wasFinished)
577 break; // return S_FALSE; 1405 LZ_LOOP_BREAK_OK
578 { 1406 // _bitStream._wasFinished == true
579 const unsigned bits7 = _bitStream.GetProcessedBits7(); 1407 // we don't need Prepare() here, because all data was read
580 if (bits7 > _bitStream._blockEndBits7) 1408 // and PadZone (16 bytes) after data was filled.
581 break; // return S_FALSE;
582 if (bits7 == _bitStream._blockEndBits7)
583 {
584 if (_isLastBlock)
585 {
586 _reps[0] = rep0;
587
588 if (_bitStream.InputEofError())
589 break;
590
591 /*
592 // packSize can be 15 bytes larger for encrypted archive
593 if (_packSize_Defined && _packSize < _bitStream.GetProcessedSize())
594 break;
595 */
596
597 return _bitStream._hres;
598 // break;
599 }
600 RINOK(ReadTables(_bitStream))
601 continue;
602 }
603 }
604 } 1409 }
605 1410 const UInt64 processed = _bitStream.GetProcessedSize_Round();
1411 // some cases are error, but the caller will process such error cases.
1412 if (processed >= _bitStream._blockEnd &&
1413 (processed > _bitStream._blockEnd
1414 || _bitStream.GetProcessedBits7() >= _bitStream._blockEndBits7))
1415 LZ_LOOP_BREAK_OK
606 // that check is not required, but it can help, if there is BUG in another code 1416 // that check is not required, but it can help, if there is BUG in another code
607 if (!_tableWasFilled) 1417 if (!_tableWasFilled)
608 break; // return S_FALSE; 1418 LZ_LOOP_BREAK_ERROR
609 } 1419 }
610 1420
611 const UInt32 sym = m_MainDecoder.Decode(&_bitStream); 1421#if 0
1422 const unsigned sym = m_MainDecoder.Decode(&_bitStream);
1423#else
1424 unsigned sym;
1425 Z7_RAR_HUFF_DECODE_CHECK_break(sym, &m_MainDecoder, k_NumHufTableBits_Main, &_bitStream)
1426#endif
612 1427
613 if (sym < 256) 1428 if (sym < 256)
614 { 1429 {
615 size_t winPos = _winPos; 1430 *winPos++ = (Byte)sym;
616 _window[winPos] = (Byte)sym; 1431 // _lzSize++;
617 _winPos = winPos + 1;
618 _lzSize++;
619 continue; 1432 continue;
620 } 1433 }
621 1434
622 UInt32 len; 1435 CLenType len;
623 1436
624 if (sym < kSymbolRep + kNumReps) 1437 if (sym < kSymbolRep + kNumReps)
625 { 1438 {
@@ -627,130 +1440,343 @@ HRESULT CDecoder::DecodeLZ()
627 { 1440 {
628 if (sym != kSymbolRep) 1441 if (sym != kSymbolRep)
629 { 1442 {
630 UInt32 dist; 1443 size_t dist = _reps[1];
631 if (sym == kSymbolRep + 1)
632 dist = _reps[1];
633 else
634 {
635 if (sym == kSymbolRep + 2)
636 dist = _reps[2];
637 else
638 {
639 dist = _reps[3];
640 _reps[3] = _reps[2];
641 }
642 _reps[2] = _reps[1];
643 }
644 _reps[1] = rep0; 1444 _reps[1] = rep0;
645 rep0 = dist; 1445 rep0 = dist;
1446 if (sym >= kSymbolRep + 2)
1447 {
1448 #if 1
1449 rep0 = _reps[(size_t)sym - kSymbolRep];
1450 _reps[(size_t)sym - kSymbolRep] = _reps[2];
1451 _reps[2] = dist;
1452 #else
1453 if (sym != kSymbolRep + 2)
1454 {
1455 rep0 = _reps[3];
1456 _reps[3] = _reps[2];
1457 _reps[2] = dist;
1458 }
1459 else
1460 {
1461 rep0 = _reps[2];
1462 _reps[2] = dist;
1463 }
1464 #endif
1465 }
646 } 1466 }
647 1467#if 0
648 const UInt32 sym2 = m_LenDecoder.Decode(&_bitStream); 1468 len = m_LenDecoder.Decode(&_bitStream);
649 if (sym2 >= kLenTableSize) 1469 if (len >= kLenTableSize)
650 break; // return S_FALSE; 1470 LZ_LOOP_BREAK_ERROR
651 len = SlotToLen(_bitStream, sym2); 1471#else
1472 Z7_RAR_HUFF_DECODE_CHECK_break(len, &m_LenDecoder, k_NumHufTableBits_Len, &_bitStream)
1473#endif
1474 if (len >= 8)
1475 len = SlotToLen(_bitStream, len);
1476 len += 2;
1477 // _lastLen = (UInt32)len;
652 } 1478 }
653 else 1479 else if (sym != 256)
654 { 1480 {
655 if (sym == 256) 1481 len = (CLenType)_lastLen;
1482 if (len == 0)
656 { 1483 {
657 RINOK(AddFilter(_bitStream)) 1484 // we ignore (_lastLen == 0) case, like original-unrar.
1485 // that case can mean error in stream.
1486 // lzError = true;
1487 // return S_FALSE;
658 continue; 1488 continue;
659 } 1489 }
660 else // if (sym == 257) 1490 }
661 { 1491 else
662 len = _lastLen; 1492 {
663 // if (len = 0), we ignore that symbol, like original unRAR code, but it can mean error in stream. 1493 _exitType = Z7_RAR_EXIT_TYPE_ADD_FILTER;
664 // if (len == 0) return S_FALSE; 1494 LZ_LOOP_BREAK_OK
665 if (len == 0)
666 continue;
667 }
668 } 1495 }
669 } 1496 }
1497#if 0
670 else if (sym >= kMainTableSize) 1498 else if (sym >= kMainTableSize)
671 break; // return S_FALSE; 1499 LZ_LOOP_BREAK_ERROR
1500#endif
672 else 1501 else
673 { 1502 {
674 _reps[3] = _reps[2]; 1503 _reps[3] = _reps[2];
675 _reps[2] = _reps[1]; 1504 _reps[2] = _reps[1];
676 _reps[1] = rep0; 1505 _reps[1] = rep0;
677 len = SlotToLen(_bitStream, sym - (kSymbolRep + kNumReps)); 1506 len = sym - (kSymbolRep + kNumReps);
678 1507 if (len >= 8)
679 rep0 = m_DistDecoder.Decode(&_bitStream); 1508 len = SlotToLen(_bitStream, len);
1509 len += 2;
1510 // _lastLen = (UInt32)len;
680 1511
1512#if 0
1513 rep0 = (UInt32)m_DistDecoder.Decode(&_bitStream);
1514#else
1515 Z7_RAR_HUFF_DECODE_CHECK_break(rep0, &m_DistDecoder, k_NumHufTableBits_Dist, &_bitStream)
1516#endif
1517
681 if (rep0 >= 4) 1518 if (rep0 >= 4)
682 { 1519 {
683 if (rep0 >= _numCorrectDistSymbols) 1520#if 0
684 break; // return S_FALSE; 1521 if (rep0 >= kDistTableSize_MAX)
685 const unsigned numBits = (rep0 >> 1) - 1; 1522 LZ_LOOP_BREAK_ERROR
1523#endif
1524 const unsigned numBits = ((unsigned)rep0 - 2) >> 1;
686 rep0 = (2 | (rep0 & 1)) << numBits; 1525 rep0 = (2 | (rep0 & 1)) << numBits;
687 1526
1527 const Byte *buf = _bitStream._buf;
1528#ifdef Z7_RAR5_USE_64BIT
1529 const UInt64 v = GetBe64(buf);
1530#else
1531 const UInt32 v = GetBe32(buf);
1532#endif
1533
1534 // _lastLen = (UInt32)len;
688 if (numBits < kNumAlignBits) 1535 if (numBits < kNumAlignBits)
689 rep0 += _bitStream.ReadBits9(numBits); 1536 {
1537 rep0 += // _bitStream.ReadBits9(numBits);
1538 _bitStream.ReadBits_Big25(numBits, v);
1539 }
690 else 1540 else
691 { 1541 {
692 len += (numBits >= 7); 1542 #if !defined(MY_CPU_AMD64)
693 len += (numBits >= 12); 1543 len += k_LenPlusTable[numBits];
694 len += (numBits >= 17); 1544 #elif 0
695 1545 len += k_LenPlusTable_LOC[numBits];
1546 #elif 1
1547 len += m_LenPlusTable[numBits];
1548 #elif 1 && defined(MY_CPU_64BIT) && defined(MY_CPU_AMD64)
1549 // len += (unsigned)((UInt64)0xfffffffeaa554000 >> (numBits * 2)) & 3;
1550 len += (unsigned)((UInt64)0xfffffffffeaa5540 >> (numBits * 2 - 8)) & 3;
1551 #elif 1
1552 len += 3;
1553 len -= (unsigned)(numBits - 7) >> (sizeof(unsigned) * 8 - 1);
1554 len -= (unsigned)(numBits - 12) >> (sizeof(unsigned) * 8 - 1);
1555 len -= (unsigned)(numBits - 17) >> (sizeof(unsigned) * 8 - 1);
1556 #elif 1
1557 len += 3;
1558 len -= (0x155aabf >> (numBits - 4) >> (numBits - 4)) & 3;
1559 #elif 1
1560 len += (numBits >= 7);
1561 len += (numBits >= 12);
1562 len += (numBits >= 17);
1563 #endif
1564 // _lastLen = (UInt32)len;
696 if (_useAlignBits) 1565 if (_useAlignBits)
697 { 1566 {
698 // if (numBits > kNumAlignBits) 1567 // if (numBits > kNumAlignBits)
699 rep0 += (_bitStream.ReadBits32(numBits - kNumAlignBits) << kNumAlignBits); 1568 rep0 += (_bitStream.ReadBits_Big25(numBits - kNumAlignBits, v) << kNumAlignBits);
700 const UInt32 a = m_AlignDecoder.Decode(&_bitStream); 1569#if 0
1570 const unsigned a = m_AlignDecoder.Decode(&_bitStream);
701 if (a >= kAlignTableSize) 1571 if (a >= kAlignTableSize)
702 break; // return S_FALSE; 1572 LZ_LOOP_BREAK_ERROR
1573#else
1574 unsigned a;
1575 Z7_RAR_HUFF_DECODE_CHECK_break(a, &m_AlignDecoder, k_NumHufTableBits_Align, &_bitStream)
1576#endif
703 rep0 += a; 1577 rep0 += a;
704 } 1578 }
705 else 1579 else
706 rep0 += _bitStream.ReadBits32(numBits); 1580 rep0 += _bitStream.ReadBits_Big(numBits, v);
1581#ifndef Z7_RAR5_USE_64BIT
1582 if (numBits >= 30) // we don't want 32-bit overflow case
1583 rep0 = (size_t)0 - 1 - 1;
1584#endif
707 } 1585 }
708 } 1586 }
1587 rep0++;
709 } 1588 }
710 1589
711 _lastLen = len;
712
713 if (rep0 >= _lzSize)
714 _lzError = true;
715
716 { 1590 {
717 UInt32 lenCur = len; 1591 _lastLen = (UInt32)len;
718 size_t winPos = _winPos; 1592 // len != 0
719 size_t pos = (winPos - (size_t)rep0 - 1) & _winMask; 1593
1594#ifdef Z7_RAR5_SHOW_STAT
720 { 1595 {
721 const size_t rem = limit - winPos; 1596 size_t index = rep0;
722 // size_t rem = _winSize - winPos; 1597 if (index >= kNumStats1)
1598 index = kNumStats1 - 1;
1599 g_stats1[index]++;
1600 g_stats2[index][len]++;
1601 }
1602#endif
723 1603
724 if (lenCur > rem) 1604 Byte *dest = winPos;
1605 winPos += len;
1606 if (rep0 <= _dictSize_forCheck)
1607 {
1608 const Byte *src;
1609 const size_t winPos_temp = (size_t)(dest - _window);
1610 if (rep0 > winPos_temp)
725 { 1611 {
726 lenCur = (UInt32)rem; 1612 if (_lzSize == 0)
727 remLen = len - lenCur; 1613 goto error_dist;
1614 size_t back = rep0 - winPos_temp;
1615 // STAT_INC(g_NumOver)
1616 src = dest + (_winSize - rep0);
1617 if (back < len)
1618 {
1619 // len -= (CLenType)back;
1620 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
1621 do
1622 *dest++ = *src++;
1623 while (--back);
1624 src = dest - rep0;
1625 }
728 } 1626 }
1627 else
1628 src = dest - rep0;
1629 CopyMatch(rep0, dest, src, winPos);
1630 continue;
729 } 1631 }
730 1632
731 Byte *win = _window; 1633error_dist:
732 _lzSize += lenCur; 1634 // LZ_LOOP_BREAK_ERROR;
733 _winPos = winPos + lenCur; 1635 _lzError = LZ_ERROR_TYPE_DIST;
734 if (_winSize - pos >= lenCur) 1636 do
1637 *dest++ = 0;
1638 while (dest < winPos);
1639 continue;
1640 }
1641 }
1642
1643 LZ_RESTORE
1644 return S_OK;
1645
1646#if 1
1647decode_error:
1648 /*
1649 if (_bitStream._hres != S_OK)
1650 return _bitStream._hres;
1651 */
1652 LZ_RESTORE
1653 return S_FALSE;
1654#endif
1655}
1656
1657
1658
1659HRESULT CDecoder::DecodeLZ()
1660{
1661 CBitDecoder _bitStream;
1662 _bitStream._stream = _inStream;
1663 _bitStream._bufBase = _inputBuf;
1664 _bitStream.Init();
1665
1666 // _reps[*] can be larger than _winSize, if _winSize was reduced in solid stream.
1667 size_t winPos = _winPos;
1668 Byte *win = _window;
1669 size_t limit;
1670 {
1671 size_t rem = _winSize - winPos;
1672 if (rem > kWriteStep)
1673 rem = kWriteStep;
1674 limit = winPos + rem;
1675 }
1676
1677 for (;;)
1678 {
1679 if (winPos >= limit)
1680 {
1681 _winPos = winPos < _winSize ? winPos : _winSize;
1682 RINOK(WriteBuf())
1683 if (_unpackSize_Defined && _writtenFileSize > _unpackSize)
1684 break; // return S_FALSE;
1685 const size_t wp = _winPos;
1686 size_t rem = _winSize - wp;
1687 if (rem == 0)
735 { 1688 {
736 const Byte *src = win + pos; 1689 _lzSize += wp;
737 Byte *dest = win + winPos; 1690 winPos -= wp;
738 do 1691 // (winPos < kMaxMatchLen < _winSize)
739 *dest++ = *src++; 1692 // so memmove is not required here
740 while (--lenCur != 0); 1693 if (winPos)
1694 memcpy(win, win + _winSize, winPos);
1695 limit = _winSize;
1696 if (limit >= kWriteStep)
1697 {
1698 limit = kWriteStep;
1699 continue;
1700 }
1701 rem = _winSize - winPos;
741 } 1702 }
742 else 1703 if (rem > kWriteStep)
1704 rem = kWriteStep;
1705 limit = winPos + rem;
1706 continue;
1707 }
1708
1709 // (winPos < limit)
1710
1711 if (_bitStream._buf >= _bitStream._bufCheck_Block)
1712 {
1713 _winPos = winPos;
1714 if (_bitStream.InputEofError())
1715 break; // return S_FALSE;
1716 _bitStream.Prepare();
1717
1718 const UInt64 processed = _bitStream.GetProcessedSize_Round();
1719 if (processed >= _bitStream._blockEnd)
743 { 1720 {
744 do 1721 if (processed > _bitStream._blockEnd)
1722 break; // return S_FALSE;
745 { 1723 {
746 win[winPos] = win[pos]; 1724 const unsigned bits7 = _bitStream.GetProcessedBits7();
747 winPos++; 1725 if (bits7 >= _bitStream._blockEndBits7)
748 pos = (pos + 1) & _winMask; 1726 {
1727 if (bits7 > _bitStream._blockEndBits7)
1728 {
1729#if 1
1730 // we ignore thar error as original unrar
1731 _bitStream._minorError = true;
1732#else
1733 break; // return S_FALSE;
1734#endif
1735 }
1736 _bitStream.AlignToByte();
1737 // if (!_bitStream.AlignToByte()) break;
1738 if (_isLastBlock)
1739 {
1740 if (_bitStream.InputEofError())
1741 break;
1742 /*
1743 // packSize can be 15 bytes larger for encrypted archive
1744 if (_packSize_Defined && _packSize < _bitStream.GetProcessedSize())
1745 break;
1746 */
1747 if (_bitStream._minorError)
1748 return S_FALSE;
1749 return _bitStream._hres;
1750 // break;
1751 }
1752 RINOK(ReadTables(_bitStream))
1753 continue;
1754 }
749 } 1755 }
750 while (--lenCur != 0);
751 } 1756 }
1757
1758 // end of block was not reached.
1759 // so we must decode more symbols
1760 // that check is not required, but it can help, if there is BUG in another code
1761 if (!_tableWasFilled)
1762 break; // return S_FALSE;
1763 }
1764
1765 _limit = limit;
1766 _winPos = winPos;
1767 RINOK(DecodeLZ2(_bitStream))
1768 _bitStream._buf = _buf_Res;
1769 _bitStream._bitPos = _bitPos_Res;
1770
1771 winPos = _winPos;
1772 if (_exitType == Z7_RAR_EXIT_TYPE_ADD_FILTER)
1773 {
1774 RINOK(AddFilter(_bitStream))
1775 continue;
752 } 1776 }
753 } 1777 }
1778
1779 _winPos = winPos;
754 1780
755 if (_bitStream._hres != S_OK) 1781 if (_bitStream._hres != S_OK)
756 return _bitStream._hres; 1782 return _bitStream._hres;
@@ -759,221 +1785,238 @@ HRESULT CDecoder::DecodeLZ()
759} 1785}
760 1786
761 1787
1788
762HRESULT CDecoder::CodeReal() 1789HRESULT CDecoder::CodeReal()
763{ 1790{
764 _unsupportedFilter = false; 1791 _unsupportedFilter = false;
765 _lzError = false;
766 _writeError = false; 1792 _writeError = false;
767 1793 /*
768 if (!_isSolid || !_wasInit) 1794 if (!_isSolid || !_wasInit)
769 { 1795 {
770 size_t clearSize = _winSize;
771 if (_lzSize < _winSize)
772 clearSize = (size_t)_lzSize;
773 memset(_window, 0, clearSize);
774
775 _wasInit = true; 1796 _wasInit = true;
776 _lzSize = 0; 1797 // _lzSize = 0;
777 _lzWritten = 0; 1798 _lzWritten = 0;
778 _winPos = 0; 1799 _winPos = 0;
779
780 for (unsigned i = 0; i < kNumReps; i++) 1800 for (unsigned i = 0; i < kNumReps; i++)
781 _reps[i] = (UInt32)0 - 1; 1801 _reps[i] = (size_t)0 - 1;
782
783 _lastLen = 0; 1802 _lastLen = 0;
784 _tableWasFilled = false; 1803 _tableWasFilled = false;
785 } 1804 }
786 1805 */
787 _isLastBlock = false; 1806 _isLastBlock = false;
788 1807
789 InitFilters(); 1808 InitFilters();
790 1809
791 _filterEnd = 0; 1810 _filterEnd = 0;
792 _writtenFileSize = 0; 1811 _writtenFileSize = 0;
793 1812 const UInt64 lzSize = _lzSize + _winPos;
794 _lzFileStart = _lzSize; 1813 _lzFileStart = lzSize;
795 _lzWritten = _lzSize; 1814 _lzWritten = lzSize;
796 1815
797 HRESULT res = DecodeLZ(); 1816 HRESULT res = DecodeLZ();
798 1817
799 HRESULT res2 = S_OK; 1818 HRESULT res2 = S_OK;
800 if (!_writeError && res != E_OUTOFMEMORY) 1819 if (!_writeError && res != E_OUTOFMEMORY)
801 res2 = WriteBuf(); 1820 res2 = WriteBuf();
802
803 /* 1821 /*
804 if (res == S_OK) 1822 if (res == S_OK)
805 if (InputEofError()) 1823 if (InputEofError())
806 res = S_FALSE; 1824 res = S_FALSE;
807 */ 1825 */
808
809 if (res == S_OK) 1826 if (res == S_OK)
810 { 1827 {
811 _solidAllowed = true; 1828 // _solidAllowed = true;
812 res = res2; 1829 res = res2;
813 } 1830 }
814
815 if (res == S_OK && _unpackSize_Defined && _writtenFileSize != _unpackSize) 1831 if (res == S_OK && _unpackSize_Defined && _writtenFileSize != _unpackSize)
816 return S_FALSE; 1832 return S_FALSE;
817 return res; 1833 return res;
818} 1834}
819 1835
820 1836
821// Original unRAR claims that maximum possible filter block size is (1 << 16) now,
822// and (1 << 17) is minimum win size required to support filter.
823// Original unRAR uses (1 << 18) for "extra safety and possible filter area size expansion"
824// We can use any win size.
825
826static const unsigned kWinSize_Log_Min = 17;
827 1837
828Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1838Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
829 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)) 1839 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress))
830{ 1840{
831 try 1841 _lzError = LZ_ERROR_TYPE_NO;
1842/*
1843 if file is soild, but decoding of previous file was not finished,
1844 we still try to decode new file.
1845 We need correct huffman table at starting block.
1846 And rar encoder probably writes huffman table at start block, if file is big.
1847 So we have good chance to get correct huffman table in some file after corruption.
1848 Also we try to recover window by filling zeros, if previous file
1849 was decoded to smaller size than required.
1850 But if filling size is big, we do full reset of window instead.
1851*/
1852 #define Z7_RAR_RECOVER_SOLID_LIMIT (1 << 20)
1853 // #define Z7_RAR_RECOVER_SOLID_LIMIT 0 // do not fill zeros
832 { 1854 {
833 if (_isSolid && !_solidAllowed) 1855 // if (_winPos > 100) _winPos -= 100; // for debug: corruption
834 return S_FALSE; 1856 const UInt64 lzSize = _lzSize + _winPos;
835 _solidAllowed = false; 1857 if (!_isSolid || !_wasInit
836 1858 || (lzSize < _lzEnd
837 if (_dictSizeLog >= sizeof(size_t) * 8) 1859#if Z7_RAR_RECOVER_SOLID_LIMIT != 0
838 return E_NOTIMPL; 1860 && lzSize + Z7_RAR_RECOVER_SOLID_LIMIT < _lzEnd
839 1861#endif
840 if (!_isSolid) 1862 ))
1863 {
1864 if (_isSolid)
1865 _lzError = LZ_ERROR_TYPE_HEADER;
841 _lzEnd = 0; 1866 _lzEnd = 0;
842 else 1867 _lzSize = 0;
1868 _lzWritten = 0;
1869 _winPos = 0;
1870 for (unsigned i = 0; i < kNumReps; i++)
1871 _reps[i] = (size_t)0 - 1;
1872 _lastLen = 0;
1873 _tableWasFilled = false;
1874 _wasInit = true;
1875 }
1876#if Z7_RAR_RECOVER_SOLID_LIMIT != 0
1877 else if (lzSize < _lzEnd)
843 { 1878 {
844 if (_lzSize < _lzEnd) 1879#if 0
1880 return S_FALSE;
1881#else
1882 // we can report that recovering was made:
1883 // _lzError = LZ_ERROR_TYPE_HEADER;
1884 // We write zeros to area after corruption:
1885 if (_window)
845 { 1886 {
846 if (_window) 1887 UInt64 rem = _lzEnd - lzSize;
1888 const size_t ws = _winSize;
1889 if (rem >= ws)
847 { 1890 {
848 UInt64 rem = _lzEnd - _lzSize; 1891 My_ZeroMemory(_window, ws);
849 if (rem >= _winSize) 1892 _lzSize = ws;
850 memset(_window, 0, _winSize); 1893 _winPos = 0;
851 else 1894 }
1895 else
1896 {
1897 const size_t cur = ws - _winPos;
1898 if (cur <= rem)
852 { 1899 {
853 const size_t pos = (size_t)_lzSize & _winSize; 1900 rem -= cur;
854 size_t rem2 = _winSize - pos; 1901 My_ZeroMemory(_window + _winPos, cur);
855 if (rem2 > rem) 1902 _lzSize += _winPos;
856 rem2 = (size_t)rem; 1903 _winPos = 0;
857 memset(_window + pos, 0, rem2);
858 rem -= rem2;
859 memset(_window, 0, (size_t)rem);
860 } 1904 }
1905 My_ZeroMemory(_window + _winPos, (size_t)rem);
1906 _winPos += (size_t)rem;
861 } 1907 }
862 _lzEnd &= ((((UInt64)1) << 33) - 1);
863 _lzSize = _lzEnd;
864 _winPos = (size_t)(_lzSize & _winSize);
865 } 1908 }
866 _lzEnd = _lzSize; 1909 // else return S_FALSE;
1910#endif
867 } 1911 }
1912#endif
1913 }
868 1914
869 size_t newSize; 1915 // we don't want _lzSize overflow
1916 if (_lzSize >= DICT_SIZE_MAX)
1917 _lzSize = DICT_SIZE_MAX;
1918 _lzEnd = _lzSize + _winPos;
1919 // _lzSize <= DICT_SIZE_MAX
1920 // _lzEnd <= DICT_SIZE_MAX * 2
1921
1922 size_t newSize = _dictSize;
1923 if (newSize < kWinSize_Min)
1924 newSize = kWinSize_Min;
1925
1926 _unpackSize = 0;
1927 _unpackSize_Defined = (outSize != NULL);
1928 if (_unpackSize_Defined)
1929 _unpackSize = *outSize;
1930
1931 if ((Int64)_unpackSize >= 0)
1932 _lzEnd += _unpackSize; // known end after current file
1933 else
1934 _lzEnd = 0; // unknown end
1935
1936 if (_isSolid && _window)
1937 {
1938 // If dictionary was decreased in solid, we use old dictionary.
1939 if (newSize > _dictSize_forCheck)
870 { 1940 {
871 unsigned newSizeLog = _dictSizeLog; 1941 // If dictionary was increased in solid, we don't want grow.
872 if (newSizeLog < kWinSize_Log_Min) 1942 return S_FALSE; // E_OUTOFMEMORY
873 newSizeLog = kWinSize_Log_Min;
874 newSize = (size_t)1 << newSizeLog;
875 _numCorrectDistSymbols = newSizeLog * 2;
876 } 1943 }
877 1944 // (newSize <= _winSize)
878 // If dictionary was reduced, we use allocated dictionary block 1945 }
879 // for compatibility with original unRAR decoder. 1946 else
880 1947 {
881 if (_window && newSize < _winSizeAllocated) 1948 _dictSize_forCheck = newSize;
882 _winSize = _winSizeAllocated;
883 else if (!_window || _winSize != newSize)
884 { 1949 {
885 if (!_isSolid) 1950 size_t newSize_small = newSize;
886 { 1951 const size_t k_Win_AlignSize = 1u << 18;
887 ::MidFree(_window); 1952 /* here we add (1 << 7) instead of (COPY_CHUNK_SIZE - 1), because
888 _window = NULL; 1953 we want to get same (_winSize) for different COPY_CHUNK_SIZE values. */
889 _winSizeAllocated = 0; 1954 // newSize += (COPY_CHUNK_SIZE - 1) + (k_Win_AlignSize - 1); // for debug : we can get smallest (_winSize)
890 } 1955 newSize += (1 << 7) + k_Win_AlignSize;
891 1956 newSize &= ~(size_t)(k_Win_AlignSize - 1);
892 Byte *win; 1957 if (newSize < newSize_small)
893 1958 return E_OUTOFMEMORY;
894 {
895 win = (Byte *)::MidAlloc(newSize);
896 if (!win)
897 return E_OUTOFMEMORY;
898 memset(win, 0, newSize);
899 }
900
901 if (_isSolid && _window)
902 {
903 // original unRAR claims:
904 // "Archiving code guarantees that win size does not grow in the same solid stream",
905 // but the original unRAR decoder still supports such grow case.
906
907 Byte *winOld = _window;
908 const size_t oldSize = _winSize;
909 const size_t newMask = newSize - 1;
910 const size_t oldMask = _winSize - 1;
911 const size_t winPos = _winPos;
912 for (size_t i = 1; i <= oldSize; i++)
913 win[(winPos - i) & newMask] = winOld[(winPos - i) & oldMask];
914 ::MidFree(_window);
915 }
916
917 _window = win;
918 _winSizeAllocated = newSize;
919 _winSize = newSize;
920 } 1959 }
921 1960 // (!_isSolid || !_window)
922 _winMask = _winSize - 1; 1961 const size_t allocSize = newSize + kMaxMatchLen + 64;
923 _winPos &= _winMask; 1962 if (allocSize < newSize)
924 1963 return E_OUTOFMEMORY;
925 if (!_inputBuf) 1964 if (!_window || allocSize > _winSize_Allocated)
926 { 1965 {
927 _inputBuf = (Byte *)::MidAlloc(kInputBufSize); 1966 Z7_RAR_FREE_WINDOW
928 if (!_inputBuf) 1967 _window = NULL;
1968 _winSize_Allocated = 0;
1969 Byte *win = (Byte *)::BigAlloc(allocSize);
1970 if (!win)
929 return E_OUTOFMEMORY; 1971 return E_OUTOFMEMORY;
1972 _window = win;
1973 _winSize_Allocated = allocSize;
930 } 1974 }
931 1975 _winSize = newSize;
932 _inStream = inStream;
933 _outStream = outStream;
934
935 /*
936 _packSize = 0;
937 _packSize_Defined = (inSize != NULL);
938 if (_packSize_Defined)
939 _packSize = *inSize;
940 */
941
942 _unpackSize = 0;
943 _unpackSize_Defined = (outSize != NULL);
944 if (_unpackSize_Defined)
945 _unpackSize = *outSize;
946
947 if ((Int64)_unpackSize >= 0)
948 _lzEnd += _unpackSize;
949 else
950 _lzEnd = 0;
951
952 _progress = progress;
953
954 const HRESULT res = CodeReal();
955
956 if (res != S_OK)
957 return res;
958 if (_lzError)
959 return S_FALSE;
960 if (_unsupportedFilter)
961 return E_NOTIMPL;
962 return S_OK;
963 } 1976 }
964 // catch(const CInBufferException &e) { return e.ErrorCode; } 1977
965 // catch(...) { return S_FALSE; } 1978 if (!_inputBuf)
966 catch(...) { return E_OUTOFMEMORY; } 1979 {
967 // CNewException is possible here. But probably CNewException is caused 1980 _inputBuf = (Byte *)z7_AlignedAlloc(kInputBufSize + kInputBufferPadZone);
968 // by error in data stream. 1981 if (!_inputBuf)
1982 return E_OUTOFMEMORY;
1983 }
1984
1985 _inStream = inStream;
1986 _outStream = outStream;
1987 _progress = progress;
1988 _progress_Pack = 0;
1989 _progress_Unpack = 0;
1990
1991 const HRESULT res = CodeReal();
1992
1993 if (res != S_OK)
1994 return res;
1995 // _lzError = LZ_ERROR_TYPE_HEADER; // for debug
1996 if (_lzError)
1997 return S_FALSE;
1998 if (_unsupportedFilter)
1999 return E_NOTIMPL;
2000 return S_OK;
969} 2001}
970 2002
2003
971Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)) 2004Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))
972{ 2005{
973 if (size != 2) 2006 if (size != 2)
2007 return E_INVALIDARG;
2008 const unsigned pow = data[0];
2009 const unsigned b1 = data[1];
2010 const unsigned frac = b1 >> 3;
2011 // unsigned pow = 15 + 8;
2012 // unsigned frac = 1;
2013 if (pow + ((frac + 31) >> 5) > MAX_DICT_LOG - 17)
2014 // if (frac + (pow << 8) >= ((8 * 2 + 7) << 5) + 8 / 8)
974 return E_NOTIMPL; 2015 return E_NOTIMPL;
975 _dictSizeLog = (Byte)((data[0] & 0xF) + 17); 2016 _dictSize = (size_t)(frac + 32) << (pow + 12);
976 _isSolid = ((data[1] & 1) != 0); 2017 _isSolid = (b1 & 1) != 0;
2018 _is_v7 = (b1 & 2) != 0;
2019 // printf("\ndict size = %p\n", (void *)(size_t)_dictSize);
977 return S_OK; 2020 return S_OK;
978} 2021}
979 2022
diff --git a/CPP/7zip/Compress/Rar5Decoder.h b/CPP/7zip/Compress/Rar5Decoder.h
index daf05dd..66c1c3c 100644
--- a/CPP/7zip/Compress/Rar5Decoder.h
+++ b/CPP/7zip/Compress/Rar5Decoder.h
@@ -5,12 +5,8 @@
5#ifndef ZIP7_INC_COMPRESS_RAR5_DECODER_H 5#ifndef ZIP7_INC_COMPRESS_RAR5_DECODER_H
6#define ZIP7_INC_COMPRESS_RAR5_DECODER_H 6#define ZIP7_INC_COMPRESS_RAR5_DECODER_H
7 7
8#include "../../../C/CpuArch.h"
9
10#include "../../Common/MyBuffer2.h" 8#include "../../Common/MyBuffer2.h"
11#include "../../Common/MyCom.h" 9#include "../../Common/MyCom.h"
12#include "../../Common/MyException.h"
13#include "../../Common/MyVector.h"
14 10
15#include "../ICoder.h" 11#include "../ICoder.h"
16 12
@@ -19,170 +15,7 @@
19namespace NCompress { 15namespace NCompress {
20namespace NRar5 { 16namespace NRar5 {
21 17
22/* 18class CBitDecoder;
23struct CInBufferException: public CSystemException
24{
25 CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}
26};
27*/
28
29class CBitDecoder
30{
31public:
32 const Byte *_buf;
33 unsigned _bitPos;
34 bool _wasFinished;
35 Byte _blockEndBits7;
36 const Byte *_bufCheck2;
37 const Byte *_bufCheck;
38 Byte *_bufLim;
39 Byte *_bufBase;
40
41 UInt64 _processedSize;
42 UInt64 _blockEnd;
43
44 ISequentialInStream *_stream;
45 HRESULT _hres;
46
47 void SetCheck2()
48 {
49 _bufCheck2 = _bufCheck;
50 if (_bufCheck > _buf)
51 {
52 UInt64 processed = GetProcessedSize_Round();
53 if (_blockEnd < processed)
54 _bufCheck2 = _buf;
55 else
56 {
57 const UInt64 delta = _blockEnd - processed;
58 if ((size_t)(_bufCheck - _buf) > delta)
59 _bufCheck2 = _buf + (size_t)delta;
60 }
61 }
62 }
63
64 bool IsBlockOverRead() const
65 {
66 const UInt64 v = GetProcessedSize_Round();
67 if (v < _blockEnd)
68 return false;
69 if (v > _blockEnd)
70 return true;
71 return _bitPos > _blockEndBits7;
72 }
73
74 /*
75 CBitDecoder() throw():
76 _buf(0),
77 _bufLim(0),
78 _bufBase(0),
79 _stream(0),
80 _processedSize(0),
81 _wasFinished(false)
82 {}
83 */
84
85 void Init() throw()
86 {
87 _blockEnd = 0;
88 _blockEndBits7 = 0;
89
90 _bitPos = 0;
91 _processedSize = 0;
92 _buf = _bufBase;
93 _bufLim = _bufBase;
94 _bufCheck = _buf;
95 _bufCheck2 = _buf;
96 _wasFinished = false;
97 }
98
99 void Prepare2() throw();
100
101 void Prepare() throw()
102 {
103 if (_buf >= _bufCheck)
104 Prepare2();
105 }
106
107 bool ExtraBitsWereRead() const
108 {
109 return _buf >= _bufLim && (_buf > _bufLim || _bitPos != 0);
110 }
111
112 bool InputEofError() const { return ExtraBitsWereRead(); }
113
114 unsigned GetProcessedBits7() const { return _bitPos; }
115 UInt64 GetProcessedSize_Round() const { return _processedSize + (size_t)(_buf - _bufBase); }
116 UInt64 GetProcessedSize() const { return _processedSize + (size_t)(_buf - _bufBase) + ((_bitPos + 7) >> 3); }
117
118 void AlignToByte()
119 {
120 _buf += (_bitPos + 7) >> 3;
121 _bitPos = 0;
122 }
123
124 Byte ReadByteInAligned()
125 {
126 return *_buf++;
127 }
128
129 UInt32 GetValue(unsigned numBits) const
130 {
131 UInt32 v = ((UInt32)_buf[0] << 16) | ((UInt32)_buf[1] << 8) | (UInt32)_buf[2];
132 v >>= (24 - numBits - _bitPos);
133 return v & ((1 << numBits) - 1);
134 }
135
136 void MovePos(unsigned numBits)
137 {
138 _bitPos += numBits;
139 _buf += (_bitPos >> 3);
140 _bitPos &= 7;
141 }
142
143 UInt32 ReadBits9(unsigned numBits)
144 {
145 const Byte *buf = _buf;
146 UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];
147 v &= ((UInt32)0xFFFF >> _bitPos);
148 numBits += _bitPos;
149 v >>= (16 - numBits);
150 _buf = buf + (numBits >> 3);
151 _bitPos = numBits & 7;
152 return v;
153 }
154
155 UInt32 ReadBits9fix(unsigned numBits)
156 {
157 const Byte *buf = _buf;
158 UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];
159 const UInt32 mask = ((1 << numBits) - 1);
160 numBits += _bitPos;
161 v >>= (16 - numBits);
162 _buf = buf + (numBits >> 3);
163 _bitPos = numBits & 7;
164 return v & mask;
165 }
166
167 UInt32 ReadBits32(unsigned numBits)
168 {
169 const UInt32 mask = ((1 << numBits) - 1);
170 numBits += _bitPos;
171 const Byte *buf = _buf;
172 UInt32 v = GetBe32(buf);
173 if (numBits > 32)
174 {
175 v <<= (numBits - 32);
176 v |= (UInt32)buf[4] >> (40 - numBits);
177 }
178 else
179 v >>= (32 - numBits);
180 _buf = buf + (numBits >> 3);
181 _bitPos = numBits & 7;
182 return v & mask;
183 }
184};
185
186 19
187struct CFilter 20struct CFilter
188{ 21{
@@ -196,13 +29,20 @@ struct CFilter
196const unsigned kNumReps = 4; 29const unsigned kNumReps = 4;
197const unsigned kLenTableSize = 11 * 4; 30const unsigned kLenTableSize = 11 * 4;
198const unsigned kMainTableSize = 256 + 1 + 1 + kNumReps + kLenTableSize; 31const unsigned kMainTableSize = 256 + 1 + 1 + kNumReps + kLenTableSize;
199const unsigned kDistTableSize = 64; 32const unsigned kExtraDistSymbols_v7 = 16;
33const unsigned kDistTableSize_v6 = 64;
34const unsigned kDistTableSize_MAX = 64 + kExtraDistSymbols_v7;
200const unsigned kNumAlignBits = 4; 35const unsigned kNumAlignBits = 4;
201const unsigned kAlignTableSize = (1 << kNumAlignBits); 36const unsigned kAlignTableSize = 1 << kNumAlignBits;
202const unsigned kLevelTableSize = 20;
203const unsigned kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;
204 37
205const unsigned kNumHuffmanBits = 15; 38const unsigned kNumHufBits = 15;
39
40const unsigned k_NumHufTableBits_Main = 10;
41const unsigned k_NumHufTableBits_Dist = 7;
42const unsigned k_NumHufTableBits_Len = 7;
43const unsigned k_NumHufTableBits_Align = 6;
44
45const unsigned DICT_SIZE_BITS_MAX = 40;
206 46
207Z7_CLASS_IMP_NOQIB_2( 47Z7_CLASS_IMP_NOQIB_2(
208 CDecoder 48 CDecoder
@@ -215,26 +55,33 @@ Z7_CLASS_IMP_NOQIB_2(
215 // bool _packSize_Defined; 55 // bool _packSize_Defined;
216 56
217 bool _unsupportedFilter; 57 bool _unsupportedFilter;
218 bool _lzError; 58 Byte _lzError;
219 bool _writeError; 59 bool _writeError;
220 60
221 bool _isSolid; 61 bool _isSolid;
222 bool _solidAllowed; 62 // bool _solidAllowed;
63 bool _is_v7;
223 bool _tableWasFilled; 64 bool _tableWasFilled;
224 bool _wasInit; 65 bool _wasInit;
225 66
226 Byte _dictSizeLog; 67 Byte _exitType;
227 68
228 // CBitDecoder _bitStream; 69 // Byte _dictSizeLog;
70 size_t _dictSize;
229 Byte *_window; 71 Byte *_window;
230 size_t _winPos; 72 size_t _winPos;
231 size_t _winSize; 73 size_t _winSize;
232 size_t _winMask; 74 size_t _dictSize_forCheck;
233 75 size_t _limit;
76 const Byte *_buf_Res;
234 UInt64 _lzSize; 77 UInt64 _lzSize;
78 size_t _reps[kNumReps];
79 unsigned _bitPos_Res;
80 UInt32 _lastLen;
235 81
236 unsigned _numCorrectDistSymbols; 82 // unsigned _numCorrectDistSymbols;
237 unsigned _numUnusedFilters; 83 unsigned _numUnusedFilters;
84 unsigned _numFilters;
238 85
239 UInt64 _lzWritten; 86 UInt64 _lzWritten;
240 UInt64 _lzFileStart; 87 UInt64 _lzFileStart;
@@ -242,53 +89,39 @@ Z7_CLASS_IMP_NOQIB_2(
242 // UInt64 _packSize; 89 // UInt64 _packSize;
243 UInt64 _lzEnd; 90 UInt64 _lzEnd;
244 UInt64 _writtenFileSize; 91 UInt64 _writtenFileSize;
245 size_t _winSizeAllocated;
246
247 UInt32 _reps[kNumReps];
248 UInt32 _lastLen;
249
250 UInt64 _filterEnd; 92 UInt64 _filterEnd;
251 CMidBuffer _filterSrc; 93 UInt64 _progress_Pack;
252 CMidBuffer _filterDst; 94 UInt64 _progress_Unpack;
253 95 CAlignedBuffer _filterSrc;
254 CRecordVector<CFilter> _filters; 96 CAlignedBuffer _filterDst;
255 97
98 CFilter *_filters;
99 size_t _winSize_Allocated;
256 ISequentialInStream *_inStream; 100 ISequentialInStream *_inStream;
257 ISequentialOutStream *_outStream; 101 ISequentialOutStream *_outStream;
258 ICompressProgressInfo *_progress; 102 ICompressProgressInfo *_progress;
259 Byte *_inputBuf; 103 Byte *_inputBuf;
260 104
261 NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder; 105 NHuffman::CDecoder<kNumHufBits, kMainTableSize, k_NumHufTableBits_Main> m_MainDecoder;
262 NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder; 106 NHuffman::CDecoder256<kNumHufBits, kDistTableSize_MAX, k_NumHufTableBits_Dist> m_DistDecoder;
263 NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder; 107 NHuffman::CDecoder256<kNumHufBits, kAlignTableSize, k_NumHufTableBits_Align> m_AlignDecoder;
264 NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder; 108 NHuffman::CDecoder256<kNumHufBits, kLenTableSize, k_NumHufTableBits_Len> m_LenDecoder;
265 NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder; 109 Byte m_LenPlusTable[DICT_SIZE_BITS_MAX];
266
267 110
268 void InitFilters() 111 void InitFilters()
269 { 112 {
270 _numUnusedFilters = 0; 113 _numUnusedFilters = 0;
271 _filters.Clear(); 114 _numFilters = 0;
272 }
273
274 void DeleteUnusedFilters()
275 {
276 if (_numUnusedFilters != 0)
277 {
278 _filters.DeleteFrontal(_numUnusedFilters);
279 _numUnusedFilters = 0;
280 }
281 } 115 }
282 116 void DeleteUnusedFilters();
283 HRESULT WriteData(const Byte *data, size_t size); 117 HRESULT WriteData(const Byte *data, size_t size);
284 HRESULT ExecuteFilter(const CFilter &f); 118 HRESULT ExecuteFilter(const CFilter &f);
285 HRESULT WriteBuf(); 119 HRESULT WriteBuf();
286 HRESULT AddFilter(CBitDecoder &_bitStream); 120 HRESULT AddFilter(CBitDecoder &_bitStream);
287
288 HRESULT ReadTables(CBitDecoder &_bitStream); 121 HRESULT ReadTables(CBitDecoder &_bitStream);
122 HRESULT DecodeLZ2(const CBitDecoder &_bitStream) throw();
289 HRESULT DecodeLZ(); 123 HRESULT DecodeLZ();
290 HRESULT CodeReal(); 124 HRESULT CodeReal();
291
292public: 125public:
293 CDecoder(); 126 CDecoder();
294 ~CDecoder(); 127 ~CDecoder();
diff --git a/CPP/7zip/Compress/XpressDecoder.cpp b/CPP/7zip/Compress/XpressDecoder.cpp
index 8816a12..47f6061 100644
--- a/CPP/7zip/Compress/XpressDecoder.cpp
+++ b/CPP/7zip/Compress/XpressDecoder.cpp
@@ -2,47 +2,301 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5// #include <stdio.h>
6
7#include "../../../C/CpuArch.h" 5#include "../../../C/CpuArch.h"
6#include "../../../C/RotateDefs.h"
8 7
9#include "HuffmanDecoder.h" 8#include "HuffmanDecoder.h"
10#include "XpressDecoder.h" 9#include "XpressDecoder.h"
11 10
12namespace NCompress { 11#ifdef MY_CPU_LE_UNALIGN
13namespace NXpress { 12 #define Z7_XPRESS_DEC_USE_UNALIGNED_COPY
13#endif
14
15#ifdef Z7_XPRESS_DEC_USE_UNALIGNED_COPY
16
17 #define COPY_CHUNK_SIZE 16
18
19 #define COPY_CHUNK_4_2(dest, src) \
20 { \
21 ((UInt32 *)(void *)dest)[0] = ((const UInt32 *)(const void *)src)[0]; \
22 ((UInt32 *)(void *)dest)[1] = ((const UInt32 *)(const void *)src)[1]; \
23 src += 4 * 2; \
24 dest += 4 * 2; \
25 }
26
27 /* sse2 doesn't help here in GCC and CLANG.
28 so we disabled sse2 here */
29#if 0
30 #if defined(MY_CPU_AMD64)
31 #define Z7_XPRESS_DEC_USE_SSE2
32 #elif defined(MY_CPU_X86)
33 #if defined(_MSC_VER) && _MSC_VER >= 1300 && defined(_M_IX86_FP) && (_M_IX86_FP >= 2) \
34 || defined(__SSE2__) \
35 // || 1 == 1 // for debug only
36 #define Z7_XPRESS_DEC_USE_SSE2
37 #endif
38 #endif
39#endif
40
41 #if defined(MY_CPU_ARM64)
42 #include <arm_neon.h>
43 #define COPY_OFFSET_MIN 16
44 #define COPY_CHUNK1(dest, src) \
45 { \
46 vst1q_u8((uint8_t *)(void *)dest, \
47 vld1q_u8((const uint8_t *)(const void *)src)); \
48 src += 16; \
49 dest += 16; \
50 }
51
52 #define COPY_CHUNK(dest, src) \
53 { \
54 COPY_CHUNK1(dest, src) \
55 if (dest >= dest_lim) break; \
56 COPY_CHUNK1(dest, src) \
57 }
58
59 #elif defined(Z7_XPRESS_DEC_USE_SSE2)
60 #include <emmintrin.h> // sse2
61 #define COPY_OFFSET_MIN 16
62
63 #define COPY_CHUNK1(dest, src) \
64 { \
65 _mm_storeu_si128((__m128i *)(void *)dest, \
66 _mm_loadu_si128((const __m128i *)(const void *)src)); \
67 src += 16; \
68 dest += 16; \
69 }
70
71 #define COPY_CHUNK(dest, src) \
72 { \
73 COPY_CHUNK1(dest, src) \
74 if (dest >= dest_lim) break; \
75 COPY_CHUNK1(dest, src) \
76 }
77
78 #elif defined(MY_CPU_64BIT)
79 #define COPY_OFFSET_MIN 8
80
81 #define COPY_CHUNK(dest, src) \
82 { \
83 ((UInt64 *)(void *)dest)[0] = ((const UInt64 *)(const void *)src)[0]; \
84 ((UInt64 *)(void *)dest)[1] = ((const UInt64 *)(const void *)src)[1]; \
85 src += 8 * 2; \
86 dest += 8 * 2; \
87 }
88
89 #else
90 #define COPY_OFFSET_MIN 4
91
92 #define COPY_CHUNK(dest, src) \
93 { \
94 COPY_CHUNK_4_2(dest, src); \
95 COPY_CHUNK_4_2(dest, src); \
96 }
97
98 #endif
99#endif
14 100
15struct CBitStream 101
102#ifndef COPY_CHUNK_SIZE
103 #define COPY_OFFSET_MIN 4
104 #define COPY_CHUNK_SIZE 8
105 #define COPY_CHUNK_2(dest, src) \
106 { \
107 const Byte a0 = src[0]; \
108 const Byte a1 = src[1]; \
109 dest[0] = a0; \
110 dest[1] = a1; \
111 src += 2; \
112 dest += 2; \
113 }
114 #define COPY_CHUNK(dest, src) \
115 { \
116 COPY_CHUNK_2(dest, src) \
117 COPY_CHUNK_2(dest, src) \
118 COPY_CHUNK_2(dest, src) \
119 COPY_CHUNK_2(dest, src) \
120 }
121#endif
122
123
124#define COPY_CHUNKS \
125{ \
126 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \
127 do { COPY_CHUNK(dest, src) } \
128 while (dest < dest_lim); \
129}
130
131
132static
133Z7_FORCE_INLINE
134// Z7_ATTRIB_NO_VECTOR
135void CopyMatch_1(Byte *dest, const Byte *dest_lim)
16{ 136{
17 UInt32 Value; 137 const unsigned b0 = dest[-1];
18 unsigned BitPos; 138 {
139#if defined(Z7_XPRESS_DEC_USE_UNALIGNED_COPY) && (COPY_CHUNK_SIZE == 16)
140 #if defined(MY_CPU_64BIT)
141 {
142 const UInt64 v64 = (UInt64)b0 * 0x0101010101010101;
143 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
144 do
145 {
146 ((UInt64 *)(void *)dest)[0] = v64;
147 ((UInt64 *)(void *)dest)[1] = v64;
148 dest += 16;
149 }
150 while (dest < dest_lim);
151 }
152 #else
153 {
154 UInt32 v = b0;
155 v |= v << 8;
156 v |= v << 16;
157 do
158 {
159 ((UInt32 *)(void *)dest)[0] = v;
160 ((UInt32 *)(void *)dest)[1] = v;
161 dest += 8;
162 ((UInt32 *)(void *)dest)[0] = v;
163 ((UInt32 *)(void *)dest)[1] = v;
164 dest += 8;
165 }
166 while (dest < dest_lim);
167 }
168 #endif
169#else
170 do
171 {
172 dest[0] = (Byte)b0;
173 dest[1] = (Byte)b0;
174 dest += 2;
175 dest[0] = (Byte)b0;
176 dest[1] = (Byte)b0;
177 dest += 2;
178 }
179 while (dest < dest_lim);
180#endif
181 }
182}
19 183
20 UInt32 GetValue(unsigned numBits) const 184
21 { 185// (offset != 1)
22 return (Value >> (BitPos - numBits)) & ((1 << numBits) - 1); 186static
23 } 187Z7_FORCE_INLINE
24 188// Z7_ATTRIB_NO_VECTOR
25 void MovePos(unsigned numBits) 189void CopyMatch_Non1(Byte *dest, size_t offset, const Byte *dest_lim)
190{
191 const Byte *src = dest - offset;
26 { 192 {
27 BitPos -= numBits; 193 // (COPY_OFFSET_MIN >= 4)
194 if (offset >= COPY_OFFSET_MIN)
195 {
196 COPY_CHUNKS
197 // return;
198 }
199 else
200#if (COPY_OFFSET_MIN > 4)
201 #if COPY_CHUNK_SIZE < 8
202 #error Stop_Compiling_Bad_COPY_CHUNK_SIZE
203 #endif
204 if (offset >= 4)
205 {
206 Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
207 do
208 {
209 COPY_CHUNK_4_2(dest, src)
210 #if COPY_CHUNK_SIZE != 16
211 if (dest >= dest_lim) break;
212 #endif
213 COPY_CHUNK_4_2(dest, src)
214 }
215 while (dest < dest_lim);
216 // return;
217 }
218 else
219#endif
220 {
221 // (offset < 4)
222 if (offset == 2)
223 {
224#if defined(Z7_XPRESS_DEC_USE_UNALIGNED_COPY)
225 UInt32 w0 = GetUi16(src);
226 w0 += w0 << 16;
227 do
228 {
229 SetUi32(dest, w0)
230 dest += 4;
231 }
232 while (dest < dest_lim);
233#else
234 const unsigned b0 = src[0];
235 const Byte b1 = src[1];
236 do
237 {
238 dest[0] = (Byte)b0;
239 dest[1] = b1;
240 dest += 2;
241 }
242 while (dest < dest_lim);
243#endif
244 }
245 else // (offset == 3)
246 {
247 const unsigned b0 = src[0];
248#if defined(Z7_XPRESS_DEC_USE_UNALIGNED_COPY)
249 const unsigned w1 = GetUi16(src + 1);
250 do
251 {
252 dest[0] = (Byte)b0;
253 SetUi16(dest + 1, (UInt16)w1)
254 dest += 3;
255 }
256 while (dest < dest_lim);
257#else
258 const Byte b1 = src[1];
259 const Byte b2 = src[2];
260 do
261 {
262 dest[0] = (Byte)b0;
263 dest[1] = b1;
264 dest[2] = b2;
265 dest += 3;
266 }
267 while (dest < dest_lim);
268#endif
269 }
270 }
28 } 271 }
29}; 272}
273
274
275namespace NCompress {
276namespace NXpress {
30 277
31#define BIT_STREAM_NORMALIZE \ 278#define BIT_STREAM_NORMALIZE \
32 if (bs.BitPos < 16) { \ 279 if (BitPos > 16) { \
33 if (in >= lim) return S_FALSE; \ 280 if (in >= lim) return S_FALSE; \
34 bs.Value = (bs.Value << 16) | GetUi16(in); \ 281 BitPos -= 16; \
35 in += 2; bs.BitPos += 16; } 282 Value |= (UInt32)GetUi16(in) << BitPos; \
36 283 in += 2; }
284
285#define MOVE_POS(bs, numBits) \
286 BitPos += (unsigned)numBits; \
287 Value <<= numBits; \
288
289
37static const unsigned kNumHuffBits = 15; 290static const unsigned kNumHuffBits = 15;
291static const unsigned kNumTableBits = 10;
38static const unsigned kNumLenBits = 4; 292static const unsigned kNumLenBits = 4;
39static const unsigned kLenMask = (1 << kNumLenBits) - 1; 293static const unsigned kLenMask = (1 << kNumLenBits) - 1;
40static const unsigned kNumPosSlots = 16; 294static const unsigned kNumPosSlots = 16;
41static const unsigned kNumSyms = 256 + (kNumPosSlots << kNumLenBits); 295static const unsigned kNumSyms = 256 + (kNumPosSlots << kNumLenBits);
42 296
43HRESULT Decode(const Byte *in, size_t inSize, Byte *out, size_t outSize) 297HRESULT Decode_WithExceedWrite(const Byte *in, size_t inSize, Byte *out, size_t outSize)
44{ 298{
45 NCompress::NHuffman::CDecoder<kNumHuffBits, kNumSyms> huff; 299 NCompress::NHuffman::CDecoder<kNumHuffBits, kNumSyms, kNumTableBits> huff;
46 300
47 if (inSize < kNumSyms / 2 + 4) 301 if (inSize < kNumSyms / 2 + 4)
48 return S_FALSE; 302 return S_FALSE;
@@ -50,50 +304,57 @@ HRESULT Decode(const Byte *in, size_t inSize, Byte *out, size_t outSize)
50 Byte levels[kNumSyms]; 304 Byte levels[kNumSyms];
51 for (unsigned i = 0; i < kNumSyms / 2; i++) 305 for (unsigned i = 0; i < kNumSyms / 2; i++)
52 { 306 {
53 const Byte b = in[i]; 307 const unsigned b = in[i];
54 levels[(size_t)i * 2] = (Byte)(b & 0xF); 308 levels[(size_t)i * 2 ] = (Byte)(b & 0xf);
55 levels[(size_t)i * 2 + 1] = (Byte)(b >> 4); 309 levels[(size_t)i * 2 + 1] = (Byte)(b >> 4);
56 } 310 }
57 if (!huff.BuildFull(levels)) 311 if (!huff.Build(levels, NHuffman::k_BuildMode_Full))
58 return S_FALSE; 312 return S_FALSE;
59 } 313 }
60 314
315 UInt32 Value;
316 unsigned BitPos; // how many bits in (Value) were processed
61 317
62 CBitStream bs; 318 const Byte *lim = in + inSize - 1; // points to last byte
63
64 const Byte *lim = in + inSize - 1;
65
66 in += kNumSyms / 2; 319 in += kNumSyms / 2;
67 bs.Value = ((UInt32)GetUi16(in) << 16) | GetUi16(in + 2); 320#ifdef MY_CPU_LE_UNALIGN
321 Value = GetUi32(in);
322 Value = rotlFixed(Value, 16);
323#else
324 Value = ((UInt32)GetUi16(in) << 16) | GetUi16(in + 2);
325#endif
326
68 in += 4; 327 in += 4;
69 bs.BitPos = 32; 328 BitPos = 0;
70 329 Byte *dest = out;
71 size_t pos = 0; 330 const Byte *outLim = out + outSize;
72 331
73 for (;;) 332 for (;;)
74 { 333 {
75 // printf("\n%d", pos); 334 unsigned sym;
76 UInt32 sym = huff.DecodeFull(&bs); 335 Z7_HUFF_DECODE_VAL_IN_HIGH32(sym, &huff, kNumHuffBits, kNumTableBits,
77 // printf(" sym = %d", sym); 336 Value, Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO, {}, MOVE_POS, {}, bs)
337 // 0 < BitPos <= 31
78 BIT_STREAM_NORMALIZE 338 BIT_STREAM_NORMALIZE
339 // 0 < BitPos <= 16
79 340
80 if (pos >= outSize) 341 if (dest >= outLim)
81 return (sym == 256 && in == lim + 1) ? S_OK : S_FALSE; 342 return (sym == 256 && Value == 0 && in == lim + 1) ? S_OK : S_FALSE;
82 343
83 if (sym < 256) 344 if (sym < 256)
84 out[pos++] = (Byte)sym; 345 *dest++ = (Byte)sym;
85 else 346 else
86 { 347 {
87 sym -= 256; 348 const unsigned distBits = (unsigned)(Byte)sym >> kNumLenBits; // (sym - 256) >> kNumLenBits;
88 UInt32 dist = sym >> kNumLenBits; 349 UInt32 len = (UInt32)(sym & kLenMask);
89 UInt32 len = sym & kLenMask;
90 350
91 if (len == kLenMask) 351 if (len == kLenMask)
92 { 352 {
93 if (in > lim) 353 if (in > lim)
94 return S_FALSE; 354 return S_FALSE;
355 // here we read input bytes in out-of-order related to main input stream (bits in Value):
95 len = *in++; 356 len = *in++;
96 if (len == 0xFF) 357 if (len == 0xff)
97 { 358 {
98 if (in >= lim) 359 if (in >= lim)
99 return S_FALSE; 360 return S_FALSE;
@@ -104,26 +365,33 @@ HRESULT Decode(const Byte *in, size_t inSize, Byte *out, size_t outSize)
104 len += kLenMask; 365 len += kLenMask;
105 } 366 }
106 367
107 bs.BitPos -= dist; 368 len += 3;
108 dist = (UInt32)1 << dist; 369 if (len > (size_t)(outLim - dest))
109 dist += ((bs.Value >> bs.BitPos) & (dist - 1));
110
111 BIT_STREAM_NORMALIZE
112
113 if (len + 3 > outSize - pos)
114 return S_FALSE;
115 if (dist > pos)
116 return S_FALSE; 370 return S_FALSE;
117 371
118 Byte *dest = out + pos; 372 if (distBits == 0)
119 const Byte *src = dest - dist; 373 {
120 pos += len + 3; 374 // d == 1
121 len += 1; 375 if (dest == out)
122 *dest++ = *src++; 376 return S_FALSE;
123 *dest++ = *src++; 377 Byte *destTemp = dest;
124 do 378 dest += len;
125 *dest++ = *src++; 379 CopyMatch_1(destTemp, dest);
126 while (--len); 380 }
381 else
382 {
383 unsigned d = (unsigned)(Value >> (32 - distBits));
384 MOVE_POS(bs, distBits)
385 d += 1u << distBits;
386 // 0 < BitPos <= 31
387 BIT_STREAM_NORMALIZE
388 // 0 < BitPos <= 16
389 if (d > (size_t)(dest - out))
390 return S_FALSE;
391 Byte *destTemp = dest;
392 dest += len;
393 CopyMatch_Non1(destTemp, d, dest);
394 }
127 } 395 }
128 } 396 }
129} 397}
diff --git a/CPP/7zip/Compress/XpressDecoder.h b/CPP/7zip/Compress/XpressDecoder.h
index aaa5b25..7d17602 100644
--- a/CPP/7zip/Compress/XpressDecoder.h
+++ b/CPP/7zip/Compress/XpressDecoder.h
@@ -3,12 +3,15 @@
3#ifndef ZIP7_INC_XPRESS_DECODER_H 3#ifndef ZIP7_INC_XPRESS_DECODER_H
4#define ZIP7_INC_XPRESS_DECODER_H 4#define ZIP7_INC_XPRESS_DECODER_H
5 5
6#include "../../Common/MyWindows.h" 6#include "../../Common/MyTypes.h"
7 7
8namespace NCompress { 8namespace NCompress {
9namespace NXpress { 9namespace NXpress {
10 10
11HRESULT Decode(const Byte *in, size_t inSize, Byte *out, size_t outSize); 11// (out) buffer size must be larger than (outSize) for the following value:
12const unsigned kAdditionalOutputBufSize = 32;
13
14HRESULT Decode_WithExceedWrite(const Byte *in, size_t inSize, Byte *out, size_t outSize);
12 15
13}} 16}}
14 17
diff --git a/CPP/7zip/Compress/XzDecoder.cpp b/CPP/7zip/Compress/XzDecoder.cpp
index 420bd71..62a78bf 100644
--- a/CPP/7zip/Compress/XzDecoder.cpp
+++ b/CPP/7zip/Compress/XzDecoder.cpp
@@ -26,6 +26,7 @@ static HRESULT SResToHRESULT_Code(SRes res) throw()
26 case SZ_OK: return S_OK; 26 case SZ_OK: return S_OK;
27 case SZ_ERROR_MEM: return E_OUTOFMEMORY; 27 case SZ_ERROR_MEM: return E_OUTOFMEMORY;
28 case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; 28 case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
29 default: break;
29 } 30 }
30 return S_FALSE; 31 return S_FALSE;
31} 32}
diff --git a/CPP/7zip/Compress/XzEncoder.cpp b/CPP/7zip/Compress/XzEncoder.cpp
index 33f0bde..1bca322 100644
--- a/CPP/7zip/Compress/XzEncoder.cpp
+++ b/CPP/7zip/Compress/XzEncoder.cpp
@@ -157,7 +157,7 @@ HRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop)
157 const int filterId = FilterIdFromName(prop.bstrVal); 157 const int filterId = FilterIdFromName(prop.bstrVal);
158 if (filterId < 0 /* || filterId == XZ_ID_LZMA2 */) 158 if (filterId < 0 /* || filterId == XZ_ID_LZMA2 */)
159 return E_INVALIDARG; 159 return E_INVALIDARG;
160 id32 = (unsigned)filterId; 160 id32 = (UInt32)(unsigned)filterId;
161 } 161 }
162 } 162 }
163 163
diff --git a/CPP/7zip/Compress/ZDecoder.cpp b/CPP/7zip/Compress/ZDecoder.cpp
index 07c5fe5..25eb80e 100644
--- a/CPP/7zip/Compress/ZDecoder.cpp
+++ b/CPP/7zip/Compress/ZDecoder.cpp
@@ -14,7 +14,7 @@
14namespace NCompress { 14namespace NCompress {
15namespace NZ { 15namespace NZ {
16 16
17static const UInt32 kBufferSize = (1 << 20); 17static const size_t kBufferSize = 1 << 20;
18static const Byte kNumBitsMask = 0x1F; 18static const Byte kNumBitsMask = 0x1F;
19static const Byte kBlockModeMask = 0x80; 19static const Byte kBlockModeMask = 0x80;
20static const unsigned kNumMinBits = 9; 20static const unsigned kNumMinBits = 9;
@@ -29,14 +29,15 @@ void CDecoder::Free()
29 29
30CDecoder::~CDecoder() { Free(); } 30CDecoder::~CDecoder() { Free(); }
31 31
32HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, 32HRESULT CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
33 const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) 33 ICompressProgressInfo *progress)
34{ 34{
35 try {
36 // PackSize = 0;
37
35 CInBuffer inBuffer; 38 CInBuffer inBuffer;
36 COutBuffer outBuffer; 39 COutBuffer outBuffer;
37 40
38 PackSize = 0;
39
40 if (!inBuffer.Create(kBufferSize)) 41 if (!inBuffer.Create(kBufferSize))
41 return E_OUTOFMEMORY; 42 return E_OUTOFMEMORY;
42 inBuffer.SetStream(inStream); 43 inBuffer.SetStream(inStream);
@@ -54,14 +55,14 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
54 if (buf[0] != 0x1F || buf[1] != 0x9D) 55 if (buf[0] != 0x1F || buf[1] != 0x9D)
55 return S_FALSE; 56 return S_FALSE;
56 } 57 }
57 Byte prop = buf[2]; 58 const Byte prop = buf[2];
58 59
59 if ((prop & 0x60) != 0) 60 if ((prop & 0x60) != 0)
60 return S_FALSE; 61 return S_FALSE;
61 const unsigned maxbits = prop & kNumBitsMask; 62 const unsigned maxbits = prop & kNumBitsMask;
62 if (maxbits < kNumMinBits || maxbits > kNumMaxBits) 63 if (maxbits < kNumMinBits || maxbits > kNumMaxBits)
63 return S_FALSE; 64 return S_FALSE;
64 const UInt32 numItems = 1 << maxbits; 65 const UInt32 numItems = (UInt32)1 << maxbits;
65 // Speed optimization: blockSymbol can contain unused velue. 66 // Speed optimization: blockSymbol can contain unused velue.
66 67
67 if (maxbits != _numMaxBits || !_parents || !_suffixes || !_stack) 68 if (maxbits != _numMaxBits || !_parents || !_suffixes || !_stack)
@@ -102,7 +103,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
102 const unsigned bytePos = bitPos >> 3; 103 const unsigned bytePos = bitPos >> 3;
103 UInt32 symbol = buf[bytePos] | ((UInt32)buf[(size_t)bytePos + 1] << 8) | ((UInt32)buf[(size_t)bytePos + 2] << 16); 104 UInt32 symbol = buf[bytePos] | ((UInt32)buf[(size_t)bytePos + 1] << 8) | ((UInt32)buf[(size_t)bytePos + 2] << 16);
104 symbol >>= (bitPos & 7); 105 symbol >>= (bitPos & 7);
105 symbol &= (1 << numBits) - 1; 106 symbol &= ((UInt32)1 << numBits) - 1;
106 bitPos += numBits; 107 bitPos += numBits;
107 if (bitPos > numBufBits) 108 if (bitPos > numBufBits)
108 break; 109 break;
@@ -152,20 +153,17 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
152 else 153 else
153 needPrev = false; 154 needPrev = false;
154 } 155 }
155 PackSize = inBuffer.GetProcessedSize(); 156 // PackSize = inBuffer.GetProcessedSize();
156 const HRESULT res2 = outBuffer.Flush(); 157 const HRESULT res2 = outBuffer.Flush();
157 return (res == S_OK) ? res2 : res; 158 return (res == S_OK) ? res2 : res;
158} 159
159 160 }
160Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
161 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
162{
163 try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
164 catch(const CInBufferException &e) { return e.ErrorCode; } 161 catch(const CInBufferException &e) { return e.ErrorCode; }
165 catch(const COutBufferException &e) { return e.ErrorCode; } 162 catch(const COutBufferException &e) { return e.ErrorCode; }
166 catch(...) { return S_FALSE; } 163 catch(...) { return S_FALSE; }
167} 164}
168 165
166
169bool CheckStream(const Byte *data, size_t size) 167bool CheckStream(const Byte *data, size_t size)
170{ 168{
171 if (size < 3) 169 if (size < 3)
@@ -178,7 +176,7 @@ bool CheckStream(const Byte *data, size_t size)
178 const unsigned maxbits = prop & kNumBitsMask; 176 const unsigned maxbits = prop & kNumBitsMask;
179 if (maxbits < kNumMinBits || maxbits > kNumMaxBits) 177 if (maxbits < kNumMinBits || maxbits > kNumMaxBits)
180 return false; 178 return false;
181 const UInt32 numItems = 1 << maxbits; 179 const UInt32 numItems = (UInt32)1 << maxbits;
182 const UInt32 blockSymbol = ((prop & kBlockModeMask) != 0) ? 256 : ((UInt32)1 << kNumMaxBits); 180 const UInt32 blockSymbol = ((prop & kBlockModeMask) != 0) ? 256 : ((UInt32)1 << kNumMaxBits);
183 unsigned numBits = kNumMinBits; 181 unsigned numBits = kNumMinBits;
184 UInt32 head = (blockSymbol == 256) ? 257 : 256; 182 UInt32 head = (blockSymbol == 256) ? 257 : 256;
@@ -202,7 +200,7 @@ bool CheckStream(const Byte *data, size_t size)
202 const unsigned bytePos = bitPos >> 3; 200 const unsigned bytePos = bitPos >> 3;
203 UInt32 symbol = buf[bytePos] | ((UInt32)buf[bytePos + 1] << 8) | ((UInt32)buf[bytePos + 2] << 16); 201 UInt32 symbol = buf[bytePos] | ((UInt32)buf[bytePos + 1] << 8) | ((UInt32)buf[bytePos + 2] << 16);
204 symbol >>= (bitPos & 7); 202 symbol >>= (bitPos & 7);
205 symbol &= (1 << numBits) - 1; 203 symbol &= ((UInt32)1 << numBits) - 1;
206 bitPos += numBits; 204 bitPos += numBits;
207 if (bitPos > numBufBits) 205 if (bitPos > numBufBits)
208 { 206 {
diff --git a/CPP/7zip/Compress/ZDecoder.h b/CPP/7zip/Compress/ZDecoder.h
index 390b013..fd67f8f 100644
--- a/CPP/7zip/Compress/ZDecoder.h
+++ b/CPP/7zip/Compress/ZDecoder.h
@@ -12,10 +12,8 @@ namespace NZ {
12 12
13// Z decoder decodes Z data stream, including 3 bytes of header. 13// Z decoder decodes Z data stream, including 3 bytes of header.
14 14
15Z7_CLASS_IMP_COM_1( 15class CDecoder
16 CDecoder 16{
17 , ICompressCoder
18)
19 UInt16 *_parents; 17 UInt16 *_parents;
20 Byte *_suffixes; 18 Byte *_suffixes;
21 Byte *_stack; 19 Byte *_stack;
@@ -25,10 +23,10 @@ public:
25 CDecoder(): _parents(NULL), _suffixes(NULL), _stack(NULL), /* _prop(0), */ _numMaxBits(0) {} 23 CDecoder(): _parents(NULL), _suffixes(NULL), _stack(NULL), /* _prop(0), */ _numMaxBits(0) {}
26 ~CDecoder(); 24 ~CDecoder();
27 void Free(); 25 void Free();
28 UInt64 PackSize; 26 // UInt64 PackSize;
29 27
30 HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, 28 HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
31 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); 29 ICompressProgressInfo *progress);
32}; 30};
33 31
34/* 32/*
diff --git a/CPP/7zip/Compress/ZlibDecoder.cpp b/CPP/7zip/Compress/ZlibDecoder.cpp
index a066932..dc01894 100644
--- a/CPP/7zip/Compress/ZlibDecoder.cpp
+++ b/CPP/7zip/Compress/ZlibDecoder.cpp
@@ -17,25 +17,41 @@ namespace NZlib {
17#define ADLER_MOD 65521 17#define ADLER_MOD 65521
18#define ADLER_LOOP_MAX 5550 18#define ADLER_LOOP_MAX 5550
19 19
20UInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size); 20UInt32 Adler32_Update(UInt32 adler, const Byte *data, size_t size);
21UInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size) 21UInt32 Adler32_Update(UInt32 adler, const Byte *data, size_t size)
22{ 22{
23 UInt32 a = adler & 0xFFFF; 23 if (size == 0)
24 UInt32 b = (adler >> 16) & 0xFFFF; 24 return adler;
25 while (size > 0) 25 UInt32 a = adler & 0xffff;
26 UInt32 b = adler >> 16;
27 do
26 { 28 {
27 const unsigned curSize = (size > ADLER_LOOP_MAX) ? ADLER_LOOP_MAX : (unsigned )size; 29 size_t cur = size;
28 unsigned i; 30 if (cur > ADLER_LOOP_MAX)
29 for (i = 0; i < curSize; i++) 31 cur = ADLER_LOOP_MAX;
32 size -= cur;
33 const Byte *lim = data + cur;
34 if (cur >= 4)
30 { 35 {
31 a += buf[i]; 36 lim -= 4 - 1;
32 b += a; 37 do
38 {
39 a += data[0]; b += a;
40 a += data[1]; b += a;
41 a += data[2]; b += a;
42 a += data[3]; b += a;
43 data += 4;
44 }
45 while (data < lim);
46 lim += 4 - 1;
33 } 47 }
34 buf += curSize; 48 if (data != lim) { a += *data++; b += a;
35 size -= curSize; 49 if (data != lim) { a += *data++; b += a;
50 if (data != lim) { a += *data++; b += a; }}}
36 a %= ADLER_MOD; 51 a %= ADLER_MOD;
37 b %= ADLER_MOD; 52 b %= ADLER_MOD;
38 } 53 }
54 while (size);
39 return (b << 16) + a; 55 return (b << 16) + a;
40} 56}
41 57
@@ -55,38 +71,63 @@ Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
55 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)) 71 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
56{ 72{
57 DEFLATE_TRY_BEGIN 73 DEFLATE_TRY_BEGIN
58 if (!AdlerStream) 74 _inputProcessedSize_Additional = 0;
59 AdlerStream = AdlerSpec = new COutStreamWithAdler; 75 AdlerStream.Create_if_Empty();
60 if (!DeflateDecoder) 76 DeflateDecoder.Create_if_Empty();
61 { 77 DeflateDecoder->Set_NeedFinishInput(true);
62 DeflateDecoderSpec = new NDeflate::NDecoder::CCOMCoder;
63 DeflateDecoderSpec->ZlibMode = true;
64 DeflateDecoder = DeflateDecoderSpec;
65 }
66 78
67 if (inSize && *inSize < 2) 79 if (inSize && *inSize < 2)
68 return S_FALSE; 80 return S_FALSE;
69 Byte buf[2]; 81 {
70 RINOK(ReadStream_FALSE(inStream, buf, 2)) 82 Byte buf[2];
71 if (!IsZlib(buf)) 83 RINOK(ReadStream_FALSE(inStream, buf, 2))
72 return S_FALSE; 84 if (!IsZlib(buf))
73 85 return S_FALSE;
74 AdlerSpec->SetStream(outStream); 86 }
75 AdlerSpec->Init(); 87 _inputProcessedSize_Additional = 2;
76 88 AdlerStream->SetStream(outStream);
89 AdlerStream->Init();
90 // NDeflate::NDecoder::Code() ignores inSize
91 /*
77 UInt64 inSize2 = 0; 92 UInt64 inSize2 = 0;
78 if (inSize) 93 if (inSize)
79 inSize2 = *inSize - 2; 94 inSize2 = *inSize - 2;
80 95 */
81 const HRESULT res = DeflateDecoder->Code(inStream, AdlerStream, inSize ? &inSize2 : NULL, outSize, progress); 96 const HRESULT res = DeflateDecoder.Interface()->Code(inStream, AdlerStream,
82 AdlerSpec->ReleaseStream(); 97 /* inSize ? &inSize2 : */ NULL, outSize, progress);
98 AdlerStream->ReleaseStream();
83 99
84 if (res == S_OK) 100 if (res == S_OK)
85 { 101 {
86 const Byte *p = DeflateDecoderSpec->ZlibFooter; 102 UInt32 footer32[1];
87 const UInt32 adler = GetBe32(p); 103 UInt32 processedSize;
88 if (adler != AdlerSpec->GetAdler()) 104 RINOK(DeflateDecoder->ReadUnusedFromInBuf(footer32, 4, &processedSize))
89 return S_FALSE; 105 if (processedSize != 4)
106 {
107 size_t processedSize2 = 4 - processedSize;
108 RINOK(ReadStream(inStream, (Byte *)(void *)footer32 + processedSize, &processedSize2))
109 _inputProcessedSize_Additional += (Int32)processedSize2;
110 processedSize += (UInt32)processedSize2;
111 }
112
113 if (processedSize == 4)
114 {
115 const UInt32 adler = GetBe32a(footer32);
116 if (adler != AdlerStream->GetAdler())
117 return S_FALSE; // adler error
118 }
119 else if (!IsAdlerOptional)
120 return S_FALSE; // unexpeced end of stream (can't read adler)
121 else
122 {
123 // IsAdlerOptional == true
124 if (processedSize != 0)
125 {
126 // we exclude adler bytes from processed size:
127 _inputProcessedSize_Additional -= (Int32)processedSize;
128 return S_FALSE;
129 }
130 }
90 } 131 }
91 return res; 132 return res;
92 DEFLATE_TRY_END 133 DEFLATE_TRY_END
diff --git a/CPP/7zip/Compress/ZlibDecoder.h b/CPP/7zip/Compress/ZlibDecoder.h
index 1dc5c67..5488653 100644
--- a/CPP/7zip/Compress/ZlibDecoder.h
+++ b/CPP/7zip/Compress/ZlibDecoder.h
@@ -14,8 +14,8 @@ Z7_CLASS_IMP_NOQIB_1(
14 COutStreamWithAdler 14 COutStreamWithAdler
15 , ISequentialOutStream 15 , ISequentialOutStream
16) 16)
17 CMyComPtr<ISequentialOutStream> _stream;
18 UInt32 _adler; 17 UInt32 _adler;
18 CMyComPtr<ISequentialOutStream> _stream;
19 UInt64 _size; 19 UInt64 _size;
20public: 20public:
21 void SetStream(ISequentialOutStream *stream) { _stream = stream; } 21 void SetStream(ISequentialOutStream *stream) { _stream = stream; }
@@ -29,13 +29,20 @@ Z7_CLASS_IMP_NOQIB_1(
29 CDecoder 29 CDecoder
30 , ICompressCoder 30 , ICompressCoder
31) 31)
32 COutStreamWithAdler *AdlerSpec; 32 CMyComPtr2<ISequentialOutStream, COutStreamWithAdler> AdlerStream;
33 CMyComPtr<ISequentialOutStream> AdlerStream; 33 CMyComPtr2<ICompressCoder, NDeflate::NDecoder::CCOMCoder> DeflateDecoder;
34 NCompress::NDeflate::NDecoder::CCOMCoder *DeflateDecoderSpec; 34 Int32 _inputProcessedSize_Additional;
35 CMyComPtr<ICompressCoder> DeflateDecoder;
36public: 35public:
37 UInt64 GetInputProcessedSize() const { return DeflateDecoderSpec->GetInputProcessedSize() + 2; } 36 bool IsAdlerOptional;
38 UInt64 GetOutputProcessedSize() const { return AdlerSpec->GetSize(); } 37
38 CDecoder(): IsAdlerOptional(false) {}
39 UInt64 GetInputProcessedSize() const
40 {
41 return (UInt64)(
42 (Int64)DeflateDecoder->GetInputProcessedSize() +
43 (Int64)_inputProcessedSize_Additional);
44 }
45 UInt64 GetOutputProcessedSize() const { return AdlerStream->GetSize(); }
39}; 46};
40 47
41static bool inline IsZlib(const Byte *p) 48static bool inline IsZlib(const Byte *p)
diff --git a/CPP/7zip/Compress/ZstdDecoder.cpp b/CPP/7zip/Compress/ZstdDecoder.cpp
new file mode 100644
index 0000000..c958475
--- /dev/null
+++ b/CPP/7zip/Compress/ZstdDecoder.cpp
@@ -0,0 +1,437 @@
1// ZstdDecoder.cpp
2
3#include "StdAfx.h"
4
5// #include <stdio.h>
6
7#include "../../../C/Alloc.h"
8
9#include "../Common/CWrappers.h"
10#include "../Common/StreamUtils.h"
11
12#include "ZstdDecoder.h"
13
14namespace NCompress {
15namespace NZstd {
16
17static const size_t k_Zstd_BlockSizeMax = 1 << 17;
18/*
19 we set _outStepMask as (k_Zstd_BlockSizeMax - 1), because:
20 - cycSize in zstd decoder for isCyclicMode is aligned for (1 << 17) only.
21 So some write sizes will be multiple of ((1 << 17) * n).
22 - Also it can be optimal to flush data after each block decoding.
23*/
24
25CDecoder::CDecoder():
26 _outStepMask(k_Zstd_BlockSizeMax - 1) // must be = (1 << x) - 1
27 , _dec(NULL)
28 , _inProcessed(0)
29 , _inBufSize(1u << 19) // larger value will reduce the number of memcpy() calls in CZstdDec code
30 , _inBuf(NULL)
31 , FinishMode(false)
32 , DisableHash(False)
33 // , DisableHash(True) // for debug : fast decoding without hash calculation
34{
35 // ZstdDecInfo_Clear(&ResInfo);
36}
37
38CDecoder::~CDecoder()
39{
40 if (_dec)
41 ZstdDec_Destroy(_dec);
42 MidFree(_inBuf);
43}
44
45
46Z7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 , UInt32 size))
47 { _inBufSize = size; return S_OK; }
48Z7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32 , UInt32 size))
49{
50 // we round it down:
51 size >>= 1;
52 size |= size >> (1 << 0);
53 size |= size >> (1 << 1);
54 size |= size >> (1 << 2);
55 size |= size >> (1 << 3);
56 size |= size >> (1 << 4);
57 _outStepMask = size; // it's (1 << x) - 1 now
58 return S_OK;
59}
60
61Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte * /* prop */, UInt32 /* size */))
62{
63 // if (size != 3 && size != 5) return E_NOTIMPL;
64 return S_OK;
65}
66
67
68Z7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))
69{
70 FinishMode = (finishMode != 0);
71 // FinishMode = false; // for debug
72 return S_OK;
73}
74
75
76Z7_COM7F_IMF(CDecoder::ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *processedSize))
77{
78 size_t cur = ZstdDec_ReadUnusedFromInBuf(_dec, _afterDecoding_tempPos, data, size);
79 _afterDecoding_tempPos += cur;
80 size -= (UInt32)cur;
81 if (size)
82 {
83 const size_t rem = _state.inLim - _state.inPos;
84 if (size > rem)
85 size = (UInt32)rem;
86 if (size)
87 {
88 memcpy((Byte *)data + cur, _state.inBuf + _state.inPos, size);
89 _state.inPos += size;
90 cur += size;
91 }
92 }
93 *processedSize = (UInt32)cur;
94 return S_OK;
95}
96
97
98
99HRESULT CDecoder::Prepare(const UInt64 *outSize)
100{
101 _inProcessed = 0;
102 _afterDecoding_tempPos = 0;
103 ZstdDecState_Clear(&_state);
104 ZstdDecInfo_CLEAR(&ResInfo)
105 // _state.outStep = _outStepMask + 1; // must be = (1 << x)
106 _state.disableHash = DisableHash;
107 if (outSize)
108 {
109 _state.outSize_Defined = True;
110 _state.outSize = *outSize;
111 // _state.outSize = 0; // for debug
112 }
113 if (!_dec)
114 {
115 _dec = ZstdDec_Create(&g_AlignedAlloc, &g_BigAlloc);
116 if (!_dec)
117 return E_OUTOFMEMORY;
118 }
119 if (!_inBuf || _inBufSize != _inBufSize_Allocated)
120 {
121 MidFree(_inBuf);
122 _inBuf = NULL;
123 _inBufSize_Allocated = 0;
124 _inBuf = (Byte *)MidAlloc(_inBufSize);
125 if (!_inBuf)
126 return E_OUTOFMEMORY;
127 _inBufSize_Allocated = _inBufSize;
128 }
129 _state.inBuf = _inBuf;
130 ZstdDec_Init(_dec);
131 return S_OK;
132}
133
134
135Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
136 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
137{
138 RINOK(Prepare(outSize))
139
140 UInt64 inPrev = 0;
141 UInt64 outPrev = 0;
142 UInt64 writtenSize = 0;
143 bool readWasFinished = false;
144 SRes sres = SZ_OK;
145 HRESULT hres = S_OK;
146 HRESULT hres_Read = S_OK;
147
148 for (;;)
149 {
150 if (_state.inPos == _state.inLim && !readWasFinished)
151 {
152 _state.inPos = 0;
153 _state.inLim = _inBufSize;
154 hres_Read = ReadStream(inStream, _inBuf, &_state.inLim);
155 // _state.inLim -= 5; readWasFinished = True; // for debug
156 if (_state.inLim != _inBufSize || hres_Read != S_OK)
157 {
158 // hres_Read = 99; // for debug
159 readWasFinished = True;
160 }
161 }
162 {
163 const size_t inPos_Start = _state.inPos;
164 sres = ZstdDec_Decode(_dec, &_state);
165 _inProcessed += _state.inPos - inPos_Start;
166 }
167 /*
168 if (_state.status == ZSTD_STATUS_FINISHED_FRAME)
169 printf("\nfinished frame pos=%8x, checksum=%08x\n", (unsigned)_state.outProcessed, (unsigned)_state.info.checksum);
170 */
171 const bool needStop = (sres != SZ_OK)
172 || _state.status == ZSTD_STATUS_OUT_REACHED
173 || (outSize && *outSize < _state.outProcessed)
174 || (readWasFinished && _state.inPos == _state.inLim
175 && ZstdDecState_DOES_NEED_MORE_INPUT_OR_FINISHED_FRAME(&_state));
176
177 size_t size = _state.winPos - _state.wrPos; // full write size
178 if (size)
179 {
180 if (!needStop)
181 {
182 // we try to flush on aligned positions, if possible
183 size = _state.needWrite_Size; // minimal required write size
184 const size_t alignedPos = _state.winPos & ~(size_t)_outStepMask;
185 if (alignedPos > _state.wrPos)
186 {
187 const size_t size2 = alignedPos - _state.wrPos; // optimized aligned size
188 if (size < size2)
189 size = size2;
190 }
191 }
192 if (size)
193 {
194 {
195 size_t curSize = size;
196 if (outSize)
197 {
198 const UInt64 rem = *outSize - writtenSize;
199 if (curSize > rem)
200 curSize = (size_t)rem;
201 }
202 if (curSize)
203 {
204 // printf("Write wrPos=%8x, size=%8x\n", (unsigned)_state.wrPos, (unsigned)size);
205 hres = WriteStream(outStream, _state.win + _state.wrPos, curSize);
206 if (hres != S_OK)
207 break;
208 writtenSize += curSize; // it's real size of data that was written to stream
209 }
210 }
211 _state.wrPos += size; // virtual written size, that will be reported to CZstdDec
212 // _state.needWrite_Size = 0; // optional
213 }
214 }
215
216 if (needStop)
217 break;
218 if (progress)
219 if (_inProcessed - inPrev >= (1 << 27)
220 || _state.outProcessed - outPrev >= (1 << 28))
221 {
222 inPrev = _inProcessed;
223 outPrev = _state.outProcessed;
224 RINOK(progress->SetRatioInfo(&inPrev, &outPrev))
225 }
226 }
227
228 if (hres == S_OK)
229 {
230 ZstdDec_GetResInfo(_dec, &_state, sres, &ResInfo);
231 sres = ResInfo.decode_SRes;
232 /* now (ResInfo.decode_SRes) can contain 2 extra error codes:
233 - SZ_ERROR_NO_ARCHIVE : if no frames
234 - SZ_ERROR_INPUT_EOF : if ZSTD_STATUS_NEEDS_MORE_INPUT
235 */
236 _inProcessed -= ResInfo.extraSize;
237 if (hres_Read != S_OK && _state.inLim == _state.inPos && readWasFinished)
238 {
239 /* if (there is stream reading error,
240 and decoding was stopped because of end of input stream),
241 then we use reading error as main error code */
242 if (sres == SZ_OK ||
243 sres == SZ_ERROR_INPUT_EOF ||
244 sres == SZ_ERROR_NO_ARCHIVE)
245 hres = hres_Read;
246 }
247 if (sres == SZ_ERROR_INPUT_EOF && !FinishMode)
248 {
249 /* SZ_ERROR_INPUT_EOF case is allowed case for (!FinishMode) mode.
250 So we restore SZ_OK result for that case: */
251 ResInfo.decode_SRes = sres = SZ_OK;
252 }
253 if (hres == S_OK)
254 {
255 hres = SResToHRESULT(sres);
256 if (hres == S_OK && FinishMode)
257 {
258 if ((inSize && *inSize != _inProcessed)
259 || ResInfo.is_NonFinishedFrame
260 || (outSize && (*outSize != writtenSize || writtenSize != _state.outProcessed)))
261 hres = S_FALSE;
262 }
263 }
264 }
265 return hres;
266}
267
268
269Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))
270{
271 *value = _inProcessed;
272 return S_OK;
273}
274
275
276#ifndef Z7_NO_READ_FROM_CODER_ZSTD
277
278Z7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize))
279{
280 _inProcessed = 0;
281 _hres_Read = S_OK;
282 _hres_Decode = S_OK;
283 _writtenSize = 0;
284 _readWasFinished = false;
285 _wasFinished = false;
286 return Prepare(outSize);
287}
288
289
290Z7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream))
291 { _inStream = inStream; return S_OK; }
292Z7_COM7F_IMF(CDecoder::ReleaseInStream())
293 { _inStream.Release(); return S_OK; }
294
295
296// if SetInStream() mode: the caller must call GetFinishResult() after full decoding
297// to check that there decoding was finished correctly
298
299HRESULT CDecoder::GetFinishResult()
300{
301 if (_state.winPos != _state.wrPos || !_wasFinished)
302 return FinishMode ? S_FALSE : S_OK;
303 // _state.winPos == _state.wrPos
304 // _wasFinished == true
305 if (FinishMode && _hres_Decode == S_OK && _state.outSize_Defined && _state.outSize != _writtenSize)
306 _hres_Decode = S_FALSE;
307 return _hres_Decode;
308}
309
310
311Z7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))
312{
313 if (processedSize)
314 *processedSize = 0;
315
316 for (;;)
317 {
318 if (_state.outSize_Defined)
319 {
320 // _writtenSize <= _state.outSize
321 const UInt64 rem = _state.outSize - _writtenSize;
322 if (size > rem)
323 size = (UInt32)rem;
324 }
325 {
326 size_t cur = _state.winPos - _state.wrPos;
327 if (cur)
328 {
329 // _state.winPos != _state.wrPos;
330 // so there is some decoded data that was not written still
331 if (size == 0)
332 {
333 // if (FinishMode) and we are not allowed to write more, then it's data error
334 if (FinishMode && _state.outSize_Defined && _state.outSize == _writtenSize)
335 return S_FALSE;
336 return S_OK;
337 }
338 if (cur > size)
339 cur = (size_t)size;
340 // cur != 0
341 memcpy(data, _state.win + _state.wrPos, cur);
342 _state.wrPos += cur;
343 _writtenSize += cur;
344 data = (void *)((Byte *)data + cur);
345 if (processedSize)
346 *processedSize += (UInt32)cur;
347 size -= (UInt32)cur;
348 continue;
349 }
350 }
351
352 // _state.winPos == _state.wrPos
353 if (_wasFinished)
354 {
355 if (_hres_Decode == S_OK && FinishMode
356 && _state.outSize_Defined && _state.outSize != _writtenSize)
357 _hres_Decode = S_FALSE;
358 return _hres_Decode;
359 }
360
361 // _wasFinished == false
362 if (size == 0 && _state.outSize_Defined && _state.outSize != _state.outProcessed)
363 {
364 /* size == 0 : so the caller don't need more data now.
365 _state.outSize > _state.outProcessed : so more data will be requested
366 later by caller for full processing.
367 So we exit without ZstdDec_Decode() call, because we don't want
368 ZstdDec_Decode() to start new block decoding
369 */
370 return S_OK;
371 }
372 // size != 0 || !_state.outSize_Defined || _state.outSize == _state.outProcessed)
373
374 if (_state.inPos == _state.inLim && !_readWasFinished)
375 {
376 _state.inPos = 0;
377 _state.inLim = _inBufSize;
378 _hres_Read = ReadStream(_inStream, _inBuf, &_state.inLim);
379 if (_state.inLim != _inBufSize || _hres_Read != S_OK)
380 {
381 // _hres_Read = 99; // for debug
382 _readWasFinished = True;
383 }
384 }
385
386 SRes sres;
387 {
388 const SizeT inPos_Start = _state.inPos;
389 sres = ZstdDec_Decode(_dec, &_state);
390 _inProcessed += _state.inPos - inPos_Start;
391 }
392
393 const bool inFinished = (_state.inPos == _state.inLim) && _readWasFinished;
394
395 _wasFinished = (sres != SZ_OK)
396 || _state.status == ZSTD_STATUS_OUT_REACHED
397 || (_state.outSize_Defined && _state.outSize < _state.outProcessed)
398 || (inFinished
399 && ZstdDecState_DOES_NEED_MORE_INPUT_OR_FINISHED_FRAME(&_state));
400
401 if (!_wasFinished)
402 continue;
403
404 // _wasFinished == true
405 /* (_state.winPos != _state.wrPos) is possible here.
406 So we still can have some data to flush,
407 but we must all result variables .
408 */
409 HRESULT hres = S_OK;
410 ZstdDec_GetResInfo(_dec, &_state, sres, &ResInfo);
411 sres = ResInfo.decode_SRes;
412 _inProcessed -= ResInfo.extraSize;
413 if (_hres_Read != S_OK && inFinished)
414 {
415 if (sres == SZ_OK ||
416 sres == SZ_ERROR_INPUT_EOF ||
417 sres == SZ_ERROR_NO_ARCHIVE)
418 hres = _hres_Read;
419 }
420 if (sres == SZ_ERROR_INPUT_EOF && !FinishMode)
421 ResInfo.decode_SRes = sres = SZ_OK;
422 if (hres == S_OK)
423 {
424 hres = SResToHRESULT(sres);
425 if (hres == S_OK && FinishMode)
426 if (!inFinished
427 || ResInfo.is_NonFinishedFrame
428 || (_state.outSize_Defined && _state.outSize != _state.outProcessed))
429 hres = S_FALSE;
430 }
431 _hres_Decode = hres;
432 }
433}
434
435#endif
436
437}}
diff --git a/CPP/7zip/Compress/ZstdDecoder.h b/CPP/7zip/Compress/ZstdDecoder.h
new file mode 100644
index 0000000..6e15a96
--- /dev/null
+++ b/CPP/7zip/Compress/ZstdDecoder.h
@@ -0,0 +1,98 @@
1// ZstdDecoder.h
2
3#ifndef ZIP7_INC_ZSTD_DECODER_H
4#define ZIP7_INC_ZSTD_DECODER_H
5
6#include "../../../C/ZstdDec.h"
7
8#include "../../Common/MyCom.h"
9#include "../ICoder.h"
10
11namespace NCompress {
12namespace NZstd {
13
14#ifdef Z7_NO_READ_FROM_CODER
15#define Z7_NO_READ_FROM_CODER_ZSTD
16#endif
17
18#ifndef Z7_NO_READ_FROM_CODER_ZSTD
19// #define Z7_NO_READ_FROM_CODER_ZSTD
20#endif
21
22class CDecoder Z7_final:
23 public ICompressCoder,
24 public ICompressSetDecoderProperties2,
25 public ICompressSetFinishMode,
26 public ICompressGetInStreamProcessedSize,
27 public ICompressReadUnusedFromInBuf,
28 public ICompressSetBufSize,
29 #ifndef Z7_NO_READ_FROM_CODER_ZSTD
30 public ICompressSetInStream,
31 public ICompressSetOutStreamSize,
32 public ISequentialInStream,
33 #endif
34 public CMyUnknownImp
35{
36 Z7_COM_QI_BEGIN2(ICompressCoder)
37 Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2)
38 Z7_COM_QI_ENTRY(ICompressSetFinishMode)
39 Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize)
40 Z7_COM_QI_ENTRY(ICompressReadUnusedFromInBuf)
41 Z7_COM_QI_ENTRY(ICompressSetBufSize)
42 #ifndef Z7_NO_READ_FROM_CODER_ZSTD
43 Z7_COM_QI_ENTRY(ICompressSetInStream)
44 Z7_COM_QI_ENTRY(ICompressSetOutStreamSize)
45 Z7_COM_QI_ENTRY(ISequentialInStream)
46 #endif
47 Z7_COM_QI_END
48 Z7_COM_ADDREF_RELEASE
49
50 Z7_IFACE_COM7_IMP(ICompressCoder)
51 Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)
52 Z7_IFACE_COM7_IMP(ICompressSetFinishMode)
53 Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize)
54 Z7_IFACE_COM7_IMP(ICompressReadUnusedFromInBuf)
55 Z7_IFACE_COM7_IMP(ICompressSetBufSize)
56 #ifndef Z7_NO_READ_FROM_CODER_ZSTD
57 Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize)
58 Z7_IFACE_COM7_IMP(ICompressSetInStream)
59 Z7_IFACE_COM7_IMP(ISequentialInStream)
60 #endif
61
62 HRESULT Prepare(const UInt64 *outSize);
63
64 UInt32 _outStepMask;
65 CZstdDecHandle _dec;
66public:
67 UInt64 _inProcessed;
68 CZstdDecState _state;
69
70private:
71 UInt32 _inBufSize;
72 UInt32 _inBufSize_Allocated;
73 Byte *_inBuf;
74 size_t _afterDecoding_tempPos;
75
76 #ifndef Z7_NO_READ_FROM_CODER_ZSTD
77 CMyComPtr<ISequentialInStream> _inStream;
78 HRESULT _hres_Read;
79 HRESULT _hres_Decode;
80 UInt64 _writtenSize;
81 bool _readWasFinished;
82 bool _wasFinished;
83 #endif
84
85public:
86 bool FinishMode;
87 Byte DisableHash;
88 CZstdDecResInfo ResInfo;
89
90 HRESULT GetFinishResult();
91
92 CDecoder();
93 ~CDecoder();
94};
95
96}}
97
98#endif
diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak
index 815142d..938fc7e 100644
--- a/CPP/7zip/Crc.mak
+++ b/CPP/7zip/Crc.mak
@@ -1,6 +1,6 @@
1C_OBJS = $(C_OBJS) \ 1C_OBJS = $(C_OBJS) \
2 $O\7zCrc.obj 2 $O\7zCrc.obj
3!IF "$(PLATFORM)" == "ia64" || "$(PLATFORM)" == "mips" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" 3!IF defined(USE_NO_ASM) || defined(USE_C_CRC) || "$(PLATFORM)" == "ia64" || "$(PLATFORM)" == "mips" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64"
4C_OBJS = $(C_OBJS) \ 4C_OBJS = $(C_OBJS) \
5!ELSE 5!ELSE
6ASM_OBJS = $(ASM_OBJS) \ 6ASM_OBJS = $(ASM_OBJS) \
diff --git a/CPP/7zip/Crc64.mak b/CPP/7zip/Crc64.mak
index d58a483..27a50d7 100644
--- a/CPP/7zip/Crc64.mak
+++ b/CPP/7zip/Crc64.mak
@@ -1,6 +1,6 @@
1C_OBJS = $(C_OBJS) \ 1C_OBJS = $(C_OBJS) \
2 $O\XzCrc64.obj 2 $O\XzCrc64.obj
3!IF "$(PLATFORM)" == "ia64" || "$(PLATFORM)" == "mips" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" 3!IF defined(USE_NO_ASM) || defined(USE_C_CRC64) || "$(PLATFORM)" == "ia64" || "$(PLATFORM)" == "mips" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64"
4C_OBJS = $(C_OBJS) \ 4C_OBJS = $(C_OBJS) \
5!ELSE 5!ELSE
6ASM_OBJS = $(ASM_OBJS) \ 6ASM_OBJS = $(ASM_OBJS) \
diff --git a/CPP/7zip/Crypto/7zAes.cpp b/CPP/7zip/Crypto/7zAes.cpp
index 6b1c648..b203105 100644
--- a/CPP/7zip/Crypto/7zAes.cpp
+++ b/CPP/7zip/Crypto/7zAes.cpp
@@ -58,7 +58,8 @@ void CKeyInfo::CalcKey()
58 58
59 // MY_ALIGN (16) 59 // MY_ALIGN (16)
60 // CSha256 sha; 60 // CSha256 sha;
61 CAlignedBuffer sha(sizeof(CSha256) + unrollSize + bufSize * 2); 61 const size_t shaAllocSize = sizeof(CSha256) + unrollSize + bufSize * 2;
62 CAlignedBuffer1 sha(shaAllocSize);
62 Byte *buf = sha + sizeof(CSha256); 63 Byte *buf = sha + sizeof(CSha256);
63 64
64 memcpy(buf, Salt, SaltSize); 65 memcpy(buf, Salt, SaltSize);
@@ -108,7 +109,7 @@ void CKeyInfo::CalcKey()
108 */ 109 */
109 110
110 Sha256_Final((CSha256 *)(void *)(Byte *)sha, Key); 111 Sha256_Final((CSha256 *)(void *)(Byte *)sha, Key);
111 memset(sha, 0, sha.Size()); 112 memset(sha, 0, shaAllocSize);
112 } 113 }
113} 114}
114 115
@@ -255,19 +256,16 @@ Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))
255 if (size == 0) 256 if (size == 0)
256 return S_OK; 257 return S_OK;
257 258
258 Byte b0 = data[0]; 259 const unsigned b0 = data[0];
259
260 _key.NumCyclesPower = b0 & 0x3F; 260 _key.NumCyclesPower = b0 & 0x3F;
261 if ((b0 & 0xC0) == 0) 261 if ((b0 & 0xC0) == 0)
262 return size == 1 ? S_OK : E_INVALIDARG; 262 return size == 1 ? S_OK : E_INVALIDARG;
263
264 if (size <= 1) 263 if (size <= 1)
265 return E_INVALIDARG; 264 return E_INVALIDARG;
266 265
267 Byte b1 = data[1]; 266 const unsigned b1 = data[1];
268 267 const unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4);
269 unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4); 268 const unsigned ivSize = ((b0 >> 6) & 1) + (b1 & 0x0F);
270 unsigned ivSize = ((b0 >> 6) & 1) + (b1 & 0x0F);
271 269
272 if (size != 2 + saltSize + ivSize) 270 if (size != 2 + saltSize + ivSize)
273 return E_INVALIDARG; 271 return E_INVALIDARG;
diff --git a/CPP/7zip/Crypto/MyAes.cpp b/CPP/7zip/Crypto/MyAes.cpp
index 6abc388..f84bca8 100644
--- a/CPP/7zip/Crypto/MyAes.cpp
+++ b/CPP/7zip/Crypto/MyAes.cpp
@@ -155,22 +155,34 @@ Z7_COM7F_IMF2(UInt32, CAesCtrCoder::Filter(Byte *data, UInt32 size))
155#ifdef MY_CPU_X86_OR_AMD64 155#ifdef MY_CPU_X86_OR_AMD64
156 #define USE_HW_AES 156 #define USE_HW_AES
157#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) 157#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)
158 #if defined(__clang__) 158
159 #if (__clang_major__ >= 8) // fix that check 159 #if defined(__ARM_FEATURE_AES) \
160 || defined(__ARM_FEATURE_CRYPTO)
161 #define USE_HW_AES
162 #else
163 #if defined(MY_CPU_ARM64) \
164 || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
165 || defined(Z7_MSC_VER_ORIGINAL)
166 #if defined(__ARM_FP) && \
167 ( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
168 || defined(__GNUC__) && (__GNUC__ >= 6) \
169 ) \
170 || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
171 #if defined(MY_CPU_ARM64) \
172 || !defined(Z7_CLANG_VERSION) \
173 || defined(__ARM_NEON) && \
174 (Z7_CLANG_VERSION < 170000 || \
175 Z7_CLANG_VERSION > 170001)
160 #define USE_HW_AES 176 #define USE_HW_AES
161 #endif 177 #endif
162 #elif defined(__GNUC__)
163 #if (__GNUC__ >= 6) // fix that check
164 #define USE_HW_AES
165 #endif 178 #endif
166 #elif defined(_MSC_VER)
167 #if _MSC_VER >= 1910
168 #define USE_HW_AES
169 #endif 179 #endif
170 #endif 180 #endif
171#endif 181#endif
172 182
173#ifdef USE_HW_AES 183#ifdef USE_HW_AES
184// #pragma message("=== MyAES.c USE_HW_AES === ")
185
174 #define SET_AES_FUNC_2(f2) \ 186 #define SET_AES_FUNC_2(f2) \
175 if (algo == 2) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW) \ 187 if (algo == 2) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW) \
176 { f = f2; } 188 { f = f2; }
diff --git a/CPP/7zip/GuiCommon.rc b/CPP/7zip/GuiCommon.rc
index b67409b..95654b6 100644
--- a/CPP/7zip/GuiCommon.rc
+++ b/CPP/7zip/GuiCommon.rc
@@ -54,31 +54,66 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
54 54
55 55
56#define MY_MODAL_DIALOG_STYLE STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU 56#define MY_MODAL_DIALOG_STYLE STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
57
58#define MY_MODAL_RESIZE_DIALOG_STYLE MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX | WS_THICKFRAME 57#define MY_MODAL_RESIZE_DIALOG_STYLE MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX | WS_THICKFRAME
59 58
60#define MY_PAGE_STYLE STYLE WS_CHILD | WS_DISABLED | WS_CAPTION 59#define MY_PAGE_STYLE STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
61 60
62#define MY_FONT FONT 8, "MS Shell Dlg" 61#define MY_FONT FONT 8, "MS Shell Dlg"
63 62
63#define MY_MODAL_DIALOG_POSTFIX 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
64
64#define SMALL_PAGE_SIZE_X 120 65#define SMALL_PAGE_SIZE_X 120
65 66
66// #define MY_DIALOG DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT 67// #define MY_DIALOG DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
67// #define MY_RESIZE_DIALOG DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT 68// #define MY_RESIZE_DIALOG DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
68#define MY_PAGE DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT 69#define MY_PAGE_POSTFIX 0, 0, xs, ys MY_PAGE_STYLE MY_FONT
70#define MY_PAGE DIALOG MY_PAGE_POSTFIX
69 71
70#define OK_CANCEL \ 72#define OK_CANCEL \
71 DEFPUSHBUTTON "OK", IDOK, bx2, by, bxs, bys \ 73 DEFPUSHBUTTON "OK", IDOK, bx2, by, bxs, bys \
72 PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys 74 PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
73 75
76#define CONTINUE_CANCEL \
77 DEFPUSHBUTTON "Continue",IDCONTINUE, bx2, by, bxs, bys \
78 PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
79
74#define MY_BUTTON__CLOSE \ 80#define MY_BUTTON__CLOSE \
75 DEFPUSHBUTTON "&Close", IDCLOSE, bx1, by, bxs, bys 81 DEFPUSHBUTTON "&Close", IDCLOSE, bx1, by, bxs, bys
76 82
77 83
78#define MY_COMBO CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP 84#define MY_COMBO CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
79#define MY_COMBO_SORTED MY_COMBO | CBS_SORT 85#define MY_COMBO_SORTED MY_COMBO | CBS_SORT
80#define MY_COMBO_WITH_EDIT CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP 86#define MY_COMBO_WITH_EDIT CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
81 87
82#define MY_CHECKBOX "Button", BS_AUTOCHECKBOX | WS_TABSTOP 88#define MY_CHECKBOX "Button", BS_AUTOCHECKBOX | WS_TABSTOP
83 89
90#define cboxColonSize 18
91#define colonString ":"
92
93#define MY_CONTROL_CHECKBOX(_text,_id,_x,_y,_xsize) CONTROL _text, _id, MY_CHECKBOX, _x,_y,_xsize,10
94#define MY_CONTROL_CHECKBOX_2LINES(_text,_id,_x,_y,_xsize) CONTROL _text, _id, MY_CHECKBOX | BS_MULTILINE, _x,_y,_xsize,16
95#define MY_CONTROL_CHECKBOX_COLON(_id,_x,_y) MY_CONTROL_CHECKBOX( colonString, _id, _x,_y,cboxColonSize)
96
97#define MY_AUTORADIOBUTTON "Button", BS_AUTORADIOBUTTON
98#define MY_AUTORADIOBUTTON_GROUP MY_AUTORADIOBUTTON | WS_GROUP
99
100#define MY_CONTROL_AUTORADIOBUTTON(_text,_id,_x,_y,_xsize) CONTROL _text, _id, MY_AUTORADIOBUTTON, _x,_y,_xsize,10
101#define MY_CONTROL_AUTORADIOBUTTON_GROUP(_text,_id,_x,_y,_xsize) CONTROL _text, _id, MY_AUTORADIOBUTTON_GROUP, _x,_y,_xsize,10
102
84#define MY_TEXT_NOPREFIX 8, SS_NOPREFIX 103#define MY_TEXT_NOPREFIX 8, SS_NOPREFIX
104
105
106// WS_EX_CLIENTEDGE
107#define MY_CONTROL_EDIT_WITH_SPIN(_id_edit, _id_spin, _text, _x, _y, _xSize) \
108 EDITTEXT _id_edit, _x, _y, _xSize, 12, ES_CENTER | ES_NUMBER | ES_AUTOHSCROLL \
109 CONTROL _text, _id_spin, L"msctls_updown32", \
110 UDS_SETBUDDYINT \
111 | UDS_ALIGNRIGHT \
112 | UDS_AUTOBUDDY \
113 | UDS_ARROWKEYS \
114 | UDS_NOTHOUSANDS, \
115 _x + _xSize, _y, 8, 12 // these values are unused
116
117
118#define OPTIONS_PAGE_XC_SIZE 280
119#define OPTIONS_PAGE_YC_SIZE 280
diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt
index eee28f7..abbaf20 100644
--- a/CPP/7zip/Guid.txt
+++ b/CPP/7zip/Guid.txt
@@ -94,6 +94,8 @@
94 04 IArchiveKeepModeForNextOpen 94 04 IArchiveKeepModeForNextOpen
95 05 IArchiveAllowTail 95 05 IArchiveAllowTail
96 96
97 09 IArchiveRequestMemoryUseCallback
98
97 10 IArchiveOpenCallback 99 10 IArchiveOpenCallback
98 100
99 20 IArchiveExtractCallback 101 20 IArchiveExtractCallback
@@ -176,7 +178,9 @@ Handler GUIDs:
176 0B lzma86 178 0B lzma86
177 0C xz 179 0C xz
178 0D ppmd 180 0D ppmd
181 0E zstd
179 182
183 BF LVM
180 C0 AVB 184 C0 AVB
181 C1 LP 185 C1 LP
182 C2 Sparse 186 C2 Sparse
diff --git a/CPP/7zip/IDecl.h b/CPP/7zip/IDecl.h
index c4d4541..4dbf1eb 100644
--- a/CPP/7zip/IDecl.h
+++ b/CPP/7zip/IDecl.h
@@ -3,7 +3,7 @@
3#ifndef ZIP7_INC_IDECL_H 3#ifndef ZIP7_INC_IDECL_H
4#define ZIP7_INC_IDECL_H 4#define ZIP7_INC_IDECL_H
5 5
6#include "../Common/Common.h" 6#include "../Common/Common0.h"
7#include "../Common/MyUnknown.h" 7#include "../Common/MyUnknown.h"
8 8
9#define k_7zip_GUID_Data1 0x23170F69 9#define k_7zip_GUID_Data1 0x23170F69
diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h
index 4a58bc9..0c44a91 100644
--- a/CPP/7zip/IStream.h
+++ b/CPP/7zip/IStream.h
@@ -3,6 +3,7 @@
3#ifndef ZIP7_INC_ISTREAM_H 3#ifndef ZIP7_INC_ISTREAM_H
4#define ZIP7_INC_ISTREAM_H 4#define ZIP7_INC_ISTREAM_H
5 5
6#include "../Common/Common0.h"
6#include "../Common/MyTypes.h" 7#include "../Common/MyTypes.h"
7#include "../Common/MyWindows.h" 8#include "../Common/MyWindows.h"
8 9
@@ -145,10 +146,18 @@ IStreamSetRestriction::SetRestriction(UInt64 begin, UInt64 end)
145 146
146 It sets region of data in output stream that is restricted. 147 It sets region of data in output stream that is restricted.
147 For restricted region it's expected (or allowed) 148 For restricted region it's expected (or allowed)
148 to change data with different calls of Write()/SetSize(). 149 that the caller can write to same region with different calls of Write()/SetSize().
149 Another regions of output stream will be supposed as non-restricted: 150 Another regions of output stream will be supposed as non-restricted:
150 - The callee usually doesn't flush the data in restricted region. 151 - The callee usually doesn't flush the data in restricted region.
151 - The callee usually can flush data from non-restricted region. 152 - The callee usually can flush data from non-restricted region after writing.
153
154Actual restiction rules depend also from current stream position.
155It's recommended to call SetRestriction() just before the Write() call.
156So the callee can optimize writing and flushing, if that Write()
157operation is not restricted.
158
159Note: Each new call of SetRestriction() sets new restictions,
160so previous restrction calls has no effect anymore.
152 161
153inputs: 162inputs:
154 163
@@ -156,35 +165,29 @@ inputs:
156 165
157 if (begin == end) 166 if (begin == end)
158 { 167 {
159 it means that there is no region restriction for flushing. 168 No restriction.
160 The callee is allowed to flush already written data and 169 The caller will call Write() in sequential order.
161 is allowed to flush all data in future calls of 170 After SetRestriction(begin, begin), but before next call of SetRestriction()
162 ISequentialOutStream::Write(), but before next call of SetRestriction(). 171 {
163 The pair of values (begin == 0 && end == 0) is recommended to 172 Additional condition:
164 remove all restrictions. 173 it's expected that current stream seek position is equal to stream size.
174 The callee can make final flushing for any data before current stream seek position.
175 For each Write(size) call:
176 The callee can make final flushing for that new written data.
177 }
178 The pair of values (begin == 0 && end == 0) is recommended to remove write restriction.
165 } 179 }
166 180
167 if (begin < end) 181 if (begin < end)
168 { 182 {
169 it means that callee must NOT to flush any data in region [begin, end). 183 it means that callee must NOT flush any data in region [begin, end).
170 The caller is allowed to Seek() to that region and rewrite the 184 The caller is allowed to Seek() to that region and rewrite the
171 data in that restriction region. 185 data in that restriction region.
172 if (end == (UInt64(Int64)-1) 186 if (end == (UInt64)(Int64)-1)
173 { 187 {
174 there is no upper bound for restricted region. 188 there is no upper bound for restricted region.
175 So non-restricted region will be [0, begin) in that case 189 So non-restricted region will be [0, begin) in that case
176 } 190 }
177
178 Note: it's not expected that some already written region was marked as
179 non-restricted by old call SetRestriction() and later the part of
180 that region was marked as restricted with new call SetRestriction().
181 For example, for different calls with non-empty restricted regions:
182 (begin_new >= begin_old) is expected :
183 {
184 SetRestriction(begin_old, ...)
185 ...
186 SetRestriction(begin_new, ...)
187 }
188 } 191 }
189 192
190 returns: 193 returns:
@@ -195,7 +198,7 @@ inputs:
195 198
196 Note: IOutStream::SetSize() also can change the data. 199 Note: IOutStream::SetSize() also can change the data.
197 So it's not expected the call 200 So it's not expected the call
198 IOutStream::SetSize() to unrestricted already written region. 201 IOutStream::SetSize() to region that was written before as unrestricted.
199*/ 202*/
200 203
201#define Z7_IFACEM_IStreamSetRestriction(x) \ 204#define Z7_IFACEM_IStreamSetRestriction(x) \
diff --git a/CPP/7zip/LzmaDec.mak b/CPP/7zip/LzmaDec.mak
index 3beb505..624ea9e 100644
--- a/CPP/7zip/LzmaDec.mak
+++ b/CPP/7zip/LzmaDec.mak
@@ -1,4 +1,4 @@
1!IF "$(PLATFORM)" == "x64" 1!IF "$(PLATFORM)" == "x64" || ("$(PLATFORM)" == "arm64" && !defined(NO_ASM_GNU))
2!IFNDEF NO_ASM 2!IFNDEF NO_ASM
3CFLAGS_C_SPEC = -DZ7_LZMA_DEC_OPT 3CFLAGS_C_SPEC = -DZ7_LZMA_DEC_OPT
4ASM_OBJS = $(ASM_OBJS) \ 4ASM_OBJS = $(ASM_OBJS) \
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp
index 6761b28..eb77f25 100644
--- a/CPP/7zip/UI/Agent/Agent.cpp
+++ b/CPP/7zip/UI/Agent/Agent.cpp
@@ -1450,7 +1450,7 @@ void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, bool i
1450 realIndices.Add(arcIndex); 1450 realIndices.Add(arcIndex);
1451 } 1451 }
1452 1452
1453 HeapSort(&realIndices.Front(), realIndices.Size()); 1453 HeapSort(realIndices.NonConstData(), realIndices.Size());
1454} 1454}
1455 1455
1456Z7_COM7F_IMF(CAgentFolder::Extract(const UInt32 *indices, 1456Z7_COM7F_IMF(CAgentFolder::Extract(const UInt32 *indices,
@@ -1496,8 +1496,8 @@ Z7_COM7F_IMF(CAgentFolder::Extract(const UInt32 *indices,
1496 if (path) 1496 if (path)
1497 { 1497 {
1498 pathU = us2fs(path); 1498 pathU = us2fs(path);
1499 if (!pathU.IsEmpty()) 1499 if (!pathU.IsEmpty()
1500 if (!NFile::NName::IsAltStreamPrefixWithColon(pathU)) 1500 && !NFile::NName::IsAltStreamPrefixWithColon(path))
1501 { 1501 {
1502 NFile::NName::NormalizeDirPathPrefix(pathU); 1502 NFile::NName::NormalizeDirPathPrefix(pathU);
1503 NFile::NDir::CreateComplexDir(pathU); 1503 NFile::NDir::CreateComplexDir(pathU);
@@ -1552,10 +1552,10 @@ Z7_COM7F_IMF(CAgentFolder::Extract(const UInt32 *indices,
1552 { 1552 {
1553 CArchiveExtractCallback_Closer ecsCloser(extractCallbackSpec); 1553 CArchiveExtractCallback_Closer ecsCloser(extractCallbackSpec);
1554 1554
1555 HRESULT res = _agentSpec->GetArchive()->Extract(&realIndices.Front(), 1555 HRESULT res = _agentSpec->GetArchive()->Extract(realIndices.ConstData(),
1556 realIndices.Size(), testMode, extractCallback); 1556 realIndices.Size(), testMode, extractCallback);
1557 1557
1558 HRESULT res2 = ecsCloser.Close(); 1558 const HRESULT res2 = ecsCloser.Close();
1559 if (res == S_OK) 1559 if (res == S_OK)
1560 res = res2; 1560 res = res2;
1561 return res; 1561 return res;
diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp
index b5a25a3..903cde2 100644
--- a/CPP/7zip/UI/Agent/AgentOut.cpp
+++ b/CPP/7zip/UI/Agent/AgentOut.cpp
@@ -326,16 +326,15 @@ Z7_COM7F_IMF(CAgent::DoOperation(
326 326
327 CUpdateCallbackAgent updateCallbackAgent; 327 CUpdateCallbackAgent updateCallbackAgent;
328 updateCallbackAgent.SetCallback(updateCallback100); 328 updateCallbackAgent.SetCallback(updateCallback100);
329 CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; 329 CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
330 CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );
331 330
332 updateCallbackSpec->DirItems = &dirItems; 331 updateCallback->DirItems = &dirItems;
333 updateCallbackSpec->ArcItems = &arcItems; 332 updateCallback->ArcItems = &arcItems;
334 updateCallbackSpec->UpdatePairs = &updatePairs2; 333 updateCallback->UpdatePairs = &updatePairs2;
335 334
336 SetInArchiveInterfaces(this, updateCallbackSpec); 335 SetInArchiveInterfaces(this, updateCallback.ClsPtr());
337 336
338 updateCallbackSpec->Callback = &updateCallbackAgent; 337 updateCallback->Callback = &updateCallbackAgent;
339 338
340 CByteBuffer processedItems; 339 CByteBuffer processedItems;
341 if (processedPaths) 340 if (processedPaths)
@@ -344,7 +343,7 @@ Z7_COM7F_IMF(CAgent::DoOperation(
344 processedItems.Alloc(num); 343 processedItems.Alloc(num);
345 for (unsigned i = 0; i < num; i++) 344 for (unsigned i = 0; i < num; i++)
346 processedItems[i] = 0; 345 processedItems[i] = 0;
347 updateCallbackSpec->ProcessedItemsStatuses = processedItems; 346 updateCallback->ProcessedItemsStatuses = processedItems;
348 } 347 }
349 348
350 Z7_DECL_CMyComPtr_QI_FROM( 349 Z7_DECL_CMyComPtr_QI_FROM(
@@ -367,7 +366,7 @@ Z7_COM7F_IMF(CAgent::DoOperation(
367 { 366 {
368 FOR_VECTOR (i, m_PropValues) 367 FOR_VECTOR (i, m_PropValues)
369 propValues[i] = m_PropValues[i]; 368 propValues[i] = m_PropValues[i];
370 RINOK(setProperties->SetProperties(&names.Front(), propValues, names.Size())) 369 RINOK(setProperties->SetProperties(names.ConstData(), propValues, names.Size()))
371 } 370 }
372 catch(...) 371 catch(...)
373 { 372 {
@@ -382,15 +381,14 @@ Z7_COM7F_IMF(CAgent::DoOperation(
382 381
383 if (sfxModule != NULL) 382 if (sfxModule != NULL)
384 { 383 {
385 CInFileStream *sfxStreamSpec = new CInFileStream; 384 CMyComPtr2_Create<IInStream, CInFileStream> sfxStream;
386 CMyComPtr<IInStream> sfxStream(sfxStreamSpec); 385 if (!sfxStream->Open(us2fs(sfxModule)))
387 if (!sfxStreamSpec->Open(us2fs(sfxModule)))
388 return E_FAIL; 386 return E_FAIL;
389 // throw "Can't open sfx module"; 387 // throw "Can't open sfx module";
390 RINOK(NCompress::CopyStream(sfxStream, outArchiveStream, NULL)) 388 RINOK(NCompress::CopyStream(sfxStream, outArchiveStream, NULL))
391 } 389 }
392 390
393 HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback); 391 const HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
394 if (res == S_OK && processedPaths) 392 if (res == S_OK && processedPaths)
395 { 393 {
396 { 394 {
@@ -443,8 +441,7 @@ Z7_COM7F_IMF(CAgent::DeleteItems(ISequentialOutStream *outArchiveStream,
443 CRecordVector<CUpdatePair2> updatePairs; 441 CRecordVector<CUpdatePair2> updatePairs;
444 CUpdateCallbackAgent updateCallbackAgent; 442 CUpdateCallbackAgent updateCallbackAgent;
445 updateCallbackAgent.SetCallback(updateCallback100); 443 updateCallbackAgent.SetCallback(updateCallback100);
446 CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; 444 CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
447 CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
448 445
449 CUIntVector realIndices; 446 CUIntVector realIndices;
450 _agentFolder->GetRealIndices(indices, numItems, 447 _agentFolder->GetRealIndices(indices, numItems,
@@ -472,11 +469,11 @@ Z7_COM7F_IMF(CAgent::DeleteItems(ISequentialOutStream *outArchiveStream,
472 up2.SetAs_NoChangeArcItem(i); 469 up2.SetAs_NoChangeArcItem(i);
473 updatePairs.Add(up2); 470 updatePairs.Add(up2);
474 } 471 }
475 updateCallbackSpec->UpdatePairs = &updatePairs; 472 updateCallback->UpdatePairs = &updatePairs;
476 473
477 SetInArchiveInterfaces(this, updateCallbackSpec); 474 SetInArchiveInterfaces(this, updateCallback.ClsPtr());
478 475
479 updateCallbackSpec->Callback = &updateCallbackAgent; 476 updateCallback->Callback = &updateCallbackAgent;
480 return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); 477 return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
481} 478}
482 479
@@ -489,8 +486,7 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream,
489 CDirItems dirItems; 486 CDirItems dirItems;
490 CUpdateCallbackAgent updateCallbackAgent; 487 CUpdateCallbackAgent updateCallbackAgent;
491 updateCallbackAgent.SetCallback(updateCallback100); 488 updateCallbackAgent.SetCallback(updateCallback100);
492 CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; 489 CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
493 CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
494 490
495 UInt32 numItemsInArchive; 491 UInt32 numItemsInArchive;
496 RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)) 492 RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
@@ -526,11 +522,11 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream,
526 522
527 dirItems.Items.Add(di); 523 dirItems.Items.Add(di);
528 524
529 updateCallbackSpec->Callback = &updateCallbackAgent; 525 updateCallback->Callback = &updateCallbackAgent;
530 updateCallbackSpec->DirItems = &dirItems; 526 updateCallback->DirItems = &dirItems;
531 updateCallbackSpec->UpdatePairs = &updatePairs; 527 updateCallback->UpdatePairs = &updatePairs;
532 528
533 SetInArchiveInterfaces(this, updateCallbackSpec); 529 SetInArchiveInterfaces(this, updateCallback.ClsPtr());
534 530
535 return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); 531 return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
536} 532}
@@ -549,8 +545,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
549 CRecordVector<CUpdatePair2> updatePairs; 545 CRecordVector<CUpdatePair2> updatePairs;
550 CUpdateCallbackAgent updateCallbackAgent; 546 CUpdateCallbackAgent updateCallbackAgent;
551 updateCallbackAgent.SetCallback(updateCallback100); 547 updateCallbackAgent.SetCallback(updateCallback100);
552 CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; 548 CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
553 CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
554 549
555 CUIntVector realIndices; 550 CUIntVector realIndices;
556 _agentFolder->GetRealIndices(indices, numItems, 551 _agentFolder->GetRealIndices(indices, numItems,
@@ -596,11 +591,11 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
596 updatePairs.Add(up2); 591 updatePairs.Add(up2);
597 } 592 }
598 593
599 updateCallbackSpec->Callback = &updateCallbackAgent; 594 updateCallback->Callback = &updateCallbackAgent;
600 updateCallbackSpec->UpdatePairs = &updatePairs; 595 updateCallback->UpdatePairs = &updatePairs;
601 updateCallbackSpec->NewNames = &newNames; 596 updateCallback->NewNames = &newNames;
602 597
603 SetInArchiveInterfaces(this, updateCallbackSpec); 598 SetInArchiveInterfaces(this, updateCallback.ClsPtr());
604 599
605 return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); 600 return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
606} 601}
@@ -620,8 +615,7 @@ HRESULT CAgent::CommentItem(ISequentialOutStream *outArchiveStream,
620 CRecordVector<CUpdatePair2> updatePairs; 615 CRecordVector<CUpdatePair2> updatePairs;
621 CUpdateCallbackAgent updateCallbackAgent; 616 CUpdateCallbackAgent updateCallbackAgent;
622 updateCallbackAgent.SetCallback(updateCallback100); 617 updateCallbackAgent.SetCallback(updateCallback100);
623 CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; 618 CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
624 CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
625 619
626 const int mainRealIndex = _agentFolder->GetRealIndex(indices[0]); 620 const int mainRealIndex = _agentFolder->GetRealIndex(indices[0]);
627 621
@@ -642,12 +636,12 @@ HRESULT CAgent::CommentItem(ISequentialOutStream *outArchiveStream,
642 updatePairs.Add(up2); 636 updatePairs.Add(up2);
643 } 637 }
644 638
645 updateCallbackSpec->Callback = &updateCallbackAgent; 639 updateCallback->Callback = &updateCallbackAgent;
646 updateCallbackSpec->UpdatePairs = &updatePairs; 640 updateCallback->UpdatePairs = &updatePairs;
647 updateCallbackSpec->CommentIndex = mainRealIndex; 641 updateCallback->CommentIndex = mainRealIndex;
648 updateCallbackSpec->Comment = &newName; 642 updateCallback->Comment = &newName;
649 643
650 SetInArchiveInterfaces(this, updateCallbackSpec); 644 SetInArchiveInterfaces(this, updateCallback.ClsPtr());
651 645
652 return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); 646 return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
653} 647}
@@ -664,8 +658,7 @@ HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream,
664 CDirItems dirItems; 658 CDirItems dirItems;
665 CUpdateCallbackAgent updateCallbackAgent; 659 CUpdateCallbackAgent updateCallbackAgent;
666 updateCallbackAgent.SetCallback(updateCallback100); 660 updateCallbackAgent.SetCallback(updateCallback100);
667 CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; 661 CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
668 CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
669 662
670 UInt32 realIndex; 663 UInt32 realIndex;
671 { 664 {
@@ -702,13 +695,13 @@ HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream,
702 } 695 }
703 updatePairs.Add(up2); 696 updatePairs.Add(up2);
704 } 697 }
705 updateCallbackSpec->DirItems = &dirItems; 698 updateCallback->DirItems = &dirItems;
706 updateCallbackSpec->Callback = &updateCallbackAgent; 699 updateCallback->Callback = &updateCallbackAgent;
707 updateCallbackSpec->UpdatePairs = &updatePairs; 700 updateCallback->UpdatePairs = &updatePairs;
708 701
709 SetInArchiveInterfaces(this, updateCallbackSpec); 702 SetInArchiveInterfaces(this, updateCallback.ClsPtr());
710 703
711 updateCallbackSpec->KeepOriginalItemNames = true; 704 updateCallback->KeepOriginalItemNames = true;
712 return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); 705 return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
713} 706}
714 707
diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp
index df9f315..176f39b 100644
--- a/CPP/7zip/UI/Agent/AgentProxy.cpp
+++ b/CPP/7zip/UI/Agent/AgentProxy.cpp
@@ -146,7 +146,7 @@ void CProxyArc::AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) cons
146int CProxyArc::GetRealIndex(unsigned dirIndex, unsigned index) const 146int CProxyArc::GetRealIndex(unsigned dirIndex, unsigned index) const
147{ 147{
148 const CProxyDir &dir = Dirs[dirIndex]; 148 const CProxyDir &dir = Dirs[dirIndex];
149 unsigned numDirItems = dir.SubDirs.Size(); 149 const unsigned numDirItems = dir.SubDirs.Size();
150 if (index < numDirItems) 150 if (index < numDirItems)
151 { 151 {
152 const CProxyDir &f = Dirs[dir.SubDirs[index]]; 152 const CProxyDir &f = Dirs[dir.SubDirs[index]];
@@ -163,14 +163,14 @@ void CProxyArc::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32
163 realIndices.Clear(); 163 realIndices.Clear();
164 for (UInt32 i = 0; i < numItems; i++) 164 for (UInt32 i = 0; i < numItems; i++)
165 { 165 {
166 UInt32 index = indices[i]; 166 const UInt32 index = indices[i];
167 unsigned numDirItems = dir.SubDirs.Size(); 167 const unsigned numDirItems = dir.SubDirs.Size();
168 if (index < numDirItems) 168 if (index < numDirItems)
169 AddRealIndices(dir.SubDirs[index], realIndices); 169 AddRealIndices(dir.SubDirs[index], realIndices);
170 else 170 else
171 realIndices.Add(dir.SubFiles[index - numDirItems]); 171 realIndices.Add(dir.SubFiles[index - numDirItems]);
172 } 172 }
173 HeapSort(&realIndices.Front(), realIndices.Size()); 173 HeapSort(realIndices.NonConstData(), realIndices.Size());
174} 174}
175 175
176/////////////////////////////////////////////// 176///////////////////////////////////////////////
@@ -198,9 +198,9 @@ void CProxyArc::CalculateSizes(unsigned dirIndex, IInArchive *archive)
198 198
199 for (i = 0; i < dir.SubFiles.Size(); i++) 199 for (i = 0; i < dir.SubFiles.Size(); i++)
200 { 200 {
201 UInt32 index = (UInt32)dir.SubFiles[i]; 201 const UInt32 index = (UInt32)dir.SubFiles[i];
202 UInt64 size, packSize; 202 UInt64 size, packSize;
203 bool sizeDefined = GetSize(archive, index, kpidSize, size); 203 const bool sizeDefined = GetSize(archive, index, kpidSize, size);
204 dir.Size += size; 204 dir.Size += size;
205 GetSize(archive, index, kpidPackSize, packSize); 205 GetSize(archive, index, kpidPackSize, packSize);
206 dir.PackSize += packSize; 206 dir.PackSize += packSize;
@@ -495,7 +495,7 @@ void CProxyArc2::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32
495 { 495 {
496 AddRealIndices_of_ArcItem(dir.Items[indices[i]], includeAltStreams, realIndices); 496 AddRealIndices_of_ArcItem(dir.Items[indices[i]], includeAltStreams, realIndices);
497 } 497 }
498 HeapSort(&realIndices.Front(), realIndices.Size()); 498 HeapSort(realIndices.NonConstData(), realIndices.Size());
499} 499}
500 500
501void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive) 501void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive)
@@ -511,7 +511,7 @@ void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive)
511 { 511 {
512 UInt32 index = dir.Items[i]; 512 UInt32 index = dir.Items[i];
513 UInt64 size, packSize; 513 UInt64 size, packSize;
514 bool sizeDefined = GetSize(archive, index, kpidSize, size); 514 const bool sizeDefined = GetSize(archive, index, kpidSize, size);
515 dir.Size += size; 515 dir.Size += size;
516 GetSize(archive, index, kpidPackSize, packSize); 516 GetSize(archive, index, kpidPackSize, packSize);
517 dir.PackSize += packSize; 517 dir.PackSize += packSize;
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
index 121a2f1..b1e43da 100644
--- a/CPP/7zip/UI/Client7z/Client7z.cpp
+++ b/CPP/7zip/UI/Client7z/Client7z.cpp
@@ -23,6 +23,11 @@
23 23
24#include "../../Archive/IArchive.h" 24#include "../../Archive/IArchive.h"
25 25
26#if 0
27// for password request functions:
28#include "../../UI/Console/UserInputUtils.h"
29#endif
30
26#include "../../IPassword.h" 31#include "../../IPassword.h"
27#include "../../../../C/7zVersion.h" 32#include "../../../../C/7zVersion.h"
28 33
@@ -32,6 +37,8 @@ HINSTANCE g_hInstance;
32HINSTANCE g_hInstance = NULL; 37HINSTANCE g_hInstance = NULL;
33#endif 38#endif
34 39
40Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
41
35// You can find full list of all GUIDs supported by 7-Zip in Guid.txt file. 42// You can find full list of all GUIDs supported by 7-Zip in Guid.txt file.
36// 7z format GUID: {23170F69-40C1-278A-1000-000110070000} 43// 7z format GUID: {23170F69-40C1-278A-1000-000110070000}
37 44
@@ -205,10 +212,13 @@ Z7_COM7F_IMF(CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password))
205 if (!PasswordIsDefined) 212 if (!PasswordIsDefined)
206 { 213 {
207 // You can ask real password here from user 214 // You can ask real password here from user
208 // Password = GetPassword(OutStream); 215#if 0
209 // PasswordIsDefined = true; 216 RINOK(GetPassword_HRESULT(&g_StdOut, Password))
217 PasswordIsDefined = true;
218#else
210 PrintError("Password is not defined"); 219 PrintError("Password is not defined");
211 return E_ABORT; 220 return E_ABORT;
221#endif
212 } 222 }
213 return StringToBstr(Password, password); 223 return StringToBstr(Password, password);
214} 224}
@@ -468,7 +478,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index,
468 478
469 _outFileStreamSpec = new COutFileStream; 479 _outFileStreamSpec = new COutFileStream;
470 CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); 480 CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
471 if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) 481 if (!_outFileStreamSpec->Create_ALWAYS(fullProcessedPath))
472 { 482 {
473 PrintError("Cannot open output file", fullProcessedPath); 483 PrintError("Cannot open output file", fullProcessedPath);
474 return E_ABORT; 484 return E_ABORT;
@@ -574,11 +584,14 @@ Z7_COM7F_IMF(CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password))
574{ 584{
575 if (!PasswordIsDefined) 585 if (!PasswordIsDefined)
576 { 586 {
587#if 0
577 // You can ask real password here from user 588 // You can ask real password here from user
578 // Password = GetPassword(OutStream); 589 RINOK(GetPassword_HRESULT(&g_StdOut, Password))
579 // PasswordIsDefined = true; 590 PasswordIsDefined = true;
591#else
580 PrintError("Password is not defined"); 592 PrintError("Password is not defined");
581 return E_ABORT; 593 return E_ABORT;
594#endif
582 } 595 }
583 return StringToBstr(Password, password); 596 return StringToBstr(Password, password);
584} 597}
@@ -773,7 +786,7 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu
773 fileName += VolExt; 786 fileName += VolExt;
774 COutFileStream *streamSpec = new COutFileStream; 787 COutFileStream *streamSpec = new COutFileStream;
775 CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); 788 CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
776 if (!streamSpec->Create(us2fs(fileName), false)) 789 if (!streamSpec->Create_NEW(us2fs(fileName)))
777 return GetLastError_noZero_HRESULT(); 790 return GetLastError_noZero_HRESULT();
778 *volumeStream = streamLoc.Detach(); 791 *volumeStream = streamLoc.Detach();
779 return S_OK; 792 return S_OK;
@@ -785,11 +798,13 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDef
785 { 798 {
786 if (AskPassword) 799 if (AskPassword)
787 { 800 {
788 // You can ask real password here from user 801#if 0
789 // Password = GetPassword(OutStream); 802 RINOK(GetPassword_HRESULT(&g_StdOut, Password))
790 // PasswordIsDefined = true; 803 PasswordIsDefined = true;
804#else
791 PrintError("Password is not defined"); 805 PrintError("Password is not defined");
792 return E_ABORT; 806 return E_ABORT;
807#endif
793 } 808 }
794 } 809 }
795 *passwordIsDefined = BoolToInt(PasswordIsDefined); 810 *passwordIsDefined = BoolToInt(PasswordIsDefined);
@@ -839,6 +854,14 @@ int Z7_CDECL main(int numArgs, const char *args[])
839 return 1; 854 return 1;
840 } 855 }
841 856
857#if defined(__clang__)
858#pragma GCC diagnostic ignored "-Wc++98-compat-pedantic"
859#endif
860
861#ifdef _WIN32
862Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
863#endif
864
842 Func_CreateObject 865 Func_CreateObject
843 f_CreateObject = Z7_GET_PROC_ADDRESS( 866 f_CreateObject = Z7_GET_PROC_ADDRESS(
844 Func_CreateObject, lib.Get_HMODULE(), 867 Func_CreateObject, lib.Get_HMODULE(),
@@ -929,7 +952,7 @@ int Z7_CDECL main(int numArgs, const char *args[])
929 952
930 COutFileStream *outFileStreamSpec = new COutFileStream; 953 COutFileStream *outFileStreamSpec = new COutFileStream;
931 CMyComPtr<IOutStream> outFileStream = outFileStreamSpec; 954 CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;
932 if (!outFileStreamSpec->Create(archiveName, false)) 955 if (!outFileStreamSpec->Create_NEW(archiveName))
933 { 956 {
934 PrintError("can't create archive file"); 957 PrintError("can't create archive file");
935 return 1; 958 return 1;
@@ -1058,7 +1081,7 @@ int Z7_CDECL main(int numArgs, const char *args[])
1058 // Get uncompressed size of file 1081 // Get uncompressed size of file
1059 NCOM::CPropVariant prop; 1082 NCOM::CPropVariant prop;
1060 archive->GetProperty(i, kpidSize, &prop); 1083 archive->GetProperty(i, kpidSize, &prop);
1061 char s[32]; 1084 char s[64];
1062 ConvertPropVariantToShortString(prop, s); 1085 ConvertPropVariantToShortString(prop, s);
1063 Print(s); 1086 Print(s);
1064 Print(" "); 1087 Print(" ");
diff --git a/CPP/7zip/UI/Client7z/Client7z.dsp b/CPP/7zip/UI/Client7z/Client7z.dsp
index d46300f..1b5826f 100644
--- a/CPP/7zip/UI/Client7z/Client7z.dsp
+++ b/CPP/7zip/UI/Client7z/Client7z.dsp
@@ -168,6 +168,10 @@ SOURCE=..\..\..\Windows\PropVariantConv.h
168# End Source File 168# End Source File
169# Begin Source File 169# Begin Source File
170 170
171SOURCE=..\..\..\Windows\TimeUtils.cpp
172# End Source File
173# Begin Source File
174
171SOURCE=..\..\..\Windows\TimeUtils.h 175SOURCE=..\..\..\Windows\TimeUtils.h
172# End Source File 176# End Source File
173# End Group 177# End Group
diff --git a/CPP/7zip/UI/Client7z/makefile b/CPP/7zip/UI/Client7z/makefile
index 988701e..9eff262 100644
--- a/CPP/7zip/UI/Client7z/makefile
+++ b/CPP/7zip/UI/Client7z/makefile
@@ -21,6 +21,7 @@ WIN_OBJS = \
21 $O\FileName.obj \ 21 $O\FileName.obj \
22 $O\PropVariant.obj \ 22 $O\PropVariant.obj \
23 $O\PropVariantConv.obj \ 23 $O\PropVariantConv.obj \
24 $O\TimeUtils.obj \
24 25
257ZIP_COMMON_OBJS = \ 267ZIP_COMMON_OBJS = \
26 $O\FileStreams.obj \ 27 $O\FileStreams.obj \
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
index 2bdbc41..f35433b 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -27,6 +27,7 @@
27#include "../../../Windows/ErrorMsg.h" 27#include "../../../Windows/ErrorMsg.h"
28#include "../../../Windows/FileDir.h" 28#include "../../../Windows/FileDir.h"
29#include "../../../Windows/FileName.h" 29#include "../../../Windows/FileName.h"
30#include "../../../Windows/PropVariantConv.h"
30#include "../../../Windows/System.h" 31#include "../../../Windows/System.h"
31#ifdef _WIN32 32#ifdef _WIN32
32#include "../../../Windows/FileMapping.h" 33#include "../../../Windows/FileMapping.h"
@@ -135,6 +136,7 @@ enum Enum
135 kHash, 136 kHash,
136 // kHashGenFile, 137 // kHashGenFile,
137 kHashDir, 138 kHashDir,
139 kExtractMemLimit,
138 140
139 kStdIn, 141 kStdIn,
140 kStdOut, 142 kStdOut,
@@ -144,6 +146,8 @@ enum Enum
144 kConsoleCharSet, 146 kConsoleCharSet,
145 kTechMode, 147 kTechMode,
146 kListFields, 148 kListFields,
149 kListPathSlash,
150 kListTimestampUTC,
147 151
148 kPreserveATime, 152 kPreserveATime,
149 kShareForWrite, 153 kShareForWrite,
@@ -283,6 +287,7 @@ static const CSwitchForm kSwitchForms[] =
283 { "scrc", SWFRM_STRING_MULT(0) }, 287 { "scrc", SWFRM_STRING_MULT(0) },
284 // { "scrf", SWFRM_STRING_SINGL(1) }, 288 // { "scrf", SWFRM_STRING_SINGL(1) },
285 { "shd", SWFRM_STRING_SINGL(1) }, 289 { "shd", SWFRM_STRING_SINGL(1) },
290 { "smemx", SWFRM_STRING },
286 291
287 { "si", SWFRM_STRING }, 292 { "si", SWFRM_STRING },
288 { "so", SWFRM_SIMPLE }, 293 { "so", SWFRM_SIMPLE },
@@ -292,6 +297,8 @@ static const CSwitchForm kSwitchForms[] =
292 { "scc", SWFRM_STRING }, 297 { "scc", SWFRM_STRING },
293 { "slt", SWFRM_SIMPLE }, 298 { "slt", SWFRM_SIMPLE },
294 { "slf", SWFRM_STRING_SINGL(1) }, 299 { "slf", SWFRM_STRING_SINGL(1) },
300 { "slsl", SWFRM_MINUS },
301 { "slmu", SWFRM_MINUS },
295 302
296 { "ssp", SWFRM_SIMPLE }, 303 { "ssp", SWFRM_SIMPLE },
297 { "ssw", SWFRM_SIMPLE }, 304 { "ssw", SWFRM_SIMPLE },
@@ -457,6 +464,7 @@ static void AddNameToCensor(NWildcard::CCensor &censor,
457 censor.AddPreItem(nop.Include, name, props); 464 censor.AddPreItem(nop.Include, name, props);
458} 465}
459 466
467#ifndef Z7_EXTRACT_ONLY
460static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs, 468static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs,
461 const UString &oldName, const UString &newName, NRecursedType::EEnum type, 469 const UString &oldName, const UString &newName, NRecursedType::EEnum type,
462 bool wildcardMatching) 470 bool wildcardMatching)
@@ -481,6 +489,7 @@ static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs,
481 throw CArcCmdLineException("Unsupported rename command:", val); 489 throw CArcCmdLineException("Unsupported rename command:", val);
482 } 490 }
483} 491}
492#endif
484 493
485static void AddToCensorFromListFile( 494static void AddToCensorFromListFile(
486 CObjectVector<CRenamePair> *renamePairs, 495 CObjectVector<CRenamePair> *renamePairs,
@@ -507,6 +516,7 @@ static void AddToCensorFromListFile(
507 } 516 }
508 if (renamePairs) 517 if (renamePairs)
509 { 518 {
519 #ifndef Z7_EXTRACT_ONLY
510 if ((names.Size() & 1) != 0) 520 if ((names.Size() & 1) != 0)
511 throw CArcCmdLineException(kIncorrectListFile, fileName); 521 throw CArcCmdLineException(kIncorrectListFile, fileName);
512 for (unsigned i = 0; i < names.Size(); i += 2) 522 for (unsigned i = 0; i < names.Size(); i += 2)
@@ -514,6 +524,9 @@ static void AddToCensorFromListFile(
514 // change type !!!! 524 // change type !!!!
515 AddRenamePair(renamePairs, names[i], names[i + 1], nop.RecursedType, nop.WildcardMatching); 525 AddRenamePair(renamePairs, names[i], names[i + 1], nop.RecursedType, nop.WildcardMatching);
516 } 526 }
527 #else
528 throw "not implemented";
529 #endif
517 } 530 }
518 else 531 else
519 FOR_VECTOR (i, names) 532 FOR_VECTOR (i, names)
@@ -562,6 +575,7 @@ static void AddToCensorFromNonSwitchesStrings(
562 AddToCensorFromListFile(renamePairs, censor, nop, s.Ptr(1), codePage); 575 AddToCensorFromListFile(renamePairs, censor, nop, s.Ptr(1), codePage);
563 else if (renamePairs) 576 else if (renamePairs)
564 { 577 {
578 #ifndef Z7_EXTRACT_ONLY
565 if (oldIndex == -1) 579 if (oldIndex == -1)
566 oldIndex = (int)i; 580 oldIndex = (int)i;
567 else 581 else
@@ -571,6 +585,9 @@ static void AddToCensorFromNonSwitchesStrings(
571 // AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, type); 585 // AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, type);
572 oldIndex = -1; 586 oldIndex = -1;
573 } 587 }
588 #else
589 throw "not implemented";
590 #endif
574 } 591 }
575 else 592 else
576 AddNameToCensor(censor, nop, s); 593 AddNameToCensor(censor, nop, s);
@@ -605,10 +622,10 @@ static const char *ParseMapWithPaths(
605 const CNameOption &nop) 622 const CNameOption &nop)
606{ 623{
607 UString s (s2); 624 UString s (s2);
608 int pos = s.Find(L':'); 625 const int pos = s.Find(L':');
609 if (pos < 0) 626 if (pos < 0)
610 return k_IncorrectMapCommand; 627 return k_IncorrectMapCommand;
611 int pos2 = s.Find(L':', (unsigned)(pos + 1)); 628 const int pos2 = s.Find(L':', (unsigned)(pos + 1));
612 if (pos2 < 0) 629 if (pos2 < 0)
613 return k_IncorrectMapCommand; 630 return k_IncorrectMapCommand;
614 631
@@ -625,7 +642,7 @@ static const char *ParseMapWithPaths(
625 CFileMapping map; 642 CFileMapping map;
626 if (map.Open(FILE_MAP_READ, GetSystemString(s)) != 0) 643 if (map.Open(FILE_MAP_READ, GetSystemString(s)) != 0)
627 return "Cannot open mapping"; 644 return "Cannot open mapping";
628 LPVOID data = map.Map(FILE_MAP_READ, 0, size); 645 const LPVOID data = map.Map(FILE_MAP_READ, 0, size);
629 if (!data) 646 if (!data)
630 return "MapViewOfFile error"; 647 return "MapViewOfFile error";
631 CFileUnmapper unmapper(data); 648 CFileUnmapper unmapper(data);
@@ -634,10 +651,10 @@ static const char *ParseMapWithPaths(
634 const wchar_t *p = (const wchar_t *)data; 651 const wchar_t *p = (const wchar_t *)data;
635 if (*p != 0) // data format marker 652 if (*p != 0) // data format marker
636 return "Unsupported Map data"; 653 return "Unsupported Map data";
637 UInt32 numChars = size / sizeof(wchar_t); 654 const UInt32 numChars = size / sizeof(wchar_t);
638 for (UInt32 i = 1; i < numChars; i++) 655 for (UInt32 i = 1; i < numChars; i++)
639 { 656 {
640 wchar_t c = p[i]; 657 const wchar_t c = p[i];
641 if (c == 0) 658 if (c == 0)
642 { 659 {
643 // MessageBoxW(0, name, L"7-Zip", 0); 660 // MessageBoxW(0, name, L"7-Zip", 0);
@@ -1002,6 +1019,7 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
1002 options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); 1019 options.IsStdErrTerminal = MY_IS_TERMINAL(stderr);
1003 1020
1004 options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; 1021 options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs;
1022 options.YesToAll = parser[NKey::kYes].ThereIs;
1005 1023
1006 options.StdInMode = parser[NKey::kStdIn].ThereIs; 1024 options.StdInMode = parser[NKey::kStdIn].ThereIs;
1007 options.StdOutMode = parser[NKey::kStdOut].ThereIs; 1025 options.StdOutMode = parser[NKey::kStdOut].ThereIs;
@@ -1011,6 +1029,13 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
1011 const UString &s = parser[NKey::kListFields].PostStrings[0]; 1029 const UString &s = parser[NKey::kListFields].PostStrings[0];
1012 options.ListFields = GetAnsiString(s); 1030 options.ListFields = GetAnsiString(s);
1013 } 1031 }
1032 if (parser[NKey::kListPathSlash].ThereIs)
1033 {
1034 options.ListPathSeparatorSlash.Val = !parser[NKey::kListPathSlash].WithMinus;
1035 options.ListPathSeparatorSlash.Def = true;
1036 }
1037 if (parser[NKey::kListTimestampUTC].ThereIs)
1038 g_Timestamp_Show_UTC = !parser[NKey::kListTimestampUTC].WithMinus;
1014 options.TechMode = parser[NKey::kTechMode].ThereIs; 1039 options.TechMode = parser[NKey::kTechMode].ThereIs;
1015 options.ShowTime = parser[NKey::kShowTime].ThereIs; 1040 options.ShowTime = parser[NKey::kShowTime].ThereIs;
1016 1041
@@ -1090,7 +1115,7 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
1090 } 1115 }
1091 1116
1092 1117
1093 #ifndef UNDER_CE 1118#ifndef UNDER_CE
1094 1119
1095 if (parser[NKey::kAffinity].ThereIs) 1120 if (parser[NKey::kAffinity].ThereIs)
1096 { 1121 {
@@ -1101,7 +1126,9 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
1101 a.SetFromWStr_if_Ascii(s); 1126 a.SetFromWStr_if_Ascii(s);
1102 Parse1Log += "Set process affinity mask: "; 1127 Parse1Log += "Set process affinity mask: ";
1103 1128
1104 #ifdef _WIN32 1129 bool isError = false;
1130
1131#ifdef _WIN32
1105 1132
1106 UInt64 v = 0; 1133 UInt64 v = 0;
1107 { 1134 {
@@ -1111,61 +1138,62 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
1111 a.Empty(); 1138 a.Empty();
1112 } 1139 }
1113 if (a.IsEmpty()) 1140 if (a.IsEmpty())
1114 throw CArcCmdLineException("Unsupported switch postfix -stm", s); 1141 isError = true;
1115 1142 else
1116 { 1143 {
1117 #ifndef _WIN64 1144#ifndef _WIN64
1118 if (v >= ((UInt64)1 << 32)) 1145 if (v >= ((UInt64)1 << 32))
1119 throw CArcCmdLineException("unsupported value -stm", s); 1146 throw CArcCmdLineException("unsupported value -stm", s);
1120 #endif 1147 else
1148#endif
1121 { 1149 {
1122 PrintHex(Parse1Log, v); 1150 PrintHex(Parse1Log, v);
1123 if (!SetProcessAffinityMask(GetCurrentProcess(), (DWORD_PTR)v)) 1151 if (!SetProcessAffinityMask(GetCurrentProcess(), (DWORD_PTR)v))
1124 { 1152 {
1125 DWORD lastError = GetLastError(); 1153 const DWORD lastError = GetLastError();
1126 Parse1Log += " : ERROR : "; 1154 Parse1Log += " : ERROR : ";
1127 Parse1Log += NError::MyFormatMessage(lastError); 1155 Parse1Log += NError::MyFormatMessage(lastError);
1128 } 1156 }
1129 } 1157 }
1130 } 1158 }
1131 1159
1132 #else // _WIN32 1160#else // _WIN32
1133 1161
1162 if (a.Len() != s.Len())
1163 isError = true;
1164 else
1134 { 1165 {
1135 Parse1Log += a; 1166 Parse1Log += a;
1136 NSystem::CProcessAffinity aff; 1167 NSystem::CProcessAffinity aff;
1137 aff.CpuZero(); 1168 aff.CpuZero();
1138 for (unsigned i = 0; i < a.Len(); i++) 1169 unsigned cpu = 0;
1170 unsigned i = a.Len();
1171 while (i)
1139 { 1172 {
1140 char c = a[i]; 1173 unsigned v = (Byte)a[--i];
1141 unsigned v; 1174 Z7_PARSE_HEX_DIGIT(v, { isError = true; break; })
1142 if (c >= '0' && c <= '9') v = (unsigned)(c - '0'); 1175 for (unsigned mask = 1; mask != 1u << 4; mask <<= 1, cpu++)
1143 else if (c >= 'A' && c <= 'F') v = 10 + (unsigned)(c - 'A'); 1176 if (v & mask)
1144 else if (c >= 'a' && c <= 'f') v = 10 + (unsigned)(c - 'a');
1145 else
1146 throw CArcCmdLineException("Unsupported switch postfix -stm", s);
1147 for (unsigned k = 0; k < 4; k++)
1148 {
1149 const unsigned cpu = (a.Len() - 1 - i) * 4 + k;
1150 if (v & ((unsigned)1 << k))
1151 aff.CpuSet(cpu); 1177 aff.CpuSet(cpu);
1152 }
1153 } 1178 }
1154 1179 if (!isError)
1155 if (!aff.SetProcAffinity()) 1180 if (!aff.SetProcAffinity())
1156 { 1181 {
1157 DWORD lastError = GetLastError(); 1182 const DWORD lastError = GetLastError();
1158 Parse1Log += " : ERROR : "; 1183 Parse1Log += " : ERROR : ";
1159 Parse1Log += NError::MyFormatMessage(lastError); 1184 Parse1Log += NError::MyFormatMessage(lastError);
1160 } 1185 }
1161 } 1186 }
1162 #endif // _WIN32 1187#endif // _WIN32
1188
1189 if (isError)
1190 throw CArcCmdLineException("Unsupported switch postfix -stm", s);
1163 1191
1164 Parse1Log.Add_LF(); 1192 Parse1Log.Add_LF();
1165 } 1193 }
1166 } 1194 }
1167 1195
1168 #endif 1196#endif
1169} 1197}
1170 1198
1171 1199
@@ -1218,6 +1246,40 @@ static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID,
1218 bp.Val = !parser[switchID].WithMinus; 1246 bp.Val = !parser[switchID].WithMinus;
1219} 1247}
1220 1248
1249
1250static bool ParseSizeString(const wchar_t *s, UInt64 &res)
1251{
1252 const wchar_t *end;
1253 const UInt64 v = ConvertStringToUInt64(s, &end);
1254 if (s == end)
1255 return false;
1256 const wchar_t c = *end;
1257
1258 if (c == 0)
1259 {
1260 res = v;
1261 return true;
1262 }
1263 if (end[1] != 0)
1264 return false;
1265
1266 unsigned numBits;
1267 switch (MyCharLower_Ascii(c))
1268 {
1269 case 'b': numBits = 0; break;
1270 case 'k': numBits = 10; break;
1271 case 'm': numBits = 20; break;
1272 case 'g': numBits = 30; break;
1273 case 't': numBits = 40; break;
1274 default: return false;
1275 }
1276 const UInt64 val2 = v << numBits;
1277 if ((val2 >> numBits) != v)
1278 return false;
1279 res = val2;
1280 return true;
1281}
1282
1221void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) 1283void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
1222{ 1284{
1223 const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; 1285 const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
@@ -1252,6 +1314,13 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
1252 if (parser[NKey::kHashDir].ThereIs) 1314 if (parser[NKey::kHashDir].ThereIs)
1253 options.ExtractOptions.HashDir = parser[NKey::kHashDir].PostStrings[0]; 1315 options.ExtractOptions.HashDir = parser[NKey::kHashDir].PostStrings[0];
1254 1316
1317 if (parser[NKey::kExtractMemLimit].ThereIs)
1318 {
1319 const UString &s = parser[NKey::kExtractMemLimit].PostStrings[0];
1320 if (!ParseSizeString(s, options.ExtractOptions.NtOptions.MemLimit))
1321 throw CArcCmdLineException("Unsupported -smemx:", s);
1322 }
1323
1255 if (parser[NKey::kElimDup].ThereIs) 1324 if (parser[NKey::kElimDup].ThereIs)
1256 { 1325 {
1257 options.ExtractOptions.ElimDup.Def = true; 1326 options.ExtractOptions.ElimDup.Def = true;
@@ -1300,7 +1369,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
1300 1369
1301 options.ConsoleCodePage = FindCharset(parser, NKey::kConsoleCharSet, true, -1); 1370 options.ConsoleCodePage = FindCharset(parser, NKey::kConsoleCharSet, true, -1);
1302 1371
1303 UInt32 codePage = (UInt32)FindCharset(parser, NKey::kListfileCharSet, false, CP_UTF8); 1372 const UInt32 codePage = (UInt32)FindCharset(parser, NKey::kListfileCharSet, false, CP_UTF8);
1304 1373
1305 bool thereAreSwitchIncludes = false; 1374 bool thereAreSwitchIncludes = false;
1306 1375
@@ -1354,9 +1423,6 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
1354 nop, 1423 nop,
1355 thereAreSwitchIncludes, codePage); 1424 thereAreSwitchIncludes, codePage);
1356 1425
1357 options.YesToAll = parser[NKey::kYes].ThereIs;
1358
1359
1360 #ifndef Z7_NO_CRYPTO 1426 #ifndef Z7_NO_CRYPTO
1361 options.PasswordEnabled = parser[NKey::kPassword].ThereIs; 1427 options.PasswordEnabled = parser[NKey::kPassword].ThereIs;
1362 if (options.PasswordEnabled) 1428 if (options.PasswordEnabled)
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h
index 9e375b5..acee63c 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.h
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h
@@ -65,6 +65,7 @@ struct CArcCmdLineOptions
65 bool ShowDialog; 65 bool ShowDialog;
66 bool TechMode; 66 bool TechMode;
67 bool ShowTime; 67 bool ShowTime;
68 CBoolPair ListPathSeparatorSlash;
68 69
69 CBoolPair NtSecurity; 70 CBoolPair NtSecurity;
70 CBoolPair AltStreams; 71 CBoolPair AltStreams;
@@ -145,6 +146,12 @@ struct CArcCmdLineOptions
145 146
146 LogLevel(0) 147 LogLevel(0)
147 { 148 {
149 ListPathSeparatorSlash.Val =
150#ifdef _WIN32
151 false;
152#else
153 true;
154#endif
148 } 155 }
149}; 156};
150 157
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index 4b0cbed..2d32694 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -47,7 +47,9 @@ static const char * const kCantRenameFile = "Cannot rename existing file";
47static const char * const kCantDeleteOutputFile = "Cannot delete output file"; 47static const char * const kCantDeleteOutputFile = "Cannot delete output file";
48static const char * const kCantDeleteOutputDir = "Cannot delete output folder"; 48static const char * const kCantDeleteOutputDir = "Cannot delete output folder";
49static const char * const kCantOpenOutFile = "Cannot open output file"; 49static const char * const kCantOpenOutFile = "Cannot open output file";
50#ifndef Z7_SFX
50static const char * const kCantOpenInFile = "Cannot open input file"; 51static const char * const kCantOpenInFile = "Cannot open input file";
52#endif
51static const char * const kCantSetFileLen = "Cannot set length for output file"; 53static const char * const kCantSetFileLen = "Cannot set length for output file";
52#ifdef SUPPORT_LINKS 54#ifdef SUPPORT_LINKS
53static const char * const kCantCreateHardLink = "Cannot create hard link"; 55static const char * const kCantCreateHardLink = "Cannot create hard link";
@@ -124,7 +126,7 @@ static bool FindExt2(const char *p, const UString &name)
124 break; 126 break;
125 if (c >= 0x80) 127 if (c >= 0x80)
126 return false; 128 return false;
127 s += (char)MyCharLower_Ascii((char)c); 129 s.Add_Char((char)MyCharLower_Ascii((char)c));
128 } 130 }
129 for (unsigned i = 0; p[i] != 0;) 131 for (unsigned i = 0; p[i] != 0;)
130 { 132 {
@@ -161,10 +163,12 @@ void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf)
161 buf.Free(); 163 buf.Free();
162} 164}
163 165
164static bool WriteZoneFile(CFSTR fileName, const CByteBuffer &buf) 166bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf)
165{ 167{
168 FString path (fileName);
169 path += k_ZoneId_StreamName;
166 NIO::COutFile file; 170 NIO::COutFile file;
167 if (!file.Create(fileName, true)) 171 if (!file.Create_ALWAYS(path))
168 return false; 172 return false;
169 return file.WriteFull(buf, buf.Size()); 173 return file.WriteFull(buf, buf.Size());
170} 174}
@@ -275,6 +279,7 @@ CArchiveExtractCallback::CArchiveExtractCallback():
275 Write_CTime(true), 279 Write_CTime(true),
276 Write_ATime(true), 280 Write_ATime(true),
277 Write_MTime(true), 281 Write_MTime(true),
282 Is_elimPrefix_Mode(false),
278 _multiArchives(false) 283 _multiArchives(false)
279{ 284{
280 LocalProgressSpec = new CLocalProgress(); 285 LocalProgressSpec = new CLocalProgress();
@@ -497,16 +502,15 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
497 } 502 }
498 #endif 503 #endif
499 504
500 // bool res = 505 HRESULT hres = S_OK;
501 CreateDir(fullPath); 506 if (!CreateDir(fullPath))
502 // if (!res) 507 hres = GetLastError_noZero_HRESULT();
503 if (isFinalDir) 508 if (isFinalDir)
504 { 509 {
505 if (!NFile::NFind::DoesDirExist(fullPath)) 510 if (!NFile::NFind::DoesDirExist(fullPath))
506 { 511 {
507 _itemFailure = true; 512 _itemFailure = true;
508 SendMessageError("Cannot create folder", fullPath); 513 SendMessageError_with_Error(hres, "Cannot create folder", fullPath);
509 // SendMessageError_with_LastError()
510 } 514 }
511 } 515 }
512 } 516 }
@@ -544,12 +548,11 @@ HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FSt
544 return _extractCallback2->MessageError(s); 548 return _extractCallback2->MessageError(s);
545} 549}
546 550
547HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) 551
552HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path)
548{ 553{
549 DWORD errorCode = GetLastError();
550 if (errorCode == 0)
551 errorCode = (DWORD)E_FAIL;
552 UString s (message); 554 UString s (message);
555 if (errorCode != S_OK)
553 { 556 {
554 s += " : "; 557 s += " : ";
555 s += NError::MyFormatMessage(errorCode); 558 s += NError::MyFormatMessage(errorCode);
@@ -558,6 +561,12 @@ HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *mes
558 return _extractCallback2->MessageError(s); 561 return _extractCallback2->MessageError(s);
559} 562}
560 563
564HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path)
565{
566 const HRESULT errorCode = GetLastError_noZero_HRESULT();
567 return SendMessageError_with_Error(errorCode, message, path);
568}
569
561HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) 570HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2)
562{ 571{
563 UString s (message); 572 UString s (message);
@@ -692,7 +701,7 @@ bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcIte
692 if (pathParts2.IsEmpty()) 701 if (pathParts2.IsEmpty())
693 pathParts2.AddNew(); 702 pathParts2.AddNew();
694 UString &back = pathParts2.Back(); 703 UString &back = pathParts2.Back();
695 back += ':'; 704 back.Add_Colon();
696 back += item.AltStreamName; 705 back += item.AltStreamName;
697 bool include2; 706 bool include2;
698 707
@@ -1064,7 +1073,7 @@ void CArchiveExtractCallback::CorrectPathParts()
1064 1073
1065 UString &name = pathParts.Back(); 1074 UString &name = pathParts.Back();
1066 if (needColon) 1075 if (needColon)
1067 name += (char)(_ntOptions.ReplaceColonForAltStream ? '_' : ':'); 1076 name.Add_Char((char)(_ntOptions.ReplaceColonForAltStream ? '_' : ':'));
1068 name += s; 1077 name += s;
1069 } 1078 }
1070 1079
@@ -1111,6 +1120,7 @@ void CArchiveExtractCallback::CreateFolders()
1111 // 21.04 : we don't change original (_item.PathParts) here 1120 // 21.04 : we don't change original (_item.PathParts) here
1112 UStringVector pathParts = _item.PathParts; 1121 UStringVector pathParts = _item.PathParts;
1113 1122
1123 // bool is_DirOp = false;
1114 if (!pathParts.IsEmpty()) 1124 if (!pathParts.IsEmpty())
1115 { 1125 {
1116 /* v23: if we extract symlink, and we know that it links to dir: 1126 /* v23: if we extract symlink, and we know that it links to dir:
@@ -1125,16 +1135,45 @@ void CArchiveExtractCallback::CreateFolders()
1125 #endif 1135 #endif
1126 ) 1136 )
1127 pathParts.DeleteBack(); 1137 pathParts.DeleteBack();
1138 // else is_DirOp = true;
1128 } 1139 }
1129 1140
1130 if (pathParts.IsEmpty()) 1141 if (pathParts.IsEmpty())
1131 return; 1142 {
1143 /* if (_some_pathParts_wereRemoved && Is_elimPrefix_Mode),
1144 then we can have empty pathParts() here for root folder.
1145 v24.00: fixed: we set timestamps for such folder still.
1146 */
1147 if (!_some_pathParts_wereRemoved ||
1148 !Is_elimPrefix_Mode)
1149 return;
1150 // return; // ignore empty paths case
1151 }
1152 /*
1153 if (is_DirOp)
1154 {
1155 RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract))
1156 _op_WasReported = true;
1157 }
1158 */
1132 1159
1133 FString fullPathNew; 1160 FString fullPathNew;
1134 CreateComplexDirectory(pathParts, fullPathNew); 1161 CreateComplexDirectory(pathParts, fullPathNew);
1135 1162
1163 /*
1164 if (is_DirOp)
1165 {
1166 RINOK(SetOperationResult(
1167 // _itemFailure ? NArchive::NExtract::NOperationResult::kDataError :
1168 NArchive::NExtract::NOperationResult::kOK
1169 ))
1170 }
1171 */
1172
1136 if (!_item.IsDir) 1173 if (!_item.IsDir)
1137 return; 1174 return;
1175 if (fullPathNew.IsEmpty())
1176 return;
1138 1177
1139 if (_itemFailure) 1178 if (_itemFailure)
1140 return; 1179 return;
@@ -1326,7 +1365,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
1326 { 1365 {
1327 const CIndexToPathPair &pair = _renamedFiles[(unsigned)renIndex]; 1366 const CIndexToPathPair &pair = _renamedFiles[(unsigned)renIndex];
1328 fullProcessedPath = pair.Path; 1367 fullProcessedPath = pair.Path;
1329 fullProcessedPath += ':'; 1368 fullProcessedPath.Add_Colon();
1330 UString s (_item.AltStreamName); 1369 UString s (_item.AltStreamName);
1331 Correct_AltStream_Name(s); 1370 Correct_AltStream_Name(s);
1332 fullProcessedPath += us2fs(s); 1371 fullProcessedPath += us2fs(s);
@@ -1408,7 +1447,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
1408 { 1447 {
1409 if (!MyCreateHardLink(fullProcessedPath, hl)) 1448 if (!MyCreateHardLink(fullProcessedPath, hl))
1410 { 1449 {
1411 HRESULT errorCode = GetLastError_noZero_HRESULT(); 1450 const HRESULT errorCode = GetLastError_noZero_HRESULT();
1412 RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, hl)) 1451 RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, hl))
1413 return S_OK; 1452 return S_OK;
1414 } 1453 }
@@ -1431,7 +1470,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
1431 _outFileStreamSpec = new COutFileStream; 1470 _outFileStreamSpec = new COutFileStream;
1432 CMyComPtr<IOutStream> outFileStream_Loc(_outFileStreamSpec); 1471 CMyComPtr<IOutStream> outFileStream_Loc(_outFileStreamSpec);
1433 1472
1434 if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) 1473 if (!_outFileStreamSpec->Create_ALWAYS_or_Open_ALWAYS(fullProcessedPath, !_isSplit))
1435 { 1474 {
1436 // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) 1475 // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
1437 { 1476 {
@@ -1590,6 +1629,9 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
1590 _isSymLinkCreated = false; 1629 _isSymLinkCreated = false;
1591 _itemFailure = false; 1630 _itemFailure = false;
1592 1631
1632 _some_pathParts_wereRemoved = false;
1633 // _op_WasReported = false;
1634
1593 #ifdef SUPPORT_LINKS 1635 #ifdef SUPPORT_LINKS
1594 // _copyFile_Path.Empty(); 1636 // _copyFile_Path.Empty();
1595 _link.Clear(); 1637 _link.Clear();
@@ -1607,6 +1649,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
1607 else 1649 else
1608 _extractMode = true; 1650 _extractMode = true;
1609 break; 1651 break;
1652 default: break;
1610 } 1653 }
1611 1654
1612 1655
@@ -1684,7 +1727,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
1684 1727
1685 unsigned numRemovePathParts = 0; 1728 unsigned numRemovePathParts = 0;
1686 1729
1687 switch (_pathMode) 1730 switch ((int)_pathMode)
1688 { 1731 {
1689 case NExtract::NPathMode::kFullPaths: 1732 case NExtract::NPathMode::kFullPaths:
1690 case NExtract::NPathMode::kCurPaths: 1733 case NExtract::NPathMode::kCurPaths:
@@ -1730,7 +1773,10 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
1730 return E_FAIL; 1773 return E_FAIL;
1731 } 1774 }
1732 else 1775 else
1776 {
1733 numRemovePathParts = _removePathParts.Size(); 1777 numRemovePathParts = _removePathParts.Size();
1778 _some_pathParts_wereRemoved = true;
1779 }
1734 break; 1780 break;
1735 } 1781 }
1736 1782
@@ -1752,7 +1798,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
1752 break; 1798 break;
1753 } 1799 }
1754 case NExtract::NPathMode::kAbsPaths: 1800 case NExtract::NPathMode::kAbsPaths:
1755 // default: 1801 default:
1756 break; 1802 break;
1757 } 1803 }
1758 1804
@@ -1777,7 +1823,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
1777 if (_item.IsAltStream) 1823 if (_item.IsAltStream)
1778 { 1824 {
1779 if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt)) 1825 if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt))
1780 name += ':'; 1826 name.Add_Colon();
1781 name += _item.AltStreamName; 1827 name += _item.AltStreamName;
1782 } 1828 }
1783 #endif 1829 #endif
@@ -1854,6 +1900,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode))
1854 COM_TRY_BEGIN 1900 COM_TRY_BEGIN
1855 1901
1856 #ifndef Z7_SFX 1902 #ifndef Z7_SFX
1903 // if (!_op_WasReported)
1857 if (ExtractToStreamCallback) 1904 if (ExtractToStreamCallback)
1858 return ExtractToStreamCallback->PrepareOperation7(askExtractMode); 1905 return ExtractToStreamCallback->PrepareOperation7(askExtractMode);
1859 #endif 1906 #endif
@@ -1868,7 +1915,10 @@ Z7_COM7F_IMF(CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode))
1868 else 1915 else
1869 _extractMode = true; 1916 _extractMode = true;
1870 break; 1917 break;
1918 default: break;
1871 } 1919 }
1920
1921 // if (_op_WasReported) return S_OK;
1872 1922
1873 return _extractCallback2->PrepareOperation(_item.Path, BoolToInt(_item.IsDir), 1923 return _extractCallback2->PrepareOperation(_item.Path, BoolToInt(_item.IsDir),
1874 askExtractMode, _isSplit ? &_position: NULL); 1924 askExtractMode, _isSplit ? &_position: NULL);
@@ -1912,8 +1962,7 @@ HRESULT CArchiveExtractCallback::CloseFile()
1912 FindExt2(kOfficeExtensions, fs2us(_diskFilePath))) 1962 FindExt2(kOfficeExtensions, fs2us(_diskFilePath)))
1913 { 1963 {
1914 // we must write zone file before setting of timestamps 1964 // we must write zone file before setting of timestamps
1915 const FString path = _diskFilePath + k_ZoneId_StreamName; 1965 if (!WriteZoneFile_To_BaseFile(_diskFilePath, ZoneBuf))
1916 if (!WriteZoneFile(path, ZoneBuf))
1917 { 1966 {
1918 // we can't write it in FAT 1967 // we can't write it in FAT
1919 // SendMessageError_with_LastError("Can't write Zone.Identifier stream", path); 1968 // SendMessageError_with_LastError("Can't write Zone.Identifier stream", path);
@@ -1998,6 +2047,11 @@ HRESULT CArchiveExtractCallback::SetFromLinkPath(
1998 const HRESULT errorCode = GetLastError_noZero_HRESULT(); 2047 const HRESULT errorCode = GetLastError_noZero_HRESULT();
1999 RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, existPath)) 2048 RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, existPath))
2000 } 2049 }
2050 /*
2051 RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract))
2052 _op_WasReported = true;
2053 RINOK(SetOperationResult(NArchive::NExtract::NOperationResult::kOK))
2054 */
2001 linkWasSet = true; 2055 linkWasSet = true;
2002 return S_OK; 2056 return S_OK;
2003 } 2057 }
@@ -2427,6 +2481,8 @@ Z7_COM7F_IMF(CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password))
2427} 2481}
2428 2482
2429 2483
2484#ifndef Z7_SFX
2485
2430// ---------- HASH functions ---------- 2486// ---------- HASH functions ----------
2431 2487
2432FString CArchiveExtractCallback::Hash_GetFullFilePath() 2488FString CArchiveExtractCallback::Hash_GetFullFilePath()
@@ -2501,6 +2557,79 @@ Z7_COM7F_IMF(CArchiveExtractCallback::ReportOperation(
2501} 2557}
2502 2558
2503 2559
2560Z7_COM7F_IMF(CArchiveExtractCallback::RequestMemoryUse(
2561 UInt32 flags, UInt32 indexType, UInt32 index, const wchar_t *path,
2562 UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags))
2563{
2564 if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)
2565 {
2566 const UInt64 memLimit = _ntOptions.MemLimit;
2567 if (memLimit != (UInt64)(Int64)-1)
2568 {
2569 // we overwrite allowedSize
2570 *allowedSize = memLimit;
2571 if (requiredSize <= memLimit)
2572 {
2573 *answerFlags = NRequestMemoryAnswerFlags::k_Allow;
2574 return S_OK;
2575 }
2576 *answerFlags = NRequestMemoryAnswerFlags::k_Limit_Exceeded;
2577 if (flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected)
2578 *answerFlags |= NRequestMemoryAnswerFlags::k_SkipArc;
2579 flags |= NRequestMemoryUseFlags::k_SLimit_Exceeded
2580 | NRequestMemoryUseFlags::k_AllowedSize_WasForced;
2581 }
2582 }
2583
2584 if (!_requestMemoryUseCallback)
2585 {
2586 _extractCallback2.QueryInterface(IID_IArchiveRequestMemoryUseCallback,
2587 &_requestMemoryUseCallback);
2588 if (!_requestMemoryUseCallback)
2589 {
2590 // keep default (answerFlags) from caller or (answerFlags) that was set in this function
2591 return S_OK;
2592 }
2593 }
2594
2595#if 0
2596 if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)
2597 if (requiredSize <= *allowedSize)
2598 {
2599 // it's expected, that *answerFlags was set to NRequestMemoryAnswerFlags::k_Allow already,
2600 // because it's default answer for (requiredSize <= *allowedSize) case.
2601 *answerFlags = NRequestMemoryAnswerFlags::k_Allow; // optional code
2602 }
2603 else
2604 {
2605 // we clear *answerFlags, because we want to disable dafault "Allow", if it's set.
2606 // *answerFlags = 0;
2607 /*
2608 NRequestMemoryAnswerFlags::k_SkipArc |
2609 NRequestMemoryAnswerFlags::k_Limit_Exceeded;
2610 */
2611 }
2612#endif
2613
2614 UString s;
2615 if (!path
2616 && indexType == NArchive::NEventIndexType::kInArcIndex
2617 && index != (UInt32)(Int32)-1
2618 && _arc)
2619 {
2620 RINOK(_arc->GetItem_Path(index, s))
2621 path = s.Ptr();
2622 }
2623
2624 return _requestMemoryUseCallback->RequestMemoryUse(
2625 flags, indexType, index, path,
2626 requiredSize, allowedSize, answerFlags);
2627}
2628
2629#endif // Z7_SFX
2630
2631
2632
2504// ------------ After Extracting functions ------------ 2633// ------------ After Extracting functions ------------
2505 2634
2506void CDirPathSortPair::SetNumSlashes(const FChar *s) 2635void CDirPathSortPair::SetNumSlashes(const FChar *s)
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index 5ed20f3..7eb2f67 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -27,9 +27,9 @@ Z7_CLASS_IMP_NOQIB_1(
27 COutStreamWithHash 27 COutStreamWithHash
28 , ISequentialOutStream 28 , ISequentialOutStream
29) 29)
30 bool _calculate;
30 CMyComPtr<ISequentialOutStream> _stream; 31 CMyComPtr<ISequentialOutStream> _stream;
31 UInt64 _size; 32 UInt64 _size;
32 bool _calculate;
33public: 33public:
34 IHashCalc *_hash; 34 IHashCalc *_hash;
35 35
@@ -66,12 +66,15 @@ struct CExtractNtOptions
66 bool PreserveATime; 66 bool PreserveATime;
67 bool OpenShareForWrite; 67 bool OpenShareForWrite;
68 68
69 UInt64 MemLimit;
70
69 CExtractNtOptions(): 71 CExtractNtOptions():
70 ReplaceColonForAltStream(false), 72 ReplaceColonForAltStream(false),
71 WriteToAltStreamIfColon(false), 73 WriteToAltStreamIfColon(false),
72 ExtractOwner(false), 74 ExtractOwner(false),
73 PreserveATime(false), 75 PreserveATime(false),
74 OpenShareForWrite(false) 76 OpenShareForWrite(false),
77 MemLimit((UInt64)(Int64)-1)
75 { 78 {
76 SymLinks.Val = true; 79 SymLinks.Val = true;
77 SymLinks_AllowDangerous.Val = false; 80 SymLinks_AllowDangerous.Val = false;
@@ -249,25 +252,35 @@ class CArchiveExtractCallback Z7_final:
249 public IArchiveExtractCallbackMessage2, 252 public IArchiveExtractCallbackMessage2,
250 public ICryptoGetTextPassword, 253 public ICryptoGetTextPassword,
251 public ICompressProgressInfo, 254 public ICompressProgressInfo,
255#ifndef Z7_SFX
252 public IArchiveUpdateCallbackFile, 256 public IArchiveUpdateCallbackFile,
253 public IArchiveGetDiskProperty, 257 public IArchiveGetDiskProperty,
258 public IArchiveRequestMemoryUseCallback,
259#endif
254 public CMyUnknownImp 260 public CMyUnknownImp
255{ 261{
256 Z7_COM_UNKNOWN_IMP_5( 262 /* IArchiveExtractCallback, */
257 /* IArchiveExtractCallback, */ 263 Z7_COM_QI_BEGIN2(IArchiveExtractCallbackMessage2)
258 IArchiveExtractCallbackMessage2, 264 Z7_COM_QI_ENTRY(ICryptoGetTextPassword)
259 ICryptoGetTextPassword, 265 Z7_COM_QI_ENTRY(ICompressProgressInfo)
260 ICompressProgressInfo, 266#ifndef Z7_SFX
261 IArchiveUpdateCallbackFile, 267 Z7_COM_QI_ENTRY(IArchiveUpdateCallbackFile)
262 IArchiveGetDiskProperty) 268 Z7_COM_QI_ENTRY(IArchiveGetDiskProperty)
269 Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback)
270#endif
271 Z7_COM_QI_END
272 Z7_COM_ADDREF_RELEASE
263 273
264 Z7_IFACE_COM7_IMP(IProgress) 274 Z7_IFACE_COM7_IMP(IProgress)
265 Z7_IFACE_COM7_IMP(IArchiveExtractCallback) 275 Z7_IFACE_COM7_IMP(IArchiveExtractCallback)
266 Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage2) 276 Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage2)
267 Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) 277 Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
268 Z7_IFACE_COM7_IMP(ICompressProgressInfo) 278 Z7_IFACE_COM7_IMP(ICompressProgressInfo)
279#ifndef Z7_SFX
269 Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackFile) 280 Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackFile)
270 Z7_IFACE_COM7_IMP(IArchiveGetDiskProperty) 281 Z7_IFACE_COM7_IMP(IArchiveGetDiskProperty)
282 Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback)
283#endif
271 284
272 const CArc *_arc; 285 const CArc *_arc;
273 CExtractNtOptions _ntOptions; 286 CExtractNtOptions _ntOptions;
@@ -290,6 +303,11 @@ class CArchiveExtractCallback Z7_final:
290 bool _isSymLinkCreated; 303 bool _isSymLinkCreated;
291 bool _itemFailure; 304 bool _itemFailure;
292 305
306 bool _some_pathParts_wereRemoved;
307public:
308 bool Is_elimPrefix_Mode;
309
310private:
293 bool _curSize_Defined; 311 bool _curSize_Defined;
294 bool _fileLength_WasSet; 312 bool _fileLength_WasSet;
295 313
@@ -317,6 +335,7 @@ class CArchiveExtractCallback Z7_final:
317 CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback; 335 CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
318 CGetProp *GetProp_Spec; 336 CGetProp *GetProp_Spec;
319 CMyComPtr<IGetProp> GetProp; 337 CMyComPtr<IGetProp> GetProp;
338 CMyComPtr<IArchiveRequestMemoryUseCallback> _requestMemoryUseCallback;
320 339
321 #endif 340 #endif
322 341
@@ -418,6 +437,7 @@ class CArchiveExtractCallback Z7_final:
418 437
419public: 438public:
420 HRESULT SendMessageError(const char *message, const FString &path); 439 HRESULT SendMessageError(const char *message, const FString &path);
440 HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path);
421 HRESULT SendMessageError_with_LastError(const char *message, const FString &path); 441 HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
422 HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2); 442 HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2);
423 443
@@ -580,5 +600,6 @@ struct CArchiveExtractCallback_Closer
580bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); 600bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
581 601
582void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf); 602void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf);
603bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf);
583 604
584#endif 605#endif
diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp
index 1c0c3a8..3c0976d 100644
--- a/CPP/7zip/UI/Common/ArchiveName.cpp
+++ b/CPP/7zip/UI/Common/ArchiveName.cpp
@@ -158,7 +158,7 @@ UString CreateArchiveName(
158 baseName = name; 158 baseName = name;
159 if (!simple_IsAllowed) 159 if (!simple_IsAllowed)
160 { 160 {
161 HeapSort(&ids.Front(), ids.Size()); 161 HeapSort(ids.NonConstData(), ids.Size());
162 UInt32 v = 2; 162 UInt32 v = 2;
163 const unsigned num = ids.Size(); 163 const unsigned num = ids.Size();
164 for (unsigned i = 0; i < num; i++) 164 for (unsigned i = 0; i < num; i++)
@@ -169,7 +169,7 @@ UString CreateArchiveName(
169 if (id == v) 169 if (id == v)
170 v = id + 1; 170 v = id + 1;
171 } 171 }
172 name += '_'; 172 name.Add_Char('_');
173 name.Add_UInt32(v); 173 name.Add_UInt32(v);
174 } 174 }
175 return name; 175 return name;
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
index 4e5f1f5..8a72936 100644
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
@@ -85,6 +85,7 @@ Z7_COM7F_IMF(COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value))
85 { 85 {
86 case kpidName: prop = _subArchiveName; break; 86 case kpidName: prop = _subArchiveName; break;
87 // case kpidSize: prop = _subArchiveSize; break; // we don't use it now 87 // case kpidSize: prop = _subArchiveSize; break; // we don't use it now
88 default: break;
88 } 89 }
89 else 90 else
90 switch (propID) 91 switch (propID)
@@ -97,6 +98,7 @@ Z7_COM7F_IMF(COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value))
97 case kpidCTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.CTime); break; 98 case kpidCTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.CTime); break;
98 case kpidATime: PropVariant_SetFrom_FiTime(prop, _fileInfo.ATime); break; 99 case kpidATime: PropVariant_SetFrom_FiTime(prop, _fileInfo.ATime); break;
99 case kpidMTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.MTime); break; 100 case kpidMTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.MTime); break;
101 default: break;
100 } 102 }
101 prop.Detach(value); 103 prop.Detach(value);
102 return S_OK; 104 return S_OK;
@@ -106,12 +108,15 @@ Z7_COM7F_IMF(COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value))
106 108
107// ---------- CInFileStreamVol ---------- 109// ---------- CInFileStreamVol ----------
108 110
109Z7_CLASS_IMP_COM_2( 111Z7_class_final(CInFileStreamVol):
110 CInFileStreamVol 112 public IInStream
111 , IInStream 113 , public IStreamGetSize
112 , IStreamGetSize 114 , public CMyUnknownImp
113) 115{
114 Z7_IFACE_COM7_IMP(ISequentialInStream) 116 Z7_IFACES_IMP_UNK_3(
117 IInStream,
118 ISequentialInStream,
119 IStreamGetSize)
115public: 120public:
116 unsigned FileIndex; 121 unsigned FileIndex;
117 COpenCallbackImp *OpenCallbackImp; 122 COpenCallbackImp *OpenCallbackImp;
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
index 4e44c9d..a7b8b76 100644
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
@@ -167,6 +167,7 @@ public:
167 167
168 COpenCallbackImp(): 168 COpenCallbackImp():
169 _subArchiveMode(false), 169 _subArchiveMode(false),
170 PasswordWasAsked(false),
170 ReOpenCallback(NULL), 171 ReOpenCallback(NULL),
171 Callback(NULL) {} 172 Callback(NULL) {}
172 173
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp
index 5da9783..87a2df4 100644
--- a/CPP/7zip/UI/Common/Bench.cpp
+++ b/CPP/7zip/UI/Common/Bench.cpp
@@ -2,12 +2,9 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../../../../C/CpuArch.h"
6
7// #include <stdio.h> 5// #include <stdio.h>
8 6
9#ifndef _WIN32 7#ifndef _WIN32
10
11#define USE_POSIX_TIME 8#define USE_POSIX_TIME
12#define USE_POSIX_TIME2 9#define USE_POSIX_TIME2
13#endif // _WIN32 10#endif // _WIN32
@@ -31,10 +28,12 @@
31#else 28#else
32#include <stdlib.h> 29#include <stdlib.h>
33#endif 30#endif
31#define BENCH_ALLOCA_VALUE(index) (((index) * 64 * 21) & 0x7FF)
34#endif 32#endif
35 33
36#include "../../../../C/7zCrc.h" 34#include "../../../../C/7zCrc.h"
37#include "../../../../C/RotateDefs.h" 35#include "../../../../C/RotateDefs.h"
36#include "../../../../C/CpuArch.h"
38 37
39#ifndef Z7_ST 38#ifndef Z7_ST
40#include "../../../Windows/Synchronization.h" 39#include "../../../Windows/Synchronization.h"
@@ -105,9 +104,9 @@ static const unsigned kOldLzmaDictBits = 32;
105 104
106// static const size_t kAdditionalSize = (size_t)1 << 32; // for debug 105// static const size_t kAdditionalSize = (size_t)1 << 32; // for debug
107static const size_t kAdditionalSize = (size_t)1 << 16; 106static const size_t kAdditionalSize = (size_t)1 << 16;
108static const UInt32 kCompressedAdditionalSize = (1 << 10); 107static const size_t kCompressedAdditionalSize = 1 << 10;
109 108
110static const UInt32 kMaxMethodPropSize = (1 << 6); 109static const UInt32 kMaxMethodPropSize = 1 << 6;
111 110
112 111
113#define ALLOC_WITH_HRESULT(_buffer_, _size_) \ 112#define ALLOC_WITH_HRESULT(_buffer_, _size_) \
@@ -126,32 +125,40 @@ public:
126 Z7_FORCE_INLINE 125 Z7_FORCE_INLINE
127 UInt32 GetRnd() 126 UInt32 GetRnd()
128 { 127 {
128#if 0
129 // for debug:
130 return 0x0c080400;
131 // return 0;
132#else
129 return Salt ^ 133 return Salt ^
130 ( 134 (
131 ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + 135 ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) +
132 ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ) 136 ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) )
133 ); 137 );
138#endif
134 } 139 }
135}; 140};
136 141
137 142
143static const size_t k_RandBuf_AlignMask = 4 - 1;
144
138Z7_NO_INLINE 145Z7_NO_INLINE
139static void RandGen(Byte *buf, size_t size) 146static void RandGen_BufAfterPad(Byte *buf, size_t size)
140{ 147{
141 CBaseRandomGenerator RG; 148 CBaseRandomGenerator RG;
142 const size_t size4 = size & ~((size_t)3); 149 for (size_t i = 0; i < size; i += 4)
143 size_t i;
144 for (i = 0; i < size4; i += 4)
145 { 150 {
146 const UInt32 v = RG.GetRnd(); 151 const UInt32 v = RG.GetRnd();
147 SetUi32(buf + i, v) 152 SetUi32a(buf + i, v)
148 } 153 }
154 /*
149 UInt32 v = RG.GetRnd(); 155 UInt32 v = RG.GetRnd();
150 for (; i < size; i++) 156 for (; i < size; i++)
151 { 157 {
152 buf[i] = (Byte)v; 158 buf[i] = (Byte)v;
153 v >>= 8; 159 v >>= 8;
154 } 160 }
161 */
155} 162}
156 163
157 164
@@ -159,14 +166,14 @@ class CBenchRandomGenerator: public CMidAlignedBuffer
159{ 166{
160 static UInt32 GetVal(UInt32 &res, unsigned numBits) 167 static UInt32 GetVal(UInt32 &res, unsigned numBits)
161 { 168 {
162 UInt32 val = res & (((UInt32)1 << numBits) - 1); 169 const UInt32 val = res & (((UInt32)1 << numBits) - 1);
163 res >>= numBits; 170 res >>= numBits;
164 return val; 171 return val;
165 } 172 }
166 173
167 static UInt32 GetLen(UInt32 &r) 174 static UInt32 GetLen(UInt32 &r)
168 { 175 {
169 UInt32 len = GetVal(r, 2); 176 const unsigned len = (unsigned)GetVal(r, 2);
170 return GetVal(r, 1 + len); 177 return GetVal(r, 1 + len);
171 } 178 }
172 179
@@ -282,7 +289,7 @@ Z7_COM7F_IMF(CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processed
282 if (size > remain) 289 if (size > remain)
283 size = (UInt32)remain; 290 size = (UInt32)remain;
284 291
285 if (size != 0) 292 if (size)
286 memcpy(data, Data + Pos, size); 293 memcpy(data, Data + Pos, size);
287 294
288 Pos += size; 295 Pos += size;
@@ -1141,6 +1148,7 @@ public:
1141 1148
1142 #ifdef USE_ALLOCA 1149 #ifdef USE_ALLOCA
1143 alloca(decoder->AllocaSize); 1150 alloca(decoder->AllocaSize);
1151 // printf("\nalloca=%d\n", (unsigned)decoder->AllocaSize);
1144 #endif 1152 #endif
1145 1153
1146 CEncoderInfo *encoder = decoder->Encoder; 1154 CEncoderInfo *encoder = decoder->Encoder;
@@ -1462,14 +1470,22 @@ HRESULT CEncoderInfo::Encode()
1462 Byte *filterData = rgCopy; 1470 Byte *filterData = rgCopy;
1463 if (i == numIterations - 1 || calcCrc || useRealData_Enc) 1471 if (i == numIterations - 1 || calcCrc || useRealData_Enc)
1464 { 1472 {
1473 // printf("\nfilterData = (Byte *)*outStreamSpec;\n");
1465 filterData = (Byte *)*outStreamSpec; 1474 filterData = (Byte *)*outStreamSpec;
1466 if (data_Was_Changed) 1475 if (data_Was_Changed)
1476 {
1477 // printf("\nmemcpy(filterData, uncompressedDataPtr\n");
1467 memcpy(filterData, uncompressedDataPtr, kBufferSize); 1478 memcpy(filterData, uncompressedDataPtr, kBufferSize);
1479 }
1468 data_Was_Changed = true; 1480 data_Was_Changed = true;
1469 } 1481 }
1470 _encoderFilter->Init(); 1482 _encoderFilter->Init();
1471 if (calcCrc) 1483 if (calcCrc)
1484 {
1485 // printf("\nInitCrc\n");
1472 outStreamSpec->InitCrc(); 1486 outStreamSpec->InitCrc();
1487 }
1488 // printf("\nMy_FilterBench\n");
1473 My_FilterBench(_encoderFilter, filterData, kBufferSize, 1489 My_FilterBench(_encoderFilter, filterData, kBufferSize,
1474 calcCrc ? &outStreamSpec->Crc : NULL); 1490 calcCrc ? &outStreamSpec->Crc : NULL);
1475 } 1491 }
@@ -1541,6 +1557,8 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex)
1541 else 1557 else
1542 coder = decoder; 1558 coder = decoder;
1543 1559
1560 // printf("\ndecoderIndex = %d, stack = %p", decoderIndex, &coder);
1561
1544 CMyComPtr<ICompressSetDecoderProperties2> setDecProps; 1562 CMyComPtr<ICompressSetDecoderProperties2> setDecProps;
1545 coder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecProps); 1563 coder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecProps);
1546 if (!setDecProps && propStreamSpec->GetPos() != 0) 1564 if (!setDecProps && propStreamSpec->GetPos() != 0)
@@ -1927,10 +1945,24 @@ static HRESULT MethodBench(
1927 CEncoderInfo &encoder = encoders[i]; 1945 CEncoderInfo &encoder = encoders[i];
1928 encoder.NumIterations = GetNumIterations(benchProps->GetNumCommands_Enc(uncompressedDataSize), complexInCommands); 1946 encoder.NumIterations = GetNumIterations(benchProps->GetNumCommands_Enc(uncompressedDataSize), complexInCommands);
1929 // encoder.NumIterations = 3; 1947 // encoder.NumIterations = 3;
1930 encoder.Salt = g_CrcTable[i & 0xFF]; 1948 {
1931 encoder.Salt ^= (g_CrcTable[(i >> 8) & 0xFF] << 3); 1949#if 0
1950 #define kCrcPoly 0xEDB88320
1951 UInt32 r = i;
1952 unsigned num = numEncoderThreads < 256 ? 8 : 16;
1953 do
1954 r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
1955 while (--num);
1956 encoder.Salt = r;
1957#else
1958 UInt32 salt0 = g_CrcTable[(Byte)i];
1959 UInt32 salt1 = g_CrcTable[(Byte)(i >> 8)];
1960 encoder.Salt = salt0 ^ (salt1 << 3);
1961#endif
1962 }
1963
1932 // (g_CrcTable[0] == 0), and (encoder.Salt == 0) for first thread 1964 // (g_CrcTable[0] == 0), and (encoder.Salt == 0) for first thread
1933 // printf(" %8x", encoder.Salt); 1965 // printf("\n encoder index = %d, Salt = %8x\n", i, encoder.Salt);
1934 1966
1935 encoder.KeySize = benchProps->KeySize; 1967 encoder.KeySize = benchProps->KeySize;
1936 1968
@@ -1953,7 +1985,7 @@ static HRESULT MethodBench(
1953 if (mtEncMode) 1985 if (mtEncMode)
1954 { 1986 {
1955 #ifdef USE_ALLOCA 1987 #ifdef USE_ALLOCA
1956 encoder.AllocaSize = (i * 16 * 21) & 0x7FF; 1988 encoder.AllocaSize = BENCH_ALLOCA_VALUE(i);
1957 #endif 1989 #endif
1958 1990
1959 encoder.Common = &encoderFlusher.Common; 1991 encoder.Common = &encoderFlusher.Common;
@@ -2055,7 +2087,7 @@ static HRESULT MethodBench(
2055 2087
2056 #ifndef Z7_ST 2088 #ifndef Z7_ST
2057 { 2089 {
2058 int numSubThreads = method.Get_NumThreads(); 2090 const int numSubThreads = method.Get_NumThreads();
2059 encoder.NumDecoderSubThreads = (numSubThreads <= 0) ? 1 : (unsigned)numSubThreads; 2091 encoder.NumDecoderSubThreads = (numSubThreads <= 0) ? 1 : (unsigned)numSubThreads;
2060 } 2092 }
2061 if (mtDecoderMode) 2093 if (mtDecoderMode)
@@ -2064,7 +2096,7 @@ static HRESULT MethodBench(
2064 { 2096 {
2065 const HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) 2097 const HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0)
2066 #ifdef USE_ALLOCA 2098 #ifdef USE_ALLOCA
2067 , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF 2099 , BENCH_ALLOCA_VALUE(i * numSubDecoderThreads + j)
2068 #endif 2100 #endif
2069 ); 2101 );
2070 RINOK(res) 2102 RINOK(res)
@@ -2200,7 +2232,7 @@ UInt64 GetBenchMemoryUsage(UInt32 numThreads, int level, UInt64 dictionary, bool
2200 const int btMode = (algo == 0 ? 0 : 1); 2232 const int btMode = (algo == 0 ? 0 : 1);
2201 2233
2202 UInt32 numBigThreads = numThreads; 2234 UInt32 numBigThreads = numThreads;
2203 bool lzmaMt = (totalBench || (numThreads > 1 && btMode)); 2235 const bool lzmaMt = (totalBench || (numThreads > 1 && btMode));
2204 if (btMode) 2236 if (btMode)
2205 { 2237 {
2206 if (!totalBench && lzmaMt) 2238 if (!totalBench && lzmaMt)
@@ -2236,19 +2268,32 @@ struct CCrcInfo_Base
2236}; 2268};
2237 2269
2238 2270
2271// for debug: define it to test hash calling with unaligned data
2272// #define Z7_BENCH_HASH_ALIGN_BUF_OFFSET 3
2273
2239HRESULT CCrcInfo_Base::Generate(const Byte *data, size_t size) 2274HRESULT CCrcInfo_Base::Generate(const Byte *data, size_t size)
2240{ 2275{
2241 Size = size; 2276 Size = size;
2242 Data = data; 2277 Data = data;
2243 if (!data || CreateLocalBuf) 2278 if (!data || CreateLocalBuf)
2244 { 2279 {
2245 ALLOC_WITH_HRESULT(&Buffer, size) 2280 Byte *buf;
2246 Data = Buffer; 2281 const size_t size2 = (size + k_RandBuf_AlignMask) & ~(size_t)k_RandBuf_AlignMask;
2282 if (size2 < size)
2283 return E_OUTOFMEMORY;
2284#ifdef Z7_BENCH_HASH_ALIGN_BUF_OFFSET
2285 ALLOC_WITH_HRESULT(&Buffer, size2 + Z7_BENCH_HASH_ALIGN_BUF_OFFSET)
2286 buf = Buffer + Z7_BENCH_HASH_ALIGN_BUF_OFFSET;
2287#else
2288 ALLOC_WITH_HRESULT(&Buffer, size2)
2289 buf = Buffer;
2290#endif
2291 Data = buf;
2292 if (!data)
2293 RandGen_BufAfterPad(buf, size);
2294 else if (size != 0) // (CreateLocalBuf == true)
2295 memcpy(buf, data, size);
2247 } 2296 }
2248 if (!data)
2249 RandGen(Buffer, size);
2250 else if (CreateLocalBuf && size != 0)
2251 memcpy(Buffer, data, size);
2252 return S_OK; 2297 return S_OK;
2253} 2298}
2254 2299
@@ -2258,13 +2303,13 @@ HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations,
2258 IBenchPrintCallback *callback) 2303 IBenchPrintCallback *callback)
2259{ 2304{
2260 MY_ALIGN(16) 2305 MY_ALIGN(16)
2261 Byte hash[64]; 2306 UInt32 hash32[64 / 4];
2262 memset(hash, 0, sizeof(hash)); 2307 memset(hash32, 0, sizeof(hash32));
2263 2308
2264 CheckSum_Res = 0; 2309 CheckSum_Res = 0;
2265 2310
2266 const UInt32 hashSize = hf->GetDigestSize(); 2311 const UInt32 hashSize = hf->GetDigestSize();
2267 if (hashSize > sizeof(hash)) 2312 if (hashSize > sizeof(hash32))
2268 return S_FALSE; 2313 return S_FALSE;
2269 2314
2270 const Byte *buf = Data; 2315 const Byte *buf = Data;
@@ -2274,7 +2319,7 @@ HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations,
2274 UInt64 prev = 0; 2319 UInt64 prev = 0;
2275 UInt64 cur = 0; 2320 UInt64 cur = 0;
2276 2321
2277 for (UInt64 i = 0; i < numIterations; i++) 2322 do
2278 { 2323 {
2279 hf->Init(); 2324 hf->Init();
2280 size_t pos = 0; 2325 size_t pos = 0;
@@ -2288,12 +2333,12 @@ HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations,
2288 } 2333 }
2289 while (pos != size); 2334 while (pos != size);
2290 2335
2291 hf->Final(hash); 2336 hf->Final((Byte *)(void *)hash32);
2292 UInt32 sum = 0; 2337 UInt32 sum = 0;
2293 for (UInt32 j = 0; j < hashSize; j += 4) 2338 for (UInt32 j = 0; j < hashSize; j += 4)
2294 { 2339 {
2295 sum = rotlFixed(sum, 11); 2340 sum = rotlFixed(sum, 11);
2296 sum += GetUi32(hash + j); 2341 sum += GetUi32((const Byte *)(const void *)hash32 + j);
2297 } 2342 }
2298 if (checkSum) 2343 if (checkSum)
2299 { 2344 {
@@ -2315,6 +2360,8 @@ HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations,
2315 } 2360 }
2316 } 2361 }
2317 } 2362 }
2363 while (--numIterations);
2364
2318 CheckSum_Res = checkSum_Prev; 2365 CheckSum_Res = checkSum_Prev;
2319 return S_OK; 2366 return S_OK;
2320} 2367}
@@ -2555,6 +2602,7 @@ WRes CCrcThreads::StartAndWait(bool exitMode)
2555#endif 2602#endif
2556 2603
2557 2604
2605/*
2558static UInt32 CrcCalc1(const Byte *buf, size_t size) 2606static UInt32 CrcCalc1(const Byte *buf, size_t size)
2559{ 2607{
2560 UInt32 crc = CRC_INIT_VAL; 2608 UInt32 crc = CRC_INIT_VAL;
@@ -2562,6 +2610,7 @@ static UInt32 CrcCalc1(const Byte *buf, size_t size)
2562 crc = CRC_UPDATE_BYTE(crc, buf[i]); 2610 crc = CRC_UPDATE_BYTE(crc, buf[i]);
2563 return CRC_GET_DIGEST(crc); 2611 return CRC_GET_DIGEST(crc);
2564} 2612}
2613*/
2565 2614
2566/* 2615/*
2567static UInt32 RandGenCrc(Byte *buf, size_t size, CBaseRandomGenerator &RG) 2616static UInt32 RandGenCrc(Byte *buf, size_t size, CBaseRandomGenerator &RG)
@@ -2574,25 +2623,21 @@ static UInt32 RandGenCrc(Byte *buf, size_t size, CBaseRandomGenerator &RG)
2574static bool CrcInternalTest() 2623static bool CrcInternalTest()
2575{ 2624{
2576 CAlignedBuffer buffer; 2625 CAlignedBuffer buffer;
2577 const size_t kBufferSize0 = (1 << 8); 2626 const size_t kBufSize = 1 << 11;
2578 const size_t kBufferSize1 = (1 << 10); 2627 const size_t kCheckSize = 1 << 6;
2579 const unsigned kCheckSize = (1 << 5); 2628 buffer.Alloc(kBufSize);
2580 buffer.Alloc(kBufferSize0 + kBufferSize1);
2581 if (!buffer.IsAllocated()) 2629 if (!buffer.IsAllocated())
2582 return false; 2630 return false;
2583 Byte *buf = (Byte *)buffer; 2631 Byte *buf = (Byte *)buffer;
2584 size_t i; 2632 RandGen_BufAfterPad(buf, kBufSize);
2585 for (i = 0; i < kBufferSize0; i++) 2633 UInt32 sum = 0;
2586 buf[i] = (Byte)i; 2634 for (size_t i = 0; i < kBufSize - kCheckSize * 2; i += kCheckSize - 1)
2587 UInt32 crc1 = CrcCalc1(buf, kBufferSize0); 2635 for (size_t j = 0; j < kCheckSize; j++)
2588 if (crc1 != 0x29058C73) 2636 {
2589 return false; 2637 sum = rotlFixed(sum, 11);
2590 RandGen(buf + kBufferSize0, kBufferSize1); 2638 sum += CrcCalc(buf + i + j, j);
2591 for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) 2639 }
2592 for (unsigned j = 0; j < kCheckSize; j++) 2640 return sum == 0x28462c7c;
2593 if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j))
2594 return false;
2595 return true;
2596} 2641}
2597 2642
2598struct CBenchMethod 2643struct CBenchMethod
@@ -2652,6 +2697,7 @@ static const CBenchMethod g_Bench[] =
2652 2697
2653 { 2, 0, 2, 0, 2, "BCJ" }, 2698 { 2, 0, 2, 0, 2, "BCJ" },
2654 { 2, 0, 1, 0, 1, "ARM64" }, 2699 { 2, 0, 1, 0, 1, "ARM64" },
2700 { 2, 0, 1, 0, 1, "RISCV" },
2655 2701
2656 // { 10, 0, 18, 0, 18, "AES128CBC:1" }, 2702 // { 10, 0, 18, 0, 18, "AES128CBC:1" },
2657 // { 10, 0, 21, 0, 21, "AES192CBC:1" }, 2703 // { 10, 0, 21, 0, 21, "AES192CBC:1" },
@@ -2668,13 +2714,13 @@ static const CBenchMethod g_Bench[] =
2668 // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES192CTR:2" }, 2714 // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES192CTR:2" },
2669 // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES256CTR:2" }, 2715 // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES256CTR:2" },
2670 2716
2671 // { 1, 0, CMPLX(6), 0, CMPLX(1), "AES128CBC:3" }, 2717 // { 1, 0, CMPLX(6), 0, -2, "AES128CBC:3" },
2672 // { 1, 0, CMPLX(7), 0, CMPLX(1), "AES192CBC:3" }, 2718 // { 1, 0, CMPLX(7), 0, -2, "AES192CBC:3" },
2673 { 1, 0, CMPLX(8), 0, CMPLX(1), "AES256CBC:3" } 2719 { 1, 0, CMPLX(8), 0, -2, "AES256CBC:3" }
2674 2720
2675 // { 1, 0, CMPLX(1), 0, CMPLX(1), "AES128CTR:3" }, 2721 // { 1, 0, CMPLX(1), 0, -2, "AES128CTR:3" },
2676 // { 1, 0, CMPLX(1), 0, CMPLX(1), "AES192CTR:3" }, 2722 // { 1, 0, CMPLX(1), 0, -2, "AES192CTR:3" },
2677 // { 1, 0, CMPLX(1), 0, CMPLX(1), "AES256CTR:3" }, 2723 // { 1, 0, CMPLX(1), 0, -2, "AES256CTR:3" },
2678}; 2724};
2679 2725
2680struct CBenchHash 2726struct CBenchHash
@@ -2692,12 +2738,11 @@ struct CBenchHash
2692 2738
2693static const CBenchHash g_Hash[] = 2739static const CBenchHash g_Hash[] =
2694{ 2740{
2695 // { 1, 1820, 0x21e207bb, "CRC32:1" }, 2741 { 20, 256, 0x21e207bb, "CRC32:12" } ,
2696 // { 10, 558, 0x21e207bb, "CRC32:4" },
2697 { 20, 339, 0x21e207bb, "CRC32:8" } ,
2698 { 2, 128 *ARM_CRC_MUL, 0x21e207bb, "CRC32:32" }, 2742 { 2, 128 *ARM_CRC_MUL, 0x21e207bb, "CRC32:32" },
2699 { 2, 64 *ARM_CRC_MUL, 0x21e207bb, "CRC32:64" }, 2743 { 2, 64 *ARM_CRC_MUL, 0x21e207bb, "CRC32:64" },
2700 { 10, 512, 0x41b901d1, "CRC64" }, 2744 { 10, 256, 0x41b901d1, "CRC64" },
2745 { 10, 64, 0x43eac94f, "XXH64" },
2701 2746
2702 { 10, 5100, 0x7913ba03, "SHA256:1" }, 2747 { 10, 5100, 0x7913ba03, "SHA256:1" },
2703 { 2, CMPLX((32 * 4 + 1) * 4 + 4), 0x7913ba03, "SHA256:2" }, 2748 { 2, CMPLX((32 * 4 + 1) * 4 + 4), 0x7913ba03, "SHA256:2" },
@@ -2705,7 +2750,15 @@ static const CBenchHash g_Hash[] =
2705 { 10, 2340, 0xff769021, "SHA1:1" }, 2750 { 10, 2340, 0xff769021, "SHA1:1" },
2706 { 2, CMPLX((20 * 6 + 1) * 4 + 4), 0xff769021, "SHA1:2" }, 2751 { 2, CMPLX((20 * 6 + 1) * 4 + 4), 0xff769021, "SHA1:2" },
2707 2752
2708 { 2, 5500, 0x85189d02, "BLAKE2sp" } 2753 { 2, 4096, 0x85189d02, "BLAKE2sp:1" },
2754 { 2, 1024, 0x85189d02, "BLAKE2sp:2" }, // sse2-way4-fast
2755 { 2, 512, 0x85189d02, "BLAKE2sp:3" } // avx2-way8-fast
2756#if 0
2757 , { 2, 2048, 0x85189d02, "BLAKE2sp:4" } // sse2-way1
2758 , { 2, 1024, 0x85189d02, "BLAKE2sp:5" } // sse2-way2
2759 , { 2, 1024, 0x85189d02, "BLAKE2sp:6" } // avx2-way2
2760 , { 2, 1024, 0x85189d02, "BLAKE2sp:7" } // avx2-way4
2761#endif
2709}; 2762};
2710 2763
2711static void PrintNumber(IBenchPrintCallback &f, UInt64 value, unsigned size) 2764static void PrintNumber(IBenchPrintCallback &f, UInt64 value, unsigned size)
@@ -3267,7 +3320,8 @@ HRESULT CFreqBench::FreqBench(IBenchPrintCallback *_file
3267 { 3320 {
3268 progressInfoSpec.SetStartTime(); 3321 progressInfoSpec.SetStartTime();
3269 UInt32 sum = g_BenchCpuFreqTemp; 3322 UInt32 sum = g_BenchCpuFreqTemp;
3270 for (UInt64 k = numIterations; k > 0; k--) 3323 UInt64 k = numIterations;
3324 do
3271 { 3325 {
3272 sum = CountCpuFreq(sum, numIterations2, g_BenchCpuFreqTemp); 3326 sum = CountCpuFreq(sum, numIterations2, g_BenchCpuFreqTemp);
3273 if (_file) 3327 if (_file)
@@ -3275,6 +3329,7 @@ HRESULT CFreqBench::FreqBench(IBenchPrintCallback *_file
3275 RINOK(_file->CheckBreak()) 3329 RINOK(_file->CheckBreak())
3276 } 3330 }
3277 } 3331 }
3332 while (--k);
3278 res += sum; 3333 res += sum;
3279 } 3334 }
3280 3335
@@ -3406,7 +3461,7 @@ static HRESULT CrcBench(
3406 } 3461 }
3407 3462
3408 #ifdef USE_ALLOCA 3463 #ifdef USE_ALLOCA
3409 ci.AllocaSize = (i * 16 * 21) & 0x7FF; 3464 ci.AllocaSize = BENCH_ALLOCA_VALUE(i);
3410 #endif 3465 #endif
3411 } 3466 }
3412 3467
@@ -3627,6 +3682,7 @@ HRESULT Bench(
3627 bool multiDict, 3682 bool multiDict,
3628 IBenchFreqCallback *freqCallback) 3683 IBenchFreqCallback *freqCallback)
3629{ 3684{
3685 // for (int y = 0; y < 10000; y++)
3630 if (!CrcInternalTest()) 3686 if (!CrcInternalTest())
3631 return E_FAIL; 3687 return E_FAIL;
3632 3688
@@ -3850,13 +3906,13 @@ HRESULT Bench(
3850 { 3906 {
3851 AString s; 3907 AString s;
3852 3908
3853 #ifndef _WIN32 3909#if 1 || !defined(Z7_MSC_VER_ORIGINAL) || (Z7_MSC_VER_ORIGINAL >= 1900)
3854 s += "Compiler: "; 3910 s += "Compiler: ";
3855 GetCompiler(s); 3911 GetCompiler(s);
3856 printCallback->Print(s); 3912 printCallback->Print(s);
3857 printCallback->NewLine(); 3913 printCallback->NewLine();
3858 s.Empty(); 3914 s.Empty();
3859 #endif 3915#endif
3860 3916
3861 GetSystemInfoText(s); 3917 GetSystemInfoText(s);
3862 printCallback->Print(s); 3918 printCallback->Print(s);
@@ -3896,7 +3952,7 @@ HRESULT Bench(
3896 start = 1; 3952 start = 1;
3897 const UInt64 freq = GetFreq(); 3953 const UInt64 freq = GetFreq();
3898 // mips is constant in some compilers 3954 // mips is constant in some compilers
3899 const UInt64 hz = MyMultDiv64(numMilCommands * 1000000, freq, start); 3955 const UInt64 hzVal = MyMultDiv64(numMilCommands * 1000000, freq, start);
3900 const UInt64 mipsVal = numMilCommands * freq / start; 3956 const UInt64 mipsVal = numMilCommands * freq / start;
3901 if (printCallback) 3957 if (printCallback)
3902 { 3958 {
@@ -3912,7 +3968,7 @@ HRESULT Bench(
3912 } 3968 }
3913 if (freqCallback) 3969 if (freqCallback)
3914 { 3970 {
3915 RINOK(freqCallback->AddCpuFreq(1, hz, kBenchmarkUsageMult)) 3971 RINOK(freqCallback->AddCpuFreq(1, hzVal, kBenchmarkUsageMult))
3916 } 3972 }
3917 3973
3918 if (jj >= 1) 3974 if (jj >= 1)
@@ -3955,7 +4011,7 @@ HRESULT Bench(
3955 /* it can show incorrect frequency for HT threads. 4011 /* it can show incorrect frequency for HT threads.
3956 so we reduce freq test to (numCPUs / 2) */ 4012 so we reduce freq test to (numCPUs / 2) */
3957 4013
3958 UInt32 numThreads = numThreadsSpecified >= numCPUs / 2 ? numCPUs / 2: numThreadsSpecified; 4014 UInt32 numThreads = (numThreadsSpecified >= numCPUs / 2 ? numCPUs / 2 : numThreadsSpecified);
3959 if (numThreads < 1) 4015 if (numThreads < 1)
3960 numThreads = 1; 4016 numThreads = 1;
3961 4017
diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp
index 42bae2a..1ded1b3 100644
--- a/CPP/7zip/UI/Common/CompressCall.cpp
+++ b/CPP/7zip/UI/Common/CompressCall.cpp
@@ -51,7 +51,7 @@ UString GetQuotedString(const UString &s)
51{ 51{
52 UString s2 ('\"'); 52 UString s2 ('\"');
53 s2 += s; 53 s2 += s;
54 s2 += '\"'; 54 s2.Add_Char('\"');
55 return s2; 55 return s2;
56} 56}
57 57
@@ -155,14 +155,14 @@ static HRESULT CreateMap(const UStringVector &names,
155 event.Close(); 155 event.Close();
156 } 156 }
157 157
158 params += '#'; 158 params.Add_Char('#');
159 params += mappingName; 159 params += mappingName;
160 params += ':'; 160 params.Add_Colon();
161 char temp[32]; 161 char temp[32];
162 ConvertUInt64ToString(totalSize, temp); 162 ConvertUInt64ToString(totalSize, temp);
163 params += temp; 163 params += temp;
164 164
165 params += ':'; 165 params.Add_Colon();
166 params += eventName; 166 params += eventName;
167 167
168 LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize); 168 LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize);
diff --git a/CPP/7zip/UI/Common/CompressCall2.cpp b/CPP/7zip/UI/Common/CompressCall2.cpp
index 21eb472..fef0877 100644
--- a/CPP/7zip/UI/Common/CompressCall2.cpp
+++ b/CPP/7zip/UI/Common/CompressCall2.cpp
@@ -68,7 +68,7 @@ UString GetQuotedString(const UString &s)
68{ 68{
69 UString s2 ('\"'); 69 UString s2 ('\"');
70 s2 += s; 70 s2 += s;
71 s2 += '\"'; 71 s2.Add_Char('\"');
72 return s2; 72 return s2;
73} 73}
74 74
diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h
index ae84937..3c19249 100644
--- a/CPP/7zip/UI/Common/DirItem.h
+++ b/CPP/7zip/UI/Common/DirItem.h
@@ -260,6 +260,8 @@ struct CDirItem: public NWindows::NFile::NFind::CFileInfoBase
260 int OwnerGroupIndex; 260 int OwnerGroupIndex;
261 #endif 261 #endif
262 262
263 // bool Attrib_IsDefined;
264
263 CDirItem(): 265 CDirItem():
264 PhyParent(-1) 266 PhyParent(-1)
265 , LogParent(-1) 267 , LogParent(-1)
@@ -269,6 +271,7 @@ struct CDirItem: public NWindows::NFile::NFind::CFileInfoBase
269 , OwnerNameIndex(-1) 271 , OwnerNameIndex(-1)
270 , OwnerGroupIndex(-1) 272 , OwnerGroupIndex(-1)
271 #endif 273 #endif
274 // , Attrib_IsDefined(true)
272 { 275 {
273 } 276 }
274 277
diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp
index d536c47..0758547 100644
--- a/CPP/7zip/UI/Common/EnumDirItems.cpp
+++ b/CPP/7zip/UI/Common/EnumDirItems.cpp
@@ -287,14 +287,12 @@ HRESULT CDirItems::EnumerateOneDir(const FString &phyPrefix, CObjectVector<NFind
287 287
288 CObjectVector<NFind::CDirEntry> entries; 288 CObjectVector<NFind::CDirEntry> entries;
289 289
290 for (unsigned ttt = 0; ; ttt++) 290 for (;;)
291 { 291 {
292 bool found; 292 bool found;
293 NFind::CDirEntry de; 293 NFind::CDirEntry de;
294 if (!enumerator.Next(de, found)) 294 if (!enumerator.Next(de, found))
295 {
296 return AddError(phyPrefix); 295 return AddError(phyPrefix);
297 }
298 if (!found) 296 if (!found)
299 break; 297 break;
300 entries.Add(de); 298 entries.Add(de);
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp
index 34b4871..010b01c 100644
--- a/CPP/7zip/UI/Common/Extract.cpp
+++ b/CPP/7zip/UI/Common/Extract.cpp
@@ -2,8 +2,6 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../../../../C/Sort.h"
6
7#include "../../../Common/StringConvert.h" 5#include "../../../Common/StringConvert.h"
8 6
9#include "../../../Windows/FileDir.h" 7#include "../../../Windows/FileDir.h"
@@ -201,6 +199,8 @@ static HRESULT DecompressArchive(
201 removePathParts, false, 199 removePathParts, false,
202 packSize); 200 packSize);
203 201
202 ecs->Is_elimPrefix_Mode = elimIsPossible;
203
204 204
205 #ifdef SUPPORT_LINKS 205 #ifdef SUPPORT_LINKS
206 206
@@ -227,7 +227,13 @@ static HRESULT DecompressArchive(
227 ConvertPropVariantToUInt64(prop, stdInProcessed); 227 ConvertPropVariantToUInt64(prop, stdInProcessed);
228 } 228 }
229 else 229 else
230 result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs); 230 {
231 // v23.02: we reset completed value that could be set by Open() operation
232 IArchiveExtractCallback *aec = ecs;
233 const UInt64 val = 0;
234 RINOK(aec->SetCompleted(&val))
235 result = archive->Extract(realIndices.ConstData(), realIndices.Size(), testMode, aec);
236 }
231 237
232 const HRESULT res2 = ecsCloser.Close(); 238 const HRESULT res2 = ecsCloser.Close();
233 if (result == S_OK) 239 if (result == S_OK)
@@ -349,11 +355,10 @@ HRESULT Extract(
349 if (options.StdInMode) 355 if (options.StdInMode)
350 { 356 {
351 // do we need ctime and mtime? 357 // do we need ctime and mtime?
352 fi.ClearBase(); 358 // fi.ClearBase();
353 fi.Size = 0; // (UInt64)(Int64)-1; 359 // fi.Size = 0; // (UInt64)(Int64)-1;
354 fi.SetAsFile(); 360 if (!fi.SetAs_StdInFile())
355 // NTime::GetCurUtc_FiTime(fi.MTime); 361 return GetLastError_noZero_HRESULT();
356 // fi.CTime = fi.ATime = fi.MTime;
357 } 362 }
358 else 363 else
359 { 364 {
diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h
index b20f607..defaa27 100644
--- a/CPP/7zip/UI/Common/Extract.h
+++ b/CPP/7zip/UI/Common/Extract.h
@@ -26,9 +26,10 @@ struct CExtractOptionsBase
26 NExtract::NPathMode::EEnum PathMode; 26 NExtract::NPathMode::EEnum PathMode;
27 NExtract::NOverwriteMode::EEnum OverwriteMode; 27 NExtract::NOverwriteMode::EEnum OverwriteMode;
28 NExtract::NZoneIdMode::EEnum ZoneMode; 28 NExtract::NZoneIdMode::EEnum ZoneMode;
29
30 CExtractNtOptions NtOptions;
29 31
30 FString OutputDir; 32 FString OutputDir;
31 CExtractNtOptions NtOptions;
32 UString HashDir; 33 UString HashDir;
33 34
34 CExtractOptionsBase(): 35 CExtractOptionsBase():
diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp
index 94c8a06..f3d65ef 100644
--- a/CPP/7zip/UI/Common/HashCalc.cpp
+++ b/CPP/7zip/UI/Common/HashCalc.cpp
@@ -249,12 +249,12 @@ static void CSum_Name_OriginalToEscape(const AString &src, AString &dest)
249 char c = src[i++]; 249 char c = src[i++];
250 if (c == '\n') 250 if (c == '\n')
251 { 251 {
252 dest += '\\'; 252 dest.Add_Char('\\');
253 c = 'n'; 253 c = 'n';
254 } 254 }
255 else if (c == '\\') 255 else if (c == '\\')
256 dest += '\\'; 256 dest.Add_Char('\\');
257 dest += c; 257 dest.Add_Char(c);
258 } 258 }
259} 259}
260 260
@@ -287,7 +287,7 @@ static bool CSum_Name_EscapeToOriginal(const char *s, AString &dest)
287 isOK = false; 287 isOK = false;
288 } 288 }
289 } 289 }
290 dest += c; 290 dest.Add_Char(c);
291 } 291 }
292 return isOK; 292 return isOK;
293} 293}
@@ -403,7 +403,7 @@ static void WriteLine(CDynLimBuf &hashFileString,
403 } 403 }
404 404
405 if (isDir && !esc.IsEmpty() && esc.Back() != '/') 405 if (isDir && !esc.IsEmpty() && esc.Back() != '/')
406 esc += '/'; 406 esc.Add_Slash();
407 407
408 if (tagMode) 408 if (tagMode)
409 { 409 {
@@ -461,8 +461,8 @@ HRESULT HashCalc(
461 if (options.StdInMode) 461 if (options.StdInMode)
462 { 462 {
463 CDirItem di; 463 CDirItem di;
464 di.Size = (UInt64)(Int64)-1; 464 if (!di.SetAs_StdInFile())
465 di.SetAsFile(); 465 return GetLastError_noZero_HRESULT();
466 dirItems.Items.Add(di); 466 dirItems.Items.Add(di);
467 } 467 }
468 else 468 else
@@ -531,7 +531,19 @@ HRESULT HashCalc(
531 531
532 if (options.StdInMode) 532 if (options.StdInMode)
533 { 533 {
534#if 1
534 inStream = new CStdInFileStream; 535 inStream = new CStdInFileStream;
536#else
537 if (!CreateStdInStream(inStream))
538 {
539 const DWORD lastError = ::GetLastError();
540 const HRESULT res = callback->OpenFileError(FString("stdin"), lastError);
541 hb.NumErrors++;
542 if (res != S_FALSE && res != S_OK)
543 return res;
544 continue;
545 }
546#endif
535 } 547 }
536 else 548 else
537 { 549 {
@@ -561,7 +573,7 @@ HRESULT HashCalc(
561 const FString phyPath = dirItems.GetPhyPath(i); 573 const FString phyPath = dirItems.GetPhyPath(i);
562 if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite)) 574 if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite))
563 { 575 {
564 HRESULT res = callback->OpenFileError(phyPath, ::GetLastError()); 576 const HRESULT res = callback->OpenFileError(phyPath, ::GetLastError());
565 hb.NumErrors++; 577 hb.NumErrors++;
566 if (res != S_FALSE) 578 if (res != S_FALSE)
567 return res; 579 return res;
@@ -645,51 +657,40 @@ HRESULT HashCalc(
645} 657}
646 658
647 659
648static inline char GetHex_Upper(unsigned v) 660void HashHexToString(char *dest, const Byte *data, size_t size)
649{
650 return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10)));
651}
652
653static inline char GetHex_Lower(unsigned v)
654{
655 return (char)((v < 10) ? ('0' + v) : ('a' + (v - 10)));
656}
657
658void HashHexToString(char *dest, const Byte *data, UInt32 size)
659{ 661{
660 dest[size * 2] = 0;
661
662 if (!data) 662 if (!data)
663 { 663 {
664 for (UInt32 i = 0; i < size; i++) 664 for (size_t i = 0; i < size; i++)
665 { 665 {
666 dest[0] = ' '; 666 dest[0] = ' ';
667 dest[1] = ' '; 667 dest[1] = ' ';
668 dest += 2; 668 dest += 2;
669 } 669 }
670 *dest = 0;
670 return; 671 return;
671 } 672 }
672 673
673 if (size <= 8) 674 if (size > 8)
675 ConvertDataToHex_Lower(dest, data, size);
676 else if (size == 0)
674 { 677 {
675 dest += size * 2; 678 *dest = 0;
676 for (UInt32 i = 0; i < size; i++) 679 return;
677 {
678 const unsigned b = data[i];
679 dest -= 2;
680 dest[0] = GetHex_Upper((b >> 4) & 0xF);
681 dest[1] = GetHex_Upper(b & 0xF);
682 }
683 } 680 }
684 else 681 else
685 { 682 {
686 for (UInt32 i = 0; i < size; i++) 683 const char *dest_start = dest;
684 dest += size * 2;
685 *dest = 0;
686 do
687 { 687 {
688 const unsigned b = data[i]; 688 const size_t b = *data++;
689 dest[0] = GetHex_Lower((b >> 4) & 0xF); 689 dest -= 2;
690 dest[1] = GetHex_Lower(b & 0xF); 690 dest[0] = GET_HEX_CHAR_UPPER(b >> 4);
691 dest += 2; 691 dest[1] = GET_HEX_CHAR_UPPER(b & 15);
692 } 692 }
693 while (dest != dest_start);
693 } 694 }
694} 695}
695 696
@@ -720,31 +721,6 @@ void CHasherState::WriteToString(unsigned digestIndex, char *s) const
720 721
721namespace NHash { 722namespace NHash {
722 723
723static size_t ParseHexString(const char *s, Byte *dest) throw()
724{
725 size_t num;
726 for (num = 0;; num++, s += 2)
727 {
728 unsigned c = (Byte)s[0];
729 unsigned v0;
730 if (c >= '0' && c <= '9') v0 = (c - '0');
731 else if (c >= 'A' && c <= 'F') v0 = 10 + (c - 'A');
732 else if (c >= 'a' && c <= 'f') v0 = 10 + (c - 'a');
733 else
734 return num;
735 c = (Byte)s[1];
736 unsigned v1;
737 if (c >= '0' && c <= '9') v1 = (c - '0');
738 else if (c >= 'A' && c <= 'F') v1 = 10 + (c - 'A');
739 else if (c >= 'a' && c <= 'f') v1 = 10 + (c - 'a');
740 else
741 return num;
742 if (dest)
743 dest[num] = (Byte)(v1 | (v0 << 4));
744 }
745}
746
747
748#define IsWhite(c) ((c) == ' ' || (c) == '\t') 724#define IsWhite(c) ((c) == ' ' || (c) == '\t')
749 725
750bool CHashPair::IsDir() const 726bool CHashPair::IsDir() const
@@ -753,7 +729,7 @@ bool CHashPair::IsDir() const
753 return false; 729 return false;
754 // here we expect that Dir items contain only zeros or no Hash 730 // here we expect that Dir items contain only zeros or no Hash
755 for (size_t i = 0; i < Hash.Size(); i++) 731 for (size_t i = 0; i < Hash.Size(); i++)
756 if (Hash[i] != 0) 732 if (Hash.ConstData()[i] != 0)
757 return false; 733 return false;
758 return true; 734 return true;
759} 735}
@@ -854,10 +830,11 @@ bool CHashPair::Parse(const char *s)
854 s++; 830 s++;
855 escape = true; 831 escape = true;
856 } 832 }
833 Escape = escape;
857 834
858 // const char *kMethod = GetMethod_from_FileName(s); 835 // const char *kMethod = GetMethod_from_FileName(s);
859 // if (kMethod) 836 // if (kMethod)
860 if (ParseHexString(s, NULL) < 4) 837 if ((size_t)(FindNonHexChar(s) - s) < 4)
861 { 838 {
862 // BSD-style checksum line 839 // BSD-style checksum line
863 { 840 {
@@ -903,10 +880,10 @@ bool CHashPair::Parse(const char *s)
903 } 880 }
904 881
905 { 882 {
906 const size_t num = ParseHexString(s, NULL); 883 const size_t numChars = (size_t)(FindNonHexChar(s) - s) & ~(size_t)1;
907 Hash.Alloc(num); 884 Hash.Alloc(numChars / 2);
908 ParseHexString(s, Hash); 885 if ((size_t)(ParseHexString(s, Hash) - Hash) != numChars / 2)
909 const size_t numChars = num * 2; 886 throw 101;
910 HashString.SetFrom(s, (unsigned)numChars); 887 HashString.SetFrom(s, (unsigned)numChars);
911 s += numChars; 888 s += numChars;
912 } 889 }
@@ -1091,7 +1068,7 @@ static void Add_OptSpace_String(UString &dest, const char *src)
1091 1068
1092Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 1069Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1093{ 1070{
1094 NWindows::NCOM::CPropVariant prop; 1071 NCOM::CPropVariant prop;
1095 switch (propID) 1072 switch (propID)
1096 { 1073 {
1097 case kpidPhySize: if (_phySize != 0) prop = _phySize; break; 1074 case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
@@ -1125,7 +1102,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1125 Add_OptSpace_String(s, "PGP"); 1102 Add_OptSpace_String(s, "PGP");
1126 if (!_pgpMethod.IsEmpty()) 1103 if (!_pgpMethod.IsEmpty())
1127 { 1104 {
1128 s += ":"; 1105 s.Add_Colon();
1129 s += _pgpMethod; 1106 s += _pgpMethod;
1130 } 1107 }
1131 } 1108 }
@@ -1146,6 +1123,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1146 prop = true; 1123 prop = true;
1147 break; 1124 break;
1148 } 1125 }
1126 default: break;
1149 } 1127 }
1150 prop.Detach(value); 1128 prop.Detach(value);
1151 return S_OK; 1129 return S_OK;
@@ -1155,8 +1133,8 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1155Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) 1133Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
1156{ 1134{
1157 // COM_TRY_BEGIN 1135 // COM_TRY_BEGIN
1158 NWindows::NCOM::CPropVariant prop; 1136 NCOM::CPropVariant prop;
1159 CHashPair &hp = HashPairs[index]; 1137 const CHashPair &hp = HashPairs[index];
1160 switch (propID) 1138 switch (propID)
1161 { 1139 {
1162 case kpidIsDir: 1140 case kpidIsDir:
@@ -1169,9 +1147,17 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1169 UString path; 1147 UString path;
1170 hp.Get_UString_Path(path); 1148 hp.Get_UString_Path(path);
1171 1149
1172 NArchive::NItemName::ReplaceToOsSlashes_Remove_TailSlash(path, 1150 bool useBackslashReplacement = true;
1173 true); // useBackslashReplacement 1151 if (_supportWindowsBackslash && !hp.Escape && path.Find(L"\\\\") < 0)
1174 1152 {
1153#if WCHAR_PATH_SEPARATOR == L'/'
1154 path.Replace(L'\\', L'/');
1155#else
1156 useBackslashReplacement = false;
1157#endif
1158 }
1159 NArchive::NItemName::ReplaceToOsSlashes_Remove_TailSlash(
1160 path, useBackslashReplacement);
1175 prop = path; 1161 prop = path;
1176 break; 1162 break;
1177 } 1163 }
@@ -1195,6 +1181,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1195 prop = hp.Method; 1181 prop = hp.Method;
1196 break; 1182 break;
1197 } 1183 }
1184 default: break;
1198 } 1185 }
1199 prop.Detach(value); 1186 prop.Detach(value);
1200 return S_OK; 1187 return S_OK;
@@ -1248,7 +1235,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
1248 bool cr_lf_Mode = false; 1235 bool cr_lf_Mode = false;
1249 { 1236 {
1250 for (size_t i = 0; i < buf.Size(); i++) 1237 for (size_t i = 0; i < buf.Size(); i++)
1251 if (buf[i] == 0) 1238 if (buf.ConstData()[i] == 0)
1252 { 1239 {
1253 zeroMode = true; 1240 zeroMode = true;
1254 break; 1241 break;
@@ -1510,15 +1497,14 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1510 if (!buf.Alloc(kBufSize)) 1497 if (!buf.Alloc(kBufSize))
1511 return E_OUTOFMEMORY; 1498 return E_OUTOFMEMORY;
1512 1499
1513 CLocalProgress *lps = new CLocalProgress; 1500 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1514 CMyComPtr<ICompressProgressInfo> progress = lps;
1515 lps->Init(extractCallback, false); 1501 lps->Init(extractCallback, false);
1516 lps->InSize = lps->OutSize = 0;
1517 1502
1518 UInt32 i; 1503 for (UInt32 i = 0;; i++)
1519 for (i = 0; i < numItems; i++)
1520 { 1504 {
1521 RINOK(lps->SetCur()) 1505 RINOK(lps->SetCur())
1506 if (i >= numItems)
1507 break;
1522 const UInt32 index = allFilesMode ? i : indices[i]; 1508 const UInt32 index = allFilesMode ? i : indices[i];
1523 1509
1524 CHashPair &hp = HashPairs[index]; 1510 CHashPair &hp = HashPairs[index];
@@ -1549,7 +1535,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1549 Attrib and security of output file */ 1535 Attrib and security of output file */
1550 askMode = NArchive::NExtract::NAskMode::kReadExternal; 1536 askMode = NArchive::NExtract::NAskMode::kReadExternal;
1551 1537
1552 extractCallback->PrepareOperation(askMode); 1538 RINOK(extractCallback->PrepareOperation(askMode))
1553 1539
1554 const bool isAltStream = false; 1540 const bool isAltStream = false;
1555 1541
@@ -1598,7 +1584,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1598 { 1584 {
1599 if ((step & 0xFF) == 0) 1585 if ((step & 0xFF) == 0)
1600 { 1586 {
1601 RINOK(progress->SetRatioInfo(NULL, &fileSize)) 1587 RINOK(lps.Interface()->SetRatioInfo(NULL, &fileSize))
1602 } 1588 }
1603 UInt32 size; 1589 UInt32 size;
1604 RINOK(inStream->Read(buf, kBufSize, &size)) 1590 RINOK(inStream->Read(buf, kBufSize, &size))
@@ -1643,8 +1629,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1643 RINOK(extractCallback->SetOperationResult(opRes)) 1629 RINOK(extractCallback->SetOperationResult(opRes))
1644 } 1630 }
1645 1631
1646 return lps->SetCur(); 1632 return S_OK;
1647
1648 COM_TRY_END 1633 COM_TRY_END
1649} 1634}
1650 1635
@@ -1805,8 +1790,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1805 1790
1806 RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS methods)) 1791 RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS methods))
1807 1792
1808 CLocalProgress *lps = new CLocalProgress; 1793 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1809 CMyComPtr<ICompressProgressInfo> progress = lps;
1810 lps->Init(callback, true); 1794 lps->Init(callback, true);
1811 1795
1812 const UInt32 kBufSize = 1 << 15; 1796 const UInt32 kBufSize = 1 << 15;
@@ -1830,7 +1814,6 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1830 if (options.HashMode_OnlyHash.Val && updateItems.Size() != 1) 1814 if (options.HashMode_OnlyHash.Val && updateItems.Size() != 1)
1831 options.HashMode_OnlyHash.Val = false; 1815 options.HashMode_OnlyHash.Val = false;
1832 1816
1833 lps->OutSize = 0;
1834 complexity = 0; 1817 complexity = 0;
1835 1818
1836 for (i = 0; i < updateItems.Size(); i++) 1819 for (i = 0; i < updateItems.Size(); i++)
@@ -1884,7 +1867,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1884 if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK) 1867 if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK)
1885 { 1868 {
1886 currentComplexity = size2; 1869 currentComplexity = size2;
1887 // item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);; 1870 // item.MTime = NTime::FileTimeToUnixTime64(mTime);;
1888 } 1871 }
1889 } 1872 }
1890 */ 1873 */
@@ -1905,7 +1888,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
1905 { 1888 {
1906 if ((step & 0xFF) == 0) 1889 if ((step & 0xFF) == 0)
1907 { 1890 {
1908 RINOK(progress->SetRatioInfo(&fileSize, NULL)) 1891 RINOK(lps.Interface()->SetRatioInfo(&fileSize, NULL))
1909 // RINOK(callback->SetCompleted(&completeValue)); 1892 // RINOK(callback->SetCompleted(&completeValue));
1910 } 1893 }
1911 UInt32 size; 1894 UInt32 size;
@@ -2027,6 +2010,9 @@ HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
2027 return S_OK; 2010 return S_OK;
2028 } 2011 }
2029 2012
2013 if (name.IsEqualTo("backslash"))
2014 return PROPVARIANT_to_bool(value, _supportWindowsBackslash);
2015
2030 if (name.IsPrefixedBy_Ascii_NoCase("crc")) 2016 if (name.IsPrefixedBy_Ascii_NoCase("crc"))
2031 { 2017 {
2032 name.Delete(0, 3); 2018 name.Delete(0, 3);
diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h
index 0b527c1..1e9dbf4 100644
--- a/CPP/7zip/UI/Common/HashCalc.h
+++ b/CPP/7zip/UI/Common/HashCalc.h
@@ -20,7 +20,7 @@ const unsigned k_HashCalc_NumGroups = 4;
20 if (size <= 8) : upper case : reversed byte order : it shows 32-bit/64-bit number, if data contains little-endian number 20 if (size <= 8) : upper case : reversed byte order : it shows 32-bit/64-bit number, if data contains little-endian number
21 if (size > 8) : lower case : original byte order (as big-endian byte sequence) 21 if (size > 8) : lower case : original byte order (as big-endian byte sequence)
22*/ 22*/
23void HashHexToString(char *dest, const Byte *data, UInt32 size); 23void HashHexToString(char *dest, const Byte *data, size_t size);
24 24
25enum 25enum
26{ 26{
@@ -226,6 +226,7 @@ struct CHashPair
226 CByteBuffer Hash; 226 CByteBuffer Hash;
227 char Mode; 227 char Mode;
228 bool IsBSD; 228 bool IsBSD;
229 bool Escape;
229 bool Size_from_Arc_Defined; 230 bool Size_from_Arc_Defined;
230 bool Size_from_Disk_Defined; 231 bool Size_from_Disk_Defined;
231 AString Method; 232 AString Method;
@@ -259,6 +260,7 @@ struct CHashPair
259 CHashPair(): 260 CHashPair():
260 Mode(0) 261 Mode(0)
261 , IsBSD(false) 262 , IsBSD(false)
263 , Escape(false)
262 , Size_from_Arc_Defined(false) 264 , Size_from_Arc_Defined(false)
263 , Size_from_Disk_Defined(false) 265 , Size_from_Disk_Defined(false)
264 // , HashLengthInBits(0) 266 // , HashLengthInBits(0)
@@ -275,6 +277,8 @@ Z7_CLASS_IMP_CHandler_IInArchive_3(
275 ISetProperties 277 ISetProperties
276) 278)
277 bool _isArc; 279 bool _isArc;
280 bool _supportWindowsBackslash;
281 bool _crcSize_WasSet;
278 UInt64 _phySize; 282 UInt64 _phySize;
279 CObjectVector<CHashPair> HashPairs; 283 CObjectVector<CHashPair> HashPairs;
280 UString _nameExtenstion; 284 UString _nameExtenstion;
@@ -287,29 +291,26 @@ Z7_CLASS_IMP_CHandler_IInArchive_3(
287 bool _are_there_Dirs; 291 bool _are_there_Dirs;
288 bool _hashSize_Defined; 292 bool _hashSize_Defined;
289 unsigned _hashSize; 293 unsigned _hashSize;
290
291 bool _crcSize_WasSet;
292 UInt32 _crcSize; 294 UInt32 _crcSize;
293 UStringVector _methods; 295 UStringVector _methods;
296 CHashOptionsLocal _options;
294 297
295 void ClearVars(); 298 void ClearVars();
296 299
297 void InitProps() 300 void InitProps()
298 { 301 {
302 _supportWindowsBackslash = true;
299 _crcSize_WasSet = false; 303 _crcSize_WasSet = false;
300 _crcSize = 4; 304 _crcSize = 4;
301 _methods.Clear(); 305 _methods.Clear();
302 _options.Init_HashOptionsLocal(); 306 _options.Init_HashOptionsLocal();
303 } 307 }
304 308
305 CHashOptionsLocal _options;
306
307 bool CanUpdate() const 309 bool CanUpdate() const
308 { 310 {
309 if (!_isArc || _is_PgpMethod || _is_CksumMode) 311 if (!_isArc || _is_PgpMethod || _is_CksumMode)
310 return false; 312 return false;
311 return true; 313 return true;
312
313 } 314 }
314 315
315 HRESULT SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value); 316 HRESULT SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value);
diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
index 5a65bdc..6bf53ea 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -263,6 +263,10 @@ static HRESULT GetMethodBoolProp(Func_GetMethodProperty getMethodProperty, UInt3
263#pragma GCC diagnostic ignored "-Wc++98-compat-pedantic" 263#pragma GCC diagnostic ignored "-Wc++98-compat-pedantic"
264#endif 264#endif
265 265
266#ifdef _WIN32
267Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
268#endif
269
266#define MY_GET_FUNC(dest, type, lib, func) \ 270#define MY_GET_FUNC(dest, type, lib, func) \
267 dest = Z7_GET_PROC_ADDRESS(type, lib.Get_HMODULE(), func); 271 dest = Z7_GET_PROC_ADDRESS(type, lib.Get_HMODULE(), func);
268// #define MY_GET_FUNC(dest, type, func) dest = (type)(func); 272// #define MY_GET_FUNC(dest, type, func) dest = (type)(func);
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
index a501b86..c26d4c0 100644
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -350,6 +350,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
350 case kpidMTime: if (item.FileTime_Defined) prop = item.FileTime; break; 350 case kpidMTime: if (item.FileTime_Defined) prop = item.FileTime; break;
351 case kpidComment: if (!item.Comment.IsEmpty()) prop = item.Comment; break; 351 case kpidComment: if (!item.Comment.IsEmpty()) prop = item.Comment; break;
352 case kpidType: if (!item.ArcType.IsEmpty()) prop = item.ArcType; break; 352 case kpidType: if (!item.ArcType.IsEmpty()) prop = item.ArcType; break;
353 default: break;
353 } 354 }
354 prop.Detach(value); 355 prop.Detach(value);
355 return S_OK; 356 return S_OK;
@@ -584,7 +585,7 @@ HRESULT CArc::GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &p
584 { 585 {
585 { 586 {
586 UString &s2 = parts[parts.Size() - 2]; 587 UString &s2 = parts[parts.Size() - 2];
587 s2 += ':'; 588 s2.Add_Colon();
588 s2 += parts.Back(); 589 s2 += parts.Back();
589 } 590 }
590 parts.DeleteBack(); 591 parts.DeleteBack();
@@ -2501,7 +2502,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2501 // printf("\nRead ask = %d", (unsigned)processedSize); 2502 // printf("\nRead ask = %d", (unsigned)processedSize);
2502 UInt64 seekPos = bufPhyPos + bytesInBuf; 2503 UInt64 seekPos = bufPhyPos + bytesInBuf;
2503 RINOK(InStream_SeekSet(op.stream, bufPhyPos + bytesInBuf)) 2504 RINOK(InStream_SeekSet(op.stream, bufPhyPos + bytesInBuf))
2504 RINOK(ReadStream(op.stream, byteBuffer + bytesInBuf, &processedSize)) 2505 RINOK(ReadStream(op.stream, byteBuffer.NonConstData() + bytesInBuf, &processedSize))
2505 // printf(" processed = %d", (unsigned)processedSize); 2506 // printf(" processed = %d", (unsigned)processedSize);
2506 if (processedSize == 0) 2507 if (processedSize == 0)
2507 { 2508 {
@@ -2523,7 +2524,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2523 { 2524 {
2524 size_t keepSize = (size_t)(kBeforeSize - skipSize); 2525 size_t keepSize = (size_t)(kBeforeSize - skipSize);
2525 // printf("\nmemmove skip = %d", (int)keepSize); 2526 // printf("\nmemmove skip = %d", (int)keepSize);
2526 memmove(byteBuffer, byteBuffer + bytesInBuf - keepSize, keepSize); 2527 memmove(byteBuffer, byteBuffer.ConstData() + bytesInBuf - keepSize, keepSize);
2527 bytesInBuf = keepSize; 2528 bytesInBuf = keepSize;
2528 bufPhyPos = pos - keepSize; 2529 bufPhyPos = pos - keepSize;
2529 continue; 2530 continue;
@@ -2539,7 +2540,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2539 { 2540 {
2540 size_t beg = (size_t)posInBuf - kBeforeSize; 2541 size_t beg = (size_t)posInBuf - kBeforeSize;
2541 // printf("\nmemmove for after beg = %d", (int)beg); 2542 // printf("\nmemmove for after beg = %d", (int)beg);
2542 memmove(byteBuffer, byteBuffer + beg, bytesInBuf - beg); 2543 memmove(byteBuffer, byteBuffer.ConstData() + beg, bytesInBuf - beg);
2543 bufPhyPos += beg; 2544 bufPhyPos += beg;
2544 bytesInBuf -= beg; 2545 bytesInBuf -= beg;
2545 continue; 2546 continue;
@@ -2597,14 +2598,14 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2597 2598
2598 scanSize++; 2599 scanSize++;
2599 2600
2600 const Byte *buf = byteBuffer + (size_t)posInBuf; 2601 const Byte *buf = byteBuffer.ConstData() + (size_t)posInBuf;
2601 const Byte *bufLimit = buf + scanSize; 2602 const Byte *bufLimit = buf + scanSize;
2602 size_t ppp = 0; 2603 size_t ppp = 0;
2603 2604
2604 if (!needCheckStartOpen) 2605 if (!needCheckStartOpen)
2605 { 2606 {
2606 for (; buf < bufLimit && hash[HASH_VAL(buf)] == 0xFF; buf++); 2607 for (; buf < bufLimit && hash[HASH_VAL(buf)] == 0xFF; buf++);
2607 ppp = (size_t)(buf - (byteBuffer + (size_t)posInBuf)); 2608 ppp = (size_t)(buf - (byteBuffer.ConstData() + (size_t)posInBuf));
2608 pos += ppp; 2609 pos += ppp;
2609 if (buf == bufLimit) 2610 if (buf == bufLimit)
2610 continue; 2611 continue;
@@ -2685,7 +2686,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
2685 const size_t offsetInBuf = (size_t)(startArcPos - bufPhyPos); 2686 const size_t offsetInBuf = (size_t)(startArcPos - bufPhyPos);
2686 if (offsetInBuf < bytesInBuf) 2687 if (offsetInBuf < bytesInBuf)
2687 { 2688 {
2688 const UInt32 isArcRes = ai.IsArcFunc(byteBuffer + offsetInBuf, bytesInBuf - offsetInBuf); 2689 const UInt32 isArcRes = ai.IsArcFunc(byteBuffer.ConstData() + offsetInBuf, bytesInBuf - offsetInBuf);
2689 if (isArcRes == k_IsArc_Res_NO) 2690 if (isArcRes == k_IsArc_Res_NO)
2690 continue; 2691 continue;
2691 if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile) 2692 if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile)
@@ -3085,7 +3086,12 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op)
3085 3086
3086 if (op.stdInMode) 3087 if (op.stdInMode)
3087 { 3088 {
3089#if 1
3088 seqStream = new CStdInFileStream; 3090 seqStream = new CStdInFileStream;
3091#else
3092 if (!CreateStdInStream(seqStream))
3093 return GetLastError_noZero_HRESULT();
3094#endif
3089 op.seqStream = seqStream; 3095 op.seqStream = seqStream;
3090 } 3096 }
3091 else if (!op.stream) 3097 else if (!op.stream)
@@ -3577,6 +3583,7 @@ static bool ParseTypeParams(const UString &s, COpenType &type)
3577 case 'e': type.EachPos = true; return true; 3583 case 'e': type.EachPos = true; return true;
3578 case 'a': type.CanReturnArc = true; return true; 3584 case 'a': type.CanReturnArc = true; return true;
3579 case 'r': type.Recursive = true; return true; 3585 case 'r': type.Recursive = true; return true;
3586 default: break;
3580 } 3587 }
3581 return false; 3588 return false;
3582 } 3589 }
diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
index ee9ff32..0b1357f 100644
--- a/CPP/7zip/UI/Common/PropIDUtils.cpp
+++ b/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -83,18 +83,26 @@ void ConvertWinAttribToString(char *s, UInt32 wa) throw()
83{ 83{
84 /* 84 /*
85 some programs store posix attributes in high 16 bits. 85 some programs store posix attributes in high 16 bits.
86 p7zip - stores additional 0x8000 flag marker. 86 p7zip - stores additional 0x8000 flag marker.
87 macos - stores additional 0x4000 flag marker. 87 macos - stores additional 0x4000 flag marker.
88 info-zip - no additional marker. 88 info-zip - no additional marker.
89 But this code works with Attrib from internal 7zip code.
90 So we expect that 0x8000 marker is set, if there are posix attributes.
91 (DT_UNKNOWN == 0) type in high bits is possible in some case for linux files.
92 0x8000 flag is possible also in ReFS (Windows)?
89 */ 93 */
90 94
91 const bool isPosix = ((wa & 0xF0000000) != 0); 95 const bool isPosix = (
92 96 (wa & 0x8000) != 0 // FILE_ATTRIBUTE_UNIX_EXTENSION;
97 // && (wa & 0xFFFF0000u) != 0
98 );
99
93 UInt32 posix = 0; 100 UInt32 posix = 0;
94 if (isPosix) 101 if (isPosix)
95 { 102 {
96 posix = wa >> 16; 103 posix = wa >> 16;
97 wa &= (UInt32)0x3FFF; 104 if ((wa & 0xF0000000u) != 0)
105 wa &= (UInt32)0x3FFF;
98 } 106 }
99 107
100 for (unsigned i = 0; i < kNumWinAtrribFlags; i++) 108 for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
@@ -243,6 +251,7 @@ void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID p
243 return; 251 return;
244 } 252 }
245 */ 253 */
254 default: break;
246 } 255 }
247 256
248 ConvertPropVariantToShortString(prop, dest); 257 ConvertPropVariantToShortString(prop, dest);
@@ -262,15 +271,10 @@ void ConvertPropertyToString2(UString &dest, const PROPVARIANT &prop, PROPID pro
262 271
263#ifndef Z7_SFX 272#ifndef Z7_SFX
264 273
265static inline unsigned GetHex(unsigned v)
266{
267 return (v < 10) ? ('0' + v) : ('A' + (v - 10));
268}
269
270static inline void AddHexToString(AString &res, unsigned v) 274static inline void AddHexToString(AString &res, unsigned v)
271{ 275{
272 res += (char)GetHex(v >> 4); 276 res.Add_Char((char)GET_HEX_CHAR_UPPER(v >> 4));
273 res += (char)GetHex(v & 0xF); 277 res.Add_Char((char)GET_HEX_CHAR_UPPER(v & 15));
274} 278}
275 279
276/* 280/*
@@ -379,27 +383,27 @@ static const CServicesToName services_to_name[] =
379 { { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , "TrustedInstaller" } 383 { { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , "TrustedInstaller" }
380}; 384};
381 385
382static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize) 386static void ParseSid(AString &s, const Byte *p, size_t lim /* , unsigned &sidSize */)
383{ 387{
384 sidSize = 0; 388 // sidSize = 0;
385 if (lim < 8) 389 if (lim < 8)
386 { 390 {
387 s += "ERROR"; 391 s += "ERROR";
388 return; 392 return;
389 } 393 }
390 const UInt32 rev = p[0]; 394 if (p[0] != 1) // rev
391 if (rev != 1)
392 { 395 {
393 s += "UNSUPPORTED"; 396 s += "UNSUPPORTED";
394 return; 397 return;
395 } 398 }
396 const UInt32 num = p[1]; 399 const unsigned num = p[1];
397 if (8 + num * 4 > lim) 400 const unsigned sidSize_Loc = 8 + num * 4;
401 if (sidSize_Loc > lim)
398 { 402 {
399 s += "ERROR"; 403 s += "ERROR";
400 return; 404 return;
401 } 405 }
402 sidSize = 8 + num * 4; 406 // sidSize = sidSize_Loc;
403 const UInt32 authority = GetBe32(p + 4); 407 const UInt32 authority = GetBe32(p + 4);
404 408
405 if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1) 409 if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1)
@@ -462,20 +466,20 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
462 } 466 }
463} 467}
464 468
465static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos) 469static void ParseOwner(AString &s, const Byte *p, size_t size, UInt32 pos)
466{ 470{
467 if (pos > size) 471 if (pos > size)
468 { 472 {
469 s += "ERROR"; 473 s += "ERROR";
470 return; 474 return;
471 } 475 }
472 UInt32 sidSize = 0; 476 // unsigned sidSize = 0;
473 ParseSid(s, p + pos, size - pos, sidSize); 477 ParseSid(s, p + pos, size - pos /* , sidSize */);
474} 478}
475 479
476static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset) 480static void ParseAcl(AString &s, const Byte *p, size_t size, const char *strName, UInt32 flags, UInt32 offset)
477{ 481{
478 const UInt32 control = Get16(p + 2); 482 const unsigned control = Get16(p + 2);
479 if ((flags & control) == 0) 483 if ((flags & control) == 0)
480 return; 484 return;
481 const UInt32 pos = Get32(p + offset); 485 const UInt32 pos = Get32(p + offset);
@@ -484,7 +488,7 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName
484 if (pos >= size) 488 if (pos >= size)
485 return; 489 return;
486 p += pos; 490 p += pos;
487 size -= pos; 491 size -= (size_t)pos;
488 if (size < 8) 492 if (size < 8)
489 return; 493 return;
490 if (Get16(p) != 2) // revision 494 if (Get16(p) != 2) // revision
@@ -547,7 +551,7 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName
547#define MY_SE_SELF_RELATIVE (0x8000) 551#define MY_SE_SELF_RELATIVE (0x8000)
548*/ 552*/
549 553
550void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s) 554void ConvertNtSecureToString(const Byte *data, size_t size, AString &s)
551{ 555{
552 s.Empty(); 556 s.Empty();
553 if (size < 20 || size > (1 << 18)) 557 if (size < 20 || size > (1 << 18))
@@ -566,30 +570,29 @@ void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s)
566 ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12); 570 ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12);
567 ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16); 571 ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16);
568 s.Add_Space(); 572 s.Add_Space();
569 s.Add_UInt32(size); 573 s.Add_UInt32((UInt32)size);
570 // s += '\n'; 574 // s.Add_LF();
571 // s += Data_To_Hex(data, size); 575 // s += Data_To_Hex(data, size);
572} 576}
573 577
574#ifdef _WIN32 578#ifdef _WIN32
575 579
576static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) throw() 580static bool CheckSid(const Byte *data, size_t size, UInt32 pos) throw()
577{ 581{
578 if (pos >= size) 582 if (pos >= size)
579 return false; 583 return false;
580 size -= pos; 584 size -= pos;
581 if (size < 8) 585 if (size < 8)
582 return false; 586 return false;
583 const UInt32 rev = data[pos]; 587 if (data[pos] != 1) // rev
584 if (rev != 1)
585 return false; 588 return false;
586 const UInt32 num = data[pos + 1]; 589 const unsigned num = data[pos + 1];
587 return (8 + num * 4 <= size); 590 return (8 + num * 4 <= size);
588} 591}
589 592
590static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) throw() 593static bool CheckAcl(const Byte *p, size_t size, UInt32 flags, size_t offset) throw()
591{ 594{
592 const UInt32 control = Get16(p + 2); 595 const unsigned control = Get16(p + 2);
593 if ((flags & control) == 0) 596 if ((flags & control) == 0)
594 return true; 597 return true;
595 const UInt32 pos = Get32(p + offset); 598 const UInt32 pos = Get32(p + offset);
@@ -599,11 +602,11 @@ static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) th
599 size -= pos; 602 size -= pos;
600 if (size < 8) 603 if (size < 8)
601 return false; 604 return false;
602 const UInt32 aclSize = Get16(p + 2); 605 const unsigned aclSize = Get16(p + 2);
603 return (aclSize <= size); 606 return (aclSize <= size);
604} 607}
605 608
606bool CheckNtSecure(const Byte *data, UInt32 size) throw() 609bool CheckNtSecure(const Byte *data, size_t size) throw()
607{ 610{
608 if (size < 20) 611 if (size < 20)
609 return false; 612 return false;
@@ -653,7 +656,7 @@ static const CSecID2Name k_ReparseTags[] =
653 { 0x80000026, "LX_BLK" } 656 { 0x80000026, "LX_BLK" }
654}; 657};
655 658
656bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) 659bool ConvertNtReparseToString(const Byte *data, size_t size, UString &s)
657{ 660{
658 s.Empty(); 661 s.Empty();
659 NFile::CReparseAttr attr; 662 NFile::CReparseAttr attr;
@@ -681,7 +684,7 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
681 if (attr.MinorError) 684 if (attr.MinorError)
682 s += " : MINOR_ERROR"; 685 s += " : MINOR_ERROR";
683 return true; 686 return true;
684 // s += " "; // for debug 687 // s.Add_Space(); // for debug
685 } 688 }
686 689
687 if (size < 8) 690 if (size < 8)
@@ -713,7 +716,7 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
713 } 716 }
714 } 717 }
715 718
716 s += ":"; 719 s.Add_Colon();
717 s.Add_UInt32(len); 720 s.Add_UInt32(len);
718 721
719 if (len != 0) 722 if (len != 0)
@@ -730,8 +733,8 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
730 break; 733 break;
731 } 734 }
732 const unsigned b = data[i]; 735 const unsigned b = data[i];
733 s += (char)GetHex((b >> 4) & 0xF); 736 s.Add_Char((char)GET_HEX_CHAR_UPPER(b >> 4));
734 s += (char)GetHex(b & 0xF); 737 s.Add_Char((char)GET_HEX_CHAR_UPPER(b & 15));
735 } 738 }
736 } 739 }
737 740
diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h
index 6df1e94..dc22793 100644
--- a/CPP/7zip/UI/Common/PropIDUtils.h
+++ b/CPP/7zip/UI/Common/PropIDUtils.h
@@ -9,9 +9,9 @@
9void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0) throw(); 9void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0) throw();
10void ConvertPropertyToString2(UString &dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0); 10void ConvertPropertyToString2(UString &dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0);
11 11
12bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s); 12bool ConvertNtReparseToString(const Byte *data, size_t size, UString &s);
13void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s); 13void ConvertNtSecureToString(const Byte *data, size_t size, AString &s);
14bool CheckNtSecure(const Byte *data, UInt32 size) throw(); 14bool CheckNtSecure(const Byte *data, size_t size) throw();
15 15
16void ConvertWinAttribToString(char *s, UInt32 wa) throw(); 16void ConvertWinAttribToString(char *s, UInt32 wa) throw();
17 17
diff --git a/CPP/7zip/UI/Common/SetProperties.cpp b/CPP/7zip/UI/Common/SetProperties.cpp
index 5e15d9c..5a05beb 100644
--- a/CPP/7zip/UI/Common/SetProperties.cpp
+++ b/CPP/7zip/UI/Common/SetProperties.cpp
@@ -83,6 +83,6 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &propert
83 for (i = 0; i < realNames.Size(); i++) 83 for (i = 0; i < realNames.Size(); i++)
84 names.Add((const wchar_t *)realNames[i]); 84 names.Add((const wchar_t *)realNames[i]);
85 85
86 return setProperties->SetProperties(&names.Front(), values.values, names.Size()); 86 return setProperties->SetProperties(names.ConstData(), values.values, names.Size());
87 } 87 }
88} 88}
diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
index 27625ae..978630e 100644
--- a/CPP/7zip/UI/Common/Update.cpp
+++ b/CPP/7zip/UI/Common/Update.cpp
@@ -507,7 +507,7 @@ static HRESULT Compress(
507 if (rp.GetNewPath(false, mainName, dest)) 507 if (rp.GetNewPath(false, mainName, dest))
508 { 508 {
509 needRename = true; 509 needRename = true;
510 dest += ':'; 510 dest.Add_Colon();
511 dest += ai.Name.Ptr((unsigned)(colonPos + 1)); 511 dest += ai.Name.Ptr((unsigned)(colonPos + 1));
512 break; 512 break;
513 } 513 }
@@ -704,7 +704,7 @@ static HRESULT Compress(
704 } 704 }
705 else 705 else
706 realPath = us2fs(archivePath.GetFinalPath()); 706 realPath = us2fs(archivePath.GetFinalPath());
707 if (outStreamSpec->Create(realPath, false)) 707 if (outStreamSpec->Create_NEW(realPath))
708 { 708 {
709 tempFiles.Paths.Add(realPath); 709 tempFiles.Paths.Add(realPath);
710 isOK = true; 710 isOK = true;
@@ -763,7 +763,7 @@ static HRESULT Compress(
763 outStreamSpec2 = new COutFileStream; 763 outStreamSpec2 = new COutFileStream;
764 sfxOutStream = outStreamSpec2; 764 sfxOutStream = outStreamSpec2;
765 const FString realPath = us2fs(archivePath.GetFinalPath()); 765 const FString realPath = us2fs(archivePath.GetFinalPath());
766 if (!outStreamSpec2->Create(realPath, false)) 766 if (!outStreamSpec2->Create_NEW(realPath))
767 return errorInfo.SetFromLastError("cannot open file", realPath); 767 return errorInfo.SetFromLastError("cannot open file", realPath);
768 } 768 }
769 769
@@ -856,7 +856,7 @@ static HRESULT Compress(
856 856
857 if (!updateCallbackSpec->AreAllFilesClosed()) 857 if (!updateCallbackSpec->AreAllFilesClosed())
858 { 858 {
859 errorInfo.Message = "There are unclosed input file:"; 859 errorInfo.Message = "There are unclosed input files:";
860 errorInfo.FileNames = updateCallbackSpec->_openFiles_Paths; 860 errorInfo.FileNames = updateCallbackSpec->_openFiles_Paths;
861 return E_FAIL; 861 return E_FAIL;
862 } 862 }
@@ -1331,12 +1331,14 @@ HRESULT UpdateArchive(
1331 if (options.StdInMode) 1331 if (options.StdInMode)
1332 { 1332 {
1333 CDirItem di; 1333 CDirItem di;
1334 di.ClearBase(); 1334 // di.ClearBase();
1335 // di.Size = (UInt64)(Int64)-1;
1336 if (!di.SetAs_StdInFile())
1337 return GetLastError_noZero_HRESULT();
1335 di.Name = options.StdInFileName; 1338 di.Name = options.StdInFileName;
1336 di.Size = (UInt64)(Int64)-1; 1339 // di.Attrib_IsDefined = false;
1337 di.SetAsFile(); 1340 // NTime::GetCurUtc_FiTime(di.MTime);
1338 NTime::GetCurUtc_FiTime(di.MTime); 1341 // di.CTime = di.ATime = di.MTime;
1339 di.CTime = di.ATime = di.MTime;
1340 dirItems.Items.Add(di); 1342 dirItems.Items.Add(di);
1341 } 1343 }
1342 else 1344 else
@@ -1626,6 +1628,8 @@ HRESULT UpdateArchive(
1626 1628
1627 1629
1628 #if defined(_WIN32) && !defined(UNDER_CE) 1630 #if defined(_WIN32) && !defined(UNDER_CE)
1631
1632Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
1629 1633
1630 if (options.EMailMode) 1634 if (options.EMailMode)
1631 { 1635 {
@@ -1695,7 +1699,7 @@ HRESULT UpdateArchive(
1695 Z7_WIN_MapiMessageW m; 1699 Z7_WIN_MapiMessageW m;
1696 memset(&m, 0, sizeof(m)); 1700 memset(&m, 0, sizeof(m));
1697 m.nFileCount = files.Size(); 1701 m.nFileCount = files.Size();
1698 m.lpFiles = &files.Front(); 1702 m.lpFiles = files.NonConstData();
1699 1703
1700 const UString addr (options.EMailAddress); 1704 const UString addr (options.EMailAddress);
1701 Z7_WIN_MapiRecipDescW rec; 1705 Z7_WIN_MapiRecipDescW rec;
@@ -1756,7 +1760,7 @@ HRESULT UpdateArchive(
1756 MapiMessage m; 1760 MapiMessage m;
1757 memset(&m, 0, sizeof(m)); 1761 memset(&m, 0, sizeof(m));
1758 m.nFileCount = files.Size(); 1762 m.nFileCount = files.Size();
1759 m.lpFiles = &files.Front(); 1763 m.lpFiles = files.NonConstData();
1760 1764
1761 const AString addr (GetAnsiString(options.EMailAddress)); 1765 const AString addr (GetAnsiString(options.EMailAddress));
1762 MapiRecipDesc rec; 1766 MapiRecipDesc rec;
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp
index 5e2860d..d3ee639 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -7,19 +7,13 @@
7#ifndef _WIN32 7#ifndef _WIN32
8// #include <grp.h> 8// #include <grp.h>
9// #include <pwd.h> 9// #include <pwd.h>
10/*
11inclusion of <sys/sysmacros.h> by <sys/types.h> is deprecated since glibc 2.25.
12Since glibc 2.3.3, macros have been aliases for three GNU-specific
13functions: gnu_dev_makedev(), gnu_dev_major(), and gnu_dev_minor()
14*/
15// for major()/minor(): 10// for major()/minor():
11#if defined(__APPLE__) || defined(__DragonFly__) || \
12 defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
16#include <sys/types.h> 13#include <sys/types.h>
17#if defined(__FreeBSD__) || defined(BSD) || defined(__APPLE__)
18#else 14#else
19#ifndef major
20#include <sys/sysmacros.h> 15#include <sys/sysmacros.h>
21#endif 16#endif
22#endif
23 17
24#endif // _WIN32 18#endif // _WIN32
25 19
@@ -176,6 +170,7 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *val
176 case kpidATime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->ATime); break; 170 case kpidATime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->ATime); break;
177 case kpidMTime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->MTime); break; 171 case kpidMTime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->MTime); break;
178 case kpidArcFileName: if (!ArcFileName.IsEmpty()) prop = ArcFileName; break; 172 case kpidArcFileName: if (!ArcFileName.IsEmpty()) prop = ArcFileName; break;
173 default: break;
179 } 174 }
180 prop.Detach(value); 175 prop.Detach(value);
181 return S_OK; 176 return S_OK;
@@ -454,6 +449,7 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
454 { 449 {
455 case kpidSize: prop = (UInt64)0; break; 450 case kpidSize: prop = (UInt64)0; break;
456 case kpidIsAnti: prop = true; break; 451 case kpidIsAnti: prop = true; break;
452 default: break;
457 } 453 }
458 } 454 }
459 else if (propID == kpidPath && up.NewNameIndex >= 0) 455 else if (propID == kpidPath && up.NewNameIndex >= 0)
@@ -481,8 +477,8 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
481 case kpidCTime: PropVariant_SetFrom_FiTime(prop, di.CTime); break; 477 case kpidCTime: PropVariant_SetFrom_FiTime(prop, di.CTime); break;
482 case kpidATime: PropVariant_SetFrom_FiTime(prop, di.ATime); break; 478 case kpidATime: PropVariant_SetFrom_FiTime(prop, di.ATime); break;
483 case kpidMTime: PropVariant_SetFrom_FiTime(prop, di.MTime); break; 479 case kpidMTime: PropVariant_SetFrom_FiTime(prop, di.MTime); break;
484 case kpidAttrib: prop = (UInt32)di.GetWinAttrib(); break; 480 case kpidAttrib: /* if (di.Attrib_IsDefined) */ prop = (UInt32)di.GetWinAttrib(); break;
485 case kpidPosixAttrib: prop = (UInt32)di.GetPosixAttrib(); break; 481 case kpidPosixAttrib: /* if (di.Attrib_IsDefined) */ prop = (UInt32)di.GetPosixAttrib(); break;
486 482
487 #if defined(_WIN32) 483 #if defined(_WIN32)
488 case kpidIsAltStream: prop = di.IsAltStream; break; 484 case kpidIsAltStream: prop = di.IsAltStream; break;
@@ -526,6 +522,7 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
526 prop = DirItems->OwnerGroupMap.Strings[(unsigned)di.OwnerGroupIndex]; 522 prop = DirItems->OwnerGroupMap.Strings[(unsigned)di.OwnerGroupIndex];
527 break; 523 break;
528 #endif 524 #endif
525 default: break;
529 } 526 }
530 } 527 }
531 prop.Detach(value); 528 prop.Detach(value);
@@ -594,8 +591,14 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
594 mode != NUpdateNotifyOp::kUpdate) 591 mode != NUpdateNotifyOp::kUpdate)
595 return S_OK; 592 return S_OK;
596 593
594#if 1
597 CStdInFileStream *inStreamSpec = new CStdInFileStream; 595 CStdInFileStream *inStreamSpec = new CStdInFileStream;
598 CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); 596 CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
597#else
598 CMyComPtr<ISequentialInStream> inStreamLoc;
599 if (!CreateStdInStream(inStreamLoc))
600 return GetLastError_noZero_HRESULT();
601#endif
599 *inStream = inStreamLoc.Detach(); 602 *inStream = inStreamLoc.Detach();
600 } 603 }
601 else 604 else
@@ -950,7 +953,7 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu
950 fileName += VolExt; 953 fileName += VolExt;
951 COutFileStream *streamSpec = new COutFileStream; 954 COutFileStream *streamSpec = new COutFileStream;
952 CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); 955 CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
953 if (!streamSpec->Create(fileName, false)) 956 if (!streamSpec->Create_NEW(fileName))
954 return GetLastError_noZero_HRESULT(); 957 return GetLastError_noZero_HRESULT();
955 *volumeStream = streamLoc.Detach(); 958 *volumeStream = streamLoc.Detach();
956 return S_OK; 959 return S_OK;
diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp
index e921dc3..88d2501 100644
--- a/CPP/7zip/UI/Common/UpdateProduce.cpp
+++ b/CPP/7zip/UI/Common/UpdateProduce.cpp
@@ -24,7 +24,7 @@ void UpdateProduce(
24 up2.NewData = up2.NewProps = true; 24 up2.NewData = up2.NewProps = true;
25 up2.UseArcProps = false; 25 up2.UseArcProps = false;
26 26
27 switch (actionSet.StateActions[(unsigned)pair.State]) 27 switch ((int)actionSet.StateActions[(unsigned)pair.State])
28 { 28 {
29 case NPairAction::kIgnore: 29 case NPairAction::kIgnore:
30 if (pair.ArcIndex >= 0 && callback) 30 if (pair.ArcIndex >= 0 && callback)
@@ -61,6 +61,8 @@ void UpdateProduce(
61 up2.IsAnti = true; 61 up2.IsAnti = true;
62 up2.UseArcProps = (pair.ArcIndex >= 0); 62 up2.UseArcProps = (pair.ArcIndex >= 0);
63 break; 63 break;
64
65 default: throw 123; // break; // is unexpected case
64 } 66 }
65 67
66 up2.IsSameTime = ((unsigned)pair.State == NUpdateArchive::NPairState::kSameFiles); 68 up2.IsSameTime = ((unsigned)pair.State == NUpdateArchive::NPairState::kSameFiles);
diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp
index 6c1b9c8..73c56cf 100644
--- a/CPP/7zip/UI/Common/ZipRegistry.cpp
+++ b/CPP/7zip/UI/Common/ZipRegistry.cpp
@@ -98,6 +98,7 @@ static LPCTSTR const kSplitDest = TEXT("SplitDest");
98static LPCTSTR const kElimDup = TEXT("ElimDup"); 98static LPCTSTR const kElimDup = TEXT("ElimDup");
99// static LPCTSTR const kAltStreams = TEXT("AltStreams"); 99// static LPCTSTR const kAltStreams = TEXT("AltStreams");
100static LPCTSTR const kNtSecur = TEXT("Security"); 100static LPCTSTR const kNtSecur = TEXT("Security");
101static LPCTSTR const kMemLimit = TEXT("MemLimit");
101 102
102void CInfo::Save() const 103void CInfo::Save() const
103{ 104{
@@ -128,6 +129,14 @@ void Save_ShowPassword(bool showPassword)
128 key.SetValue(kShowPassword, showPassword); 129 key.SetValue(kShowPassword, showPassword);
129} 130}
130 131
132void Save_LimitGB(UInt32 limit_GB)
133{
134 CS_LOCK
135 CKey key;
136 CreateMainKey(key, kKeyName);
137 Key_Set_UInt32(key, kMemLimit, limit_GB);
138}
139
131void CInfo::Load() 140void CInfo::Load()
132{ 141{
133 PathMode = NPathMode::kCurPaths; 142 PathMode = NPathMode::kCurPaths;
@@ -176,6 +185,19 @@ bool Read_ShowPassword()
176 return showPassword; 185 return showPassword;
177} 186}
178 187
188UInt32 Read_LimitGB()
189{
190 CS_LOCK
191 CKey key;
192 if (OpenMainKey(key, kKeyName) == ERROR_SUCCESS)
193 {
194 UInt32 v;
195 if (key.QueryValue(kMemLimit, v) == ERROR_SUCCESS)
196 return v;
197 }
198 return (UInt32)(Int32)-1;
199}
200
179} 201}
180 202
181namespace NCompression 203namespace NCompression
diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h
index 6bc6977..ce084f4 100644
--- a/CPP/7zip/UI/Common/ZipRegistry.h
+++ b/CPP/7zip/UI/Common/ZipRegistry.h
@@ -43,6 +43,9 @@ namespace NExtract
43 43
44 void Save_ShowPassword(bool showPassword); 44 void Save_ShowPassword(bool showPassword);
45 bool Read_ShowPassword(); 45 bool Read_ShowPassword();
46
47 void Save_LimitGB(UInt32 limit_GB);
48 UInt32 Read_LimitGB();
46} 49}
47 50
48namespace NCompression 51namespace NCompression
diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp
index 26e8c7f..0ca250d 100644
--- a/CPP/7zip/UI/Console/Console.dsp
+++ b/CPP/7zip/UI/Console/Console.dsp
@@ -397,6 +397,10 @@ SOURCE=..\..\..\Common\Common.h
397# End Source File 397# End Source File
398# Begin Source File 398# Begin Source File
399 399
400SOURCE=..\..\..\Common\Common0.h
401# End Source File
402# Begin Source File
403
400SOURCE=..\..\..\Common\ComTry.h 404SOURCE=..\..\..\Common\ComTry.h
401# End Source File 405# End Source File
402# Begin Source File 406# Begin Source File
@@ -869,6 +873,10 @@ SOURCE=..\..\..\..\C\7zTypes.h
869# End Source File 873# End Source File
870# Begin Source File 874# Begin Source File
871 875
876SOURCE=..\..\..\..\C\7zVersion.h
877# End Source File
878# Begin Source File
879
872SOURCE=..\..\..\..\C\7zWindows.h 880SOURCE=..\..\..\..\C\7zWindows.h
873# End Source File 881# End Source File
874# Begin Source File 882# Begin Source File
@@ -904,6 +912,10 @@ SOURCE=..\..\..\..\C\DllSecur.h
904# End Source File 912# End Source File
905# Begin Source File 913# Begin Source File
906 914
915SOURCE=..\..\..\..\C\Precomp.h
916# End Source File
917# Begin Source File
918
907SOURCE=..\..\..\..\C\Sort.c 919SOURCE=..\..\..\..\C\Sort.c
908# SUBTRACT CPP /YX /Yc /Yu 920# SUBTRACT CPP /YX /Yc /Yu
909# End Source File 921# End Source File
diff --git a/CPP/7zip/UI/Console/Console.mak b/CPP/7zip/UI/Console/Console.mak
index 1a47bfa..4effea6 100644
--- a/CPP/7zip/UI/Console/Console.mak
+++ b/CPP/7zip/UI/Console/Console.mak
@@ -1,7 +1,8 @@
1MY_CONSOLE = 1 1MY_CONSOLE = 1
2 2
3!IFNDEF UNDER_CE 3!IFNDEF UNDER_CE
4CFLAGS = $(CFLAGS) -DZ7_LONG_PATH -DZ7_LARGE_PAGES -DZ7_DEVICE_FILE 4CFLAGS = $(CFLAGS) -DZ7_DEVICE_FILE
5# -DZ7_LONG_PATH -DZ7_LARGE_PAGES
5!ENDIF 6!ENDIF
6 7
7CONSOLE_OBJS = \ 8CONSOLE_OBJS = \
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
index dd7a214..66d7123 100644
--- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
@@ -64,7 +64,7 @@ HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError)
64 if (_se) 64 if (_se)
65 { 65 {
66 *_se << endl << kError << NError::MyFormatMessage(systemError) << endl; 66 *_se << endl << kError << NError::MyFormatMessage(systemError) << endl;
67 _se->NormalizePrint_UString(fs2us(path)); 67 _se->NormalizePrint_UString_Path(fs2us(path));
68 *_se << endl << endl; 68 *_se << endl << endl;
69 _se->Flush(); 69 _se->Flush();
70 } 70 }
@@ -102,7 +102,7 @@ void PrintSize_bytes_Smart(AString &s, UInt64 val)
102 temp[0] = c; 102 temp[0] = c;
103 s += " ("; 103 s += " (";
104 Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp); 104 Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp);
105 s += ')'; 105 s.Add_Char(')');
106} 106}
107 107
108static void PrintSize_bytes_Smart_comma(AString &s, UInt64 val) 108static void PrintSize_bytes_Smart_comma(AString &s, UInt64 val)
@@ -265,7 +265,7 @@ static const char * const kTab = " ";
265static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size) 265static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size)
266{ 266{
267 *_so << kTab << "Path: "; 267 *_so << kTab << "Path: ";
268 _so->NormalizePrint_wstr(path); 268 _so->NormalizePrint_wstr_Path(path);
269 *_so << endl; 269 *_so << endl;
270 if (size && *size != (UInt64)(Int64)-1) 270 if (size && *size != (UInt64)(Int64)-1)
271 { 271 {
@@ -358,7 +358,7 @@ Z7_COM7F_IMF(CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int3
358 if (name) 358 if (name)
359 { 359 {
360 _tempU = name; 360 _tempU = name;
361 _so->Normalize_UString(_tempU); 361 _so->Normalize_UString_Path(_tempU);
362 // 21.04 362 // 21.04
363 if (isFolder) 363 if (isFolder)
364 { 364 {
@@ -448,6 +448,7 @@ void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest)
448 case NArchive::NExtract::NOperationResult::kWrongPassword: 448 case NArchive::NExtract::NOperationResult::kWrongPassword:
449 s = kWrongPassword; 449 s = kWrongPassword;
450 break; 450 break;
451 default: break;
451 } 452 }
452 453
453 dest += kError; 454 dest += kError;
@@ -489,7 +490,7 @@ Z7_COM7F_IMF(CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encr
489 if (!_currentName.IsEmpty()) 490 if (!_currentName.IsEmpty())
490 { 491 {
491 *_se << " : "; 492 *_se << " : ";
492 _se->NormalizePrint_UString(_currentName); 493 _se->NormalizePrint_UString_Path(_currentName);
493 } 494 }
494 *_se << endl; 495 *_se << endl;
495 _se->Flush(); 496 _se->Flush();
@@ -531,8 +532,100 @@ Z7_COM7F_IMF(CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password))
531 532
532#endif 533#endif
533 534
535
536#ifndef Z7_SFX
537
538void CExtractCallbackConsole::PrintTo_se_Path_WithTitle(const UString &path, const char *title)
539{
540 *_se << title;
541 _se->NormalizePrint_UString_Path(path);
542 *_se << endl;
543}
544
545void CExtractCallbackConsole::Add_ArchiveName_Error()
546{
547 if (_needWriteArchivePath)
548 {
549 PrintTo_se_Path_WithTitle(_currentArchivePath, "Archive: ");
550 _needWriteArchivePath = false;
551 }
552}
553
554
555Z7_COM7F_IMF(CExtractCallbackConsole::RequestMemoryUse(
556 UInt32 flags, UInt32 /* indexType */, UInt32 /* index */, const wchar_t *path,
557 UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags))
558{
559 if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0
560 && requiredSize <= *allowedSize)
561 {
562#if 0
563 // it's expected, that *answerFlags was set to NRequestMemoryAnswerFlags::k_Allow already,
564 // because it's default answer for (requiredSize <= *allowedSize) case.
565 // optional code:
566 *answerFlags = NRequestMemoryAnswerFlags::k_Allow;
567#endif
568 }
569 else
570 {
571 if ((flags & NRequestMemoryUseFlags::k_NoErrorMessage) == 0)
572 if (_se)
573 {
574 const UInt64 num_GB_allowed = (*allowedSize + ((1u << 30) - 1)) >> 30;
575 const UInt64 num_GB_required = (requiredSize + ((1u << 30) - 1)) >> 30;
576 ClosePercentsAndFlush();
577 Add_ArchiveName_Error();
578 if (path)
579 PrintTo_se_Path_WithTitle(path, "File: ");
580 *_se << "The extraction operation requires big amount memory (RAM):" << endl
581 << " " << num_GB_required << " GB : required memory usage size" << endl
582 << " " << num_GB_allowed << " GB : allowed memory usage limit" << endl
583 << " Use -smemx{size}g switch to set allowed memory usage limit for extraction." << endl;
584 *_se << "ERROR: Memory usage limit was exceeded." << endl;
585 const char *m = NULL;
586 // if (indexType == NArchive::NEventIndexType::kNoIndex)
587 if ((flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected) ||
588 (flags & NRequestMemoryUseFlags::k_Report_SkipArc))
589 m = "Archive unpacking was skipped.";
590/*
591 else if ((flags & NRequestMemoryUseFlags::k_SkipBigFiles_IsExpected) ||
592 (flags & NRequestMemoryUseFlags::k_Report_SkipBigFiles))
593 m = "Extraction for some files will be skipped.";
594 else if ((flags & NRequestMemoryUseFlags::k_SkipBigFile_IsExpected) ||
595 (flags & NRequestMemoryUseFlags::k_Report_SkipBigFile))
596 m = "File extraction was skipped.";
597*/
598 if (m)
599 *_se << m;
600 _se->Flush();
601 }
602
603 if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)
604 {
605 // default answer can be k_Allow, if limit was not forced,
606 // so we change answer to non-allowed here.
607 *answerFlags = NRequestMemoryAnswerFlags::k_Limit_Exceeded;
608 if (flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected)
609 *answerFlags |= NRequestMemoryAnswerFlags::k_SkipArc;
610/*
611 else if (flags & NRequestMemoryUseFlags::k_SkipBigFile_IsExpected)
612 *answerFlags |= NRequestMemoryAnswerFlags::k_SkipBigFile;
613 else if (flags & NRequestMemoryUseFlags::k_SkipBigFiles_IsExpected)
614 *answerFlags |= NRequestMemoryAnswerFlags::k_SkipBigFiles;
615*/
616 }
617 }
618 return CheckBreak2();
619}
620
621#endif
622
623
534HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode) 624HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode)
535{ 625{
626 _currentArchivePath = name;
627 _needWriteArchivePath = true;
628
536 RINOK(CheckBreak2()) 629 RINOK(CheckBreak2())
537 630
538 NumTryArcs++; 631 NumTryArcs++;
@@ -544,7 +637,7 @@ HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode)
544 if (_so) 637 if (_so)
545 { 638 {
546 *_so << endl << (testMode ? kTesting : kExtracting); 639 *_so << endl << (testMode ? kTesting : kExtracting);
547 _so->NormalizePrint_wstr(name); 640 _so->NormalizePrint_wstr_Path(name);
548 *_so << endl; 641 *_so << endl;
549 } 642 }
550 643
@@ -609,7 +702,7 @@ void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, c
609 const CArcErrorInfo &er = arc.ErrorInfo; 702 const CArcErrorInfo &er = arc.ErrorInfo;
610 703
611 *_so << "WARNING:\n"; 704 *_so << "WARNING:\n";
612 _so->NormalizePrint_UString(arc.Path); 705 _so->NormalizePrint_UString_Path(arc.Path);
613 UString s; 706 UString s;
614 if (arc.FormatIndex == er.ErrorFormatIndex) 707 if (arc.FormatIndex == er.ErrorFormatIndex)
615 { 708 {
@@ -630,6 +723,9 @@ HRESULT CExtractCallbackConsole::OpenResult(
630 const CCodecs *codecs, const CArchiveLink &arcLink, 723 const CCodecs *codecs, const CArchiveLink &arcLink,
631 const wchar_t *name, HRESULT result) 724 const wchar_t *name, HRESULT result)
632{ 725{
726 _currentArchivePath = name;
727 _needWriteArchivePath = true;
728
633 ClosePercents(); 729 ClosePercents();
634 730
635 if (NeedPercents()) 731 if (NeedPercents())
@@ -656,7 +752,7 @@ HRESULT CExtractCallbackConsole::OpenResult(
656 *_se << endl; 752 *_se << endl;
657 if (level != 0) 753 if (level != 0)
658 { 754 {
659 _se->NormalizePrint_UString(arc.Path); 755 _se->NormalizePrint_UString_Path(arc.Path);
660 *_se << endl; 756 *_se << endl;
661 } 757 }
662 } 758 }
@@ -693,7 +789,7 @@ HRESULT CExtractCallbackConsole::OpenResult(
693 *_so << endl; 789 *_so << endl;
694 if (level != 0) 790 if (level != 0)
695 { 791 {
696 _so->NormalizePrint_UString(arc.Path); 792 _so->NormalizePrint_UString_Path(arc.Path);
697 *_so << endl; 793 *_so << endl;
698 } 794 }
699 } 795 }
@@ -751,7 +847,7 @@ HRESULT CExtractCallbackConsole::OpenResult(
751 if (_se) 847 if (_se)
752 { 848 {
753 *_se << kError; 849 *_se << kError;
754 _se->NormalizePrint_wstr(name); 850 _se->NormalizePrint_wstr_Path(name);
755 *_se << endl; 851 *_se << endl;
756 const HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink); 852 const HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
757 RINOK(res) 853 RINOK(res)
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
index 478b293..8db80e7 100644
--- a/CPP/7zip/UI/Console/ExtractCallbackConsole.h
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
@@ -87,6 +87,10 @@ class CExtractCallbackConsole Z7_final:
87 #ifndef Z7_NO_CRYPTO 87 #ifndef Z7_NO_CRYPTO
88 public ICryptoGetTextPassword, 88 public ICryptoGetTextPassword,
89 #endif 89 #endif
90 #ifndef Z7_SFX
91 public IArchiveRequestMemoryUseCallback,
92 #endif
93
90 public COpenCallbackConsole, 94 public COpenCallbackConsole,
91 public CMyUnknownImp 95 public CMyUnknownImp
92{ 96{
@@ -96,6 +100,10 @@ class CExtractCallbackConsole Z7_final:
96 #ifndef Z7_NO_CRYPTO 100 #ifndef Z7_NO_CRYPTO
97 Z7_COM_QI_ENTRY(ICryptoGetTextPassword) 101 Z7_COM_QI_ENTRY(ICryptoGetTextPassword)
98 #endif 102 #endif
103 #ifndef Z7_SFX
104 Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback)
105 #endif
106
99 Z7_COM_QI_END 107 Z7_COM_QI_END
100 Z7_COM_ADDREF_RELEASE 108 Z7_COM_ADDREF_RELEASE
101 109
@@ -107,13 +115,29 @@ class CExtractCallbackConsole Z7_final:
107 #ifndef Z7_NO_CRYPTO 115 #ifndef Z7_NO_CRYPTO
108 Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) 116 Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
109 #endif 117 #endif
110 118 #ifndef Z7_SFX
119 Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback)
120 #endif
121
122 bool _needWriteArchivePath;
123
124public:
125 bool ThereIsError_in_Current;
126 bool ThereIsWarning_in_Current;
127 bool NeedFlush;
111 128
129private:
112 AString _tempA; 130 AString _tempA;
113 UString _tempU; 131 UString _tempU;
114 132
133 UString _currentArchivePath;
115 UString _currentName; 134 UString _currentName;
116 135
136#ifndef Z7_SFX
137 void PrintTo_se_Path_WithTitle(const UString &path, const char *title);
138 void Add_ArchiveName_Error();
139#endif
140
117 void ClosePercents_for_so() 141 void ClosePercents_for_so()
118 { 142 {
119 if (NeedPercents() && _so == _percent._so) 143 if (NeedPercents() && _so == _percent._so)
@@ -130,9 +154,6 @@ class CExtractCallbackConsole Z7_final:
130public: 154public:
131 UInt64 NumTryArcs; 155 UInt64 NumTryArcs;
132 156
133 bool ThereIsError_in_Current;
134 bool ThereIsWarning_in_Current;
135
136 UInt64 NumOkArcs; 157 UInt64 NumOkArcs;
137 UInt64 NumCantOpenArcs; 158 UInt64 NumCantOpenArcs;
138 UInt64 NumArcsWithError; 159 UInt64 NumArcsWithError;
@@ -144,11 +165,11 @@ public:
144 UInt64 NumFileErrors; 165 UInt64 NumFileErrors;
145 UInt64 NumFileErrors_in_Current; 166 UInt64 NumFileErrors_in_Current;
146 167
147 bool NeedFlush;
148 unsigned PercentsNameLevel; 168 unsigned PercentsNameLevel;
149 unsigned LogLevel; 169 unsigned LogLevel;
150 170
151 CExtractCallbackConsole(): 171 CExtractCallbackConsole():
172 _needWriteArchivePath(true),
152 NeedFlush(false), 173 NeedFlush(false),
153 PercentsNameLevel(1), 174 PercentsNameLevel(1),
154 LogLevel(0) 175 LogLevel(0)
diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp
index c0e69e2..078a625 100644
--- a/CPP/7zip/UI/Console/HashCon.cpp
+++ b/CPP/7zip/UI/Console/HashCon.cpp
@@ -314,7 +314,7 @@ HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBun
314 else 314 else
315 { 315 {
316 UString temp (_fileName); 316 UString temp (_fileName);
317 _so->Normalize_UString(temp); 317 _so->Normalize_UString_Path(temp);
318 _so->Convert_UString_to_AString(temp, s); 318 _so->Convert_UString_to_AString(temp, s);
319 } 319 }
320 PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash, s); 320 PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash, s);
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
index 46819f1..3f33dac 100644
--- a/CPP/7zip/UI/Console/List.cpp
+++ b/CPP/7zip/UI/Console/List.cpp
@@ -240,11 +240,13 @@ static void PrintUString(EAdjustment adj, unsigned width, const UString &s, AStr
240 { 240 {
241 numSpaces = width - s.Len(); 241 numSpaces = width - s.Len();
242 unsigned numLeftSpaces = 0; 242 unsigned numLeftSpaces = 0;
243 switch (adj) 243 switch ((int)adj)
244 { 244 {
245 case kLeft: numLeftSpaces = 0; break; 245 // case kLeft: numLeftSpaces = 0; break;
246 case kCenter: numLeftSpaces = numSpaces / 2; break; 246 case kCenter: numLeftSpaces = numSpaces / 2; break;
247 case kRight: numLeftSpaces = numSpaces; break; 247 case kRight: numLeftSpaces = numSpaces; break;
248 // case kLeft:
249 default: break;
248 } 250 }
249 PrintSpaces(numLeftSpaces); 251 PrintSpaces(numLeftSpaces);
250 numSpaces -= numLeftSpaces; 252 numSpaces -= numLeftSpaces;
@@ -263,11 +265,13 @@ static void PrintString(EAdjustment adj, unsigned width, const char *s)
263 { 265 {
264 numSpaces = width - len; 266 numSpaces = width - len;
265 unsigned numLeftSpaces = 0; 267 unsigned numLeftSpaces = 0;
266 switch (adj) 268 switch ((int)adj)
267 { 269 {
268 case kLeft: numLeftSpaces = 0; break; 270 // case kLeft: numLeftSpaces = 0; break;
269 case kCenter: numLeftSpaces = numSpaces / 2; break; 271 case kCenter: numLeftSpaces = numSpaces / 2; break;
270 case kRight: numLeftSpaces = numSpaces; break; 272 case kRight: numLeftSpaces = numSpaces; break;
273 // case kLeft:
274 default: break;
271 } 275 }
272 PrintSpaces(numLeftSpaces); 276 PrintSpaces(numLeftSpaces);
273 numSpaces -= numLeftSpaces; 277 numSpaces -= numLeftSpaces;
@@ -286,11 +290,13 @@ static void PrintStringToString(char *dest, EAdjustment adj, unsigned width, con
286 { 290 {
287 numSpaces = width - len; 291 numSpaces = width - len;
288 unsigned numLeftSpaces = 0; 292 unsigned numLeftSpaces = 0;
289 switch (adj) 293 switch ((int)adj)
290 { 294 {
291 case kLeft: numLeftSpaces = 0; break; 295 // case kLeft: numLeftSpaces = 0; break;
292 case kCenter: numLeftSpaces = numSpaces / 2; break; 296 case kCenter: numLeftSpaces = numSpaces / 2; break;
293 case kRight: numLeftSpaces = numSpaces; break; 297 case kRight: numLeftSpaces = numSpaces; break;
298 // case kLeft:
299 default: break;
294 } 300 }
295 PrintSpacesToString(dest, numLeftSpaces); 301 PrintSpacesToString(dest, numLeftSpaces);
296 dest += numLeftSpaces; 302 dest += numLeftSpaces;
@@ -443,10 +449,10 @@ void CFieldPrinter::AddProp(const wchar_t *name, PROPID propID, bool isRawProp)
443 unsigned i; 449 unsigned i;
444 for (i = 0; i < s.Len(); i++) 450 for (i = 0; i < s.Len(); i++)
445 { 451 {
446 wchar_t c = s[i]; 452 const wchar_t c = s[i];
447 if (c >= 0x80) 453 if (c >= 0x80)
448 break; 454 break;
449 sA += (char)c; 455 sA.Add_Char((char)c);
450 } 456 }
451 if (i == s.Len()) 457 if (i == s.Len())
452 f.NameA = sA; 458 f.NameA = sA;
@@ -504,7 +510,8 @@ static void PrintTime(char *dest, const CListFileTimeDef &t, bool showNS)
504 if (t.IsZero()) 510 if (t.IsZero())
505 return; 511 return;
506 int prec = kTimestampPrintLevel_SEC; 512 int prec = kTimestampPrintLevel_SEC;
507 if (showNS) 513 unsigned flags = 0;
514 if (showNS) // techmode
508 { 515 {
509 prec = kTimestampPrintLevel_NTFS; 516 prec = kTimestampPrintLevel_NTFS;
510 if (t.Prec != 0) 517 if (t.Prec != 0)
@@ -514,33 +521,30 @@ static void PrintTime(char *dest, const CListFileTimeDef &t, bool showNS)
514 prec = kTimestampPrintLevel_NTFS; 521 prec = kTimestampPrintLevel_NTFS;
515 } 522 }
516 } 523 }
524 else
525 {
526 // we want same default number of characters, so we disable 'Z' marker:
527 flags = kTimestampPrintFlags_DisableZ;
528 }
517 529
518 ConvertUtcFileTimeToString2(t.FT, t.Ns100, dest, prec); 530 ConvertUtcFileTimeToString2(t.FT, t.Ns100, dest, prec, flags);
519} 531}
520 532
521#ifndef Z7_SFX 533#ifndef Z7_SFX
522 534
523static inline char GetHex(Byte value)
524{
525 return (char)((value < 10) ? ('0' + value) : ('a' + (value - 10)));
526}
527
528static void HexToString(char *dest, const Byte *data, UInt32 size)
529{
530 for (UInt32 i = 0; i < size; i++)
531 {
532 Byte b = data[i];
533 dest[0] = GetHex((Byte)((b >> 4) & 0xF));
534 dest[1] = GetHex((Byte)(b & 0xF));
535 dest += 2;
536 }
537 *dest = 0;
538}
539
540#endif 535#endif
541 536
542#define MY_ENDL endl 537#define MY_ENDL endl
543 538
539inline bool IsPropId_for_PathString(UInt32 propId)
540{
541 return (propId == kpidPath
542 // || propId == kpidName
543 || propId == kpidSymLink
544 || propId == kpidHardLink
545 || propId == kpidCopyLink);
546}
547
544HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st) 548HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)
545{ 549{
546 char temp[128]; 550 char temp[128];
@@ -577,7 +581,7 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)
577 { 581 {
578 if (!techMode) 582 if (!techMode)
579 g_StdOut << temp; 583 g_StdOut << temp;
580 g_StdOut.NormalizePrint_UString(FilePath, TempWString, TempAString); 584 g_StdOut.NormalizePrint_UString_Path(FilePath, TempWString, TempAString);
581 if (techMode) 585 if (techMode)
582 g_StdOut << MY_ENDL; 586 g_StdOut << MY_ENDL;
583 continue; 587 continue;
@@ -633,7 +637,7 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)
633 else 637 else
634 { 638 {
635 char hexStr[kMaxDataSize * 2 + 4]; 639 char hexStr[kMaxDataSize * 2 + 4];
636 HexToString(hexStr, (const Byte *)data, dataSize); 640 ConvertDataToHex_Lower(hexStr, (const Byte *)data, dataSize);
637 g_StdOut << hexStr; 641 g_StdOut << hexStr;
638 } 642 }
639 } 643 }
@@ -697,11 +701,12 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)
697 { 701 {
698 TempWString.SetFromBstr(prop.bstrVal); 702 TempWString.SetFromBstr(prop.bstrVal);
699 // do we need multi-line support here ? 703 // do we need multi-line support here ?
700 g_StdOut.Normalize_UString(TempWString); 704 if (IsPropId_for_PathString(f.PropID))
705 g_StdOut.Normalize_UString_Path(TempWString);
706 else
707 g_StdOut.Normalize_UString(TempWString);
701 if (techMode) 708 if (techMode)
702 {
703 g_StdOut.PrintUString(TempWString, TempAString); 709 g_StdOut.PrintUString(TempWString, TempAString);
704 }
705 else 710 else
706 PrintUString(f.TextAdjustment, width, TempWString, TempAString); 711 PrintUString(f.TextAdjustment, width, TempWString, TempAString);
707 } 712 }
@@ -857,10 +862,9 @@ static void UString_Replace_CRLF_to_LF(UString &s)
857 } 862 }
858 *dest++ = c; 863 *dest++ = c;
859 } 864 }
860 s.ReleaseBuf_SetEnd((unsigned)(dest - s.GetBuf())); 865 s.ReleaseBuf_SetEnd((unsigned)(size_t)(dest - s.GetBuf()));
861} 866}
862 867
863
864static void PrintPropVal_MultiLine(CStdOutStream &so, const wchar_t *val) 868static void PrintPropVal_MultiLine(CStdOutStream &so, const wchar_t *val)
865{ 869{
866 UString s (val); 870 UString s (val);
@@ -870,21 +874,34 @@ static void PrintPropVal_MultiLine(CStdOutStream &so, const wchar_t *val)
870 so << "{"; 874 so << "{";
871 so << endl; 875 so << endl;
872 UString_Replace_CRLF_to_LF(s); 876 UString_Replace_CRLF_to_LF(s);
873 so.Normalize_UString_LF_Allowed(s); 877 UString temp;
874 so << s; 878 unsigned start = 0;
875 so << endl; 879 for (;;)
880 {
881 unsigned size = s.Len() - start;
882 if (size == 0)
883 break;
884 const int next = s.Find(L'\n', start);
885 if (next >= 0)
886 size = (unsigned)next - start;
887 temp.SetFrom(s.Ptr() + start, size);
888 so.NormalizePrint_UString(temp);
889 so << endl;
890 if (next < 0)
891 break;
892 start = (unsigned)next + 1;
893 }
876 so << "}"; 894 so << "}";
877 } 895 }
878 else 896 else
879 { 897 {
880 so.Normalize_UString(s); 898 so.NormalizePrint_UString(s);
881 so << s;
882 } 899 }
883 so << endl; 900 so << endl;
884} 901}
885 902
886 903
887static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val, bool multiLine) 904static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val, bool multiLine, bool isPath = false)
888{ 905{
889 so << name << " = "; 906 so << name << " = ";
890 if (multiLine) 907 if (multiLine)
@@ -893,12 +910,22 @@ static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *va
893 return; 910 return;
894 } 911 }
895 UString s (val); 912 UString s (val);
896 so.Normalize_UString(s); 913 if (isPath)
914 so.Normalize_UString_Path(s);
915 else
916 so.Normalize_UString(s);
897 so << s; 917 so << s;
898 so << endl; 918 so << endl;
899} 919}
900 920
901 921
922static void PrintPropPair_Path(CStdOutStream &so, const wchar_t *path)
923{
924 PrintPropPair(so, "Path", path,
925 false, // multiLine
926 true); // isPath
927}
928
902static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop) 929static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop)
903{ 930{
904 UString s; 931 UString s;
@@ -959,7 +986,7 @@ HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const
959 const CArcErrorInfo &er = arc.ErrorInfo; 986 const CArcErrorInfo &er = arc.ErrorInfo;
960 987
961 so << "--\n"; 988 so << "--\n";
962 PrintPropPair(so, "Path", arc.Path, false); 989 PrintPropPair_Path(so, arc.Path);
963 if (er.ErrorFormatIndex >= 0) 990 if (er.ErrorFormatIndex >= 0)
964 { 991 {
965 if (er.ErrorFormatIndex == arc.FormatIndex) 992 if (er.ErrorFormatIndex == arc.FormatIndex)
@@ -1026,7 +1053,7 @@ HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const
1026 { 1053 {
1027 if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) 1054 if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
1028 { 1055 {
1029 so.NormalizePrint_UString(arcLink.NonOpen_ArcPath); 1056 so.NormalizePrint_UString_Path(arcLink.NonOpen_ArcPath);
1030 so << endl; 1057 so << endl;
1031 PrintArcTypeError(so, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); 1058 PrintArcTypeError(so, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);
1032 } 1059 }
@@ -1103,7 +1130,7 @@ HRESULT ListArchives(
1103 if (g_ErrStream) 1130 if (g_ErrStream)
1104 { 1131 {
1105 *g_ErrStream << endl << kError << NError::MyFormatMessage(errorCode) << endl; 1132 *g_ErrStream << endl << kError << NError::MyFormatMessage(errorCode) << endl;
1106 g_ErrStream->NormalizePrint_UString(arcPath); 1133 g_ErrStream->NormalizePrint_UString_Path(arcPath);
1107 *g_ErrStream << endl << endl; 1134 *g_ErrStream << endl << endl;
1108 } 1135 }
1109 numErrors++; 1136 numErrors++;
@@ -1115,7 +1142,7 @@ HRESULT ListArchives(
1115 if (g_ErrStream) 1142 if (g_ErrStream)
1116 { 1143 {
1117 *g_ErrStream << endl << kError; 1144 *g_ErrStream << endl << kError;
1118 g_ErrStream->NormalizePrint_UString(arcPath); 1145 g_ErrStream->NormalizePrint_UString_Path(arcPath);
1119 *g_ErrStream << " is not a file" << endl << endl; 1146 *g_ErrStream << " is not a file" << endl << endl;
1120 } 1147 }
1121 numErrors++; 1148 numErrors++;
@@ -1157,7 +1184,7 @@ HRESULT ListArchives(
1157 if (enableHeaders) 1184 if (enableHeaders)
1158 { 1185 {
1159 g_StdOut << endl << kListing; 1186 g_StdOut << endl << kListing;
1160 g_StdOut.NormalizePrint_UString(arcPath); 1187 g_StdOut.NormalizePrint_UString_Path(arcPath);
1161 g_StdOut << endl << endl; 1188 g_StdOut << endl << endl;
1162 } 1189 }
1163 1190
@@ -1173,7 +1200,7 @@ HRESULT ListArchives(
1173 if (g_ErrStream) 1200 if (g_ErrStream)
1174 { 1201 {
1175 *g_ErrStream << endl << kError; 1202 *g_ErrStream << endl << kError;
1176 g_ErrStream->NormalizePrint_UString(arcPath); 1203 g_ErrStream->NormalizePrint_UString_Path(arcPath);
1177 *g_ErrStream << " : "; 1204 *g_ErrStream << " : ";
1178 if (result == S_FALSE) 1205 if (result == S_FALSE)
1179 { 1206 {
@@ -1361,7 +1388,7 @@ HRESULT ListArchives(
1361 if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) 1388 if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
1362 { 1389 {
1363 g_StdOut << "----------\n"; 1390 g_StdOut << "----------\n";
1364 PrintPropPair(g_StdOut, "Path", arcLink.NonOpen_ArcPath, false); 1391 PrintPropPair_Path(g_StdOut, arcLink.NonOpen_ArcPath);
1365 PrintArcTypeError(g_StdOut, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); 1392 PrintArcTypeError(g_StdOut, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);
1366 } 1393 }
1367 } 1394 }
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
index eb9e2a8..854e110 100644
--- a/CPP/7zip/UI/Console/Main.cpp
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -16,7 +16,7 @@
16 16
17#else // Z7_OLD_WIN_SDK 17#else // Z7_OLD_WIN_SDK
18 18
19typedef struct _PROCESS_MEMORY_COUNTERS { 19typedef struct {
20 DWORD cb; 20 DWORD cb;
21 DWORD PageFaultCount; 21 DWORD PageFaultCount;
22 SIZE_T PeakWorkingSetSize; 22 SIZE_T PeakWorkingSetSize;
@@ -114,7 +114,7 @@ DECLARE_AND_SET_CLIENT_VERSION_VAR
114#elif defined(Z7_PROG_VARIANT_R) 114#elif defined(Z7_PROG_VARIANT_R)
115 #define PROG_POSTFIX "r" 115 #define PROG_POSTFIX "r"
116 #define PROG_POSTFIX_2 " (r)" 116 #define PROG_POSTFIX_2 " (r)"
117#elif !defined(Z7_EXTERNAL_CODECS) 117#elif defined(Z7_PROG_VARIANT_A) || !defined(Z7_EXTERNAL_CODECS)
118 #define PROG_POSTFIX "a" 118 #define PROG_POSTFIX "a"
119 #define PROG_POSTFIX_2 " (a)" 119 #define PROG_POSTFIX_2 " (a)"
120#else 120#else
@@ -148,15 +148,15 @@ static const char * const kHelpString =
148 "\n" 148 "\n"
149 "<Switches>\n" 149 "<Switches>\n"
150 " -- : Stop switches and @listfile parsing\n" 150 " -- : Stop switches and @listfile parsing\n"
151 " -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n" 151 " -ai[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : Include archives\n"
152 " -ax[r[-|0]]{@listfile|!wildcard} : eXclude archives\n" 152 " -ax[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : eXclude archives\n"
153 " -ao{a|s|t|u} : set Overwrite mode\n" 153 " -ao{a|s|t|u} : set Overwrite mode\n"
154 " -an : disable archive_name field\n" 154 " -an : disable archive_name field\n"
155 " -bb[0-3] : set output log level\n" 155 " -bb[0-3] : set output log level\n"
156 " -bd : disable progress indicator\n" 156 " -bd : disable progress indicator\n"
157 " -bs{o|e|p}{0|1|2} : set output stream for output/error/progress line\n" 157 " -bs{o|e|p}{0|1|2} : set output stream for output/error/progress line\n"
158 " -bt : show execution time statistics\n" 158 " -bt : show execution time statistics\n"
159 " -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n" 159 " -i[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : Include filenames\n"
160 " -m{Parameters} : set compression Method\n" 160 " -m{Parameters} : set compression Method\n"
161 " -mmt[N] : set number of CPU threads\n" 161 " -mmt[N] : set number of CPU threads\n"
162 " -mx[N] : set compression level: -mx1 (fastest) ... -mx9 (ultra)\n" 162 " -mx[N] : set compression level: -mx1 (fastest) ... -mx9 (ultra)\n"
@@ -168,7 +168,14 @@ static const char * const kHelpString =
168 " -sa{a|e|s} : set Archive name mode\n" 168 " -sa{a|e|s} : set Archive name mode\n"
169 " -scc{UTF-8|WIN|DOS} : set charset for console input/output\n" 169 " -scc{UTF-8|WIN|DOS} : set charset for console input/output\n"
170 " -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n" 170 " -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n"
171 " -scrc[CRC32|CRC64|SHA1|SHA256|*] : set hash function for x, e, h commands\n" 171 " -scrc[CRC32|CRC64|SHA256"
172#ifndef Z7_PROG_VARIANT_R
173 "|SHA1|XXH64"
174#ifdef Z7_PROG_VARIANT_Z
175 "|BLAKE2SP"
176#endif
177#endif
178 "|*] : set hash function for x, e, h commands\n"
172 " -sdel : delete files after compression\n" 179 " -sdel : delete files after compression\n"
173 " -seml[.] : send archive by email\n" 180 " -seml[.] : send archive by email\n"
174 " -sfx[{name}] : Create SFX archive\n" 181 " -sfx[{name}] : Create SFX archive\n"
@@ -194,7 +201,7 @@ static const char * const kHelpString =
194 " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n" 201 " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n"
195 " -v{Size}[b|k|m|g] : Create volumes\n" 202 " -v{Size}[b|k|m|g] : Create volumes\n"
196 " -w[{path}] : assign Work directory. Empty path means a temporary directory\n" 203 " -w[{path}] : assign Work directory. Empty path means a temporary directory\n"
197 " -x[r[-|0]]{@listfile|!wildcard} : eXclude filenames\n" 204 " -x[r[-|0]][m[-|2]][w[-]]{@listfile|!wildcard} : eXclude filenames\n"
198 " -y : assume Yes on all queries\n"; 205 " -y : assume Yes on all queries\n";
199 206
200// --------------------------- 207// ---------------------------
@@ -206,7 +213,9 @@ static const char * const kNoFormats = "7-Zip cannot find the code that works wi
206static const char * const kUnsupportedArcTypeMessage = "Unsupported archive type"; 213static const char * const kUnsupportedArcTypeMessage = "Unsupported archive type";
207// static const char * const kUnsupportedUpdateArcType = "Can't create archive for that type"; 214// static const char * const kUnsupportedUpdateArcType = "Can't create archive for that type";
208 215
216#ifndef Z7_EXTRACT_ONLY
209#define kDefaultSfxModule "7zCon.sfx" 217#define kDefaultSfxModule "7zCon.sfx"
218#endif
210 219
211Z7_ATTR_NORETURN 220Z7_ATTR_NORETURN
212static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code) 221static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code)
@@ -244,10 +253,50 @@ static void ShowProgInfo(CStdOutStream *so)
244 253
245 #ifdef __ARM_ARCH 254 #ifdef __ARM_ARCH
246 << " arm_v:" << __ARM_ARCH 255 << " arm_v:" << __ARM_ARCH
256 #if (__ARM_ARCH == 8)
257 // for macos:
258 #if defined(__ARM_ARCH_8_9__)
259 << ".9"
260 #elif defined(__ARM_ARCH_8_8__)
261 << ".8"
262 #elif defined(__ARM_ARCH_8_7__)
263 << ".7"
264 #elif defined(__ARM_ARCH_8_6__)
265 << ".6"
266 #elif defined(__ARM_ARCH_8_5__)
267 << ".5"
268 #elif defined(__ARM_ARCH_8_4__)
269 << ".4"
270 #elif defined(__ARM_ARCH_8_3__)
271 << ".3"
272 #elif defined(__ARM_ARCH_8_2__)
273 << ".2"
274 #elif defined(__ARM_ARCH_8_1__)
275 << ".1"
276 #endif
277 #endif
278
279 #if defined(__ARM_ARCH_PROFILE) && \
280 ( __ARM_ARCH_PROFILE >= 'A' && __ARM_ARCH_PROFILE <= 'Z' \
281 || __ARM_ARCH_PROFILE >= 65 && __ARM_ARCH_PROFILE <= 65 + 25)
282 << "-" << (char)__ARM_ARCH_PROFILE
283 #endif
284
247 #ifdef __ARM_ARCH_ISA_THUMB 285 #ifdef __ARM_ARCH_ISA_THUMB
248 << " thumb:" << __ARM_ARCH_ISA_THUMB 286 << " thumb:" << __ARM_ARCH_ISA_THUMB
249 #endif 287 #endif
250 #endif 288 #endif
289
290 #ifdef _MIPS_ARCH
291 << " mips_arch:" << _MIPS_ARCH
292 #endif
293 #ifdef __mips_isa_rev
294 << " mips_isa_rev:" << __mips_isa_rev
295 #endif
296
297 #ifdef __iset__
298 << " e2k_v:" << __iset__
299 #endif
251 ; 300 ;
252 301
253 302
@@ -380,16 +429,11 @@ static void PrintString(CStdOutStream &so, const UString &s, unsigned size)
380 so << ' '; 429 so << ' ';
381} 430}
382 431
383static inline char GetHex(unsigned val)
384{
385 return (char)((val < 10) ? ('0' + val) : ('A' + (val - 10)));
386}
387
388static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so) 432static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so)
389{ 433{
390 FOR_VECTOR(i, pc.Paths) 434 FOR_VECTOR(i, pc.Paths)
391 { 435 {
392 so.NormalizePrint_UString(fs2us(pc.Paths[i])); 436 so.NormalizePrint_UString_Path(fs2us(pc.Paths[i]));
393 so << " : "; 437 so << " : ";
394 so << NError::MyFormatMessage(pc.Codes[i]) << endl; 438 so << NError::MyFormatMessage(pc.Codes[i]) << endl;
395 } 439 }
@@ -570,6 +614,8 @@ static void PrintStat()
570 614
571 #ifndef UNDER_CE 615 #ifndef UNDER_CE
572 616
617Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
618
573 PROCESS_MEMORY_COUNTERS m; 619 PROCESS_MEMORY_COUNTERS m;
574 memset(&m, 0, sizeof(m)); 620 memset(&m, 0, sizeof(m));
575 BOOL memDefined = FALSE; 621 BOOL memDefined = FALSE;
@@ -811,11 +857,11 @@ int Main2(
811 for (int i = 0; i < numArgs; i++) 857 for (int i = 0; i < numArgs; i++)
812 { 858 {
813 AString a (args[i]); 859 AString a (args[i]);
814 /* 860#if 0
815 printf("\n%d %s :", i, a.Ptr()); 861 printf("\n%d %s :", i, a.Ptr());
816 for (unsigned k = 0; k < a.Len(); k++) 862 for (unsigned k = 0; k < a.Len(); k++)
817 printf(" %2x", (unsigned)(Byte)a[k]); 863 printf(" %2x", (unsigned)(Byte)a[k]);
818 */ 864#endif
819 const UString s = MultiByteToUnicodeString(a); 865 const UString s = MultiByteToUnicodeString(a);
820 commandStrings.Add(s); 866 commandStrings.Add(s);
821 } 867 }
@@ -907,6 +953,8 @@ int Main2(
907 if (stderr_cp != -1) g_StdErr.CodePage = stderr_cp; 953 if (stderr_cp != -1) g_StdErr.CodePage = stderr_cp;
908 if (stdin_cp != -1) g_StdIn.CodePage = stdin_cp; 954 if (stdin_cp != -1) g_StdIn.CodePage = stdin_cp;
909 } 955 }
956 g_StdOut.ListPathSeparatorSlash = options.ListPathSeparatorSlash;
957 g_StdErr.ListPathSeparatorSlash = options.ListPathSeparatorSlash;
910 958
911 unsigned percentsNameLevel = 1; 959 unsigned percentsNameLevel = 1;
912 if (options.LogLevel == 0 || options.Number_for_Percents != options.Number_for_Out) 960 if (options.LogLevel == 0 || options.Number_for_Percents != options.Number_for_Out)
@@ -921,15 +969,16 @@ int Main2(
921 #if !defined(UNDER_CE) 969 #if !defined(UNDER_CE)
922 CONSOLE_SCREEN_BUFFER_INFO consoleInfo; 970 CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
923 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo)) 971 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo))
924 consoleWidth = (unsigned)(unsigned short)consoleInfo.dwSize.X; 972 consoleWidth = (USHORT)consoleInfo.dwSize.X;
925 #endif 973 #endif
926 974
927 #else 975 #else
928 976
977#if !defined(__sun)
929 struct winsize w; 978 struct winsize w;
930 if (ioctl(0, TIOCGWINSZ, &w) == 0) 979 if (ioctl(0, TIOCGWINSZ, &w) == 0)
931 consoleWidth = w.ws_col; 980 consoleWidth = w.ws_col;
932 981#endif
933 #endif 982 #endif
934 } 983 }
935 984
@@ -1080,7 +1129,7 @@ int Main2(
1080 { 1129 {
1081 s += " ("; 1130 s += " (";
1082 s += ext.AddExt; 1131 s += ext.AddExt;
1083 s += ')'; 1132 s.Add_Char(')');
1084 } 1133 }
1085 } 1134 }
1086 1135
@@ -1103,15 +1152,15 @@ int Main2(
1103 { 1152 {
1104 if (j != 0) 1153 if (j != 0)
1105 so << ' '; 1154 so << ' ';
1106 Byte b = sig[j]; 1155 const unsigned b = sig.ConstData()[j];
1107 if (b > 0x20 && b < 0x80) 1156 if (b > 0x20 && b < 0x80)
1108 { 1157 {
1109 so << (char)b; 1158 so << (char)b;
1110 } 1159 }
1111 else 1160 else
1112 { 1161 {
1113 so << GetHex((b >> 4) & 0xF); 1162 so << GET_HEX_CHAR_UPPER(b >> 4);
1114 so << GetHex(b & 0xF); 1163 so << GET_HEX_CHAR_UPPER(b & 15);
1115 } 1164 }
1116 } 1165 }
1117 } 1166 }
@@ -1481,6 +1530,9 @@ int Main2(
1481 } 1530 }
1482 else if (options.Command.IsFromUpdateGroup()) 1531 else if (options.Command.IsFromUpdateGroup())
1483 { 1532 {
1533 #ifdef Z7_EXTRACT_ONLY
1534 throw "update commands are not implemented";
1535 #else
1484 CUpdateOptions &uo = options.UpdateOptions; 1536 CUpdateOptions &uo = options.UpdateOptions;
1485 if (uo.SfxMode && uo.SfxModule.IsEmpty()) 1537 if (uo.SfxMode && uo.SfxModule.IsEmpty())
1486 uo.SfxModule = kDefaultSfxModule; 1538 uo.SfxModule = kDefaultSfxModule;
@@ -1536,6 +1588,7 @@ int Main2(
1536 g_StdStream, se, 1588 g_StdStream, se,
1537 true // options.EnableHeaders 1589 true // options.EnableHeaders
1538 ); 1590 );
1591 #endif
1539 } 1592 }
1540 else if (options.Command.CommandType == NCommandType::kHash) 1593 else if (options.Command.CommandType == NCommandType::kHash)
1541 { 1594 {
diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp
index 80f84f5..dca05a8 100644
--- a/CPP/7zip/UI/Console/MainAr.cpp
+++ b/CPP/7zip/UI/Console/MainAr.cpp
@@ -61,6 +61,8 @@ static inline bool CheckIsa()
61{ 61{
62 // __try 62 // __try
63 { 63 {
64 // some compilers (e2k) support SSE/AVX, but cpuid() can be unavailable or return lower isa support
65#ifdef MY_CPU_X86_OR_AMD64
64 #if defined(__AVX2__) 66 #if defined(__AVX2__)
65 if (!CPU_IsSupported_AVX2()) 67 if (!CPU_IsSupported_AVX2())
66 return false; 68 return false;
@@ -75,6 +77,7 @@ static inline bool CheckIsa()
75 !CPU_IsSupported_CMOV()) 77 !CPU_IsSupported_CMOV())
76 return false; 78 return false;
77 #endif 79 #endif
80#endif
78 /* 81 /*
79 __asm 82 __asm
80 { 83 {
diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp
index 9d392ab..1e3cfce 100644
--- a/CPP/7zip/UI/Console/PercentPrinter.cpp
+++ b/CPP/7zip/UI/Console/PercentPrinter.cpp
@@ -143,7 +143,7 @@ void CPercentPrinter::Print()
143 _s.Add_Space(); 143 _s.Add_Space();
144 144
145 _tempU = FileName; 145 _tempU = FileName;
146 _so->Normalize_UString(_tempU); 146 _so->Normalize_UString_Path(_tempU);
147 _so->Convert_UString_to_AString(_tempU, _temp); 147 _so->Convert_UString_to_AString(_tempU, _temp);
148 if (_s.Len() + _temp.Len() > MaxLen) 148 if (_s.Len() + _temp.Len() > MaxLen)
149 { 149 {
@@ -157,7 +157,7 @@ void CPercentPrinter::Print()
157 _tempU = FileName; 157 _tempU = FileName;
158 _tempU.Delete(len / 2, _tempU.Len() - len); 158 _tempU.Delete(len / 2, _tempU.Len() - len);
159 _tempU.Insert(len / 2, L" . "); 159 _tempU.Insert(len / 2, L" . ");
160 _so->Normalize_UString(_tempU); 160 _so->Normalize_UString_Path(_tempU);
161 _so->Convert_UString_to_AString(_tempU, _temp); 161 _so->Convert_UString_to_AString(_tempU, _temp);
162 if (_s.Len() + _temp.Len() <= MaxLen) 162 if (_s.Len() + _temp.Len() <= MaxLen)
163 break; 163 break;
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
index 85496f5..3e79645 100644
--- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
@@ -147,7 +147,7 @@ HRESULT CUpdateCallbackConsole::OpenResult(
147 if (_se) 147 if (_se)
148 { 148 {
149 *_se << kError; 149 *_se << kError;
150 _se->NormalizePrint_wstr(name); 150 _se->NormalizePrint_wstr_Path(name);
151 *_se << endl; 151 *_se << endl;
152 HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink); 152 HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
153 RINOK(res) 153 RINOK(res)
@@ -191,7 +191,7 @@ void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, b
191 *_se << endl << (isWarning ? kWarning : kError) 191 *_se << endl << (isWarning ? kWarning : kError)
192 << NError::MyFormatMessage(systemError) 192 << NError::MyFormatMessage(systemError)
193 << endl; 193 << endl;
194 _se->NormalizePrint_UString(fs2us(path)); 194 _se->NormalizePrint_UString_Path(fs2us(path));
195 *_se << endl << endl; 195 *_se << endl << endl;
196 _se->Flush(); 196 _se->Flush();
197 } 197 }
@@ -312,7 +312,7 @@ HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
312 { 312 {
313 *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage); 313 *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage);
314 if (name) 314 if (name)
315 _so->NormalizePrint_wstr(name); 315 _so->NormalizePrint_wstr_Path(name);
316 else 316 else
317 *_so << k_StdOut_ArcName; 317 *_so << k_StdOut_ArcName;
318 *_so << endl << endl; 318 *_so << endl << endl;
@@ -379,7 +379,7 @@ HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool
379 _tempA.Add_Space(); 379 _tempA.Add_Space();
380 *_so << _tempA; 380 *_so << _tempA;
381 _tempU = fs2us(path); 381 _tempU = fs2us(path);
382 _so->Normalize_UString(_tempU); 382 _so->Normalize_UString_Path(_tempU);
383 _so->PrintUString(_tempU, _tempA); 383 _so->PrintUString(_tempU, _tempA);
384 *_so << endl; 384 *_so << endl;
385 if (NeedFlush) 385 if (NeedFlush)
@@ -516,7 +516,7 @@ HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, bool isDir, con
516 _tempU = name; 516 _tempU = name;
517 if (isDir) 517 if (isDir)
518 NWindows::NFile::NName::NormalizeDirPathPrefix(_tempU); 518 NWindows::NFile::NName::NormalizeDirPathPrefix(_tempU);
519 _so->Normalize_UString(_tempU); 519 _so->Normalize_UString_Path(_tempU);
520 } 520 }
521 _so->PrintUString(_tempU, _tempA); 521 _so->PrintUString(_tempU, _tempA);
522 *_so << endl; 522 *_so << endl;
@@ -642,7 +642,7 @@ HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypt
642 AString s; 642 AString s;
643 SetExtractErrorMessage(opRes, isEncrypted, s); 643 SetExtractErrorMessage(opRes, isEncrypted, s);
644 *_se << s << " : " << endl; 644 *_se << s << " : " << endl;
645 _se->NormalizePrint_wstr(name); 645 _se->NormalizePrint_wstr_Path(name);
646 *_se << endl << endl; 646 *_se << endl << endl;
647 _se->Flush(); 647 _se->Flush();
648 } 648 }
diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp
index 04d675e..2adf9df 100644
--- a/CPP/7zip/UI/Console/UserInputUtils.cpp
+++ b/CPP/7zip/UI/Console/UserInputUtils.cpp
@@ -49,6 +49,7 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
49 case kNoAll: return NUserAnswerMode::kNoAll; 49 case kNoAll: return NUserAnswerMode::kNoAll;
50 case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll; 50 case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll;
51 case kQuit: return NUserAnswerMode::kQuit; 51 case kQuit: return NUserAnswerMode::kQuit;
52 default: break;
52 } 53 }
53 } 54 }
54} 55}
diff --git a/CPP/7zip/UI/Console/makefile.gcc b/CPP/7zip/UI/Console/makefile.gcc
index 8a293d8..da995a7 100644
--- a/CPP/7zip/UI/Console/makefile.gcc
+++ b/CPP/7zip/UI/Console/makefile.gcc
@@ -38,15 +38,16 @@ endif
38 38
39 39
40 40
41LOCAL_FLAGS_WIN= 41LOCAL_FLAGS_SYS=
42 42
43ifdef IS_MINGW 43ifdef IS_MINGW
44 44
45LOCAL_FLAGS_WIN = \ 45LOCAL_FLAGS_SYS = \
46 -DZ7_LARGE_PAGES \
47 -DZ7_LONG_PATH \
48 -DZ7_DEVICE_FILE \ 46 -DZ7_DEVICE_FILE \
49 47
48# -DZ7_LARGE_PAGES
49# -DZ7_LONG_PATH
50
50SYS_OBJS = \ 51SYS_OBJS = \
51 $O/FileSystem.o \ 52 $O/FileSystem.o \
52 $O/Registry.o \ 53 $O/Registry.o \
@@ -64,7 +65,7 @@ endif
64 65
65 66
66LOCAL_FLAGS = \ 67LOCAL_FLAGS = \
67 $(LOCAL_FLAGS_WIN) \ 68 $(LOCAL_FLAGS_SYS) \
68 $(LOCAL_FLAGS_ST) \ 69 $(LOCAL_FLAGS_ST) \
69 -DZ7_EXTERNAL_CODECS \ 70 -DZ7_EXTERNAL_CODECS \
70 71
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp
index 7815e13..d79bab1 100644
--- a/CPP/7zip/UI/Explorer/ContextMenu.cpp
+++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp
@@ -295,8 +295,10 @@ static const CHashCommand g_HashCommands[] =
295{ 295{
296 { CZipContextMenu::kHash_CRC32, "CRC-32", "CRC32" }, 296 { CZipContextMenu::kHash_CRC32, "CRC-32", "CRC32" },
297 { CZipContextMenu::kHash_CRC64, "CRC-64", "CRC64" }, 297 { CZipContextMenu::kHash_CRC64, "CRC-64", "CRC64" },
298 { CZipContextMenu::kHash_XXH64, "XXH64", "XXH64" },
298 { CZipContextMenu::kHash_SHA1, "SHA-1", "SHA1" }, 299 { CZipContextMenu::kHash_SHA1, "SHA-1", "SHA1" },
299 { CZipContextMenu::kHash_SHA256, "SHA-256", "SHA256" }, 300 { CZipContextMenu::kHash_SHA256, "SHA-256", "SHA256" },
301 { CZipContextMenu::kHash_BLAKE2SP, "BLAKE2sp", "BLAKE2sp" },
300 { CZipContextMenu::kHash_All, "*", "*" }, 302 { CZipContextMenu::kHash_All, "*", "*" },
301 { CZipContextMenu::kHash_Generate_SHA256, "SHA-256 -> file.sha256", "SHA256" }, 303 { CZipContextMenu::kHash_Generate_SHA256, "SHA-256 -> file.sha256", "SHA256" },
302 { CZipContextMenu::kHash_TestArc, "Checksum : Test", "Hash" } 304 { CZipContextMenu::kHash_TestArc, "Checksum : Test", "Hash" }
@@ -505,7 +507,7 @@ static const char * const kExtractExcludeExtensions =
505 " sed sh shn shtml sln sql srt swa" 507 " sed sh shn shtml sln sql srt swa"
506 " tcl tex tiff tta txt" 508 " tcl tex tiff tta txt"
507 " vb vcproj vbs" 509 " vb vcproj vbs"
508 " wav wma wv" 510 " mkv wav webm wma wv"
509 " xml xsd xsl xslt" 511 " xml xsd xsl xslt"
510 " "; 512 " ";
511 513
@@ -593,9 +595,11 @@ Z7_COMWF_B CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
593 } 595 }
594 */ 596 */
595 597
598 #define MAKE_HRESULT_SUCCESS_FAC0(code) (HRESULT)(code)
599
596 if (_fileNames.Size() == 0) 600 if (_fileNames.Size() == 0)
597 { 601 {
598 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); 602 return MAKE_HRESULT_SUCCESS_FAC0(0);
599 // return E_INVALIDARG; 603 // return E_INVALIDARG;
600 } 604 }
601 605
@@ -607,8 +611,8 @@ Z7_COMWF_B CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
607 if ((flags & 0x000F) != CMF_NORMAL 611 if ((flags & 0x000F) != CMF_NORMAL
608 && (flags & CMF_VERBSONLY) == 0 612 && (flags & CMF_VERBSONLY) == 0
609 && (flags & CMF_EXPLORE) == 0) 613 && (flags & CMF_EXPLORE) == 0)
610 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID - commandIDFirst); 614 return MAKE_HRESULT_SUCCESS_FAC0(currentCommandID - commandIDFirst);
611 // return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID); 615 // return MAKE_HRESULT_SUCCESS_FAC0(currentCommandID);
612 // 19.01 : we changed from (currentCommandID) to (currentCommandID - commandIDFirst) 616 // 19.01 : we changed from (currentCommandID) to (currentCommandID - commandIDFirst)
613 // why it was so before? 617 // why it was so before?
614 618
@@ -1162,7 +1166,7 @@ Z7_COMWF_B CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
1162 assigned in multiple menu items from different subhandlers. 1166 assigned in multiple menu items from different subhandlers.
1163 And we must add items to _commandMap before adding to menu. 1167 And we must add items to _commandMap before adding to menu.
1164 */ 1168 */
1165 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, _commandMap.Size()); 1169 return MAKE_HRESULT_SUCCESS_FAC0(_commandMap.Size());
1166 COM_TRY_END 1170 COM_TRY_END
1167} 1171}
1168 1172
@@ -1332,8 +1336,10 @@ HRESULT CZipContextMenu::InvokeCommandCommon(const CCommandMapItem &cmi)
1332 1336
1333 case kHash_CRC32: 1337 case kHash_CRC32:
1334 case kHash_CRC64: 1338 case kHash_CRC64:
1339 case kHash_XXH64:
1335 case kHash_SHA1: 1340 case kHash_SHA1:
1336 case kHash_SHA256: 1341 case kHash_SHA256:
1342 case kHash_BLAKE2SP:
1337 case kHash_All: 1343 case kHash_All:
1338 case kHash_Generate_SHA256: 1344 case kHash_Generate_SHA256:
1339 case kHash_TestArc: 1345 case kHash_TestArc:
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h
index 3f25f6a..a68ba9d 100644
--- a/CPP/7zip/UI/Explorer/ContextMenu.h
+++ b/CPP/7zip/UI/Explorer/ContextMenu.h
@@ -87,8 +87,10 @@ public:
87 kCompressToZipEmail, 87 kCompressToZipEmail,
88 kHash_CRC32, 88 kHash_CRC32,
89 kHash_CRC64, 89 kHash_CRC64,
90 kHash_XXH64,
90 kHash_SHA1, 91 kHash_SHA1,
91 kHash_SHA256, 92 kHash_SHA256,
93 kHash_BLAKE2SP,
92 kHash_All, 94 kHash_All,
93 kHash_Generate_SHA256, 95 kHash_Generate_SHA256,
94 kHash_TestArc 96 kHash_TestArc
diff --git a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
index 7307b07..c92c983 100644
--- a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
+++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
@@ -66,6 +66,10 @@ extern
66LONG g_DllRefCount; 66LONG g_DllRefCount;
67LONG g_DllRefCount = 0; // Reference count of this DLL. 67LONG g_DllRefCount = 0; // Reference count of this DLL.
68 68
69extern
70bool g_DisableUserQuestions;
71bool g_DisableUserQuestions;
72
69 73
70// #define ODS(sz) OutputDebugStringW(L#sz) 74// #define ODS(sz) OutputDebugStringW(L#sz)
71#define ODS(sz) 75#define ODS(sz)
diff --git a/CPP/7zip/UI/Explorer/Explorer.dsp b/CPP/7zip/UI/Explorer/Explorer.dsp
index ff8503b..2ed491f 100644
--- a/CPP/7zip/UI/Explorer/Explorer.dsp
+++ b/CPP/7zip/UI/Explorer/Explorer.dsp
@@ -589,6 +589,14 @@ SOURCE=..\..\..\Windows\Synchronization.h
589# End Source File 589# End Source File
590# Begin Source File 590# Begin Source File
591 591
592SOURCE=..\..\..\Windows\TimeUtils.cpp
593# End Source File
594# Begin Source File
595
596SOURCE=..\..\..\Windows\TimeUtils.h
597# End Source File
598# Begin Source File
599
592SOURCE=..\..\..\Windows\Window.cpp 600SOURCE=..\..\..\Windows\Window.cpp
593# End Source File 601# End Source File
594# Begin Source File 602# Begin Source File
diff --git a/CPP/7zip/UI/Explorer/MyExplorerCommand.h b/CPP/7zip/UI/Explorer/MyExplorerCommand.h
index 11ac247..41ac8d6 100644
--- a/CPP/7zip/UI/Explorer/MyExplorerCommand.h
+++ b/CPP/7zip/UI/Explorer/MyExplorerCommand.h
@@ -89,7 +89,7 @@ enum GETPROPERTYSTOREFLAGS
89#define PROPERTYKEY_DEFINED 89#define PROPERTYKEY_DEFINED
90 90
91typedef 91typedef
92struct _tagpropertykey 92struct
93{ 93{
94 GUID fmtid; 94 GUID fmtid;
95 DWORD pid; 95 DWORD pid;
diff --git a/CPP/7zip/UI/Explorer/MyMessages.cpp b/CPP/7zip/UI/Explorer/MyMessages.cpp
index daff7de..c079e31 100644
--- a/CPP/7zip/UI/Explorer/MyMessages.cpp
+++ b/CPP/7zip/UI/Explorer/MyMessages.cpp
@@ -11,12 +11,15 @@
11 11
12using namespace NWindows; 12using namespace NWindows;
13 13
14extern bool g_DisableUserQuestions;
15
14void ShowErrorMessage(HWND window, LPCWSTR message) 16void ShowErrorMessage(HWND window, LPCWSTR message)
15{ 17{
16 ::MessageBoxW(window, message, L"7-Zip", MB_OK | MB_ICONSTOP); 18 if (!g_DisableUserQuestions)
19 ::MessageBoxW(window, message, L"7-Zip", MB_OK | MB_ICONSTOP);
17} 20}
18 21
19void ShowErrorMessageHwndRes(HWND window, UINT resID) 22void ShowErrorMessageHwndRes(HWND window, UInt32 resID)
20{ 23{
21 UString s = LangString(resID); 24 UString s = LangString(resID);
22 if (s.IsEmpty()) 25 if (s.IsEmpty())
@@ -24,7 +27,7 @@ void ShowErrorMessageHwndRes(HWND window, UINT resID)
24 ShowErrorMessage(window, s); 27 ShowErrorMessage(window, s);
25} 28}
26 29
27void ShowErrorMessageRes(UINT resID) 30void ShowErrorMessageRes(UInt32 resID)
28{ 31{
29 ShowErrorMessageHwndRes(NULL, resID); 32 ShowErrorMessageHwndRes(NULL, resID);
30} 33}
diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp
index bc03d6a..6563d89 100644
--- a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp
+++ b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp
@@ -48,17 +48,16 @@ static const bool k_shellex_Statuses[2][4] =
48}; 48};
49 49
50 50
51// can we use static RegDeleteKeyExW in _WIN64 mode? 51// RegDeleteKeyExW is supported starting from win2003sp1/xp-pro-x64
52// is it supported by Windows 2003 x64? 52// Z7_WIN32_WINNT_MIN < 0x0600 // Vista
53 53#if !defined(Z7_WIN32_WINNT_MIN) \
54/* 54 || Z7_WIN32_WINNT_MIN < 0x0502 /* < win2003 */ \
55#ifdef _WIN64 55 || Z7_WIN32_WINNT_MIN == 0x0502 && !defined(_M_AMD64)
56 56#define Z7_USE_DYN_RegDeleteKeyExW
57#define INIT_REG_WOW 57#endif
58
59#else
60*/
61 58
59#ifdef Z7_USE_DYN_RegDeleteKeyExW
60Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
62typedef 61typedef
63// WINADVAPI 62// WINADVAPI
64LONG (APIENTRY *Func_RegDeleteKeyExW)(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved); 63LONG (APIENTRY *Func_RegDeleteKeyExW)(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved);
@@ -71,25 +70,24 @@ static void Init_RegDeleteKeyExW()
71 Func_RegDeleteKeyExW, GetModuleHandleW(L"advapi32.dll"), 70 Func_RegDeleteKeyExW, GetModuleHandleW(L"advapi32.dll"),
72 "RegDeleteKeyExW"); 71 "RegDeleteKeyExW");
73} 72}
74
75#define INIT_REG_WOW if (wow != 0) Init_RegDeleteKeyExW(); 73#define INIT_REG_WOW if (wow != 0) Init_RegDeleteKeyExW();
74#else
75#define INIT_REG_WOW
76#endif
76 77
77// #endif
78 78
79static LONG MyRegistry_DeleteKey(HKEY parentKey, LPCTSTR name, UInt32 wow) 79static LONG MyRegistry_DeleteKey(HKEY parentKey, LPCTSTR name, UInt32 wow)
80{ 80{
81 if (wow == 0) 81 if (wow == 0)
82 return RegDeleteKey(parentKey, name); 82 return RegDeleteKey(parentKey, name);
83 83
84 /* 84#ifdef Z7_USE_DYN_RegDeleteKeyExW
85 #ifdef _WIN64
86 return RegDeleteKeyExW
87 #else
88 */
89 if (!func_RegDeleteKeyExW) 85 if (!func_RegDeleteKeyExW)
90 return E_NOTIMPL; 86 return E_NOTIMPL;
91 return func_RegDeleteKeyExW 87 return func_RegDeleteKeyExW
92 // #endif 88#else
89 return RegDeleteKeyExW
90#endif
93 (parentKey, GetUnicodeString(name), wow, 0); 91 (parentKey, GetUnicodeString(name), wow, 0);
94} 92}
95 93
diff --git a/CPP/7zip/UI/Explorer/makefile b/CPP/7zip/UI/Explorer/makefile
index da63a5c..3901d6b 100644
--- a/CPP/7zip/UI/Explorer/makefile
+++ b/CPP/7zip/UI/Explorer/makefile
@@ -7,7 +7,8 @@ CFLAGS = $(CFLAGS) \
7LIBS = $(LIBS) Commctrl.lib 7LIBS = $(LIBS) Commctrl.lib
8!ELSE 8!ELSE
9LIBS = $(LIBS) htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib 9LIBS = $(LIBS) htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib
10CFLAGS = $(CFLAGS) -DZ7_LONG_PATH 10# CFLAGS = $(CFLAGS) -DZ7_LONG_PATH
11# -DZ7_NO_LARGE_PAGES
11!ENDIF 12!ENDIF
12 13
13EXPLORER_OBJS = \ 14EXPLORER_OBJS = \
@@ -41,6 +42,7 @@ WIN_OBJS = \
41 $O\ResourceString.obj \ 42 $O\ResourceString.obj \
42 $O\Shell.obj \ 43 $O\Shell.obj \
43 $O\Synchronization.obj \ 44 $O\Synchronization.obj \
45 $O\TimeUtils.obj \
44 $O\Window.obj \ 46 $O\Window.obj \
45 47
46!IFDEF UNDER_CE 48!IFDEF UNDER_CE
diff --git a/CPP/7zip/UI/Far/Far.cpp b/CPP/7zip/UI/Far/Far.cpp
index 74d5e60..211dde8 100644
--- a/CPP/7zip/UI/Far/Far.cpp
+++ b/CPP/7zip/UI/Far/Far.cpp
@@ -346,7 +346,7 @@ static HANDLE MyOpenFilePlugin(const char *name, bool isAbortCodeSupported)
346 return MyOpenFilePluginW(GetUnicodeString(name, codePage), isAbortCodeSupported); 346 return MyOpenFilePluginW(GetUnicodeString(name, codePage), isAbortCodeSupported);
347} 347}
348 348
349EXTERN_C HANDLE WINAPI OpenFilePlugin(char *name, const unsigned char * /* data */, int /* dataSize */) 349EXTERN_C HANDLE WINAPI OpenFilePlugin(char *name, const Byte * /* data */, int /* dataSize */)
350{ 350{
351 MY_TRY_BEGIN 351 MY_TRY_BEGIN
352 // OutputDebugStringA("--- OpenFilePlugin"); 352 // OutputDebugStringA("--- OpenFilePlugin");
@@ -360,7 +360,7 @@ EXTERN_C HANDLE WINAPI OpenFilePlugin(char *name, const unsigned char * /* data
360} 360}
361 361
362/* 362/*
363EXTERN_C HANDLE WINAPI OpenFilePluginW(const wchar_t *name,const unsigned char *Data,int DataSize,int OpMode) 363EXTERN_C HANDLE WINAPI OpenFilePluginW(const wchar_t *name,const Byte *Data,int DataSize,int OpMode)
364{ 364{
365 MY_TRY_BEGIN 365 MY_TRY_BEGIN
366 if (name == NULL || (!g_Options.Enabled)) 366 if (name == NULL || (!g_Options.Enabled))
@@ -553,7 +553,7 @@ EXTERN_C int WINAPI DeleteFiles(HANDLE plugin, PluginPanelItem *panelItems, int
553 MY_TRY_END2("DeleteFiles", FALSE) 553 MY_TRY_END2("DeleteFiles", FALSE)
554} 554}
555 555
556EXTERN_C int WINAPI ProcessKey(HANDLE plugin, int key, unsigned int controlState) 556EXTERN_C int WINAPI ProcessKey(HANDLE plugin, int key, unsigned controlState)
557{ 557{
558 MY_TRY_BEGIN 558 MY_TRY_BEGIN
559 /* FIXME: after folder creation with F7, it doesn't reload new file list 559 /* FIXME: after folder creation with F7, it doesn't reload new file list
diff --git a/CPP/7zip/UI/Far/FarPlugin.h b/CPP/7zip/UI/Far/FarPlugin.h
index ad3ed38..68c767b 100644
--- a/CPP/7zip/UI/Far/FarPlugin.h
+++ b/CPP/7zip/UI/Far/FarPlugin.h
@@ -7,7 +7,7 @@ const int kInfoPanelLineSize = 80;
7// #define __FAR_PLUGIN_H 7// #define __FAR_PLUGIN_H
8 8
9#ifdef UNDER_CE 9#ifdef UNDER_CE
10typedef struct _CHAR_INFO { 10typedef struct {
11 union { 11 union {
12 WCHAR UnicodeChar; 12 WCHAR UnicodeChar;
13 CHAR AsciiChar; 13 CHAR AsciiChar;
@@ -29,9 +29,9 @@ typedef struct _CHAR_INFO {
29#endif 29#endif
30#endif 30#endif
31 31
32 #if _MSC_VER 32 // #if _MSC_VER
33 #define _export 33 #define _export
34 #endif 34 // #endif
35 35
36#define NM 260 36#define NM 260
37 37
@@ -82,7 +82,7 @@ typedef int (WINAPI *FARAPIMENU)(
82 int X, 82 int X,
83 int Y, 83 int Y,
84 int MaxHeight, 84 int MaxHeight,
85 unsigned int Flags, 85 unsigned Flags,
86 char *Title, 86 char *Title,
87 char *Bottom, 87 char *Bottom,
88 char *HelpTopic, 88 char *HelpTopic,
@@ -122,7 +122,7 @@ enum {
122 122
123typedef int (WINAPI *FARAPIMESSAGE)( 123typedef int (WINAPI *FARAPIMESSAGE)(
124 INT_PTR PluginNumber, 124 INT_PTR PluginNumber,
125 unsigned int Flags, 125 unsigned Flags,
126 const char *HelpTopic, 126 const char *HelpTopic,
127 const char * const *Items, 127 const char * const *Items,
128 int ItemsNumber, 128 int ItemsNumber,
@@ -177,7 +177,7 @@ struct FarDialogItem
177 int ListPos; 177 int ListPos;
178 CHAR_INFO *VBuf; 178 CHAR_INFO *VBuf;
179 }; 179 };
180 unsigned int Flags; 180 unsigned Flags;
181 int DefaultButton; 181 int DefaultButton;
182 char Data[512]; 182 char Data[512];
183}; 183};
@@ -495,7 +495,7 @@ enum OPERATION_MODES {
495EXTERN_C_BEGIN 495EXTERN_C_BEGIN
496 496
497 void WINAPI _export ClosePluginW(HANDLE hPlugin); 497 void WINAPI _export ClosePluginW(HANDLE hPlugin);
498 int WINAPI _export CompareW(HANDLE hPlugin,const struct PluginPanelItem *Item1,const struct PluginPanelItem *Item2,unsigned int Mode); 498 int WINAPI _export CompareW(HANDLE hPlugin,const struct PluginPanelItem *Item1,const struct PluginPanelItem *Item2,unsigned Mode);
499 int WINAPI _export ConfigureW(int ItemNumber); 499 int WINAPI _export ConfigureW(int ItemNumber);
500 int WINAPI _export DeleteFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); 500 int WINAPI _export DeleteFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode);
501 void WINAPI _export ExitFARW(void); 501 void WINAPI _export ExitFARW(void);
@@ -515,7 +515,7 @@ EXTERN_C_BEGIN
515 int WINAPI _export ProcessEditorInputW(const INPUT_RECORD *Rec); 515 int WINAPI _export ProcessEditorInputW(const INPUT_RECORD *Rec);
516 int WINAPI _export ProcessEventW(HANDLE hPlugin,int Event,void *Param); 516 int WINAPI _export ProcessEventW(HANDLE hPlugin,int Event,void *Param);
517 int WINAPI _export ProcessHostFileW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); 517 int WINAPI _export ProcessHostFileW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode);
518 int WINAPI _export ProcessKeyW(HANDLE hPlugin,int Key,unsigned int ControlState); 518 int WINAPI _export ProcessKeyW(HANDLE hPlugin,int Key,unsigned ControlState);
519 int WINAPI _export ProcessSynchroEventW(int Event,void *Param); 519 int WINAPI _export ProcessSynchroEventW(int Event,void *Param);
520 int WINAPI _export ProcessViewerEventW(int Event,void *Param); 520 int WINAPI _export ProcessViewerEventW(int Event,void *Param);
521 int WINAPI _export PutFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t *SrcPath,int OpMode); 521 int WINAPI _export PutFilesW(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t *SrcPath,int OpMode);
@@ -528,7 +528,7 @@ EXTERN_C_END
528EXTERN_C_BEGIN 528EXTERN_C_BEGIN
529 529
530 void WINAPI _export ClosePlugin(HANDLE hPlugin); 530 void WINAPI _export ClosePlugin(HANDLE hPlugin);
531 int WINAPI _export Compare(HANDLE hPlugin,const struct PluginPanelItem *Item1,const struct PluginPanelItem *Item2,unsigned int Mode); 531 int WINAPI _export Compare(HANDLE hPlugin,const struct PluginPanelItem *Item1,const struct PluginPanelItem *Item2,unsigned Mode);
532 int WINAPI _export Configure(int ItemNumber); 532 int WINAPI _export Configure(int ItemNumber);
533 int WINAPI _export DeleteFiles(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); 533 int WINAPI _export DeleteFiles(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode);
534 void WINAPI _export ExitFAR(void); 534 void WINAPI _export ExitFAR(void);
@@ -541,14 +541,14 @@ EXTERN_C_BEGIN
541 void WINAPI _export GetPluginInfo(struct PluginInfo *Info); 541 void WINAPI _export GetPluginInfo(struct PluginInfo *Info);
542 int WINAPI _export GetVirtualFindData(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,const char *Path); 542 int WINAPI _export GetVirtualFindData(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,const char *Path);
543 int WINAPI _export MakeDirectory(HANDLE hPlugin,char *Name,int OpMode); 543 int WINAPI _export MakeDirectory(HANDLE hPlugin,char *Name,int OpMode);
544 HANDLE WINAPI _export OpenFilePlugin(char *Name,const unsigned char *Data,int DataSize); 544 HANDLE WINAPI _export OpenFilePlugin(char *Name,const BYTE *Data,int DataSize);
545 HANDLE WINAPI _export OpenPlugin(int OpenFrom,INT_PTR Item); 545 HANDLE WINAPI _export OpenPlugin(int OpenFrom,INT_PTR Item);
546 int WINAPI _export ProcessDialogEvent(int Event,void *Param); 546 int WINAPI _export ProcessDialogEvent(int Event,void *Param);
547 int WINAPI _export ProcessEditorEvent(int Event,void *Param); 547 int WINAPI _export ProcessEditorEvent(int Event,void *Param);
548 int WINAPI _export ProcessEditorInput(const INPUT_RECORD *Rec); 548 int WINAPI _export ProcessEditorInput(const INPUT_RECORD *Rec);
549 int WINAPI _export ProcessEvent(HANDLE hPlugin,int Event,void *Param); 549 int WINAPI _export ProcessEvent(HANDLE hPlugin,int Event,void *Param);
550 int WINAPI _export ProcessHostFile(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); 550 int WINAPI _export ProcessHostFile(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode);
551 int WINAPI _export ProcessKey(HANDLE hPlugin,int Key,unsigned int ControlState); 551 int WINAPI _export ProcessKey(HANDLE hPlugin,int Key,unsigned ControlState);
552 int WINAPI _export ProcessViewerEvent(int Event,void *Param); 552 int WINAPI _export ProcessViewerEvent(int Event,void *Param);
553 int WINAPI _export PutFiles(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,int OpMode); 553 int WINAPI _export PutFiles(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int Move,int OpMode);
554 int WINAPI _export SetDirectory(HANDLE hPlugin,const char *Dir,int OpMode); 554 int WINAPI _export SetDirectory(HANDLE hPlugin,const char *Dir,int OpMode);
diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp
index 9fddbc1..ed61ccc 100644
--- a/CPP/7zip/UI/Far/FarUtils.cpp
+++ b/CPP/7zip/UI/Far/FarUtils.cpp
@@ -35,7 +35,7 @@ const char *CStartupInfo::GetMsgString(int messageId)
35 return (const char*)m_Data.GetMsg(m_Data.ModuleNumber, messageId); 35 return (const char*)m_Data.GetMsg(m_Data.ModuleNumber, messageId);
36} 36}
37 37
38int CStartupInfo::ShowMessage(unsigned int flags, 38int CStartupInfo::ShowMessage(UInt32 flags,
39 const char *helpTopic, const char **items, unsigned numItems, int numButtons) 39 const char *helpTopic, const char **items, unsigned numItems, int numButtons)
40{ 40{
41 return m_Data.Message(m_Data.ModuleNumber, flags, helpTopic, 41 return m_Data.Message(m_Data.ModuleNumber, flags, helpTopic,
@@ -186,8 +186,8 @@ void CStartupInfo::InitDialogItems(const CInitDialogItem *srcItems,
186 MyStringCopy(destItem.Data, GetMsgString(srcItem.DataMessageId)); 186 MyStringCopy(destItem.Data, GetMsgString(srcItem.DataMessageId));
187 187
188 /* 188 /*
189 if ((unsigned int)Init[i].Data < 0xFFF) 189 if ((unsigned)Init[i].Data < 0xFFF)
190 MyStringCopy(destItem.Data, GetMsg((unsigned int)srcItem.Data)); 190 MyStringCopy(destItem.Data, GetMsg((unsigned)srcItem.Data));
191 else 191 else
192 MyStringCopy(destItem.Data,srcItem.Data); 192 MyStringCopy(destItem.Data,srcItem.Data);
193 */ 193 */
@@ -367,7 +367,7 @@ int CStartupInfo::Menu(
367 int x, 367 int x,
368 int y, 368 int y,
369 int maxHeight, 369 int maxHeight,
370 unsigned int flags, 370 unsigned flags,
371 const char *title, 371 const char *title,
372 const char *aBottom, 372 const char *aBottom,
373 const char *helpTopic, 373 const char *helpTopic,
@@ -384,7 +384,7 @@ int CStartupInfo::Menu(
384} 384}
385 385
386int CStartupInfo::Menu( 386int CStartupInfo::Menu(
387 unsigned int flags, 387 unsigned flags,
388 const char *title, 388 const char *title,
389 const char *helpTopic, 389 const char *helpTopic,
390 struct FarMenuItem *items, 390 struct FarMenuItem *items,
@@ -395,7 +395,7 @@ int CStartupInfo::Menu(
395} 395}
396 396
397int CStartupInfo::Menu( 397int CStartupInfo::Menu(
398 unsigned int flags, 398 unsigned flags,
399 const char *title, 399 const char *title,
400 const char *helpTopic, 400 const char *helpTopic,
401 const AStringVector &items, 401 const AStringVector &items,
@@ -412,7 +412,7 @@ int CStartupInfo::Menu(
412 MyStringCopy(item.Text, reducedString); 412 MyStringCopy(item.Text, reducedString);
413 farMenuItems.Add(item); 413 farMenuItems.Add(item);
414 } 414 }
415 return Menu(flags, title, helpTopic, &farMenuItems.Front(), farMenuItems.Size()); 415 return Menu(flags, title, helpTopic, farMenuItems.NonConstData(), farMenuItems.Size());
416} 416}
417 417
418 418
diff --git a/CPP/7zip/UI/Far/FarUtils.h b/CPP/7zip/UI/Far/FarUtils.h
index 6e6ff3c..fefbc22 100644
--- a/CPP/7zip/UI/Far/FarUtils.h
+++ b/CPP/7zip/UI/Far/FarUtils.h
@@ -36,7 +36,7 @@ struct CInitDialogItem
36 int X1,Y1,X2,Y2; 36 int X1,Y1,X2,Y2;
37 bool Focus; 37 bool Focus;
38 bool Selected; 38 bool Selected;
39 unsigned int Flags; //FarDialogItemFlags Flags; 39 UInt32 Flags; //FarDialogItemFlags Flags;
40 bool DefaultButton; 40 bool DefaultButton;
41 int DataMessageId; 41 int DataMessageId;
42 const char *DataString; 42 const char *DataString;
@@ -60,7 +60,7 @@ public:
60 const char *pluginNameForRegistry); 60 const char *pluginNameForRegistry);
61 const char *GetMsgString(int messageId); 61 const char *GetMsgString(int messageId);
62 62
63 int ShowMessage(unsigned int flags, const char *helpTopic, 63 int ShowMessage(UInt32 flags, const char *helpTopic,
64 const char **items, unsigned numItems, int numButtons); 64 const char **items, unsigned numItems, int numButtons);
65 int ShowWarningWithOk(const char **items, unsigned numItems); 65 int ShowWarningWithOk(const char **items, unsigned numItems);
66 66
@@ -112,7 +112,7 @@ public:
112 int x, 112 int x,
113 int y, 113 int y,
114 int maxHeight, 114 int maxHeight,
115 unsigned int flags, 115 unsigned flags,
116 const char *title, 116 const char *title,
117 const char *aBottom, 117 const char *aBottom,
118 const char *helpTopic, 118 const char *helpTopic,
@@ -121,14 +121,14 @@ public:
121 FarMenuItem *items, 121 FarMenuItem *items,
122 unsigned numItems); 122 unsigned numItems);
123 int Menu( 123 int Menu(
124 unsigned int flags, 124 unsigned flags,
125 const char *title, 125 const char *title,
126 const char *helpTopic, 126 const char *helpTopic,
127 FarMenuItem *items, 127 FarMenuItem *items,
128 unsigned numItems); 128 unsigned numItems);
129 129
130 int Menu( 130 int Menu(
131 unsigned int flags, 131 unsigned flags,
132 const char *title, 132 const char *title,
133 const char *helpTopic, 133 const char *helpTopic,
134 const AStringVector &items, 134 const AStringVector &items,
diff --git a/CPP/7zip/UI/Far/OverwriteDialogFar.cpp b/CPP/7zip/UI/Far/OverwriteDialogFar.cpp
index a45d2b2..4d1b971 100644
--- a/CPP/7zip/UI/Far/OverwriteDialogFar.cpp
+++ b/CPP/7zip/UI/Far/OverwriteDialogFar.cpp
@@ -46,7 +46,7 @@ static void SetFileInfoStrings(const CFileInfo &fileInfo,
46 fileInfoStrings.Time.Empty(); 46 fileInfoStrings.Time.Empty();
47 if (fileInfo.TimeIsDefined) 47 if (fileInfo.TimeIsDefined)
48 { 48 {
49 char timeString[32]; 49 char timeString[64];
50 ConvertUtcFileTimeToString(fileInfo.Time, timeString); 50 ConvertUtcFileTimeToString(fileInfo.Time, timeString);
51 fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn); 51 fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn);
52 fileInfoStrings.Time.Add_Space(); 52 fileInfoStrings.Time.Add_Space();
diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp
index fe6fcce..2d31b8a 100644
--- a/CPP/7zip/UI/Far/Plugin.cpp
+++ b/CPP/7zip/UI/Far/Plugin.cpp
@@ -509,7 +509,7 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info)
509 509
510 m_PannelTitle = ' '; 510 m_PannelTitle = ' ';
511 m_PannelTitle += _archiveTypeName; 511 m_PannelTitle += _archiveTypeName;
512 m_PannelTitle += ':'; 512 m_PannelTitle.Add_Colon();
513 m_PannelTitle += name; 513 m_PannelTitle += name;
514 m_PannelTitle.Add_Space(); 514 m_PannelTitle.Add_Space();
515 if (!m_CurrentDir.IsEmpty()) 515 if (!m_CurrentDir.IsEmpty())
@@ -686,14 +686,9 @@ struct CArchiveItemProperty
686 VARTYPE Type; 686 VARTYPE Type;
687}; 687};
688 688
689static inline char GetHex_Upper(unsigned v) 689static inline char GetHex_A_minus10(unsigned v, unsigned a10)
690{ 690{
691 return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10))); 691 return (char)(v < 10 ? v + '0' : v + a10);
692}
693
694static inline char GetHex_Lower(unsigned v)
695{
696 return (char)((v < 10) ? ('0' + v) : ('a' + (v - 10)));
697} 692}
698 693
699HRESULT CPlugin::ShowAttributesWindow() 694HRESULT CPlugin::ShowAttributesWindow()
@@ -815,21 +810,14 @@ HRESULT CPlugin::ShowAttributesWindow()
815 } 810 }
816 else 811 else
817 { 812 {
818 const bool needUpper = (dataSize <= 8) 813 const unsigned a = dataSize <= 8
819 && (property.ID == kpidCRC || property.ID == kpidChecksum); 814 && (property.ID == kpidCRC || property.ID == kpidChecksum)
815 ? 'A' - 10 : 'a' - 10;
820 for (UInt32 k = 0; k < dataSize; k++) 816 for (UInt32 k = 0; k < dataSize; k++)
821 { 817 {
822 unsigned b = ((const Byte *)data)[k]; 818 const unsigned b = ((const Byte *)data)[k];
823 if (needUpper) 819 s += GetHex_A_minus10(b >> 4, a);
824 { 820 s += GetHex_A_minus10(b & 15, a);
825 s += GetHex_Upper((b >> 4) & 0xF);
826 s += GetHex_Upper(b & 0xF);
827 }
828 else
829 {
830 s += GetHex_Lower((b >> 4) & 0xF);
831 s += GetHex_Lower(b & 0xF);
832 }
833 } 821 }
834 } 822 }
835 } 823 }
@@ -866,7 +854,7 @@ HRESULT CPlugin::ShowAttributesWindow()
866 const unsigned numDialogItems = initDialogItems.Size(); 854 const unsigned numDialogItems = initDialogItems.Size();
867 855
868 CObjArray<FarDialogItem> dialogItems(numDialogItems); 856 CObjArray<FarDialogItem> dialogItems(numDialogItems);
869 g_StartupInfo.InitDialogItems(&initDialogItems.Front(), dialogItems, numDialogItems); 857 g_StartupInfo.InitDialogItems(initDialogItems.ConstData(), dialogItems, numDialogItems);
870 858
871 unsigned maxLen = 0; 859 unsigned maxLen = 0;
872 860
@@ -900,7 +888,7 @@ HRESULT CPlugin::ShowAttributesWindow()
900 return S_OK; 888 return S_OK;
901} 889}
902 890
903int CPlugin::ProcessKey(int key, unsigned int controlState) 891int CPlugin::ProcessKey(int key, unsigned controlState)
904{ 892{
905 if (key == VK_F7 && controlState == 0) 893 if (key == VK_F7 && controlState == 0)
906 { 894 {
diff --git a/CPP/7zip/UI/Far/Plugin.h b/CPP/7zip/UI/Far/Plugin.h
index 00ccc81..84f6bed 100644
--- a/CPP/7zip/UI/Far/Plugin.h
+++ b/CPP/7zip/UI/Far/Plugin.h
@@ -86,7 +86,7 @@ public:
86 86
87 HRESULT ShowAttributesWindow(); 87 HRESULT ShowAttributesWindow();
88 88
89 int ProcessKey(int key, unsigned int controlState); 89 int ProcessKey(int key, unsigned controlState);
90}; 90};
91 91
92HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems); 92HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems);
diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp
index 3f1fba8..8a00049 100644
--- a/CPP/7zip/UI/Far/PluginWrite.cpp
+++ b/CPP/7zip/UI/Far/PluginWrite.cpp
@@ -322,7 +322,7 @@ void CParsedPath::ParsePath(const UString &path)
322 { 322 {
323 case NPathType::kLocal: 323 case NPathType::kLocal:
324 { 324 {
325 int posDiskDelimiter = path.Find(kDiskDelimiter); 325 const int posDiskDelimiter = path.Find(kDiskDelimiter);
326 if (posDiskDelimiter >= 0) 326 if (posDiskDelimiter >= 0)
327 { 327 {
328 curPos = posDiskDelimiter + 1; 328 curPos = posDiskDelimiter + 1;
@@ -352,7 +352,8 @@ UString CParsedPath::MergePath() const
352 FOR_VECTOR (i, PathParts) 352 FOR_VECTOR (i, PathParts)
353 { 353 {
354 if (i != 0) 354 if (i != 0)
355 result += kDirDelimiter; 355 // result += kDirDelimiter;
356 result.Add_PathSepar();
356 result += PathParts[i]; 357 result += PathParts[i];
357 } 358 }
358 return result; 359 return result;
diff --git a/CPP/7zip/UI/Far/makefile b/CPP/7zip/UI/Far/makefile
index f3809a8..a66f9d7 100644
--- a/CPP/7zip/UI/Far/makefile
+++ b/CPP/7zip/UI/Far/makefile
@@ -4,7 +4,8 @@ CFLAGS = $(CFLAGS) \
4 -DZ7_EXTERNAL_CODECS \ 4 -DZ7_EXTERNAL_CODECS \
5 5
6!IFNDEF UNDER_CE 6!IFNDEF UNDER_CE
7CFLAGS = $(CFLAGS) -DZ7_LONG_PATH 7# CFLAGS = $(CFLAGS) -DZ7_LONG_PATH
8# -DZ7_NO_LARGE_PAGES
8!ENDIF 9!ENDIF
9 10
10CURRENT_OBJS = \ 11CURRENT_OBJS = \
diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp
index b3d354d..446f6de 100644
--- a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp
+++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp
@@ -462,7 +462,7 @@ Z7_COM7F_IMF(CAltStreamsFolder::CreateFile(const wchar_t *name, IProgress * /* p
462 FString absPath; 462 FString absPath;
463 GetAbsPath(name, absPath); 463 GetAbsPath(name, absPath);
464 NIO::COutFile outFile; 464 NIO::COutFile outFile;
465 if (!outFile.Create(absPath, false)) 465 if (!outFile.Create_NEW(absPath))
466 return GetLastError_noZero_HRESULT(); 466 return GetLastError_noZero_HRESULT();
467 return S_OK; 467 return S_OK;
468} 468}
@@ -566,7 +566,7 @@ EXTERN_C_END
566 566
567// static Func_NtSetInformationFile f_NtSetInformationFile; 567// static Func_NtSetInformationFile f_NtSetInformationFile;
568// static bool g_NtSetInformationFile_WasRequested = false; 568// static bool g_NtSetInformationFile_WasRequested = false;
569 569Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
570 570
571Z7_COM7F_IMF(CAltStreamsFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress)) 571Z7_COM7F_IMF(CAltStreamsFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress))
572{ 572{
diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp
index 3461c92..d049fc9 100644
--- a/CPP/7zip/UI/FileManager/App.cpp
+++ b/CPP/7zip/UI/FileManager/App.cpp
@@ -35,7 +35,6 @@ using namespace NDir;
35using namespace NFind; 35using namespace NFind;
36using namespace NName; 36using namespace NName;
37 37
38extern DWORD g_ComCtl32Version;
39extern HINSTANCE g_hInstance; 38extern HINSTANCE g_hInstance;
40 39
41#define kTempDirPrefix FTEXT("7zE") 40#define kTempDirPrefix FTEXT("7zE")
diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h
index fc54501..1e20532 100644
--- a/CPP/7zip/UI/FileManager/App.h
+++ b/CPP/7zip/UI/FileManager/App.h
@@ -203,11 +203,19 @@ public:
203 int GetTimestampLevel() const { return Panels[LastFocusedPanel]._timestampLevel; } 203 int GetTimestampLevel() const { return Panels[LastFocusedPanel]._timestampLevel; }
204 void SetTimestampLevel(int level) 204 void SetTimestampLevel(int level)
205 { 205 {
206 unsigned i; 206 for (unsigned i = 0; i < kNumPanelsMax; i++)
207 for (i = 0; i < kNumPanelsMax; i++)
208 { 207 {
209 CPanel &panel = Panels[i]; 208 CPanel &panel = Panels[i];
210 panel._timestampLevel = level; 209 panel._timestampLevel = level;
210 }
211 RedrawListItems_InPanels();
212 }
213
214 void RedrawListItems_InPanels()
215 {
216 for (unsigned i = 0; i < kNumPanelsMax; i++)
217 {
218 CPanel &panel = Panels[i];
211 if (panel.PanelCreated) 219 if (panel.PanelCreated)
212 panel.RedrawListItems(); 220 panel.RedrawListItems();
213 } 221 }
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
index 5170302..6464ed8 100644
--- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
@@ -62,6 +62,9 @@ static void MessageBox_Error_Global(HWND wnd, const wchar_t *message)
62 62
63#ifdef USE_MY_BROWSE_DIALOG 63#ifdef USE_MY_BROWSE_DIALOG
64 64
65#if 0
66extern HINSTANCE g_hInstance;
67#endif
65extern bool g_LVN_ITEMACTIVATE_Support; 68extern bool g_LVN_ITEMACTIVATE_Support;
66 69
67static const int kParentIndex = -1; 70static const int kParentIndex = -1;
@@ -286,6 +289,39 @@ bool CBrowseDialog::OnInit()
286 PostMsg(Z7_WIN_WM_UPDATEUISTATE, MAKEWPARAM(Z7_WIN_UIS_CLEAR, Z7_WIN_UISF_HIDEFOCUS)); 289 PostMsg(Z7_WIN_WM_UPDATEUISTATE, MAKEWPARAM(Z7_WIN_UIS_CLEAR, Z7_WIN_UISF_HIDEFOCUS));
287 #endif 290 #endif
288 291
292#if 0
293 {
294 const HWND hwndTool = GetItem(IDB_BROWSE_CREATE_DIR);
295 if (hwndTool)
296 {
297 // Create the tooltip:
298 const HWND hwndTip = CreateWindowEx(0, TOOLTIPS_CLASS, NULL,
299 WS_POPUP | TTS_ALWAYSTIP
300 // | TTS_BALLOON
301 , CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
302 *this, NULL, g_hInstance, NULL);
303 if (hwndTip)
304 {
305 // Associate the tooltip with the tool:
306 TOOLINFOW toolInfo;
307 memset(&toolInfo, 0, sizeof(toolInfo));
308 toolInfo.cbSize = sizeof(toolInfo);
309 toolInfo.hwnd = *this;
310 toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
311 toolInfo.uId = (UINT_PTR)hwndTool;
312 UString s;
313#ifdef Z7_LANG
314 LangString_OnlyFromLangFile(IDM_CREATE_FOLDER, s);
315 s.RemoveChar(L'&');
316 if (s.IsEmpty())
317#endif
318 s = "Create Folder";
319 toolInfo.lpszText = s.Ptr_non_const();
320 SendMessage(hwndTip, TTM_ADDTOOLW, 0, (LPARAM)&toolInfo);
321 }
322 }
323 }
324#endif
289 return CModalDialog::OnInit(); 325 return CModalDialog::OnInit();
290} 326}
291 327
@@ -379,7 +415,7 @@ bool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header)
379 OnItemEnter(); 415 OnItemEnter();
380 break; 416 break;
381 case NM_DBLCLK: 417 case NM_DBLCLK:
382 case NM_RETURN: // probabably it's unused 418 case NM_RETURN: // probably it's unused
383 if (!g_LVN_ITEMACTIVATE_Support) 419 if (!g_LVN_ITEMACTIVATE_Support)
384 OnItemEnter(); 420 OnItemEnter();
385 break; 421 break;
@@ -483,15 +519,19 @@ bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, US
483 519
484int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2) const 520int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2) const
485{ 521{
522 if (lParam1 == lParam2) return 0;
486 if (lParam1 == kParentIndex) return -1; 523 if (lParam1 == kParentIndex) return -1;
487 if (lParam2 == kParentIndex) return 1; 524 if (lParam2 == kParentIndex) return 1;
525
488 const CFileInfo &f1 = _files[(int)lParam1]; 526 const CFileInfo &f1 = _files[(int)lParam1];
489 const CFileInfo &f2 = _files[(int)lParam2]; 527 const CFileInfo &f2 = _files[(int)lParam2];
490 528
491 const bool isDir1 = f1.IsDir();
492 const bool isDir2 = f2.IsDir(); 529 const bool isDir2 = f2.IsDir();
493 if (isDir1 && !isDir2) return -1; 530 if (f1.IsDir())
494 if (isDir2 && !isDir1) return 1; 531 {
532 if (!isDir2) return -1;
533 }
534 else if (isDir2) return 1;
495 535
496 int res = 0; 536 int res = 0;
497 switch (_sortIndex) 537 switch (_sortIndex)
@@ -508,7 +548,8 @@ static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
508 return ((CBrowseDialog *)lpData)->CompareItems(lParam1, lParam2); 548 return ((CBrowseDialog *)lpData)->CompareItems(lParam1, lParam2);
509} 549}
510 550
511static void ConvertSizeToString(UInt64 v, wchar_t *s) 551wchar_t *Browse_ConvertSizeToString(UInt64 v, wchar_t *s);
552wchar_t *Browse_ConvertSizeToString(UInt64 v, wchar_t *s)
512{ 553{
513 char c = 0; 554 char c = 0;
514 if (v >= ((UInt64)10000 << 20)) { v >>= 30; c = 'G'; } 555 if (v >= ((UInt64)10000 << 20)) { v >>= 30; c = 'G'; }
@@ -520,8 +561,9 @@ static void ConvertSizeToString(UInt64 v, wchar_t *s)
520 *s++ = ' '; 561 *s++ = ' ';
521 *s++ = (wchar_t)c; 562 *s++ = (wchar_t)c;
522 *s++ = 'B'; 563 *s++ = 'B';
523 *s++ = 0; 564 *s = 0;
524 } 565 }
566 return s;
525} 567}
526 568
527// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter 569// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
@@ -657,7 +699,7 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected
657 if (item.iImage < 0) 699 if (item.iImage < 0)
658 item.iImage = 0; 700 item.iImage = 0;
659 _list.InsertItem(&item); 701 _list.InsertItem(&item);
660 wchar_t s[32]; 702 wchar_t s[64];
661 { 703 {
662 s[0] = 0; 704 s[0] = 0;
663 ConvertUtcFileTimeToString(fi.MTime, s, 705 ConvertUtcFileTimeToString(fi.MTime, s,
@@ -672,7 +714,7 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected
672 { 714 {
673 s[0] = 0; 715 s[0] = 0;
674 if (!fi.IsDir()) 716 if (!fi.IsDir())
675 ConvertSizeToString(fi.Size, s); 717 Browse_ConvertSizeToString(fi.Size, s);
676 _list.SetSubItem(index, subItem++, s); 718 _list.SetSubItem(index, subItem++, s);
677 } 719 }
678 } 720 }
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog2.cpp b/CPP/7zip/UI/FileManager/BrowseDialog2.cpp
new file mode 100644
index 0000000..59f7527
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/BrowseDialog2.cpp
@@ -0,0 +1,1834 @@
1// BrowseDialog2.cpp
2
3#include "StdAfx.h"
4
5#ifdef UNDER_CE
6#include <commdlg.h>
7#endif
8
9#include <windowsx.h>
10
11#include "../../../Common/IntToString.h"
12#include "../../../Common/StringConvert.h"
13#include "../../../Common/Wildcard.h"
14
15#include "../../../Windows/DLL.h"
16#include "../../../Windows/FileFind.h"
17#include "../../../Windows/FileDir.h"
18#include "../../../Windows/FileName.h"
19#include "../../../Windows/Menu.h"
20#include "../../../Windows/ProcessUtils.h"
21#include "../../../Windows/PropVariantConv.h"
22#include "../../../Windows/Control/ComboBox.h"
23#include "../../../Windows/Control/Dialog.h"
24#include "../../../Windows/Control/Edit.h"
25#include "../../../Windows/Control/ListView.h"
26
27#include "../Explorer/MyMessages.h"
28
29#ifndef Z7_NO_REGISTRY
30#include "HelpUtils.h"
31#endif
32
33#include "../Common/PropIDUtils.h"
34
35#include "PropertyNameRes.h"
36#include "RegistryUtils.h"
37#include "SysIconUtils.h"
38#include "FormatUtils.h"
39#include "LangUtils.h"
40
41#include "resource.h"
42#include "BrowseDialog2Res.h"
43#include "BrowseDialog2.h"
44
45using namespace NWindows;
46using namespace NFile;
47using namespace NName;
48using namespace NFind;
49
50#ifndef _UNICODE
51extern bool g_IsNT;
52#endif
53
54extern bool g_LVN_ITEMACTIVATE_Support;
55
56static const int kParentIndex = -1;
57// static const UINT k_Message_RefreshPathEdit = WM_APP + 1;
58
59
60static const wchar_t *k_Message_Link_operation_was_Blocked =
61 L"link openning was blocked by 7-Zip";
62
63extern UString HResultToMessage(HRESULT errorCode);
64
65static void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *name)
66{
67 UString s = HResultToMessage(errorCode);
68 if (name)
69 {
70 s.Add_LF();
71 s += name;
72 }
73 ShowErrorMessage(wnd, s);
74}
75
76static void MessageBox_LastError_path(HWND wnd, const FString &path)
77{
78 const HRESULT hres = GetLastError_noZero_HRESULT();
79 MessageBox_HResError(wnd, hres, fs2us(path));
80}
81
82
83static const UInt32 k_EnumerateDirsLimit = 200;
84static const UInt32 k_EnumerateFilesLimit = 2000;
85
86struct CBrowseItem
87{
88 unsigned MainFileIndex;
89 int SubFileIndex;
90 bool WasInterrupted;
91 UInt32 NumFiles;
92 UInt32 NumDirs;
93 UInt32 NumRootItems;
94 UInt64 Size;
95
96 CBrowseItem():
97 // MainFileIndex(0),
98 SubFileIndex(-1),
99 WasInterrupted(false),
100 NumFiles(0),
101 NumDirs(0),
102 NumRootItems(0),
103 Size(0)
104 {}
105};
106
107
108struct CBrowseEnumerator
109{
110 FString Path; // folder path without slash at the end
111 CFileInfo fi; // temp
112 CFileInfo fi_SubFile;
113 CBrowseItem bi;
114
115 void Enumerate(unsigned level);
116 bool NeedInterrupt() const
117 {
118 return bi.NumFiles >= k_EnumerateFilesLimit
119 || bi.NumDirs >= k_EnumerateDirsLimit;
120 }
121};
122
123void CBrowseEnumerator::Enumerate(unsigned level)
124{
125 Path.Add_PathSepar();
126 const unsigned len = Path.Len();
127 CObjectVector<FString> names;
128 {
129 CEnumerator enumerator;
130 enumerator.SetDirPrefix(Path);
131 while (enumerator.Next(fi))
132 {
133 if (level == 0)
134 {
135 if (bi.NumRootItems == 0)
136 fi_SubFile = fi;
137 bi.NumRootItems++;
138 }
139
140 if (fi.IsDir())
141 {
142 bi.NumDirs++;
143 if (!fi.HasReparsePoint())
144 names.Add(fi.Name);
145 }
146 else
147 {
148 bi.NumFiles++;
149 bi.Size += fi.Size;
150 }
151
152 if (level != 0 || bi.NumRootItems > 1)
153 if (NeedInterrupt())
154 {
155 bi.WasInterrupted = true;
156 return;
157 }
158 }
159 }
160
161 FOR_VECTOR (i, names)
162 {
163 if (NeedInterrupt())
164 {
165 bi.WasInterrupted = true;
166 return;
167 }
168 Path.DeleteFrom(len);
169 Path += names[i];
170 Enumerate(level + 1);
171 }
172}
173
174
175
176
177class CBrowseDialog2: public NControl::CModalDialog
178{
179 CRecordVector<CBrowseItem> _items;
180 CObjectVector<CFileInfo> _files;
181
182 NControl::CListView _list;
183 // NControl::CEdit _pathEdit;
184 NControl::CComboBox _filterCombo;
185
186 CExtToIconMap _extToIconMap;
187 int _sortIndex;
188 int _columnIndex_fileNameInDir;
189 int _columnIndex_NumFiles;
190 int _columnIndex_NumDirs;
191 bool _ascending;
192 #ifndef Z7_SFX
193 bool _showDots;
194 #endif
195 UString _topDirPrefix; // we don't open parent of that folder
196 UString DirPrefix;
197
198 virtual bool OnInit() Z7_override;
199 virtual bool OnSize(WPARAM wParam, int xSize, int ySize) Z7_override;
200 virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam) Z7_override;
201 virtual bool OnNotify(UINT controlID, LPNMHDR header) Z7_override;
202 // virtual bool OnCommand(unsigned code, unsigned itemID, LPARAM lParam) Z7_override;
203 virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;
204 virtual void OnOK() Z7_override;
205
206 bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo);
207
208 // void Post_RefreshPathEdit() { PostMsg(k_Message_RefreshPathEdit); }
209 bool GetParentPath(const UString &path, UString &parentPrefix, UString &name);
210 // Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
211 HRESULT Reload(const UString &pathPrefix, const UStringVector &selectedNames, const UString &focusedName);
212 HRESULT Reload(const UString &pathPrefix, const UString &selectedNames);
213 HRESULT Reload();
214
215 void ChangeSorting_and_Reload(int columnIndex);
216
217 const CFileInfo & Get_MainFileInfo_for_realIndex(unsigned realIndex) const
218 {
219 return _files[_items[realIndex].MainFileIndex];
220 }
221
222 const FString & Get_MainFileName_for_realIndex(unsigned realIndex) const
223 {
224 return Get_MainFileInfo_for_realIndex(realIndex).Name;
225 }
226
227 void Reload_WithErrorMessage();
228 void OpenParentFolder();
229 // void SetPathEditText();
230 void PrintFileProps(UString &s, const CFileInfo &file);
231 void Show_FileProps_Window(const CFileInfo &file);
232 void OnItemEnter();
233 // void FinishOnOK();
234 void OnDelete(/* bool toRecycleBin */);
235 virtual void OnHelp() Z7_override;
236 bool OnContextMenu(HANDLE windowHandle, int xPos, int yPos);
237
238 int GetRealItemIndex(int indexInListView) const
239 {
240 LPARAM param;
241 if (!_list.GetItemParam((unsigned)indexInListView, param))
242 return (int)-1;
243 return (int)param;
244 }
245
246 void GetSelected_RealIndexes(CUIntVector &vector);
247
248public:
249 // bool TempMode;
250 // bool Show_Non7zDirs_InTemp;
251 // int FilterIndex; // [in / out]
252 // CObjectVector<CBrowseFilterInfo> Filters;
253
254 UString TempFolderPath; // with slash
255 UString Title;
256
257 bool IsExactTempFolder(const UString &pathPrefix) const
258 {
259 return CompareFileNames(pathPrefix, TempFolderPath) == 0;
260 }
261
262 CBrowseDialog2():
263 #ifndef Z7_SFX
264 _showDots(false)
265 #endif
266 // , TempMode(false)
267 // Show_Non7zDirs_InTemp(false),
268 // FilterIndex(-1)
269 {}
270 INT_PTR Create(HWND parent = NULL) { return CModalDialog::Create(IDD_BROWSE2, parent); }
271 int CompareItems(LPARAM lParam1, LPARAM lParam2) const;
272};
273
274
275#ifdef Z7_LANG
276static const UInt32 kLangIDs[] =
277{
278 IDS_BUTTON_DELETE,
279 IDM_VIEW_REFRESH
280};
281#endif
282
283bool CBrowseDialog2::OnInit()
284{
285 #ifdef Z7_LANG
286 LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));
287 #endif
288 if (!Title.IsEmpty())
289 SetText(Title);
290
291 _list.Attach(GetItem(IDL_BROWSE2));
292 _filterCombo.Attach(GetItem(IDC_BROWSE2_FILTER));
293
294 _ascending = true;
295 _sortIndex = 0;
296 _columnIndex_fileNameInDir = -1;
297 _columnIndex_NumFiles = -1;
298 _columnIndex_NumDirs = -1;
299 // _pathEdit.Attach(GetItem(IDE_BROWSE_PATH));
300
301 #ifndef UNDER_CE
302 _list.SetUnicodeFormat();
303 #endif
304
305 #ifndef Z7_SFX
306 {
307 CFmSettings st;
308 st.Load();
309
310 DWORD extendedStyle = 0;
311 if (st.FullRow)
312 extendedStyle |= LVS_EX_FULLROWSELECT;
313 if (st.ShowGrid)
314 extendedStyle |= LVS_EX_GRIDLINES;
315 if (st.SingleClick)
316 {
317 extendedStyle |= LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT;
318 /*
319 if (ReadUnderline())
320 extendedStyle |= LVS_EX_UNDERLINEHOT;
321 */
322 }
323 if (extendedStyle)
324 _list.SetExtendedListViewStyle(extendedStyle);
325 _showDots = st.ShowDots;
326 }
327 #endif
328
329 {
330 /*
331 Filters.Clear(); // for debug
332 if (Filters.IsEmpty() && !FolderMode)
333 {
334 CBrowseFilterInfo &f = Filters.AddNew();
335 const UString mask("*.*");
336 f.Masks.Add(mask);
337 // f.Description = "(";
338 f.Description += mask;
339 // f.Description += ")";
340 }
341 */
342 _filterCombo.AddString(L"7-Zip temp files (7z*)");
343 _filterCombo.SetCurSel(0);
344 EnableItem(IDC_BROWSE2_FILTER, false);
345#if 0
346 FOR_VECTOR (i, Filters)
347 {
348 _filterCombo.AddString(Filters[i].Description);
349 }
350 if (Filters.Size() <= 1)
351 {
352 EnableItem(IDC_BROWSE_FILTER, false);
353 }
354 if (/* FilterIndex >= 0 && */ (unsigned)FilterIndex < Filters.Size())
355 _filterCombo.SetCurSel(FilterIndex);
356#endif
357 }
358
359 _list.SetImageList(GetSysImageList(true), LVSIL_SMALL);
360 _list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
361
362 unsigned columnIndex = 0;
363 _list.InsertColumn(columnIndex++, LangString(IDS_PROP_NAME), 100);
364 _list.InsertColumn(columnIndex++, LangString(IDS_PROP_MTIME), 100);
365 {
366 LV_COLUMNW column;
367 column.iSubItem = (int)columnIndex;
368 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
369 column.fmt = LVCFMT_RIGHT;
370 column.cx = 100;
371 UString s = LangString(IDS_PROP_SIZE);
372 column.pszText = s.Ptr_non_const();
373 _list.InsertColumn(columnIndex++, &column);
374
375 // if (TempMode)
376 {
377 _columnIndex_NumFiles = (int)columnIndex;
378 s = LangString(IDS_PROP_FILES);
379 column.pszText = s.Ptr_non_const();
380 _list.InsertColumn(columnIndex++, &column);
381
382 _columnIndex_NumDirs = (int)columnIndex;
383 s = LangString(IDS_PROP_FOLDERS);
384 column.pszText = s.Ptr_non_const();
385 _list.InsertColumn(columnIndex++, &column);
386
387 _columnIndex_fileNameInDir = (int)columnIndex;
388 s = LangString(IDS_PROP_NAME);
389 s += "-2";
390 _list.InsertColumn(columnIndex++, s, 100);
391 }
392 }
393
394 _list.InsertItem(0, L"12345678901234567"
395 #ifndef UNDER_CE
396 L"1234567890"
397 #endif
398 );
399 _list.SetSubItem(0, 1, L"2009-09-09"
400 #ifndef UNDER_CE
401 L" 09:09:09"
402 #endif
403 );
404 _list.SetSubItem(0, 2, L"99999 MB+");
405
406 if (_columnIndex_NumFiles >= 0)
407 _list.SetSubItem(0, (unsigned)_columnIndex_NumFiles, L"123456789+");
408 if (_columnIndex_NumDirs >= 0)
409 _list.SetSubItem(0, (unsigned)_columnIndex_NumDirs, L"123456789+");
410 if (_columnIndex_fileNameInDir >= 0)
411 _list.SetSubItem(0, (unsigned)_columnIndex_fileNameInDir, L"12345678901234567890");
412
413 for (unsigned i = 0; i < columnIndex; i++)
414 _list.SetColumnWidthAuto((int)i);
415 _list.DeleteAllItems();
416
417 // if (TempMode)
418 {
419 _sortIndex = 1; // for MTime column
420 // _ascending = false;
421 }
422
423
424 NormalizeSize();
425
426 _topDirPrefix.Empty();
427 {
428 unsigned rootSize = GetRootPrefixSize(TempFolderPath);
429 #if defined(_WIN32) && !defined(UNDER_CE)
430 // We can go up from root folder to drives list
431 if (IsDrivePath(TempFolderPath))
432 rootSize = 0;
433 else if (IsSuperPath(TempFolderPath))
434 {
435 if (IsDrivePath(TempFolderPath.Ptr(kSuperPathPrefixSize)))
436 rootSize = kSuperPathPrefixSize;
437 }
438 #endif
439 _topDirPrefix.SetFrom(TempFolderPath, rootSize);
440 }
441
442 if (Reload(TempFolderPath, UString()) != S_OK)
443 {
444 // return false;
445 }
446/*
447 UString name;
448 DirPrefix = TempFolderPath;
449 for (;;)
450 {
451 UString baseFolder = DirPrefix;
452 if (Reload(baseFolder, name) == S_OK)
453 break;
454 name.Empty();
455 if (DirPrefix.IsEmpty())
456 break;
457 UString parent, name2;
458 GetParentPath(DirPrefix, parent, name2);
459 DirPrefix = parent;
460 }
461*/
462
463 #ifndef UNDER_CE
464 /* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible,
465 even if we use mouse for pressing the button to open this dialog. */
466 PostMsg(Z7_WIN_WM_UPDATEUISTATE, MAKEWPARAM(Z7_WIN_UIS_CLEAR, Z7_WIN_UISF_HIDEFOCUS));
467 #endif
468
469 /*
470 */
471
472 return CModalDialog::OnInit();
473}
474
475
476bool CBrowseDialog2::OnSize(WPARAM /* wParam */, int xSize, int ySize)
477{
478 int mx, my;
479 {
480 RECT r;
481 GetClientRectOfItem(IDS_BUTTON_DELETE, r);
482 mx = r.left;
483 my = r.top;
484 }
485 InvalidateRect(NULL);
486
487 const int xLim = xSize - mx;
488 {
489 RECT r;
490 GetClientRectOfItem(IDT_BROWSE2_FOLDER, r);
491 MoveItem(IDT_BROWSE2_FOLDER, r.left, r.top, xLim - r.left, RECT_SIZE_Y(r));
492 }
493
494 int bx1, bx2, by;
495 GetItemSizes(IDCLOSE, bx1, by);
496 GetItemSizes(IDHELP, bx2, by);
497 const int y = ySize - my - by;
498 const int x = xLim - bx1;
499 MoveItem(IDCLOSE, x - mx - bx2, y, bx1, by);
500 MoveItem(IDHELP, x, y, bx2, by);
501 /*
502 int yPathSize;
503 {
504 RECT r;
505 GetClientRectOfItem(IDE_BROWSE_PATH, r);
506 yPathSize = RECT_SIZE_Y(r);
507 _pathEdit.Move(r.left, y - my - yPathSize - my - yPathSize, xLim - r.left, yPathSize);
508 }
509 */
510 // Y_Size of ComboBox is tricky. Can we use it?
511 int yFilterSize;
512 {
513 RECT r;
514 GetClientRectOfItem(IDC_BROWSE2_FILTER, r);
515 yFilterSize = RECT_SIZE_Y(r);
516 _filterCombo.Move(r.left, y - my - yFilterSize, xLim - r.left, yFilterSize);
517 }
518 {
519 RECT r;
520 GetClientRectOfItem(IDL_BROWSE2, r);
521 _list.Move(r.left, r.top, xLim - r.left, y - my - yFilterSize - my - r.top);
522 }
523 return false;
524}
525
526
527bool CBrowseDialog2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
528{
529 /*
530 if (message == k_Message_RefreshPathEdit)
531 {
532 // SetPathEditText();
533 return true;
534 }
535 */
536 if (message == WM_CONTEXTMENU)
537 {
538 if (OnContextMenu((HANDLE)wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)))
539 return true;
540 }
541 return CModalDialog::OnMessage(message, wParam, lParam);
542}
543
544
545/*
546bool CBrowseDialog2::OnCommand(unsigned code, unsigned itemID, LPARAM lParam)
547{
548 if (code == CBN_SELCHANGE)
549 {
550 switch (itemID)
551 {
552 case IDC_BROWSE2_FILTER:
553 {
554 Reload();
555 return true;
556 }
557 }
558 }
559 return CModalDialog::OnCommand(code, itemID, lParam);
560}
561*/
562
563bool CBrowseDialog2::OnNotify(UINT /* controlID */, LPNMHDR header)
564{
565 if (header->hwndFrom != _list)
566 {
567 if (::GetParent(header->hwndFrom) == _list)
568 {
569 // NMHDR:code is UINT
570 // NM_RCLICK is unsigned in windows sdk
571 // NM_RCLICK is int in MinGW
572 if (header->code == (UINT)NM_RCLICK)
573 {
574#ifdef UNDER_CE
575#define MY_NMLISTVIEW_NMITEMACTIVATE NMLISTVIEW
576#else
577#define MY_NMLISTVIEW_NMITEMACTIVATE NMITEMACTIVATE
578#endif
579 MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate = (MY_NMLISTVIEW_NMITEMACTIVATE *)header;
580 if (itemActivate->hdr.hwndFrom == HWND(_list))
581 return false;
582 /*
583 POINT point;
584 ::GetCursorPos(&point);
585 ShowColumnsContextMenu(point.x, point.y);
586 */
587 // we want to disable menu for columns.
588 // to return the value from a dialog procedure we must
589 // call SetMsgResult(val) and return true;
590 // NM_RCLICK : Return nonzero to not allow the default processing
591 SetMsgResult(TRUE); // do not allow default processing
592 return true;
593 }
594 }
595 return false;
596 }
597
598 switch (header->code)
599 {
600 case LVN_ITEMACTIVATE:
601 if (g_LVN_ITEMACTIVATE_Support)
602 OnItemEnter();
603 break;
604 case NM_DBLCLK:
605 case NM_RETURN: // probably it's unused
606 if (!g_LVN_ITEMACTIVATE_Support)
607 OnItemEnter();
608 break;
609 case LVN_COLUMNCLICK:
610 {
611 const int index = LPNMLISTVIEW(header)->iSubItem;
612 ChangeSorting_and_Reload(index);
613 return false;
614 }
615 case LVN_KEYDOWN:
616 {
617 bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header));
618 // Post_RefreshPathEdit();
619 return boolResult;
620 }
621 /*
622 case NM_RCLICK:
623 case NM_CLICK:
624 case LVN_BEGINDRAG:
625 Post_RefreshPathEdit();
626 break;
627 */
628 }
629
630 return false;
631}
632
633bool CBrowseDialog2::OnKeyDown(LPNMLVKEYDOWN keyDownInfo)
634{
635 const bool ctrl = IsKeyDown(VK_CONTROL);
636 // const bool alt = IsKeyDown(VK_MENU);
637 // const bool leftCtrl = IsKeyDown(VK_LCONTROL);
638 // const bool rightCtrl = IsKeyDown(VK_RCONTROL);
639 // const bool shift = IsKeyDown(VK_SHIFT);
640
641 switch (keyDownInfo->wVKey)
642 {
643 case VK_BACK:
644 OpenParentFolder();
645 return true;
646 case 'R':
647 if (ctrl)
648 {
649 Reload_WithErrorMessage();
650 return true;
651 }
652 return false;
653 case VK_F3:
654 case VK_F5:
655 case VK_F6:
656 if (ctrl)
657 {
658 int index = 0; // name
659 if (keyDownInfo->wVKey == VK_F5) index = 1; // MTime
660 else if (keyDownInfo->wVKey == VK_F6) index = 2; // Size
661 ChangeSorting_and_Reload(index);
662 Reload_WithErrorMessage();
663 return true;
664 }
665 return false;
666 case 'A':
667 if (ctrl)
668 {
669 // if (TempMode)
670 _list.SelectAll();
671 return true;
672 }
673 return false;
674
675 case VK_DELETE:
676 // if (TempMode)
677 OnDelete(/* !shift */);
678 return true;
679#if 0
680 case VK_NEXT:
681 case VK_PRIOR:
682 {
683 if (ctrl && !alt && !shift)
684 {
685 if (keyDownInfo->wVKey == VK_NEXT)
686 OnItemEnter();
687 else
688 OpenParentFolder();
689 SetMsgResult(TRUE); // to disable processing
690 return true;
691 }
692 break;
693 }
694#endif
695 }
696 return false;
697}
698
699
700bool CBrowseDialog2::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
701{
702 switch (buttonID)
703 {
704 case IDB_BROWSE2_PARENT: OpenParentFolder(); break;
705 case IDS_BUTTON_DELETE:
706 {
707 OnDelete(/* !IsKeyDown(VK_SHIFT) */);
708 break;
709 }
710 case IDM_VIEW_REFRESH:
711 {
712 Reload_WithErrorMessage();
713 break;
714 }
715 default: return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
716 }
717 _list.SetFocus();
718 return true;
719}
720
721
722
723static void PrintPropsPrefix(UString &s, UInt32 id)
724{
725 s.Add_LF();
726 s += " ";
727 AddLangString(s, id);
728 s += ": ";
729}
730
731wchar_t *Browse_ConvertSizeToString(UInt64 v, wchar_t *s);
732
733static void Browse_ConvertSizeToString(const CBrowseItem &bi, wchar_t *s)
734{
735 s = Browse_ConvertSizeToString(bi.Size, s);
736 if (bi.WasInterrupted)
737 {
738 *s++ = '+';
739 *s = 0;
740 }
741}
742
743void AddSizeValue(UString &s, UInt64 value);
744
745static void PrintProps_Size(UString &s, UInt64 size)
746{
747 PrintPropsPrefix(s, IDS_PROP_SIZE);
748#if 1
749 AddSizeValue(s, size);
750#else
751 s.Add_UInt64(size);
752 if (size >= 10000)
753 {
754 s += " (";
755 wchar_t temp[64];
756 Browse_ConvertSizeToString(size, temp);
757 s += temp;
758 s.Add_Char(')');
759 }
760#endif
761}
762
763static void PrintProps_MTime(UString &s, const CFileInfo &fi)
764{
765 PrintPropsPrefix(s, IDS_PROP_MTIME);
766 char t[64];
767 ConvertUtcFileTimeToString(fi.MTime, t);
768 s += t;
769}
770
771
772static void PrintProps_Name(UString &s, const CFileInfo &fi)
773{
774 s += fs2us(fi.Name);
775 if (fi.IsDir())
776 s.Add_PathSepar();
777}
778
779static void PrintProps_Attrib(UString &s, const CFileInfo &fi)
780{
781 PrintPropsPrefix(s, IDS_PROP_ATTRIBUTES);
782 char props[64];
783 ConvertWinAttribToString(props, fi.Attrib);
784 s += props;
785#if 0
786 if (fi.HasReparsePoint())
787 {
788 s.Add_LF();
789 s += "IsLink: +";
790 }
791#endif
792}
793
794static void PrintProps(UString &s, const CBrowseItem &bi,
795 const CFileInfo &fi, const CFileInfo *fi2)
796{
797 PrintProps_Name(s, fi);
798 PrintProps_Attrib(s, fi);
799 if (bi.NumDirs != 0)
800 {
801 PrintPropsPrefix(s, IDS_PROP_FOLDERS);
802 s.Add_UInt32(bi.NumDirs);
803 if (bi.WasInterrupted)
804 s += "+";
805 }
806 if (bi.NumFiles != 0)
807 {
808 PrintPropsPrefix(s, IDS_PROP_FILES);
809 s.Add_UInt32(bi.NumFiles);
810 if (bi.WasInterrupted)
811 s += "+";
812 }
813 {
814 PrintProps_Size(s, bi.Size);
815 if (bi.WasInterrupted)
816 s += "+";
817 }
818
819 PrintProps_MTime(s, fi);
820
821 if (fi2)
822 {
823 s.Add_LF();
824 s += "----------------";
825 s.Add_LF();
826 PrintProps_Name(s, *fi2);
827 PrintProps_Attrib(s, *fi2);
828 if (!fi2->IsDir())
829 PrintProps_Size(s, fi2->Size);
830 PrintProps_MTime(s, *fi2);
831 }
832}
833
834
835void CBrowseDialog2::GetSelected_RealIndexes(CUIntVector &vector)
836{
837 vector.Clear();
838 int index = -1;
839 for (;;)
840 {
841 index = _list.GetNextSelectedItem(index);
842 if (index < 0)
843 break;
844 const int realIndex = GetRealItemIndex(index);
845 if (realIndex >= 0)
846 vector.Add((unsigned)realIndex);
847 }
848}
849
850
851void CBrowseDialog2::PrintFileProps(UString &s, const CFileInfo &file)
852{
853 CFileInfo file2;
854 FString path = us2fs(DirPrefix);
855 path += file.Name;
856 if (!file2.Find(path))
857 {
858 MessageBox_LastError_path(*this, path);
859 Reload_WithErrorMessage();
860 return;
861 }
862 CBrowseEnumerator enumer;
863 enumer.bi.Size = file2.Size;
864 if (file2.IsDir() && !file2.HasReparsePoint())
865 {
866 enumer.Path = path;
867 enumer.Enumerate(0); // level
868 }
869 PrintProps(s, enumer.bi, file2,
870 enumer.bi.NumRootItems == 1 ? &enumer.fi_SubFile : NULL);
871}
872
873
874void CBrowseDialog2::Show_FileProps_Window(const CFileInfo &file)
875{
876 UString s;
877 PrintFileProps(s, file);
878 MessageBoxW(*this, s, LangString(IDS_PROPERTIES), MB_OK);
879}
880
881
882void CBrowseDialog2::OnDelete(/* bool toRecycleBin */)
883{
884#if 1
885 // we don't want deleting in non temp folders
886 if (!DirPrefix.IsPrefixedBy(TempFolderPath))
887 return;
888#endif
889
890 CUIntVector indices;
891 GetSelected_RealIndexes(indices);
892 if (indices.Size() == 0)
893 return;
894 {
895 UInt32 titleID, messageID;
896 UString messageParam;
897 UString s2;
898 if (indices.Size() == 1)
899 {
900 const unsigned index = indices[0];
901 const CBrowseItem &bi = _items[index];
902 const CFileInfo &file = _files[bi.MainFileIndex];
903 PrintFileProps(s2, file);
904 messageParam = fs2us(file.Name);
905 if (file.IsDir())
906 {
907 titleID = IDS_CONFIRM_FOLDER_DELETE;
908 messageID = IDS_WANT_TO_DELETE_FOLDER;
909 }
910 else
911 {
912 titleID = IDS_CONFIRM_FILE_DELETE;
913 messageID = IDS_WANT_TO_DELETE_FILE;
914 }
915 }
916 else
917 {
918 titleID = IDS_CONFIRM_ITEMS_DELETE;
919 messageID = IDS_WANT_TO_DELETE_ITEMS;
920 messageParam = NumberToString(indices.Size());
921
922 for (UInt32 i = 0; i < indices.Size(); i++)
923 {
924 if (i >= 10)
925 {
926 s2 += "...";
927 break;
928 }
929 const CBrowseItem &bi = _items[indices[i]];
930 const CFileInfo &fi = _files[bi.MainFileIndex];
931 PrintProps_Name(s2, fi);
932 s2.Add_LF();
933 }
934 }
935 UString s = MyFormatNew(messageID, messageParam);
936 if (!s2.IsEmpty())
937 {
938 s.Add_LF();
939 s.Add_LF();
940 s += s2;
941 }
942 if (::MessageBoxW((HWND)*this, s, LangString(titleID), MB_OKCANCEL | MB_ICONQUESTION) != IDOK)
943 return;
944 }
945
946 for (UInt32 i = 0; i < indices.Size(); i++)
947 {
948 const unsigned index = indices[i];
949 bool result = true;
950 const CBrowseItem &bi = _items[index];
951 const CFileInfo &fi = _files[bi.MainFileIndex];
952 if (fi.Name.IsEmpty())
953 return; // some error
954 const FString fullPath = us2fs(DirPrefix) + fi.Name;
955 if (fi.IsDir())
956 result = NFile::NDir::RemoveDirWithSubItems(fullPath);
957 else
958 result = NFile::NDir::DeleteFileAlways(fullPath);
959 if (!result)
960 {
961 MessageBox_LastError_path(*this, fullPath);
962 return;
963 }
964 }
965
966 Reload_WithErrorMessage();
967}
968
969
970#ifndef Z7_NO_REGISTRY
971#define kHelpTopic "fm/temp.htm"
972void CBrowseDialog2::OnHelp()
973{
974 ShowHelpWindow(kHelpTopic);
975 CModalDialog::OnHelp();
976}
977#endif
978
979
980HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process);
981HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process)
982{
983 UString path2 = path;
984
985 #ifdef _WIN32
986 {
987 const int dot = path2.ReverseFind_Dot();
988 const int separ = path2.ReverseFind_PathSepar();
989 if (dot < 0 || dot < separ)
990 path2.Add_Dot();
991 }
992 #endif
993
994 UINT32 result;
995
996#ifndef _UNICODE
997 if (g_IsNT)
998 {
999 SHELLEXECUTEINFOW execInfo;
1000 execInfo.cbSize = sizeof(execInfo);
1001 execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
1002 execInfo.hwnd = NULL;
1003 execInfo.lpVerb = NULL;
1004 execInfo.lpFile = path2;
1005 execInfo.lpParameters = NULL;
1006 execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir;
1007 execInfo.nShow = SW_SHOWNORMAL;
1008 execInfo.hProcess = NULL;
1009typedef BOOL (WINAPI * Func_ShellExecuteExW)(LPSHELLEXECUTEINFOW lpExecInfo);
1010Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
1011 const
1012 Func_ShellExecuteExW
1013 f_ShellExecuteExW = Z7_GET_PROC_ADDRESS(
1014 Func_ShellExecuteExW, ::GetModuleHandleW(L"shell32.dll"),
1015 "ShellExecuteExW");
1016 if (!f_ShellExecuteExW)
1017 return 0;
1018 f_ShellExecuteExW(&execInfo);
1019 result = (UINT32)(UINT_PTR)execInfo.hInstApp;
1020 process.Attach(execInfo.hProcess);
1021 }
1022 else
1023#endif
1024 {
1025 SHELLEXECUTEINFO execInfo;
1026 execInfo.cbSize = sizeof(execInfo);
1027 execInfo.fMask = SEE_MASK_NOCLOSEPROCESS
1028 #ifndef UNDER_CE
1029 | SEE_MASK_FLAG_DDEWAIT
1030 #endif
1031 ;
1032 execInfo.hwnd = NULL;
1033 execInfo.lpVerb = NULL;
1034 const CSysString sysPath (GetSystemString(path2));
1035 const CSysString sysDir (GetSystemString(dir));
1036 execInfo.lpFile = sysPath;
1037 execInfo.lpParameters = NULL;
1038 execInfo.lpDirectory =
1039 #ifdef UNDER_CE
1040 NULL
1041 #else
1042 sysDir.IsEmpty() ? NULL : (LPCTSTR)sysDir
1043 #endif
1044 ;
1045 execInfo.nShow = SW_SHOWNORMAL;
1046 execInfo.hProcess = NULL;
1047 ::ShellExecuteEx(&execInfo);
1048 result = (UINT32)(UINT_PTR)execInfo.hInstApp;
1049 process.Attach(execInfo.hProcess);
1050 }
1051
1052 // DEBUG_PRINT_NUM("-- ShellExecuteEx -- execInfo.hInstApp = ", result)
1053
1054 if (result <= 32)
1055 {
1056 switch (result)
1057 {
1058 case SE_ERR_NOASSOC:
1059 MessageBox_HResError(window,
1060 GetLastError_noZero_HRESULT(),
1061 NULL
1062 // L"There is no application associated with the given file name extension",
1063 );
1064 }
1065
1066 return E_FAIL; // fixed in 15.13. Can we use it for any Windows version?
1067 }
1068
1069 return S_OK;
1070}
1071
1072void StartApplicationDontWait(const UString &dir, const UString &path, HWND window);
1073void StartApplicationDontWait(const UString &dir, const UString &path, HWND window)
1074{
1075 CProcess process;
1076 StartApplication(dir, path, window, process);
1077}
1078
1079
1080static UString GetQuotedString2(const UString &s)
1081{
1082 UString s2 ('\"');
1083 s2 += s;
1084 s2.Add_Char('\"');
1085 return s2;
1086}
1087
1088
1089bool CBrowseDialog2::OnContextMenu(HANDLE windowHandle, int xPos, int yPos)
1090{
1091 if (windowHandle != _list)
1092 return false;
1093
1094 CUIntVector indices;
1095 GetSelected_RealIndexes(indices);
1096
1097 // negative x,y are possible for multi-screen modes.
1098 // x=-1 && y=-1 for keyboard call (SHIFT+F10 and others).
1099#if 1 // 0 : for debug
1100 if (xPos == -1 && yPos == -1)
1101#endif
1102 {
1103/*
1104 if (indices.Size() == 0)
1105 {
1106 xPos = 0;
1107 yPos = 0;
1108 }
1109 else
1110*/
1111 {
1112 const int itemIndex = _list.GetFocusedItem();
1113 if (itemIndex == -1)
1114 return false;
1115 RECT rect;
1116 if (!_list.GetItemRect(itemIndex, &rect, LVIR_ICON))
1117 return false;
1118 // rect : rect of file icon relative to listVeiw.
1119 xPos = (rect.left + rect.right) / 2;
1120 yPos = (rect.top + rect.bottom) / 2;
1121 RECT r;
1122 GetClientRectOfItem(IDL_BROWSE2, r);
1123 if (yPos < 0 || yPos >= RECT_SIZE_Y(r))
1124 yPos = 0;
1125 }
1126 POINT point = {xPos, yPos};
1127 _list.ClientToScreen(&point);
1128 xPos = point.x;
1129 yPos = point.y;
1130 }
1131
1132 const UInt32 k_CmdId_Delete = 1;
1133 const UInt32 k_CmdId_Open_Explorer = 2;
1134 const UInt32 k_CmdId_Open_7zip = 3;
1135 const UInt32 k_CmdId_Props = 4;
1136 int menuResult;
1137 {
1138 CMenu menu;
1139 CMenuDestroyer menuDestroyer(menu);
1140 menu.CreatePopup();
1141
1142 unsigned numMenuItems = 0;
1143 // unsigned defaultCmd = 0;
1144
1145 for (unsigned cmd = k_CmdId_Delete; cmd <= k_CmdId_Props; cmd++)
1146 {
1147 if (cmd == k_CmdId_Delete)
1148 {
1149 if (/* !TempMode || */ indices.Size() == 0)
1150 continue;
1151 // defaultCmd = cmd;
1152 }
1153 else if (indices.Size() > 1)
1154 break;
1155
1156
1157 if (numMenuItems != 0)
1158 {
1159 if (cmd == k_CmdId_Open_Explorer)
1160 menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)NULL);
1161 if (cmd == k_CmdId_Props)
1162 menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)NULL);
1163 }
1164
1165 const UINT flags = MF_STRING;
1166 UString s;
1167 if (cmd == k_CmdId_Delete)
1168 {
1169 s = LangString(IDS_BUTTON_DELETE);
1170 s += "\tDelete";
1171 }
1172 else if (cmd == k_CmdId_Open_Explorer)
1173 {
1174 s = LangString(IDM_OPEN_OUTSIDE);
1175 if (s.IsEmpty())
1176 s = "Open Outside";
1177 s += "\tShift+Enter";
1178 }
1179 else if (cmd == k_CmdId_Open_7zip)
1180 {
1181 s = LangString(IDM_OPEN_OUTSIDE);
1182 if (s.IsEmpty())
1183 s = "Open Outside";
1184 s += " : 7-Zip";
1185 }
1186 else if (cmd == k_CmdId_Props)
1187 {
1188 s = LangString(IDS_PROPERTIES);
1189 if (s.IsEmpty())
1190 s = "Properties";
1191 s += "\tAlt+Enter";
1192 }
1193 else
1194 break;
1195 s.RemoveChar(L'&');
1196 menu.AppendItem(flags, cmd, s);
1197 numMenuItems++;
1198 }
1199 // default item is useless for us
1200 /*
1201 if (defaultCmd != 0)
1202 SetMenuDefaultItem(menu, (unsigned)defaultCmd,
1203 FALSE); // byPos
1204 */
1205 /* hwnd for TrackPopupMenuEx(): DOCS:
1206 A handle to the window that owns the shortcut menu.
1207 This window receives all messages from the menu.
1208 The window does not receive a WM_COMMAND message from the menu
1209 until the function returns.
1210 If you specify TPM_NONOTIFY in the fuFlags parameter,
1211 the function does not send messages to the window identified by hwnd.
1212 */
1213 if (numMenuItems == 0)
1214 return true;
1215 menuResult = menu.Track(TPM_LEFTALIGN | TPM_RETURNCMD | TPM_NONOTIFY,
1216 xPos, yPos, *this);
1217 /* menu.Track() return value is zero, if the user cancels
1218 the menu without making a selection, or if an error occurs */
1219 if (menuResult <= 0)
1220 return true;
1221 }
1222
1223 if (menuResult == k_CmdId_Delete)
1224 {
1225 OnDelete(/* !IsKeyDown(VK_SHIFT) */);
1226 return true;
1227 }
1228
1229 if (indices.Size() <= 1)
1230 {
1231 UString fullPath = DirPrefix;
1232 if (indices.Size() != 0)
1233 {
1234 const CBrowseItem &bi = _items[indices[0]];
1235 const CFileInfo &file = _files[bi.MainFileIndex];
1236 if (file.HasReparsePoint())
1237 {
1238 // we don't want external program was used to work with Links
1239 ShowErrorMessage(*this, k_Message_Link_operation_was_Blocked);
1240 return true;
1241 }
1242 fullPath += fs2us(file.Name);
1243 }
1244 if (menuResult == k_CmdId_Open_Explorer)
1245 {
1246 StartApplicationDontWait(DirPrefix, fullPath, (HWND)*this);
1247 return true;
1248 }
1249
1250 if (menuResult == k_CmdId_Open_7zip)
1251 {
1252 UString imageName = fs2us(NWindows::NDLL::GetModuleDirPrefix());
1253 imageName += "7zFM.exe";
1254 WRes wres;
1255 {
1256 CProcess process;
1257 wres = process.Create(imageName, GetQuotedString2(fullPath), NULL); // curDir
1258 }
1259 if (wres != 0)
1260 {
1261 const HRESULT hres = HRESULT_FROM_WIN32(wres);
1262 MessageBox_HResError(*this, hres, imageName);
1263 }
1264 return true;
1265 }
1266
1267 if (indices.Size() == 1)
1268 if (menuResult == k_CmdId_Props)
1269 {
1270 const CBrowseItem &bi = _items[indices[0]];
1271 const CFileInfo &file = _files[bi.MainFileIndex];
1272 Show_FileProps_Window(file);
1273 return true;
1274 }
1275 }
1276
1277 return true;
1278}
1279
1280
1281
1282struct CWaitCursor2
1283{
1284 HCURSOR _waitCursor;
1285 HCURSOR _oldCursor;
1286
1287 CWaitCursor2():
1288 _waitCursor(NULL),
1289 _oldCursor(NULL)
1290 {}
1291 void Set()
1292 {
1293 if (!_waitCursor)
1294 {
1295 _waitCursor = LoadCursor(NULL, IDC_WAIT);
1296 if (_waitCursor)
1297 _oldCursor = SetCursor(_waitCursor);
1298 }
1299 }
1300 ~CWaitCursor2()
1301 {
1302 if (_waitCursor)
1303 SetCursor(_oldCursor);
1304 }
1305};
1306
1307
1308void CBrowseDialog2::OnOK()
1309{
1310 /* DOCS:
1311 If a dialog box or one of its controls currently has the input focus,
1312 then pressing the ENTER key causes Windows to send a WM_COMMAND message
1313 with the idItem (wParam) parameter set to the ID of the default command button.
1314 If the dialog box does not have a default command button,
1315 then the idItem parameter is set to IDOK by default.
1316
1317 We process IDOK here for Enter pressing, because we have no DEFPUSHBUTTON.
1318 */
1319 if (GetFocus() == _list)
1320 {
1321 OnItemEnter();
1322 return;
1323 }
1324 // Enter can be pressed in another controls (Edit).
1325 // So we don't need End() call here
1326}
1327
1328
1329bool CBrowseDialog2::GetParentPath(const UString &path, UString &parentPrefix, UString &name)
1330{
1331 parentPrefix.Empty();
1332 name.Empty();
1333 if (path.IsEmpty())
1334 return false;
1335 if (_topDirPrefix == path)
1336 return false;
1337 UString s = path;
1338 if (IS_PATH_SEPAR(s.Back()))
1339 s.DeleteBack();
1340 if (s.IsEmpty())
1341 return false;
1342 if (IS_PATH_SEPAR(s.Back()))
1343 return false;
1344 const unsigned pos1 = (unsigned)(s.ReverseFind_PathSepar() + 1);
1345 parentPrefix.SetFrom(s, pos1);
1346 name = s.Ptr(pos1);
1347 return true;
1348}
1349
1350
1351int CBrowseDialog2::CompareItems(LPARAM lParam1, LPARAM lParam2) const
1352{
1353 if (lParam1 == lParam2) return 0;
1354 if (lParam1 == kParentIndex) return -1;
1355 if (lParam2 == kParentIndex) return 1;
1356
1357 const int index1 = (int)lParam1;
1358 const int index2 = (int)lParam2;
1359
1360 const CBrowseItem &item1 = _items[index1];
1361 const CBrowseItem &item2 = _items[index2];
1362
1363 const CFileInfo &f1 = _files[item1.MainFileIndex];
1364 const CFileInfo &f2 = _files[item2.MainFileIndex];
1365
1366 const bool isDir2 = f2.IsDir();
1367 if (f1.IsDir())
1368 {
1369 if (!isDir2) return -1;
1370 }
1371 else if (isDir2) return 1;
1372
1373 const int res2 = MyCompare(index1, index2);
1374 int res = 0;
1375 switch (_sortIndex)
1376 {
1377 case 0: res = CompareFileNames(fs2us(f1.Name), fs2us(f2.Name)); break;
1378 case 1: res = CompareFileTime(&f1.MTime, &f2.MTime); break;
1379 case 2: res = MyCompare(item1.Size, item2.Size); break;
1380 case 3: res = MyCompare(item1.NumFiles, item2.NumFiles); break;
1381 case 4: res = MyCompare(item1.NumDirs, item2.NumDirs); break;
1382 case 5:
1383 {
1384 const int sub1 = item1.SubFileIndex;
1385 const int sub2 = item2.SubFileIndex;
1386 if (sub1 < 0)
1387 {
1388 if (sub2 >= 0)
1389 res = -1;
1390 }
1391 else if (sub2 < 0)
1392 res = 1;
1393 else
1394 res = CompareFileNames(fs2us(_files[sub1].Name), fs2us(_files[sub2].Name));
1395 break;
1396 }
1397 }
1398 if (res == 0)
1399 res = res2;
1400 return _ascending ? res: -res;
1401}
1402
1403static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
1404{
1405 return ((CBrowseDialog2 *)lpData)->CompareItems(lParam1, lParam2);
1406}
1407
1408
1409static const FChar *FindNonHexChar_F(const FChar *s) throw()
1410{
1411 for (;;)
1412 {
1413 const FChar c = (FChar)*s++; // pointer can go 1 byte after end
1414 if ( (c < '0' || c > '9')
1415 && (c < 'a' || c > 'z')
1416 && (c < 'A' || c > 'Z'))
1417 return s - 1;
1418 }
1419}
1420
1421
1422void CBrowseDialog2::Reload_WithErrorMessage()
1423{
1424 const HRESULT res = Reload();
1425 if (res != S_OK)
1426 MessageBox_HResError(*this, res, DirPrefix);
1427}
1428
1429void CBrowseDialog2::ChangeSorting_and_Reload(int columnIndex)
1430{
1431 if (columnIndex == _sortIndex)
1432 _ascending = !_ascending;
1433 else
1434 {
1435 _ascending = (columnIndex == 0 || columnIndex == _columnIndex_fileNameInDir); // for name columns
1436 _sortIndex = columnIndex;
1437 }
1438 Reload_WithErrorMessage();
1439}
1440
1441
1442// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
1443HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UString &selectedName)
1444{
1445 UStringVector selectedVector;
1446 if (!selectedName.IsEmpty())
1447 selectedVector.Add(selectedName);
1448 return Reload(pathPrefix, selectedVector, selectedName);
1449}
1450
1451
1452HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UStringVector &selectedVector2, const UString &focusedName)
1453{
1454 UStringVector selectedVector = selectedVector2;
1455 selectedVector.Sort();
1456 CObjectVector<CFileInfo> files;
1457 CRecordVector<CBrowseItem> items;
1458 CWaitCursor2 waitCursor;
1459
1460 #ifndef UNDER_CE
1461 bool isDrive = false;
1462 if (pathPrefix.IsEmpty() || pathPrefix.IsEqualTo(kSuperPathPrefix))
1463 {
1464 isDrive = true;
1465 FStringVector drives;
1466 if (!MyGetLogicalDriveStrings(drives))
1467 return GetLastError_noZero_HRESULT();
1468 FOR_VECTOR (i, drives)
1469 {
1470 const FString &d = drives[i];
1471 if (d.Len() < 2 || d.Back() != '\\')
1472 return E_FAIL;
1473 CBrowseItem item;
1474 item.MainFileIndex = files.Size();
1475 CFileInfo &fi = files.AddNew();
1476 fi.SetAsDir();
1477 fi.Name = d;
1478 fi.Name.DeleteBack();
1479 items.Add(item);
1480 }
1481 }
1482 else
1483 #endif
1484 {
1485 {
1486 CEnumerator enumerator;
1487 enumerator.SetDirPrefix(us2fs(pathPrefix));
1488 CFileInfo fi;
1489 FString tail;
1490
1491 const bool isTempFolder = (
1492 // TempMode &&
1493 IsExactTempFolder(pathPrefix)
1494 );
1495 for (;;)
1496 {
1497 {
1498 bool found;
1499 if (!enumerator.Next(fi, found))
1500 return GetLastError_noZero_HRESULT();
1501 if (!found)
1502 break;
1503 }
1504 if (isTempFolder)
1505 {
1506 // if (!Show_Non7zDirs_InTemp)
1507 {
1508 if (!fi.Name.IsPrefixedBy_Ascii_NoCase("7z"))
1509 continue;
1510 tail = fi.Name.Ptr(2);
1511 if ( !tail.IsPrefixedBy_Ascii_NoCase("E") // drag and drop / Copy / create to email
1512 && !tail.IsPrefixedBy_Ascii_NoCase("O") // open
1513 && !tail.IsPrefixedBy_Ascii_NoCase("S")) // SFXSetup
1514 continue;
1515 const FChar *beg = tail.Ptr(1);
1516 const FChar *end = FindNonHexChar_F(beg);
1517 if (end - beg != 8 || *end != 0)
1518 continue;
1519 }
1520 }
1521 CBrowseItem item;
1522 item.MainFileIndex = files.Size();
1523 item.Size = fi.Size;
1524 files.Add(fi);
1525 items.Add(item);
1526 }
1527 }
1528
1529 UInt64 cnt = items.Size();
1530 // if (TempMode)
1531 {
1532 FOR_VECTOR (i, items)
1533 {
1534 CBrowseItem &item = items[i];
1535 const CFileInfo &fi = files[item.MainFileIndex];
1536 if (!fi.IsDir() || fi.HasReparsePoint())
1537 continue;
1538
1539 CBrowseEnumerator enumer;
1540 // we need to keep MainFileIndex and Size value of item:
1541 enumer.bi = item; // don't change it
1542 enumer.Path = us2fs(pathPrefix);
1543 enumer.Path += fi.Name;
1544 enumer.Enumerate(0); // level
1545 item = enumer.bi;
1546 if (item.NumRootItems == 1)
1547 {
1548 item.SubFileIndex = (int)files.Size();
1549 files.Add(enumer.fi_SubFile);
1550 }
1551 cnt += item.NumDirs;
1552 cnt += item.NumFiles;
1553 if (cnt > 1000)
1554 waitCursor.Set();
1555 }
1556 }
1557 }
1558 _items = items;
1559 _files = files;
1560
1561 DirPrefix = pathPrefix;
1562
1563 EnableItem(IDB_BROWSE2_PARENT, !IsExactTempFolder(pathPrefix));
1564
1565 SetItemText(IDT_BROWSE2_FOLDER, DirPrefix);
1566
1567 _list.SetRedraw(false);
1568 _list.DeleteAllItems();
1569
1570 LVITEMW item;
1571
1572 unsigned index = 0;
1573 int cursorIndex = -1;
1574
1575 #ifndef Z7_SFX
1576 if (_showDots && _topDirPrefix != DirPrefix)
1577 {
1578 item.iItem = (int)index;
1579 const UString itemName ("..");
1580 if (focusedName == itemName)
1581 cursorIndex = (int)index;
1582 /*
1583 if (selectedVector.IsEmpty()
1584 // && focusedName.IsEmpty()
1585 // && focusedName == ".."
1586 )
1587 cursorIndex = (int)index;
1588 */
1589 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
1590 unsigned subItem = 0;
1591 item.iSubItem = (int)(subItem++);
1592 item.lParam = kParentIndex;
1593 item.pszText = itemName.Ptr_non_const();
1594 item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, DirPrefix);
1595 if (item.iImage < 0)
1596 item.iImage = 0;
1597 _list.InsertItem(&item);
1598#if 0
1599 for (int k = 1; k < 6; k++)
1600 _list.SetSubItem(index, subItem++, L"2");
1601#endif
1602 index++;
1603 }
1604 #endif
1605
1606 for (unsigned i = 0; i < _items.Size(); i++, index++)
1607 {
1608 item.iItem = (int)index;
1609 const CBrowseItem &bi = _items[i];
1610 const CFileInfo &fi = _files[bi.MainFileIndex];
1611 const UString name = fs2us(fi.Name);
1612 // if (!selectedName.IsEmpty() && CompareFileNames(name, selectedName) == 0)
1613 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
1614 item.state = 0;
1615 if (selectedVector.FindInSorted(name) != -1)
1616 {
1617 /*
1618 if (cursorIndex == -1)
1619 cursorIndex = (int)index;
1620 */
1621 item.mask |= LVIF_STATE;
1622 item.state |= LVIS_SELECTED;
1623 }
1624 if (focusedName == name)
1625 {
1626 if (cursorIndex == -1)
1627 cursorIndex = (int)index;
1628 item.mask |= LVIF_STATE;
1629 item.state |= LVIS_FOCUSED;
1630 }
1631
1632 unsigned subItem = 0;
1633 item.iSubItem = (int)(subItem++);
1634 item.lParam = (LPARAM)i;
1635 item.pszText = name.Ptr_non_const();
1636
1637 const UString fullPath = DirPrefix + name;
1638 #ifndef UNDER_CE
1639 if (isDrive)
1640 {
1641 if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0)
1642 item.iImage = 0;
1643 }
1644 else
1645 #endif
1646 item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
1647 if (item.iImage < 0)
1648 item.iImage = 0;
1649
1650 _list.InsertItem(&item);
1651 wchar_t s[64];
1652 {
1653 s[0] = 0;
1654 if (!FILETIME_IsZero(fi.MTime))
1655 ConvertUtcFileTimeToString(fi.MTime, s,
1656 #ifndef UNDER_CE
1657 kTimestampPrintLevel_MIN
1658 #else
1659 kTimestampPrintLevel_DAY
1660 #endif
1661 );
1662 _list.SetSubItem(index, subItem++, s);
1663 }
1664
1665 {
1666 s[0] = 0;
1667 Browse_ConvertSizeToString(bi, s);
1668 _list.SetSubItem(index, subItem++, s);
1669 }
1670 if (_columnIndex_NumFiles >= 0)
1671 {
1672 UString s2;
1673 if (fi.HasReparsePoint())
1674 {
1675 s2 = "Link";
1676 }
1677 else if (bi.NumFiles != 0)
1678 {
1679 s2.Add_UInt32(bi.NumFiles);
1680 if (bi.WasInterrupted)
1681 s2 += "+";
1682 }
1683 _list.SetSubItem(index, subItem, s2);
1684 }
1685 subItem++;
1686 if (_columnIndex_NumDirs >= 0 && bi.NumDirs != 0)
1687 {
1688 UString s2;
1689 s2.Add_UInt32(bi.NumDirs);
1690 if (bi.WasInterrupted)
1691 s2 += "+";
1692 _list.SetSubItem(index, subItem, s2);
1693 }
1694 subItem++;
1695 if (_columnIndex_fileNameInDir >= 0 && bi.SubFileIndex >= 0)
1696 {
1697 _list.SetSubItem(index, subItem, fs2us(_files[bi.SubFileIndex].Name));
1698 }
1699 subItem++;
1700 }
1701
1702 if (_list.GetItemCount() > 0 && cursorIndex >= 0)
1703 {
1704 // _list.SetItemState_FocusedSelected(cursorIndex);
1705 // _list.SetItemState_Focused(cursorIndex);
1706 }
1707 _list.SortItems(CompareItems2, (LPARAM)this);
1708 if (_list.GetItemCount() > 0 && cursorIndex < 0)
1709 {
1710 if (selectedVector.IsEmpty())
1711 _list.SetItemState_FocusedSelected(0);
1712 else
1713 _list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);
1714 }
1715 _list.EnsureVisible(_list.GetFocusedItem(), false);
1716 _list.SetRedraw(true);
1717 _list.InvalidateRect(NULL, true);
1718 return S_OK;
1719}
1720
1721
1722
1723HRESULT CBrowseDialog2::Reload()
1724{
1725 UStringVector selected;
1726 {
1727 CUIntVector indexes;
1728 GetSelected_RealIndexes(indexes);
1729 FOR_VECTOR (i, indexes)
1730 selected.Add(fs2us(Get_MainFileName_for_realIndex(indexes[i])));
1731 }
1732 UString focusedName;
1733 const int focusedItem = _list.GetFocusedItem();
1734 if (focusedItem >= 0)
1735 {
1736 const int realIndex = GetRealItemIndex(focusedItem);
1737 if (realIndex != kParentIndex)
1738 focusedName = fs2us(Get_MainFileName_for_realIndex((unsigned)realIndex));
1739 }
1740 const UString dirPathTemp = DirPrefix;
1741 return Reload(dirPathTemp, selected, focusedName);
1742}
1743
1744
1745void CBrowseDialog2::OpenParentFolder()
1746{
1747#if 1 // 0 : for debug
1748 // we don't allow to go to parent of TempFolder.
1749 // if (TempMode)
1750 {
1751 if (IsExactTempFolder(DirPrefix))
1752 return;
1753 }
1754#endif
1755
1756 UString parent, selected;
1757 if (GetParentPath(DirPrefix, parent, selected))
1758 Reload(parent, selected);
1759}
1760
1761
1762void CBrowseDialog2::OnItemEnter()
1763{
1764 const bool alt = IsKeyDown(VK_MENU);
1765 const bool ctrl = IsKeyDown(VK_CONTROL);
1766 const bool shift = IsKeyDown(VK_SHIFT);
1767
1768 const int index = _list.GetNextSelectedItem(-1);
1769 if (index < 0)
1770 return;
1771 if (_list.GetNextSelectedItem(index) >= 0)
1772 return; // more than one selected
1773 const int realIndex = GetRealItemIndex(index);
1774 if (realIndex == kParentIndex)
1775 OpenParentFolder();
1776 else
1777 {
1778 const CBrowseItem &bi = _items[realIndex];
1779 const CFileInfo &file = _files[bi.MainFileIndex];
1780 if (alt)
1781 {
1782 Show_FileProps_Window(file);
1783 return;
1784 }
1785 if (file.HasReparsePoint())
1786 {
1787 // we don't want Link open operation,
1788 // because user can think that it's usual folder/file (non-link).
1789 ShowErrorMessage(*this, k_Message_Link_operation_was_Blocked);
1790 return;
1791 }
1792 bool needExternal = true;
1793 if (file.IsDir())
1794 {
1795 if (!shift || alt || ctrl) // open folder in Explorer:
1796 needExternal = false;
1797 }
1798 const UString fullPath = DirPrefix + fs2us(file.Name);
1799 if (needExternal)
1800 {
1801 StartApplicationDontWait(DirPrefix, fullPath, (HWND)*this);
1802 return;
1803 }
1804 UString s = fullPath;
1805 s.Add_PathSepar();
1806 const HRESULT res = Reload(s, UString());
1807 if (res != S_OK)
1808 MessageBox_HResError(*this, res, s);
1809 // SetPathEditText();
1810 }
1811}
1812
1813
1814void MyBrowseForTempFolder(HWND owner)
1815{
1816 FString tempPathF;
1817 if (!NFile::NDir::MyGetTempPath(tempPathF) || tempPathF.IsEmpty())
1818 {
1819 MessageBox_LastError_path(owner, tempPathF);
1820 return;
1821 }
1822 CBrowseDialog2 dialog;
1823
1824 LangString_OnlyFromLangFile(IDM_TEMP_DIR, dialog.Title);
1825 dialog.Title.Replace(L"...", L"");
1826 if (dialog.Title.IsEmpty())
1827 dialog.Title = "Delete Temporary Files";
1828
1829 dialog.TempFolderPath = fs2us(tempPathF);
1830 dialog.Create(owner);
1831 // we can exit from dialog with 2 ways:
1832 // IDCANCEL : Esc Key, or close icons
1833 // IDCLOSE : with Close button
1834}
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog2.h b/CPP/7zip/UI/FileManager/BrowseDialog2.h
new file mode 100644
index 0000000..6d5fb23
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/BrowseDialog2.h
@@ -0,0 +1,10 @@
1// BrowseDialog2.h
2
3#ifndef ZIP7_INC_BROWSE_DIALOG2_H
4#define ZIP7_INC_BROWSE_DIALOG2_H
5
6#include "../../../Windows/Window.h"
7
8void MyBrowseForTempFolder(HWND owner);
9
10#endif
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog2.rc b/CPP/7zip/UI/FileManager/BrowseDialog2.rc
new file mode 100644
index 0000000..2ce2e45
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/BrowseDialog2.rc
@@ -0,0 +1,32 @@
1#include "BrowseDialog2Res.h"
2#include "../../GuiCommon.rc"
3// #include "resource.h"
4
5#define xc 450
6#define yc 328
7
8#define k_BROWSE2_y_CtrlSize 14
9
10#define k_BROWSE2_y_List 40
11
12IDD_BROWSE2 DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
13CAPTION "7-Zip: Browse Temp Files"
14{
15// EDITTEXT IDE_BROWSE_PATH, m, by - m - k_BROWSE_y_CtrlSize - k_BROWSE_y_CtrlSize - m, xc, k_BROWSE_y_CtrlSize, ES_AUTOHSCROLL
16 COMBOBOX IDC_BROWSE2_FILTER, m, by - m - k_BROWSE2_y_CtrlSize, xc, 30, MY_COMBO
17
18// DON'T USE DEFPUSHBUTTON here, because we use IDOK as default action for Enter key.
19 PUSHBUTTON "Close", IDCLOSE, bx2, by, bxs, bys, WS_GROUP
20 PUSHBUTTON "Help", IDHELP, bx1, by, bxs, bys
21
22 PUSHBUTTON "Delete", IDS_BUTTON_DELETE, m , m, 64, bys
23 PUSHBUTTON "Refresh", IDM_VIEW_REFRESH, m + 64 + 8, m, 64, bys
24
25 PUSHBUTTON "<--", IDB_BROWSE2_PARENT, m, m + 21, 24, bys
26// LTEXT "", IDT_BROWSE_FOLDER, m + 30, m + 24, xc - 30, 8
27 EDITTEXT IDT_BROWSE2_FOLDER, m + 28, m + 22, xc - 28, 14, ES_AUTOHSCROLL | ES_READONLY
28
29 CONTROL "List1", IDL_BROWSE2, "SysListView32",
30 LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | WS_BORDER | WS_TABSTOP,
31 m, m + k_BROWSE2_y_List, xc, yc - bys - m - k_BROWSE2_y_List - k_BROWSE2_y_CtrlSize - m
32}
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog2Res.h b/CPP/7zip/UI/FileManager/BrowseDialog2Res.h
new file mode 100644
index 0000000..add9158
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/BrowseDialog2Res.h
@@ -0,0 +1,9 @@
1#define IDD_BROWSE2 93
2
3#define IDL_BROWSE2 100
4#define IDT_BROWSE2_FOLDER 101
5// #define IDE_BROWSE2_PATH 102
6#define IDC_BROWSE2_FILTER 103
7
8#define IDB_BROWSE2_PARENT 110
9// #define IDB_BROWSE2_CREATE_DIR 112
diff --git a/CPP/7zip/UI/FileManager/EditPage.rc b/CPP/7zip/UI/FileManager/EditPage.rc
index 38f74ea..56c1ec0 100644
--- a/CPP/7zip/UI/FileManager/EditPage.rc
+++ b/CPP/7zip/UI/FileManager/EditPage.rc
@@ -1,8 +1,8 @@
1#include "EditPageRes.h" 1#include "EditPageRes.h"
2#include "../../GuiCommon.rc" 2#include "../../GuiCommon.rc"
3 3
4#define xc 240 4#define xc OPTIONS_PAGE_XC_SIZE
5#define yc 80 5#define yc 100
6 6
7IDD_EDIT MY_PAGE 7IDD_EDIT MY_PAGE
8#include "EditPage2.rc" 8#include "EditPage2.rc"
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
index f674044..093534b 100644
--- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
@@ -31,12 +31,15 @@
31#ifndef Z7_NO_CRYPTO 31#ifndef Z7_NO_CRYPTO
32#include "PasswordDialog.h" 32#include "PasswordDialog.h"
33#endif 33#endif
34#include "MemDialog.h"
34#include "PropertyName.h" 35#include "PropertyName.h"
35 36
36using namespace NWindows; 37using namespace NWindows;
37using namespace NFile; 38using namespace NFile;
38using namespace NFind; 39using namespace NFind;
39 40
41extern bool g_DisableUserQuestions;
42
40CExtractCallbackImp::~CExtractCallbackImp() {} 43CExtractCallbackImp::~CExtractCallbackImp() {}
41 44
42void CExtractCallbackImp::Init() 45void CExtractCallbackImp::Init()
@@ -60,6 +63,13 @@ void CExtractCallbackImp::AddError_Message(LPCWSTR s)
60 ProgressDialog->Sync.AddError_Message(s); 63 ProgressDialog->Sync.AddError_Message(s);
61} 64}
62 65
66void CExtractCallbackImp::AddError_Message_ShowArcPath(LPCWSTR s)
67{
68 Add_ArchiveName_Error();
69 AddError_Message(s);
70}
71
72
63#ifndef Z7_SFX 73#ifndef Z7_SFX
64 74
65Z7_COM7F_IMF(CExtractCallbackImp::SetNumFiles(UInt64 numFiles)) 75Z7_COM7F_IMF(CExtractCallbackImp::SetNumFiles(UInt64 numFiles))
@@ -371,11 +381,11 @@ Z7_COM7F_IMF(CExtractCallbackImp::SetOperationResult(Int32 opRes, Int32 encrypte
371 { 381 {
372 UString s; 382 UString s;
373 SetExtractErrorMessage(opRes, encrypted, _currentFilePath, s); 383 SetExtractErrorMessage(opRes, encrypted, _currentFilePath, s);
374 Add_ArchiveName_Error(); 384 AddError_Message_ShowArcPath(s);
375 AddError_Message(s);
376 } 385 }
377 } 386 }
378 387
388 _currentFilePath.Empty();
379 #ifndef Z7_SFX 389 #ifndef Z7_SFX
380 if (_isFolder) 390 if (_isFolder)
381 NumFolders++; 391 NumFolders++;
@@ -393,8 +403,7 @@ Z7_COM7F_IMF(CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypt
393 { 403 {
394 UString s; 404 UString s;
395 SetExtractErrorMessage(opRes, encrypted, name, s); 405 SetExtractErrorMessage(opRes, encrypted, name, s);
396 Add_ArchiveName_Error(); 406 AddError_Message_ShowArcPath(s);
397 AddError_Message(s);
398 } 407 }
399 return S_OK; 408 return S_OK;
400} 409}
@@ -404,11 +413,12 @@ Z7_COM7F_IMF(CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypt
404 413
405HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name, bool /* testMode */) 414HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name, bool /* testMode */)
406{ 415{
416 _currentArchivePath = name;
417 _needWriteArchivePath = true;
407 #ifndef Z7_SFX 418 #ifndef Z7_SFX
408 RINOK(ProgressDialog->Sync.CheckStop()) 419 RINOK(ProgressDialog->Sync.CheckStop())
409 ProgressDialog->Sync.Set_TitleFileName(name); 420 ProgressDialog->Sync.Set_TitleFileName(name);
410 #endif 421 #endif
411 _currentArchivePath = name;
412 return S_OK; 422 return S_OK;
413} 423}
414 424
@@ -530,7 +540,7 @@ static UString GetBracedType(const wchar_t *type)
530{ 540{
531 UString s ('['); 541 UString s ('[');
532 s += type; 542 s += type;
533 s += ']'; 543 s.Add_Char(']');
534 return s; 544 return s;
535} 545}
536 546
@@ -641,6 +651,10 @@ void CExtractCallbackImp::Add_ArchiveName_Error()
641 651
642HRESULT CExtractCallbackImp::ExtractResult(HRESULT result) 652HRESULT CExtractCallbackImp::ExtractResult(HRESULT result)
643{ 653{
654 #ifndef Z7_SFX
655 ProgressDialog->Sync.Set_FilePath(L"");
656 #endif
657
644 if (result == S_OK) 658 if (result == S_OK)
645 return result; 659 return result;
646 NumArchiveErrors++; 660 NumArchiveErrors++;
@@ -834,11 +848,11 @@ Z7_COM7F_IMF(CExtractCallbackImp::GetStream7(const wchar_t *name,
834 COM_TRY_BEGIN 848 COM_TRY_BEGIN
835 *outStream = NULL; 849 *outStream = NULL;
836 _newVirtFileWasAdded = false; 850 _newVirtFileWasAdded = false;
837 _hashStreamWasUsed = false; 851 _hashStream_WasUsed = false;
838 _needUpdateStat = false; 852 _needUpdateStat = false;
839 853
840 if (_hashStream) 854 if (_hashStream)
841 _hashStreamSpec->ReleaseStream(); 855 _hashStream->ReleaseStream();
842 856
843 GetItemBoolProp(getProp, kpidIsAltStream, _isAltStream); 857 GetItemBoolProp(getProp, kpidIsAltStream, _isAltStream);
844 858
@@ -903,10 +917,10 @@ Z7_COM7F_IMF(CExtractCallbackImp::GetStream7(const wchar_t *name,
903 if (_hashStream) 917 if (_hashStream)
904 { 918 {
905 { 919 {
906 _hashStreamSpec->SetStream(outStreamLoc); 920 _hashStream->SetStream(outStreamLoc);
907 outStreamLoc = _hashStream; 921 outStreamLoc = _hashStream;
908 _hashStreamSpec->Init(true); 922 _hashStream->Init(true);
909 _hashStreamWasUsed = true; 923 _hashStream_WasUsed = true;
910 } 924 }
911 } 925 }
912 926
@@ -951,13 +965,13 @@ Z7_COM7F_IMF(CExtractCallbackImp::SetOperationResult8(Int32 opRes, Int32 encrypt
951 // _curSize_Defined = true; 965 // _curSize_Defined = true;
952 RINOK(VirtFileSystemSpec->CloseMemFile()) 966 RINOK(VirtFileSystemSpec->CloseMemFile())
953 } 967 }
954 if (_hashStream && _hashStreamWasUsed) 968 if (_hashStream && _hashStream_WasUsed)
955 { 969 {
956 _hashStreamSpec->_hash->Final(_isFolder, _isAltStream, _filePath); 970 _hashStream->_hash->Final(_isFolder, _isAltStream, _filePath);
957 _curSize = _hashStreamSpec->GetSize(); 971 _curSize = _hashStream->GetSize();
958 _curSize_Defined = true; 972 _curSize_Defined = true;
959 _hashStreamSpec->ReleaseStream(); 973 _hashStream->ReleaseStream();
960 _hashStreamWasUsed = false; 974 _hashStream_WasUsed = false;
961 } 975 }
962 else if (_hashCalc && _needUpdateStat) 976 else if (_hashCalc && _needUpdateStat)
963 { 977 {
@@ -969,6 +983,114 @@ Z7_COM7F_IMF(CExtractCallbackImp::SetOperationResult8(Int32 opRes, Int32 encrypt
969} 983}
970 984
971 985
986Z7_COM7F_IMF(CExtractCallbackImp::RequestMemoryUse(
987 UInt32 flags, UInt32 indexType, UInt32 /* index */, const wchar_t *path,
988 UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags))
989{
990 UInt32 limit_GB = (UInt32)((*allowedSize + ((1u << 30) - 1)) >> 30);
991
992 if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)
993 {
994 UInt64 limit_bytes = *allowedSize;
995 const UInt32 limit_GB_Registry = NExtract::Read_LimitGB();
996 if (limit_GB_Registry != 0 && limit_GB_Registry != (UInt32)(Int32)-1)
997 {
998 const UInt64 limit_bytes_Registry = (UInt64)limit_GB_Registry << 30;
999 // registry_WasForced = true;
1000 if ((flags & NRequestMemoryUseFlags::k_AllowedSize_WasForced) == 0
1001 || limit_bytes < limit_bytes_Registry)
1002 {
1003 limit_bytes = limit_bytes_Registry;
1004 limit_GB = limit_GB_Registry;
1005 }
1006 }
1007 *allowedSize = limit_bytes;
1008 if (requiredSize <= limit_bytes)
1009 {
1010 *answerFlags = NRequestMemoryAnswerFlags::k_Allow;
1011 return S_OK;
1012 }
1013 // default answer can be k_Allow, if limit was not forced,
1014 // so we change answer to non-allowed here,
1015 // because user has chance to change limit in GUI.
1016 *answerFlags = NRequestMemoryAnswerFlags::k_Limit_Exceeded;
1017 if (flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected)
1018 *answerFlags |= NRequestMemoryAnswerFlags::k_SkipArc;
1019 }
1020
1021 const UInt32 required_GB = (UInt32)((requiredSize + ((1u << 30) - 1)) >> 30);
1022
1023 CMemDialog dialog;
1024 dialog.Limit_GB = limit_GB;
1025 dialog.Required_GB = required_GB;
1026 dialog.TestMode = TestMode;
1027 if (MultiArcMode)
1028 dialog.ArcPath = _currentArchivePath;
1029 if (path)
1030 dialog.FilePath = path;
1031
1032 if (!g_DisableUserQuestions
1033 && (flags & NRequestMemoryUseFlags::k_IsReport) == 0)
1034 {
1035 if (_remember)
1036 dialog.SkipArc = _skipArc;
1037 else
1038 {
1039 dialog.ShowRemember =
1040 (MultiArcMode
1041 || indexType != NArchive::NEventIndexType::kNoIndex
1042 || path);
1043 ProgressDialog->WaitCreating();
1044 if (dialog.Create(*ProgressDialog) != IDCONTINUE)
1045 {
1046 *answerFlags = NRequestMemoryAnswerFlags::k_Stop;
1047 return E_ABORT;
1048 }
1049 if (dialog.NeedSave)
1050 NExtract::Save_LimitGB(dialog.Limit_GB);
1051 if (dialog.Remember)
1052 {
1053 _remember = true;
1054 _skipArc = dialog.SkipArc;
1055 }
1056 }
1057
1058 *allowedSize = (UInt64)dialog.Limit_GB << 30;
1059 if (!dialog.SkipArc)
1060 {
1061 *answerFlags = NRequestMemoryAnswerFlags::k_Allow;
1062 return S_OK;
1063 }
1064 *answerFlags =
1065 NRequestMemoryAnswerFlags::k_SkipArc
1066 | NRequestMemoryAnswerFlags::k_Limit_Exceeded;
1067 flags |= NRequestMemoryUseFlags::k_Report_SkipArc;
1068 }
1069
1070 if ((flags & NRequestMemoryUseFlags::k_NoErrorMessage) == 0)
1071 {
1072 UString s ("ERROR: ");
1073 dialog.AddInfoMessage_To_String(s);
1074 s.Add_LF();
1075 // if (indexType == NArchive::NEventIndexType::kNoIndex)
1076 if ((flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected) ||
1077 (flags & NRequestMemoryUseFlags::k_Report_SkipArc))
1078 s += LangString(IDS_MSG_ARC_UNPACKING_WAS_SKIPPED);
1079/*
1080 else
1081 s += LangString(IDS_MSG_ARC_FILES_UNPACKING_WAS_SKIPPED);
1082*/
1083 AddError_Message_ShowArcPath(s);
1084 }
1085
1086/*
1087 if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)
1088 *answerFlags |= NRequestMemoryAnswerFlags::k_Limit_Exceeded;
1089*/
1090 return S_OK;
1091}
1092
1093
972 1094
973// static const UInt32 kBlockSize = ((UInt32)1 << 31); 1095// static const UInt32 kBlockSize = ((UInt32)1 << 31);
974 1096
@@ -1010,25 +1132,23 @@ Z7_COM7F_IMF(CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *proce
1010 _fileMode = true; 1132 _fileMode = true;
1011 } 1133 }
1012 RINOK(FlushToDisk(false)) 1134 RINOK(FlushToDisk(false))
1013 return _outFileStream->Write(data, size, processedSize); 1135 return _outFileStream.Interface()->Write(data, size, processedSize);
1014} 1136}
1015 1137
1138
1016HRESULT CVirtFileSystem::FlushToDisk(bool closeLast) 1139HRESULT CVirtFileSystem::FlushToDisk(bool closeLast)
1017{ 1140{
1018 if (!_outFileStream) 1141 _outFileStream.Create_if_Empty();
1019 {
1020 _outFileStreamSpec = new COutFileStream;
1021 _outFileStream = _outFileStreamSpec;
1022 }
1023 while (_numFlushed < Files.Size()) 1142 while (_numFlushed < Files.Size())
1024 { 1143 {
1025 const CVirtFile &file = Files[_numFlushed]; 1144 const CVirtFile &file = Files[_numFlushed];
1026 const FString path = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.Name)); 1145 const FString path = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.Name));
1027 if (!_fileIsOpen) 1146 if (!_fileIsOpen)
1028 { 1147 {
1029 if (!_outFileStreamSpec->Create(path, false)) 1148 if (!_outFileStream->Create_NEW(path))
1030 { 1149 {
1031 _outFileStream.Release(); 1150 // do we need to release stream here?
1151 // _outFileStream.Release();
1032 return E_FAIL; 1152 return E_FAIL;
1033 // MessageBoxMyError(UString("Can't create file ") + fs2us(tempFilePath)); 1153 // MessageBoxMyError(UString("Can't create file ") + fs2us(tempFilePath));
1034 } 1154 }
@@ -1040,13 +1160,17 @@ HRESULT CVirtFileSystem::FlushToDisk(bool closeLast)
1040 if (file.CTimeDefined || 1160 if (file.CTimeDefined ||
1041 file.ATimeDefined || 1161 file.ATimeDefined ||
1042 file.MTimeDefined) 1162 file.MTimeDefined)
1043 _outFileStreamSpec->SetTime( 1163 _outFileStream->SetTime(
1044 file.CTimeDefined ? &file.CTime : NULL, 1164 file.CTimeDefined ? &file.CTime : NULL,
1045 file.ATimeDefined ? &file.ATime : NULL, 1165 file.ATimeDefined ? &file.ATime : NULL,
1046 file.MTimeDefined ? &file.MTime : NULL); 1166 file.MTimeDefined ? &file.MTime : NULL);
1047 _outFileStreamSpec->Close(); 1167 _outFileStream->Close();
1048 _numFlushed++; 1168 _numFlushed++;
1049 _fileIsOpen = false; 1169 _fileIsOpen = false;
1170
1171 if (ZoneBuf.Size() != 0)
1172 WriteZoneFile_To_BaseFile(path, ZoneBuf);
1173
1050 if (file.AttribDefined) 1174 if (file.AttribDefined)
1051 NDir::SetFileAttrib_PosixHighDetect(path, file.Attrib); 1175 NDir::SetFileAttrib_PosixHighDetect(path, file.Attrib);
1052 } 1176 }
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h
index c2aa470..daef5ec 100644
--- a/CPP/7zip/UI/FileManager/ExtractCallback.h
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.h
@@ -103,13 +103,14 @@ Z7_CLASS_IMP_NOQIB_1(
103 unsigned _numFlushed; 103 unsigned _numFlushed;
104 bool _fileIsOpen; 104 bool _fileIsOpen;
105 bool _fileMode; 105 bool _fileMode;
106 COutFileStream *_outFileStreamSpec; 106 CMyComPtr2<ISequentialOutStream, COutFileStream> _outFileStream;
107 CMyComPtr<ISequentialOutStream> _outFileStream;
108public: 107public:
109 CObjectVector<CVirtFile> Files; 108 CObjectVector<CVirtFile> Files;
110 UInt64 MaxTotalAllocSize; 109 UInt64 MaxTotalAllocSize;
111 FString DirPrefix; 110 FString DirPrefix;
112 111 CByteBuffer ZoneBuf;
112
113
113 CVirtFile &AddNewFile() 114 CVirtFile &AddNewFile()
114 { 115 {
115 if (!Files.IsEmpty()) 116 if (!Files.IsEmpty())
@@ -143,7 +144,9 @@ public:
143 144
144 size_t GetMemStreamWrittenSize() const { return _pos; } 145 size_t GetMemStreamWrittenSize() const { return _pos; }
145 146
146 CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {} 147 CVirtFileSystem():
148 MaxTotalAllocSize((UInt64)0 - 1)
149 {}
147 150
148 void Init() 151 void Init()
149 { 152 {
@@ -161,6 +164,8 @@ public:
161 164
162#endif 165#endif
163 166
167
168
164class CExtractCallbackImp Z7_final: 169class CExtractCallbackImp Z7_final:
165 public IFolderArchiveExtractCallback, 170 public IFolderArchiveExtractCallback,
166 /* IExtractCallbackUI: 171 /* IExtractCallbackUI:
@@ -174,6 +179,7 @@ class CExtractCallbackImp Z7_final:
174 public IFolderOperationsExtractCallback, 179 public IFolderOperationsExtractCallback,
175 public IFolderExtractToStreamCallback, 180 public IFolderExtractToStreamCallback,
176 public ICompressProgressInfo, 181 public ICompressProgressInfo,
182 public IArchiveRequestMemoryUseCallback,
177 #endif 183 #endif
178 #ifndef Z7_NO_CRYPTO 184 #ifndef Z7_NO_CRYPTO
179 public ICryptoGetTextPassword, 185 public ICryptoGetTextPassword,
@@ -186,6 +192,7 @@ class CExtractCallbackImp Z7_final:
186 Z7_COM_QI_ENTRY(IFolderOperationsExtractCallback) 192 Z7_COM_QI_ENTRY(IFolderOperationsExtractCallback)
187 Z7_COM_QI_ENTRY(IFolderExtractToStreamCallback) 193 Z7_COM_QI_ENTRY(IFolderExtractToStreamCallback)
188 Z7_COM_QI_ENTRY(ICompressProgressInfo) 194 Z7_COM_QI_ENTRY(ICompressProgressInfo)
195 Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback)
189 #endif 196 #endif
190 #ifndef Z7_NO_CRYPTO 197 #ifndef Z7_NO_CRYPTO
191 Z7_COM_QI_ENTRY(ICryptoGetTextPassword) 198 Z7_COM_QI_ENTRY(ICryptoGetTextPassword)
@@ -202,65 +209,70 @@ class CExtractCallbackImp Z7_final:
202 Z7_IFACE_COM7_IMP(IFolderOperationsExtractCallback) 209 Z7_IFACE_COM7_IMP(IFolderOperationsExtractCallback)
203 Z7_IFACE_COM7_IMP(IFolderExtractToStreamCallback) 210 Z7_IFACE_COM7_IMP(IFolderExtractToStreamCallback)
204 Z7_IFACE_COM7_IMP(ICompressProgressInfo) 211 Z7_IFACE_COM7_IMP(ICompressProgressInfo)
212 Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback)
205 #endif 213 #endif
206 #ifndef Z7_NO_CRYPTO 214 #ifndef Z7_NO_CRYPTO
207 Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) 215 Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
208 #endif 216 #endif
209 217
210
211 UString _currentArchivePath;
212 bool _needWriteArchivePath; 218 bool _needWriteArchivePath;
213
214 bool _isFolder; 219 bool _isFolder;
215 UString _currentFilePath; 220 bool _totalFilesDefined;
216 UString _filePath; 221 bool _totalBytesDefined;
222public:
223 bool MultiArcMode;
224 bool ProcessAltStreams;
225 bool StreamMode;
226 bool ThereAreMessageErrors;
227#ifndef Z7_NO_CRYPTO
228 bool PasswordIsDefined;
229 bool PasswordWasAsked;
230#endif
217 231
218 #ifndef Z7_SFX 232private:
233#ifndef Z7_SFX
219 bool _needUpdateStat; 234 bool _needUpdateStat;
220 bool _newVirtFileWasAdded; 235 bool _newVirtFileWasAdded;
221 bool _isAltStream; 236 bool _isAltStream;
222 bool _curSize_Defined;
223 UInt64 _curSize;
224 // bool _extractMode; 237 // bool _extractMode;
225 // bool _testMode; 238 // bool _testMode;
226 bool _hashStreamWasUsed; 239 bool _hashStream_WasUsed;
227 COutStreamWithHash *_hashStreamSpec; 240 bool _curSize_Defined;
228 CMyComPtr<ISequentialOutStream> _hashStream; 241 bool NeedAddFile;
229 IHashCalc *_hashCalc; // it's for stat in Test operation
230 #endif
231 242
232 HRESULT SetCurrentFilePath2(const wchar_t *filePath); 243 bool _remember;
233 void AddError_Message(LPCWSTR message); 244 bool _skipArc;
234 HRESULT MessageError(const char *message, const FString &path); 245#endif
235 void Add_ArchiveName_Error(); 246
247 UString _currentArchivePath;
248 UString _currentFilePath;
249 UString _filePath;
250
251#ifndef Z7_SFX
252 UInt64 _curSize;
253 CMyComPtr2<ISequentialOutStream, COutStreamWithHash> _hashStream;
254 IHashCalc *_hashCalc; // it's for stat in Test operation
255#endif
236 256
237public: 257public:
258 CProgressDialog *ProgressDialog;
238 259
239 #ifndef Z7_SFX 260#ifndef Z7_SFX
240 CVirtFileSystem *VirtFileSystemSpec; 261 CVirtFileSystem *VirtFileSystemSpec;
241 CMyComPtr<ISequentialOutStream> VirtFileSystem; 262 CMyComPtr<ISequentialOutStream> VirtFileSystem;
242 #endif
243
244 bool ProcessAltStreams;
245
246 bool StreamMode;
247
248 CProgressDialog *ProgressDialog;
249 #ifndef Z7_SFX
250 UInt64 NumFolders; 263 UInt64 NumFolders;
251 UInt64 NumFiles; 264 UInt64 NumFiles;
252 bool NeedAddFile; 265#endif
253 #endif 266
254 UInt32 NumArchiveErrors; 267 UInt32 NumArchiveErrors;
255 bool ThereAreMessageErrors;
256 NExtract::NOverwriteMode::EEnum OverwriteMode; 268 NExtract::NOverwriteMode::EEnum OverwriteMode;
257 269
258 #ifndef Z7_NO_CRYPTO 270 bool YesToAll;
259 bool PasswordIsDefined; 271 bool TestMode;
260 bool PasswordWasAsked;
261 UString Password;
262 #endif
263 272
273#ifndef Z7_NO_CRYPTO
274 UString Password;
275#endif
264 276
265 UString _lang_Extracting; 277 UString _lang_Extracting;
266 UString _lang_Testing; 278 UString _lang_Testing;
@@ -268,29 +280,35 @@ public:
268 UString _lang_Reading; 280 UString _lang_Reading;
269 UString _lang_Empty; 281 UString _lang_Empty;
270 282
271 bool _totalFilesDefined;
272 bool _totalBytesDefined;
273 bool MultiArcMode;
274
275 CExtractCallbackImp(): 283 CExtractCallbackImp():
276 #ifndef Z7_SFX 284 _totalFilesDefined(false)
277 _hashCalc(NULL), 285 , _totalBytesDefined(false)
278 #endif 286 , MultiArcMode(false)
279 ProcessAltStreams(true), 287 , ProcessAltStreams(true)
280 StreamMode(false), 288 , StreamMode(false)
281 OverwriteMode(NExtract::NOverwriteMode::kAsk), 289#ifndef Z7_NO_CRYPTO
282 #ifndef Z7_NO_CRYPTO 290 , PasswordIsDefined(false)
283 PasswordIsDefined(false), 291 , PasswordWasAsked(false)
284 PasswordWasAsked(false), 292#endif
285 #endif 293#ifndef Z7_SFX
286 _totalFilesDefined(false), 294 , _remember(false)
287 _totalBytesDefined(false), 295 , _skipArc(false)
288 MultiArcMode(false) 296 , _hashCalc(NULL)
297#endif
298 , OverwriteMode(NExtract::NOverwriteMode::kAsk)
299 , YesToAll(false)
300 , TestMode(false)
289 {} 301 {}
290 302
291 ~CExtractCallbackImp(); 303 ~CExtractCallbackImp();
292 void Init(); 304 void Init();
293 305
306 HRESULT SetCurrentFilePath2(const wchar_t *filePath);
307 void AddError_Message(LPCWSTR message);
308 void AddError_Message_ShowArcPath(LPCWSTR message);
309 HRESULT MessageError(const char *message, const FString &path);
310 void Add_ArchiveName_Error();
311
294 #ifndef Z7_SFX 312 #ifndef Z7_SFX
295 void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; } 313 void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }
296 314
@@ -298,9 +316,8 @@ public:
298 { 316 {
299 if (!hash) 317 if (!hash)
300 return; 318 return;
301 _hashStreamSpec = new COutStreamWithHash; 319 _hashStream.Create_if_Empty();
302 _hashStream = _hashStreamSpec; 320 _hashStream->_hash = hash;
303 _hashStreamSpec->_hash = hash;
304 } 321 }
305 #endif 322 #endif
306 323
diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp
index 13189a7..fe4f2bd 100644
--- a/CPP/7zip/UI/FileManager/FM.cpp
+++ b/CPP/7zip/UI/FileManager/FM.cpp
@@ -48,6 +48,10 @@ using namespace NFind;
48// #define MAX_LOADSTRING 100 48// #define MAX_LOADSTRING 100
49 49
50extern 50extern
51bool g_DisableUserQuestions;
52bool g_DisableUserQuestions;
53
54extern
51bool g_RAM_Size_Defined; 55bool g_RAM_Size_Defined;
52bool g_RAM_Size_Defined; 56bool g_RAM_Size_Defined;
53 57
@@ -78,8 +82,9 @@ void FreeGlobalCodecs();
78 82
79#ifndef UNDER_CE 83#ifndef UNDER_CE
80 84
81extern 85#ifdef Z7_USE_DYN_ComCtl32Version
82DWORD g_ComCtl32Version; 86Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
87
83DWORD g_ComCtl32Version; 88DWORD g_ComCtl32Version;
84 89
85static DWORD GetDllVersion(LPCTSTR dllName) 90static DWORD GetDllVersion(LPCTSTR dllName)
@@ -107,6 +112,7 @@ static DWORD GetDllVersion(LPCTSTR dllName)
107} 112}
108 113
109#endif 114#endif
115#endif
110 116
111bool g_IsSmallScreen = false; 117bool g_IsSmallScreen = false;
112 118
@@ -202,7 +208,36 @@ static const wchar_t * const kWindowClass = L"7-Zip::FM";
202 WS_MAXIMIZEBOX) 208 WS_MAXIMIZEBOX)
203#endif 209#endif
204 210
205// FUNCTION: InitInstance(HANDLE, int) 211
212/*
213typedef HRESULT (WINAPI *Func_SetWindowTheme)(
214 HWND hwnd,
215 LPCWSTR pszSubAppName,
216 LPCWSTR pszSubIdList
217);
218
219typedef BOOL (WINAPI *Func_AllowDarkModeForWindow)(
220 HWND a_HWND, BOOL a_Allow);
221
222enum PreferredAppMode
223{
224 Default,
225 AllowDark,
226 ForceDark,
227 ForceLight,
228 Max
229};
230// ordinal 135, in 1903
231typedef BOOL (WINAPI *Func_SetPreferredAppMode)(PreferredAppMode appMode);
232
233typedef HRESULT (WINAPI *Func_DwmSetWindowAttribute)(
234 HWND hwnd,
235 DWORD dwAttribute,
236 LPCVOID pvAttribute,
237 DWORD cbAttribute
238);
239*/
240
206static BOOL InitInstance(int nCmdShow) 241static BOOL InitInstance(int nCmdShow)
207{ 242{
208 CWindow wnd; 243 CWindow wnd;
@@ -293,6 +328,69 @@ static BOOL InitInstance(int nCmdShow)
293 x, y, xSize, ySize, NULL, NULL, g_hInstance, NULL)) 328 x, y, xSize, ySize, NULL, NULL, g_hInstance, NULL))
294 return FALSE; 329 return FALSE;
295 330
331 /*
332 // doesn't work
333 {
334 const HMODULE hmodule = LoadLibrary("UxTheme.dll");
335 if (hmodule)
336 {
337 {
338 const
339 Func_AllowDarkModeForWindow f = Z7_GET_PROC_ADDRESS(
340 Func_AllowDarkModeForWindow, hmodule,
341 MAKEINTRESOURCEA(133));
342 if (f)
343 {
344 BOOL res = f((HWND)wnd, TRUE);
345 res = res;
346 }
347 }
348 {
349 const
350 Func_SetPreferredAppMode f = Z7_GET_PROC_ADDRESS(
351 Func_SetPreferredAppMode, hmodule,
352 MAKEINTRESOURCEA(135));
353 if (f)
354 {
355 f(ForceDark);
356 }
357 }
358 {
359 const
360 Func_SetWindowTheme f = Z7_GET_PROC_ADDRESS(
361 Func_SetWindowTheme, hmodule,
362 "SetWindowTheme");
363 if (f)
364 {
365 // HRESULT hres = f((HWND)wnd, L"DarkMode_Explorer", NULL);
366 HRESULT hres = f((HWND)wnd, L"Explorer", NULL);
367 hres = hres;
368 }
369 }
370 FreeLibrary(hmodule);
371 }
372 }
373 {
374 const HMODULE hmodule = LoadLibrary("Dwmapi.dll");
375 if (hmodule)
376 {
377 const
378 Func_DwmSetWindowAttribute f = Z7_GET_PROC_ADDRESS(
379 Func_DwmSetWindowAttribute, hmodule,
380 "DwmSetWindowAttribute");
381 if (f)
382 {
383 #ifndef Z7_WIN_DWMWA_USE_IMMERSIVE_DARK_MODE
384 #define Z7_WIN_DWMWA_USE_IMMERSIVE_DARK_MODE 20
385 #endif
386 BOOL value = TRUE;
387 f((HWND)wnd, Z7_WIN_DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
388 }
389 FreeLibrary(hmodule);
390 }
391 }
392 */
393
296 if (nCmdShow == SW_SHOWNORMAL || 394 if (nCmdShow == SW_SHOWNORMAL ||
297 nCmdShow == SW_SHOW 395 nCmdShow == SW_SHOW
298 #ifndef UNDER_CE 396 #ifndef UNDER_CE
@@ -519,10 +617,10 @@ static int WINAPI WinMain2(int nCmdShow)
519 617
520 InitCommonControls(); 618 InitCommonControls();
521 619
522 #ifndef UNDER_CE 620#ifdef Z7_USE_DYN_ComCtl32Version
523 g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll")); 621 g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll"));
524 g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4)); 622 g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4));
525 #endif 623#endif
526 624
527 #if defined(_WIN32) && !defined(_WIN64) && !defined(UNDER_CE) 625 #if defined(_WIN32) && !defined(_WIN64) && !defined(UNDER_CE)
528 Set_Wow64(); 626 Set_Wow64();
diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp
index 1ae054d..4c549d6 100644
--- a/CPP/7zip/UI/FileManager/FM.dsp
+++ b/CPP/7zip/UI/FileManager/FM.dsp
@@ -475,6 +475,14 @@ SOURCE=.\BrowseDialog.h
475# End Source File 475# End Source File
476# Begin Source File 476# Begin Source File
477 477
478SOURCE=.\BrowseDialog2.cpp
479# End Source File
480# Begin Source File
481
482SOURCE=.\BrowseDialog2.h
483# End Source File
484# Begin Source File
485
478SOURCE=.\ComboDialog.cpp 486SOURCE=.\ComboDialog.cpp
479# End Source File 487# End Source File
480# Begin Source File 488# Begin Source File
@@ -519,6 +527,14 @@ SOURCE=.\ListViewDialog.h
519# End Source File 527# End Source File
520# Begin Source File 528# Begin Source File
521 529
530SOURCE=.\MemDialog.cpp
531# End Source File
532# Begin Source File
533
534SOURCE=.\MemDialog.h
535# End Source File
536# Begin Source File
537
522SOURCE=MessagesDialog.cpp 538SOURCE=MessagesDialog.cpp
523# End Source File 539# End Source File
524# Begin Source File 540# Begin Source File
@@ -707,6 +723,10 @@ SOURCE=..\..\..\..\C\7zTypes.h
707# End Source File 723# End Source File
708# Begin Source File 724# Begin Source File
709 725
726SOURCE=..\..\..\..\C\7zVersion.h
727# End Source File
728# Begin Source File
729
710SOURCE=..\..\..\..\C\7zWindows.h 730SOURCE=..\..\..\..\C\7zWindows.h
711# End Source File 731# End Source File
712# Begin Source File 732# Begin Source File
@@ -742,6 +762,10 @@ SOURCE=..\..\..\..\C\DllSecur.h
742# End Source File 762# End Source File
743# Begin Source File 763# Begin Source File
744 764
765SOURCE=..\..\..\..\C\Precomp.h
766# End Source File
767# Begin Source File
768
745SOURCE=..\..\..\..\C\Sort.c 769SOURCE=..\..\..\..\C\Sort.c
746# SUBTRACT CPP /YX /Yc /Yu 770# SUBTRACT CPP /YX /Yc /Yu
747# End Source File 771# End Source File
@@ -1068,10 +1092,18 @@ SOURCE=..\..\..\Windows\Window.h
1068# PROP Default_Filter "" 1092# PROP Default_Filter ""
1069# Begin Source File 1093# Begin Source File
1070 1094
1095SOURCE=..\..\..\Common\AutoPtr.h
1096# End Source File
1097# Begin Source File
1098
1071SOURCE=..\..\..\Common\Common.h 1099SOURCE=..\..\..\Common\Common.h
1072# End Source File 1100# End Source File
1073# Begin Source File 1101# Begin Source File
1074 1102
1103SOURCE=..\..\..\Common\Common0.h
1104# End Source File
1105# Begin Source File
1106
1075SOURCE=..\..\..\Common\ComTry.h 1107SOURCE=..\..\..\Common\ComTry.h
1076# End Source File 1108# End Source File
1077# Begin Source File 1109# Begin Source File
diff --git a/CPP/7zip/UI/FileManager/FM.mak b/CPP/7zip/UI/FileManager/FM.mak
index 8331285..d8e2469 100644
--- a/CPP/7zip/UI/FileManager/FM.mak
+++ b/CPP/7zip/UI/FileManager/FM.mak
@@ -5,7 +5,8 @@ CFLAGS = $(CFLAGS) \
5LIBS = $(LIBS) ceshell.lib Commctrl.lib 5LIBS = $(LIBS) ceshell.lib Commctrl.lib
6!ELSE 6!ELSE
7LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib 7LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib
8CFLAGS = $(CFLAGS) -DZ7_LONG_PATH -DZ7_DEVICE_FILE 8CFLAGS = $(CFLAGS) -DZ7_DEVICE_FILE
9# -DZ7_LONG_PATH
9LFLAGS = $(LFLAGS) /DELAYLOAD:mpr.dll 10LFLAGS = $(LFLAGS) /DELAYLOAD:mpr.dll
10LIBS = $(LIBS) delayimp.lib 11LIBS = $(LIBS) delayimp.lib
11!ENDIF 12!ENDIF
@@ -13,6 +14,7 @@ LIBS = $(LIBS) delayimp.lib
13FM_OBJS = \ 14FM_OBJS = \
14 $O\App.obj \ 15 $O\App.obj \
15 $O\BrowseDialog.obj \ 16 $O\BrowseDialog.obj \
17 $O\BrowseDialog2.obj \
16 $O\ClassDefs.obj \ 18 $O\ClassDefs.obj \
17 $O\EnumFormatEtc.obj \ 19 $O\EnumFormatEtc.obj \
18 $O\ExtractCallback.obj \ 20 $O\ExtractCallback.obj \
@@ -25,6 +27,7 @@ FM_OBJS = \
25 $O\FSFolderCopy.obj \ 27 $O\FSFolderCopy.obj \
26 $O\HelpUtils.obj \ 28 $O\HelpUtils.obj \
27 $O\LangUtils.obj \ 29 $O\LangUtils.obj \
30 $O\MemDialog.obj \
28 $O\MenuPage.obj \ 31 $O\MenuPage.obj \
29 $O\MyLoadMenu.obj \ 32 $O\MyLoadMenu.obj \
30 $O\OpenCallback.obj \ 33 $O\OpenCallback.obj \
diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp
index 985d7c4..19d0814 100644
--- a/CPP/7zip/UI/FileManager/FSDrives.cpp
+++ b/CPP/7zip/UI/FileManager/FSDrives.cpp
@@ -64,7 +64,7 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
64 return GetLastError_noZero_HRESULT(); 64 return GetLastError_noZero_HRESULT();
65 } 65 }
66 else 66 else
67 if (!outFile.Create(toPath, true)) 67 if (!outFile.Create_ALWAYS(toPath))
68 return GetLastError_noZero_HRESULT(); 68 return GetLastError_noZero_HRESULT();
69 69
70 CPhysTempBuffer tempBuffer; 70 CPhysTempBuffer tempBuffer;
diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp
index 06c572d..26a2ccf 100644
--- a/CPP/7zip/UI/FileManager/FSFolder.cpp
+++ b/CPP/7zip/UI/FileManager/FSFolder.cpp
@@ -45,7 +45,7 @@ typedef struct _IO_STATUS_BLOCK {
45 45
46#include "SysIconUtils.h" 46#include "SysIconUtils.h"
47 47
48#if _WIN32_WINNT < 0x0501 48#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0501
49#ifdef _APISETFILE_ 49#ifdef _APISETFILE_
50// Windows SDK 8.1 defines in fileapi.h the function GetCompressedFileSizeW only if _WIN32_WINNT >= 0x0501 50// Windows SDK 8.1 defines in fileapi.h the function GetCompressedFileSizeW only if _WIN32_WINNT >= 0x0501
51// But real support version for that function is NT 3.1 (probably) 51// But real support version for that function is NT 3.1 (probably)
@@ -63,6 +63,7 @@ using namespace NDir;
63using namespace NName; 63using namespace NName;
64 64
65#ifndef USE_UNICODE_FSTRING 65#ifndef USE_UNICODE_FSTRING
66int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2);
66int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2) 67int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2)
67{ 68{
68 return CompareFileNames_ForFolderList(fs2us(s1), fs2us(s2)); 69 return CompareFileNames_ForFolderList(fs2us(s1), fs2us(s2));
@@ -119,7 +120,7 @@ HRESULT CFSFolder::Init(const FString &path /* , IFolderFolder *parentFolder */)
119 CFindFile findFile; 120 CFindFile findFile;
120 CFileInfo fi; 121 CFileInfo fi;
121 FString path2 = _path; 122 FString path2 = _path;
122 path2 += '*'; // CHAR_ANY_MASK; 123 path2.Add_Char('*'); // CHAR_ANY_MASK;
123 if (!findFile.FindFirst(path2, fi)) 124 if (!findFile.FindFirst(path2, fi))
124 return lastError; 125 return lastError;
125 } 126 }
@@ -357,7 +358,7 @@ bool CFSFolder::SaveComments()
357 attrib = fi.Attrib; 358 attrib = fi.Attrib;
358 } 359 }
359 NIO::COutFile file; 360 NIO::COutFile file;
360 if (!file.CreateAlways(path, attrib)) 361 if (!file.Create_ALWAYS_with_Attribs(path, attrib))
361 return false; 362 return false;
362 UInt32 processed; 363 UInt32 processed;
363 file.Write(utf, utf.Len(), processed); 364 file.Write(utf, utf.Len(), processed);
@@ -467,7 +468,7 @@ typedef enum
467Z7_WIN_FILE_INFORMATION_CLASS; 468Z7_WIN_FILE_INFORMATION_CLASS;
468 469
469 470
470#if (_WIN32_WINNT >= 0x0500) && !defined(_M_IA64) 471#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500) && !defined(_M_IA64)
471#define Z7_WIN_NTSTATUS NTSTATUS 472#define Z7_WIN_NTSTATUS NTSTATUS
472#define Z7_WIN_IO_STATUS_BLOCK IO_STATUS_BLOCK 473#define Z7_WIN_IO_STATUS_BLOCK IO_STATUS_BLOCK
473#else 474#else
@@ -495,6 +496,7 @@ EXTERN_C_END
495static Func_NtQueryInformationFile f_NtQueryInformationFile; 496static Func_NtQueryInformationFile f_NtQueryInformationFile;
496static bool g_NtQueryInformationFile_WasRequested = false; 497static bool g_NtQueryInformationFile_WasRequested = false;
497 498
499Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
498 500
499void CFSFolder::ReadChangeTime(CDirItem &di) 501void CFSFolder::ReadChangeTime(CDirItem &di)
500{ 502{
@@ -907,7 +909,7 @@ Z7_COM7F_IMF(CFSFolder::BindToParentFolder(IFolderFolder **resultFolder))
907 int pos = _path.ReverseFind_PathSepar(); 909 int pos = _path.ReverseFind_PathSepar();
908 if (pos < 0 || pos != (int)_path.Len() - 1) 910 if (pos < 0 || pos != (int)_path.Len() - 1)
909 return E_FAIL; 911 return E_FAIL;
910 FString parentPath = _path.Left(pos); 912 FString parentPath = _path.Left((unsigned)pos);
911 pos = parentPath.ReverseFind_PathSepar(); 913 pos = parentPath.ReverseFind_PathSepar();
912 parentPath.DeleteFrom((unsigned)(pos + 1)); 914 parentPath.DeleteFrom((unsigned)(pos + 1));
913 915
@@ -1071,7 +1073,7 @@ Z7_COM7F_IMF(CFSFolder::CreateFile(const wchar_t *name, IProgress * /* progress
1071 FString absPath; 1073 FString absPath;
1072 GetAbsPath(name, absPath); 1074 GetAbsPath(name, absPath);
1073 NIO::COutFile outFile; 1075 NIO::COutFile outFile;
1074 if (!outFile.Create(absPath, false)) 1076 if (!outFile.Create_NEW(absPath))
1075 return GetLastError_noZero_HRESULT(); 1077 return GetLastError_noZero_HRESULT();
1076 return S_OK; 1078 return S_OK;
1077} 1079}
diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
index db4ae0a..67499fc 100644
--- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
+++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
@@ -51,7 +51,7 @@ HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath, DWORD attrib)
51 return S_OK; 51 return S_OK;
52 } 52 }
53 53
54 if (!outFile.Create(outPath, true)) 54 if (!outFile.Create_ALWAYS(outPath))
55 { 55 {
56 ErrorFileIndex = 1; 56 ErrorFileIndex = 1;
57 return S_OK; 57 return S_OK;
@@ -184,6 +184,12 @@ static DWORD CALLBACK CopyProgressRoutine(
184 return (pi.ProgressResult == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL); 184 return (pi.ProgressResult == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL);
185} 185}
186 186
187#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // win2000
188#define Z7_USE_DYN_MoveFileWithProgressW
189#endif
190
191#ifdef Z7_USE_DYN_MoveFileWithProgressW
192// nt4
187typedef BOOL (WINAPI * Func_CopyFileExA)( 193typedef BOOL (WINAPI * Func_CopyFileExA)(
188 IN LPCSTR lpExistingFileName, 194 IN LPCSTR lpExistingFileName,
189 IN LPCSTR lpNewFileName, 195 IN LPCSTR lpNewFileName,
@@ -193,6 +199,7 @@ typedef BOOL (WINAPI * Func_CopyFileExA)(
193 IN DWORD dwCopyFlags 199 IN DWORD dwCopyFlags
194 ); 200 );
195 201
202// nt4
196typedef BOOL (WINAPI * Func_CopyFileExW)( 203typedef BOOL (WINAPI * Func_CopyFileExW)(
197 IN LPCWSTR lpExistingFileName, 204 IN LPCWSTR lpExistingFileName,
198 IN LPCWSTR lpNewFileName, 205 IN LPCWSTR lpNewFileName,
@@ -202,6 +209,7 @@ typedef BOOL (WINAPI * Func_CopyFileExW)(
202 IN DWORD dwCopyFlags 209 IN DWORD dwCopyFlags
203 ); 210 );
204 211
212// win2000
205typedef BOOL (WINAPI * Func_MoveFileWithProgressW)( 213typedef BOOL (WINAPI * Func_MoveFileWithProgressW)(
206 IN LPCWSTR lpExistingFileName, 214 IN LPCWSTR lpExistingFileName,
207 IN LPCWSTR lpNewFileName, 215 IN LPCWSTR lpNewFileName,
@@ -209,6 +217,7 @@ typedef BOOL (WINAPI * Func_MoveFileWithProgressW)(
209 IN LPVOID lpData OPTIONAL, 217 IN LPVOID lpData OPTIONAL,
210 IN DWORD dwFlags 218 IN DWORD dwFlags
211 ); 219 );
220#endif
212 221
213struct CCopyState 222struct CCopyState
214{ 223{
@@ -218,6 +227,8 @@ struct CCopyState
218 bool UseReadWriteMode; 227 bool UseReadWriteMode;
219 bool IsAltStreamsDest; 228 bool IsAltStreamsDest;
220 229
230#ifdef Z7_USE_DYN_MoveFileWithProgressW
231private:
221 Func_CopyFileExW my_CopyFileExW; 232 Func_CopyFileExW my_CopyFileExW;
222 #ifndef UNDER_CE 233 #ifndef UNDER_CE
223 Func_MoveFileWithProgressW my_MoveFileWithProgressW; 234 Func_MoveFileWithProgressW my_MoveFileWithProgressW;
@@ -225,8 +236,10 @@ struct CCopyState
225 #ifndef _UNICODE 236 #ifndef _UNICODE
226 Func_CopyFileExA my_CopyFileExA; 237 Func_CopyFileExA my_CopyFileExA;
227 #endif 238 #endif
239public:
240 CCopyState();
241#endif
228 242
229 void Prepare();
230 bool CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile); 243 bool CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile);
231 bool CopyFile_Sys(CFSTR oldFile, CFSTR newFile); 244 bool CopyFile_Sys(CFSTR oldFile, CFSTR newFile);
232 bool MoveFile_Sys(CFSTR oldFile, CFSTR newFile); 245 bool MoveFile_Sys(CFSTR oldFile, CFSTR newFile);
@@ -241,7 +254,9 @@ HRESULT CCopyState::CallProgress()
241 return ProgressInfo.Progress->SetCompleted(&ProgressInfo.StartPos); 254 return ProgressInfo.Progress->SetCompleted(&ProgressInfo.StartPos);
242} 255}
243 256
244void CCopyState::Prepare() 257#ifdef Z7_USE_DYN_MoveFileWithProgressW
258
259CCopyState::CCopyState()
245{ 260{
246 my_CopyFileExW = NULL; 261 my_CopyFileExW = NULL;
247 #ifndef UNDER_CE 262 #ifndef UNDER_CE
@@ -276,6 +291,8 @@ void CCopyState::Prepare()
276 } 291 }
277} 292}
278 293
294#endif
295
279/* WinXP-64: 296/* WinXP-64:
280 CopyFileW(fromFile, toFile:altStream) 297 CopyFileW(fromFile, toFile:altStream)
281 OK - there are NO alt streams in fromFile 298 OK - there are NO alt streams in fromFile
@@ -285,10 +302,20 @@ void CCopyState::Prepare()
285bool CCopyState::CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile) 302bool CCopyState::CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile)
286{ 303{
287 BOOL cancelFlag = FALSE; 304 BOOL cancelFlag = FALSE;
305#ifdef Z7_USE_DYN_MoveFileWithProgressW
288 if (my_CopyFileExW) 306 if (my_CopyFileExW)
289 return BOOLToBool(my_CopyFileExW(oldFile, newFile, CopyProgressRoutine, 307#endif
308 return BOOLToBool(
309#ifdef Z7_USE_DYN_MoveFileWithProgressW
310 my_CopyFileExW
311#else
312 CopyFileExW
313#endif
314 (oldFile, newFile, CopyProgressRoutine,
290 &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS)); 315 &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS));
316#ifdef Z7_USE_DYN_MoveFileWithProgressW
291 return BOOLToBool(::CopyFileW(oldFile, newFile, TRUE)); 317 return BOOLToBool(::CopyFileW(oldFile, newFile, TRUE));
318#endif
292} 319}
293 320
294bool CCopyState::CopyFile_Sys(CFSTR oldFile, CFSTR newFile) 321bool CCopyState::CopyFile_Sys(CFSTR oldFile, CFSTR newFile)
@@ -296,10 +323,18 @@ bool CCopyState::CopyFile_Sys(CFSTR oldFile, CFSTR newFile)
296 #ifndef _UNICODE 323 #ifndef _UNICODE
297 if (!g_IsNT) 324 if (!g_IsNT)
298 { 325 {
326#ifdef Z7_USE_DYN_MoveFileWithProgressW
299 if (my_CopyFileExA) 327 if (my_CopyFileExA)
328#endif
300 { 329 {
301 BOOL cancelFlag = FALSE; 330 BOOL cancelFlag = FALSE;
302 if (my_CopyFileExA(fs2fas(oldFile), fs2fas(newFile), 331 if (
332#ifdef Z7_USE_DYN_MoveFileWithProgressW
333 my_CopyFileExA
334#else
335 CopyFileExA
336#endif
337 (fs2fas(oldFile), fs2fas(newFile),
303 CopyProgressRoutine, &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS)) 338 CopyProgressRoutine, &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS))
304 return true; 339 return true;
305 if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) 340 if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
@@ -336,11 +371,19 @@ bool CCopyState::MoveFile_Sys(CFSTR oldFile, CFSTR newFile)
336 #ifndef UNDER_CE 371 #ifndef UNDER_CE
337 // if (IsItWindows2000orHigher()) 372 // if (IsItWindows2000orHigher())
338 // { 373 // {
374#ifdef Z7_USE_DYN_MoveFileWithProgressW
339 if (my_MoveFileWithProgressW) 375 if (my_MoveFileWithProgressW)
376#endif
340 { 377 {
341 IF_USE_MAIN_PATH_2(oldFile, newFile) 378 IF_USE_MAIN_PATH_2(oldFile, newFile)
342 { 379 {
343 if (my_MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine, 380 if (
381#ifdef Z7_USE_DYN_MoveFileWithProgressW
382 my_MoveFileWithProgressW
383#else
384 MoveFileWithProgressW
385#endif
386 (fs2us(oldFile), fs2us(newFile), CopyProgressRoutine,
344 &ProgressInfo, MOVEFILE_COPY_ALLOWED)) 387 &ProgressInfo, MOVEFILE_COPY_ALLOWED))
345 return true; 388 return true;
346 } 389 }
@@ -352,7 +395,13 @@ bool CCopyState::MoveFile_Sys(CFSTR oldFile, CFSTR newFile)
352 UString superPathOld, superPathNew; 395 UString superPathOld, superPathNew;
353 if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2)) 396 if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2))
354 return false; 397 return false;
355 if (my_MoveFileWithProgressW(superPathOld, superPathNew, CopyProgressRoutine, 398 if (
399#ifdef Z7_USE_DYN_MoveFileWithProgressW
400 my_MoveFileWithProgressW
401#else
402 MoveFileWithProgressW
403#endif
404 (superPathOld, superPathNew, CopyProgressRoutine,
356 &ProgressInfo, MOVEFILE_COPY_ALLOWED)) 405 &ProgressInfo, MOVEFILE_COPY_ALLOWED))
357 return true; 406 return true;
358 } 407 }
@@ -645,7 +694,6 @@ Z7_COM7F_IMF(CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
645 if there are alt streams in fromFile. 694 if there are alt streams in fromFile.
646 So we don't use CopyFileW() for alt Streams. */ 695 So we don't use CopyFileW() for alt Streams. */
647 state.UseReadWriteMode = isAltDest; 696 state.UseReadWriteMode = isAltDest;
648 state.Prepare();
649 697
650 for (i = 0; i < numItems; i++) 698 for (i = 0; i < numItems; i++)
651 { 699 {
@@ -746,7 +794,6 @@ HRESULT CopyFileSystemItems(
746 if there are alt streams in fromFile. 794 if there are alt streams in fromFile.
747 So we don't use CopyFileW() for alt Streams. */ 795 So we don't use CopyFileW() for alt Streams. */
748 state.UseReadWriteMode = isAltDest; 796 state.UseReadWriteMode = isAltDest;
749 state.Prepare();
750 797
751 FOR_VECTOR (i, itemsPaths) 798 FOR_VECTOR (i, itemsPaths)
752 { 799 {
diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp
index e4e9997..1c33464 100644
--- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp
+++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp
@@ -166,7 +166,7 @@ static UString GetBracedType(const wchar_t *type)
166{ 166{
167 UString s ('['); 167 UString s ('[');
168 s += type; 168 s += type;
169 s += ']'; 169 s.Add_Char(']');
170 return s; 170 return s;
171} 171}
172 172
diff --git a/CPP/7zip/UI/FileManager/FoldersPage.rc b/CPP/7zip/UI/FileManager/FoldersPage.rc
index cb345ea..3317a08 100644
--- a/CPP/7zip/UI/FileManager/FoldersPage.rc
+++ b/CPP/7zip/UI/FileManager/FoldersPage.rc
@@ -1,7 +1,7 @@
1#include "FoldersPageRes.h" 1#include "FoldersPageRes.h"
2#include "../../GuiCommon.rc" 2#include "../../GuiCommon.rc"
3 3
4#define xc 240 4#define xc OPTIONS_PAGE_XC_SIZE
5#define yc 100 5#define yc 100
6 6
7IDD_FOLDERS MY_PAGE 7IDD_FOLDERS MY_PAGE
diff --git a/CPP/7zip/UI/FileManager/FoldersPage2.rc b/CPP/7zip/UI/FileManager/FoldersPage2.rc
index 9b9276e..70f832e 100644
--- a/CPP/7zip/UI/FileManager/FoldersPage2.rc
+++ b/CPP/7zip/UI/FileManager/FoldersPage2.rc
@@ -1,16 +1,11 @@
1CAPTION "Folders" 1CAPTION "Folders"
2BEGIN 2BEGIN
3 // GROUPBOX "&Working folder", IDT_FOLDERS_WORKING_FOLDER, m, m, xc, 98 3 // GROUPBOX "&Working folder", IDT_FOLDERS_WORKING_FOLDER, m, m, xc, 98
4
5 LTEXT "&Working folder", IDT_FOLDERS_WORKING_FOLDER, m, m, xc, 8 4 LTEXT "&Working folder", IDT_FOLDERS_WORKING_FOLDER, m, m, xc, 8
6 CONTROL "&System temp folder", IDR_FOLDERS_WORK_SYSTEM, "Button", BS_AUTORADIOBUTTON | WS_GROUP, 5 MY_CONTROL_AUTORADIOBUTTON_GROUP ( "&System temp folder", IDR_FOLDERS_WORK_SYSTEM, m, 20, xc)
7 m, 20, xc, 10 6 MY_CONTROL_AUTORADIOBUTTON ( "&Current", IDR_FOLDERS_WORK_CURRENT, m, 34, xc)
8 CONTROL "&Current", IDR_FOLDERS_WORK_CURRENT, "Button", BS_AUTORADIOBUTTON, 7 MY_CONTROL_AUTORADIOBUTTON ( "Specified:", IDR_FOLDERS_WORK_SPECIFIED, m, 48, xc)
9 m, 34, xc, 10
10 CONTROL "Specified:", IDR_FOLDERS_WORK_SPECIFIED, "Button", BS_AUTORADIOBUTTON,
11 m, 48, xc, 10
12 EDITTEXT IDE_FOLDERS_WORK_PATH, m + m, 62, xc - m - m - bxsDots, 14, ES_AUTOHSCROLL 8 EDITTEXT IDE_FOLDERS_WORK_PATH, m + m, 62, xc - m - m - bxsDots, 14, ES_AUTOHSCROLL
13 PUSHBUTTON "...", IDB_FOLDERS_WORK_PATH, xs - m - bxsDots, 61, bxsDots, bys 9 PUSHBUTTON "...", IDB_FOLDERS_WORK_PATH, xs - m - bxsDots, 61, bxsDots, bys
14 CONTROL "Use for removable drives only", IDX_FOLDERS_WORK_FOR_REMOVABLE, MY_CHECKBOX, 10 MY_CONTROL_CHECKBOX ( "Use for removable drives only", IDX_FOLDERS_WORK_FOR_REMOVABLE, m, 86, xc)
15 m, 86, xc, 10
16END 11END
diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp
index ec1dd2e..3aeaf13 100644
--- a/CPP/7zip/UI/FileManager/LangPage.cpp
+++ b/CPP/7zip/UI/FileManager/LangPage.cpp
@@ -16,7 +16,7 @@
16using namespace NWindows; 16using namespace NWindows;
17 17
18 18
19static const unsigned k_NumLangLines_EN = 429; 19static const unsigned k_NumLangLines_EN = 443;
20 20
21#ifdef Z7_LANG 21#ifdef Z7_LANG
22static const UInt32 kLangIDs[] = 22static const UInt32 kLangIDs[] =
@@ -50,7 +50,7 @@ static void NativeLangString(UString &dest, const wchar_t *s)
50{ 50{
51 dest += " ("; 51 dest += " (";
52 dest += s; 52 dest += s;
53 dest += ')'; 53 dest.Add_Char(')');
54} 54}
55 55
56bool LangOpen(CLang &lang, CFSTR fileName); 56bool LangOpen(CLang &lang, CFSTR fileName);
diff --git a/CPP/7zip/UI/FileManager/LangPage.rc b/CPP/7zip/UI/FileManager/LangPage.rc
index 506f102..60d730f 100644
--- a/CPP/7zip/UI/FileManager/LangPage.rc
+++ b/CPP/7zip/UI/FileManager/LangPage.rc
@@ -1,12 +1,12 @@
1#include "LangPageRes.h" 1#include "LangPageRes.h"
2#include "../../GuiCommon.rc" 2#include "../../GuiCommon.rc"
3 3
4#define xc 240 4#define xc OPTIONS_PAGE_XC_SIZE
5#define yc 252 5#define yc OPTIONS_PAGE_YC_SIZE
6 6
7#define y 32 7#define y 32
8 8
9IDD_LANG DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT 9IDD_LANG DIALOG MY_PAGE_POSTFIX
10CAPTION "Language" 10CAPTION "Language"
11{ 11{
12 LTEXT "Language:", IDT_LANG_LANG, m, m, xc, 8 12 LTEXT "Language:", IDT_LANG_LANG, m, m, xc, 8
diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp
index 4c9d16f..8fcb507 100644
--- a/CPP/7zip/UI/FileManager/LangUtils.cpp
+++ b/CPP/7zip/UI/FileManager/LangUtils.cpp
@@ -56,6 +56,10 @@ void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID)
56 } 56 }
57} 57}
58 58
59#ifndef IDCONTINUE
60#define IDCONTINUE 11
61#endif
62
59static const CIDLangPair kLangPairs[] = 63static const CIDLangPair kLangPairs[] =
60{ 64{
61 { IDOK, 401 }, 65 { IDOK, 401 },
@@ -63,7 +67,8 @@ static const CIDLangPair kLangPairs[] =
63 { IDYES, 406 }, 67 { IDYES, 406 },
64 { IDNO, 407 }, 68 { IDNO, 407 },
65 { IDCLOSE, 408 }, 69 { IDCLOSE, 408 },
66 { IDHELP, 409 } 70 { IDHELP, 409 },
71 { IDCONTINUE, 411 }
67}; 72};
68 73
69 74
@@ -99,7 +104,7 @@ void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems)
99 { 104 {
100 CWindow window(GetDlgItem(dialog, (int)id)); 105 CWindow window(GetDlgItem(dialog, (int)id));
101 UString s2 = s; 106 UString s2 = s;
102 s2 += ':'; 107 s2.Add_Colon();
103 window.SetText(s2); 108 window.SetText(s2);
104 } 109 }
105 } 110 }
@@ -163,7 +168,7 @@ void LangString_OnlyFromLangFile(UInt32 langID, UString &dest)
163 168
164static const char * const kLangs = 169static const char * const kLangs =
165 "ar.bg.ca.zh.-tw.-cn.cs.da.de.el.en.es.fi.fr.he.hu.is." 170 "ar.bg.ca.zh.-tw.-cn.cs.da.de.el.en.es.fi.fr.he.hu.is."
166 "it.ja.ko.nl.no.=nb.=nn.pl.pt.-br.rm.ro.ru.sr.=hr.-spl.-spc.sk.sq.sv.th.tr." 171 "it.ja.ko.nl.no.=nb.=nn.pl.pt.-br.rm.ro.ru.sr.=hr.-spl.-spc.=hr.=bs.sk.sq.sv.th.tr."
167 "ur.id.uk.be.sl.et.lv.lt.tg.fa.vi.hy.az.eu.hsb.mk." 172 "ur.id.uk.be.sl.et.lv.lt.tg.fa.vi.hy.az.eu.hsb.mk."
168 "st.ts.tn.ve.xh.zu.af.ka.fo.hi.mt.se.ga.yi.ms.kk." 173 "st.ts.tn.ve.xh.zu.af.ka.fo.hi.mt.se.ga.yi.ms.kk."
169 "ky.sw.tk.uz.-latn.-cyrl.tt.bn.pa.-in.gu.or.ta.te.kn.ml.as.mr.sa." 174 "ky.sw.tk.uz.-latn.-cyrl.tt.bn.pa.-in.gu.or.ta.te.kn.ml.as.mr.sa."
@@ -198,7 +203,7 @@ static void FindShortNames(UInt32 primeLang, AStringVector &names)
198 p++; 203 p++;
199 } 204 }
200 while (p != p2) 205 while (p != p2)
201 s += (char)(Byte)*p++; 206 s.Add_Char((char)(Byte)*p++);
202 names.Add(s); 207 names.Add(s);
203 } 208 }
204 p = p2 + 1; 209 p = p2 + 1;
@@ -238,10 +243,14 @@ void Lang_GetShortNames_for_DefaultLang(AStringVector &names, unsigned &subLang)
238{ 243{
239 names.Clear(); 244 names.Clear();
240 subLang = 0; 245 subLang = 0;
241 const LANGID sysLang = GetSystemDefaultLangID(); // "Language for non-Unicode programs" in XP64 246 // Region / Administative / Language for non-Unicode programs:
242 const LANGID userLang = GetUserDefaultLangID(); // "Standards and formats" language in XP64 247 const LANGID sysLang = GetSystemDefaultLangID();
248
249 // Region / Formats / Format:
250 const LANGID userLang = GetUserDefaultLangID();
243 251
244 if (sysLang != userLang) 252 if (PRIMARYLANGID(sysLang) !=
253 PRIMARYLANGID(userLang))
245 return; 254 return;
246 const LANGID langID = userLang; 255 const LANGID langID = userLang;
247 256
diff --git a/CPP/7zip/UI/FileManager/MemDialog.cpp b/CPP/7zip/UI/FileManager/MemDialog.cpp
new file mode 100644
index 0000000..1ba717e
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MemDialog.cpp
@@ -0,0 +1,218 @@
1// MemDialog.cpp
2
3#include "StdAfx.h"
4
5#include <CommCtrl.h>
6
7#include "MemDialog.h"
8
9#include "../../../Common/StringToInt.h"
10#include "../../../Windows/System.h"
11#include "../../../Windows/ErrorMsg.h"
12
13#include "../Explorer/MyMessages.h"
14#include "../GUI/ExtractRes.h"
15
16#include "resourceGui.h"
17
18#ifdef Z7_LANG
19#include "LangUtils.h"
20#endif
21
22#ifdef Z7_LANG
23static const UInt32 kLangIDs[] =
24{
25 IDX_MEM_SAVE_LIMIT,
26 IDX_MEM_REMEMBER,
27 IDG_MEM_ACTION,
28 IDR_MEM_ACTION_ALLOW,
29 IDR_MEM_ACTION_SKIP_ARC
30 // , IDR_MEM_SKIP_FILE
31};
32#endif
33
34static const unsigned k_Action_Buttons[] =
35{
36 IDR_MEM_ACTION_ALLOW,
37 IDR_MEM_ACTION_SKIP_ARC
38 // , IDR_MEM_SKIP_FILE
39};
40
41
42void CMemDialog::EnableSpin(bool enable)
43{
44 EnableItem(IDC_MEM_SPIN, enable);
45 EnableItem(IDE_MEM_SPIN_EDIT, enable);
46}
47
48
49static void AddSize_GB(UString &s, UInt32 size_GB, UInt32 id)
50{
51 s.Add_LF();
52 s += " ";
53 s.Add_UInt32(size_GB);
54 s += " GB : ";
55 AddLangString(s, id);
56}
57
58void CMemDialog::AddInfoMessage_To_String(UString &s, UInt64 *ramSize_GB)
59{
60 AddLangString(s, IDS_MEM_REQUIRES_BIG_MEM);
61 AddSize_GB(s, Required_GB, IDS_MEM_REQUIRED_MEM_SIZE);
62 AddSize_GB(s, Limit_GB, IDS_MEM_CURRENT_MEM_LIMIT);
63 if (ramSize_GB)
64 AddSize_GB(s, (UInt32)*ramSize_GB, IDS_MEM_RAM_SIZE);
65 if (!FilePath.IsEmpty())
66 {
67 s.Add_LF();
68 s += "File: ";
69 s += FilePath;
70 }
71}
72
73/*
74int CMemDialog::AddAction(UINT id)
75{
76 const int index = (int)m_Action.AddString(LangString(id));
77 m_Action.SetItemData(index, (LPARAM)id);
78 return index;
79}
80*/
81
82bool CMemDialog::OnInit()
83{
84 #ifdef Z7_LANG
85 LangSetWindowText(*this, IDD_MEM);
86 LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));
87 #endif
88
89 // m_Action.Attach(GetItem(IDC_MEM_ACTION));
90
91 UInt64 ramSize = (UInt64)sizeof(size_t) << 29;
92 const bool ramSize_defined = NWindows::NSystem::GetRamSize(ramSize);
93 // ramSize *= 10; // for debug
94
95 UInt64 ramSize_GB = (ramSize + (1u << 29)) >> 30;
96 if (ramSize_GB == 0)
97 ramSize_GB = 1;
98
99 const bool is_Allowed = (!ramSize_defined || ramSize > ((UInt64)Required_GB << 30));
100 {
101 UString s;
102 if (!is_Allowed)
103 {
104 AddLangString(s, IDS_MEM_ERROR);
105 s.Add_LF();
106 }
107 AddInfoMessage_To_String(s, is_Allowed ? NULL : &ramSize_GB);
108 if (!ArcPath.IsEmpty())
109 // for (int i = 0; i < 10; i++)
110 {
111 s.Add_LF();
112 AddLangString(s, TestMode ?
113 IDS_PROGRESS_TESTING :
114 IDS_PROGRESS_EXTRACTING);
115 s += ": ";
116 s += ArcPath;
117 }
118 SetItemText(IDT_MEM_MESSAGE, s);
119
120 s = "GB";
121 if (ramSize_defined)
122 {
123 s += " / ";
124 s.Add_UInt64(ramSize_GB);
125 s += " GB (RAM)";
126 }
127 SetItemText(IDT_MEM_GB, s);
128 }
129 const UINT valMin = 1;
130 UINT valMax = 64; // 64GB for RAR7
131 if (ramSize_defined /* && ramSize_GB > valMax */)
132 {
133 const UINT k_max_val = 1u << 14;
134 if (ramSize_GB >= k_max_val)
135 valMax = k_max_val;
136 else if (ramSize_GB > 1)
137 valMax = (UINT)ramSize_GB - 1;
138 else
139 valMax = 1;
140 }
141
142 SendItemMessage(IDC_MEM_SPIN, UDM_SETRANGE, 0, MAKELPARAM(valMax, valMin)); // Sets the controls direction
143 // UDM_SETPOS doesn't set value larger than max value (valMax) of range:
144 SendItemMessage(IDC_MEM_SPIN, UDM_SETPOS, 0, Required_GB);
145 {
146 UString s;
147 s.Add_UInt32(Required_GB);
148 SetItemText(IDE_MEM_SPIN_EDIT, s);
149 }
150
151 EnableSpin(false);
152
153 /*
154 AddAction(IDB_ALLOW_OPERATION);
155 m_Action.SetCurSel(0);
156 AddAction(IDB_MEM_SKIP_ARC);
157 AddAction(IDB_MEM_SKIP_FILE);
158 */
159
160 const UINT buttonId = is_Allowed ?
161 IDR_MEM_ACTION_ALLOW :
162 IDR_MEM_ACTION_SKIP_ARC;
163
164 CheckRadioButton(
165 k_Action_Buttons[0],
166 k_Action_Buttons[Z7_ARRAY_SIZE(k_Action_Buttons) - 1],
167 buttonId);
168 /*
169 if (!ShowSkipFile)
170 HideItem(IDR_MEM_SKIP_FILE);
171 */
172 if (!ShowRemember)
173 HideItem(IDX_MEM_REMEMBER);
174 return CModalDialog::OnInit();
175}
176
177
178bool CMemDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
179{
180 if (buttonID == IDX_MEM_SAVE_LIMIT)
181 {
182 EnableSpin(IsButtonCheckedBool(IDX_MEM_SAVE_LIMIT));
183 return true;
184 }
185 return CDialog::OnButtonClicked(buttonID, buttonHWND);
186}
187
188
189void CMemDialog::OnContinue()
190{
191 Remember = IsButtonCheckedBool(IDX_MEM_REMEMBER);
192 NeedSave = IsButtonCheckedBool(IDX_MEM_SAVE_LIMIT);
193 SkipArc = IsButtonCheckedBool(IDR_MEM_ACTION_SKIP_ARC);
194 if (NeedSave)
195 {
196#if 0
197 // UDM_GETPOS doesn't support value outside of range that was set:
198 LRESULT lresult = SendItemMessage(IDC_MEM_SPIN, UDM_GETPOS, 0, 0);
199 const UInt32 val = LOWORD(lresult);
200 if (HIWORD(lresult) != 0) // the value outside of allowed range
201#else
202 UString s;
203 GetItemText(IDE_MEM_SPIN_EDIT, s);
204 const wchar_t *end;
205 const UInt32 val = ConvertStringToUInt32(s.Ptr(), &end);
206 if (s.IsEmpty() || *end != 0 || val > (1u << 30))
207#endif
208 {
209 ShowErrorMessage(*this,
210 NWindows::NError::MyFormatMessage(E_INVALIDARG)
211 // L"Incorrect value"
212 );
213 return;
214 }
215 Limit_GB = val;
216 }
217 CModalDialog::OnContinue();
218}
diff --git a/CPP/7zip/UI/FileManager/MemDialog.h b/CPP/7zip/UI/FileManager/MemDialog.h
new file mode 100644
index 0000000..79de658
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MemDialog.h
@@ -0,0 +1,48 @@
1// MemDialog.h
2
3#ifndef ZIP7_INC_MEM_DIALOG_H
4#define ZIP7_INC_MEM_DIALOG_H
5
6#include "../../../Windows/Control/Dialog.h"
7// #include "../../../Windows/Control/ComboBox.h"
8
9#include "MemDialogRes.h"
10
11class CMemDialog: public NWindows::NControl::CModalDialog
12{
13 // NWindows::NControl::CComboBox m_Action;
14 // we can disable default OnOK() when we press Enter
15 // virtual void OnOK() Z7_override { }
16 virtual void OnContinue() Z7_override;
17 virtual bool OnInit() Z7_override;
18 virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;
19 void EnableSpin(bool enable);
20 // int AddAction(UINT id);
21public:
22 bool NeedSave;
23 bool Remember;
24 bool SkipArc;
25 bool TestMode;
26 bool ShowRemember;
27 // bool ShowSkipFile;
28 UInt32 Required_GB;
29 UInt32 Limit_GB;
30 UString ArcPath;
31 UString FilePath;
32
33 void AddInfoMessage_To_String(UString &s, UInt64 *ramSize_GB = NULL);
34
35 CMemDialog():
36 NeedSave(false),
37 Remember(false),
38 SkipArc(false),
39 TestMode(false),
40 ShowRemember(true),
41 // ShowSkipFile(true),
42 Required_GB(4),
43 Limit_GB(4)
44 {}
45 INT_PTR Create(HWND parentWindow = NULL) { return CModalDialog::Create(IDD_MEM, parentWindow); }
46};
47
48#endif
diff --git a/CPP/7zip/UI/FileManager/MemDialog.rc b/CPP/7zip/UI/FileManager/MemDialog.rc
new file mode 100644
index 0000000..d8bcb54
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MemDialog.rc
@@ -0,0 +1,49 @@
1#include "MemDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 320
5#define yc 200
6
7#define spin_x_size 50
8#define info_y_size 72
9#define save_y (m + info_y_size + 4)
10#define spin_y (save_y + 16)
11
12#define xsg (xc - m - m)
13#define xg (m + m)
14#define yg (spin_y + 20)
15
16IDD_MEM DIALOG MY_MODAL_DIALOG_POSTFIX
17CAPTION "Memory usage request"
18BEGIN
19 LTEXT "", IDT_MEM_MESSAGE, m, m, xc, info_y_size, SS_NOPREFIX
20 CONTROL "Change allowed limit for next operations", IDX_MEM_SAVE_LIMIT, MY_CHECKBOX,
21 m, save_y, xc, 10
22
23 MY_CONTROL_EDIT_WITH_SPIN(
24 IDE_MEM_SPIN_EDIT,
25 IDC_MEM_SPIN,
26 "4", m + 10, spin_y, spin_x_size)
27
28 LTEXT "GB", IDT_MEM_GB, m + 10 + spin_x_size + 8, spin_y + 2, 160, 10
29
30 GROUPBOX "Action", IDG_MEM_ACTION, m, yg, xc, 62
31
32 MY_CONTROL_AUTORADIOBUTTON_GROUP (
33 "&Allow archive unpacking", IDR_MEM_ACTION_ALLOW,
34 xg, yg + 14, xsg)
35 MY_CONTROL_AUTORADIOBUTTON (
36 "&Skip archive unpacking", IDR_MEM_ACTION_SKIP_ARC,
37 xg, yg + 28, xsg)
38// CONTROL "&Skip file extracting", IDR_MEM_SKIP_FILE, MY_AUTORADIOBUTTON,
39// xg, yg + 42, xsg, 10
40
41 CONTROL "&Repeat selected action for current operation", IDX_MEM_REMEMBER, MY_CHECKBOX,
42 xg + 10, yg + 44, xsg - 10, 10
43
44 CONTINUE_CANCEL
45END
46
47#undef save_y
48#undef spin_y
49#undef spin_x_size
diff --git a/CPP/7zip/UI/FileManager/MemDialogRes.h b/CPP/7zip/UI/FileManager/MemDialogRes.h
new file mode 100644
index 0000000..9ece82d
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MemDialogRes.h
@@ -0,0 +1,13 @@
1#define IDD_MEM 7800
2
3#define IDX_MEM_SAVE_LIMIT 7801
4#define IDX_MEM_REMEMBER 7802
5#define IDG_MEM_ACTION 7803
6
7#define IDR_MEM_ACTION_ALLOW 7820
8#define IDR_MEM_ACTION_SKIP_ARC 7821
9
10#define IDT_MEM_MESSAGE 101
11#define IDE_MEM_SPIN_EDIT 110
12#define IDC_MEM_SPIN 111
13#define IDT_MEM_GB 112
diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp
index 2da7f3a..e8736b8 100644
--- a/CPP/7zip/UI/FileManager/MenuPage.cpp
+++ b/CPP/7zip/UI/FileManager/MenuPage.cpp
@@ -123,9 +123,9 @@ bool CMenuPage::OnInit()
123 bit64.Replace(L"64", L"32"); 123 bit64.Replace(L"64", L"32");
124 #endif 124 #endif
125 s.Add_Space(); 125 s.Add_Space();
126 s += '('; 126 s.Add_Char('(');
127 s += bit64; 127 s += bit64;
128 s += ')'; 128 s.Add_Char(')');
129 SetItemText(IDX_SYSTEM_INTEGRATE_TO_MENU_2, s); 129 SetItemText(IDX_SYSTEM_INTEGRATE_TO_MENU_2, s);
130 } 130 }
131 131
diff --git a/CPP/7zip/UI/FileManager/MenuPage.rc b/CPP/7zip/UI/FileManager/MenuPage.rc
index fc21107..66162f6 100644
--- a/CPP/7zip/UI/FileManager/MenuPage.rc
+++ b/CPP/7zip/UI/FileManager/MenuPage.rc
@@ -1,8 +1,8 @@
1#include "MenuPageRes.h" 1#include "MenuPageRes.h"
2#include "../../GuiCommon.rc" 2#include "../../GuiCommon.rc"
3 3
4#define xc 240 4#define xc OPTIONS_PAGE_XC_SIZE
5#define yc 252 5#define yc OPTIONS_PAGE_YC_SIZE
6 6
7IDD_MENU MY_PAGE 7IDD_MENU MY_PAGE
8#include "MenuPage2.rc" 8#include "MenuPage2.rc"
diff --git a/CPP/7zip/UI/FileManager/MenuPage2.rc b/CPP/7zip/UI/FileManager/MenuPage2.rc
index 4d1ba21..df0cc54 100644
--- a/CPP/7zip/UI/FileManager/MenuPage2.rc
+++ b/CPP/7zip/UI/FileManager/MenuPage2.rc
@@ -2,15 +2,15 @@
2 2
3#define y 96 3#define y 96
4 4
5#define zoneX 90 5#define zoneX 100
6 6
7CAPTION "7-Zip" 7CAPTION "7-Zip"
8BEGIN 8BEGIN
9 CONTROL "Integrate 7-Zip to shell context menu", IDX_SYSTEM_INTEGRATE_TO_MENU, MY_CHECKBOX, m, m, xc, 10 9 MY_CONTROL_CHECKBOX ( "Integrate 7-Zip to shell context menu", IDX_SYSTEM_INTEGRATE_TO_MENU, m, m, xc)
10 CONTROL "(32-bit)", IDX_SYSTEM_INTEGRATE_TO_MENU_2, MY_CHECKBOX, m, m + 14, xc, 10 10 MY_CONTROL_CHECKBOX ( "(32-bit)", IDX_SYSTEM_INTEGRATE_TO_MENU_2, m, m + 14, xc)
11 CONTROL "Cascaded context menu", IDX_SYSTEM_CASCADED_MENU, MY_CHECKBOX, m, m + 28, xc, 10 11 MY_CONTROL_CHECKBOX ( "Cascaded context menu", IDX_SYSTEM_CASCADED_MENU, m, m + 28, xc)
12 CONTROL "Icons in context menu", IDX_SYSTEM_ICON_IN_MENU, MY_CHECKBOX, m, m + 42, xc, 10 12 MY_CONTROL_CHECKBOX ( "Icons in context menu", IDX_SYSTEM_ICON_IN_MENU, m, m + 42, xc)
13 CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX, m, m + 56, xc, 10 13 MY_CONTROL_CHECKBOX ( "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, m, m + 56, xc)
14 14
15 LTEXT "Propagate Zone.Id stream:", IDT_SYSTEM_ZONE, m, m + 70, xc - zoneX, 8 15 LTEXT "Propagate Zone.Id stream:", IDT_SYSTEM_ZONE, m, m + 70, xc - zoneX, 8
16 COMBOBOX IDC_SYSTEM_ZONE, m + xc - zoneX, m + 70 - 2, zoneX, 50, MY_COMBO 16 COMBOBOX IDC_SYSTEM_ZONE, m + xc - zoneX, m + 70 - 2, zoneX, 50, MY_COMBO
diff --git a/CPP/7zip/UI/FileManager/MyCom2.h b/CPP/7zip/UI/FileManager/MyCom2.h
index d3b49fe..a0cbd45 100644
--- a/CPP/7zip/UI/FileManager/MyCom2.h
+++ b/CPP/7zip/UI/FileManager/MyCom2.h
@@ -5,20 +5,11 @@
5 5
6#include "../../../Common/MyCom.h" 6#include "../../../Common/MyCom.h"
7 7
8#define Z7_COM_ADDREF_RELEASE_MT \
9 private: \
10 STDMETHOD_(ULONG, AddRef)() Z7_override Z7_final \
11 { return (ULONG)InterlockedIncrement((LONG *)&_m_RefCount); } \
12 STDMETHOD_(ULONG, Release)() Z7_override Z7_final \
13 { const LONG v = InterlockedDecrement((LONG *)&_m_RefCount); \
14 if (v != 0) return (ULONG)v; \
15 delete this; return 0; }
16
17#define Z7_COM_UNKNOWN_IMP_SPEC_MT2(i1, i) \ 8#define Z7_COM_UNKNOWN_IMP_SPEC_MT2(i1, i) \
18 Z7_COM_QI_BEGIN \ 9 Z7_COM_QI_BEGIN \
19 Z7_COM_QI_ENTRY_UNKNOWN(i1) \ 10 Z7_COM_QI_ENTRY_UNKNOWN(i1) \
20 i \ 11 i \
21 Z7_COM_QI_END \ 12 Z7_COM_QI_END_MT \
22 Z7_COM_ADDREF_RELEASE_MT 13 Z7_COM_ADDREF_RELEASE_MT
23 14
24 15
diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
index 9453536..51b8648 100644
--- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
+++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
@@ -2,6 +2,7 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../../../Windows/FileDir.h"
5#include "../../../Windows/Menu.h" 6#include "../../../Windows/Menu.h"
6#include "../../../Windows/TimeUtils.h" 7#include "../../../Windows/TimeUtils.h"
7#include "../../../Windows/Control/Dialog.h" 8#include "../../../Windows/Control/Dialog.h"
@@ -12,6 +13,7 @@
12 13
13#include "AboutDialog.h" 14#include "AboutDialog.h"
14#include "App.h" 15#include "App.h"
16#include "BrowseDialog2.h"
15#include "HelpUtils.h" 17#include "HelpUtils.h"
16#include "LangUtils.h" 18#include "LangUtils.h"
17#include "MyLoadMenu.h" 19#include "MyLoadMenu.h"
@@ -27,6 +29,10 @@ static const UINT k_MenuID_SetBookmark = 810;
27static const UINT k_MenuID_TimePopup = IDM_VIEW_TIME_POPUP; 29static const UINT k_MenuID_TimePopup = IDM_VIEW_TIME_POPUP;
28static const UINT k_MenuID_Time = IDM_VIEW_TIME; 30static const UINT k_MenuID_Time = IDM_VIEW_TIME;
29 31
32#if 0
33// static const UINT k_MenuID_Bookmark_Temp = 850;
34#endif
35
30extern HINSTANCE g_hInstance; 36extern HINSTANCE g_hInstance;
31 37
32#define kFMHelpTopic "FM/index.htm" 38#define kFMHelpTopic "FM/index.htm"
@@ -493,6 +499,9 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position)
493 } 499 }
494 if (selectedCommand != 0) 500 if (selectedCommand != 0)
495 menu.CheckRadioItem(k_MenuID_Time, last, selectedCommand, MF_BYCOMMAND); 501 menu.CheckRadioItem(k_MenuID_Time, last, selectedCommand, MF_BYCOMMAND);
502
503 if (subMenu.AppendItem(MF_STRING, IDM_VIEW_TIME_UTC, L"UTC"))
504 subMenu.CheckItemByID(IDM_VIEW_TIME_UTC, g_Timestamp_Show_UTC);
496 } 505 }
497 } 506 }
498 } 507 }
@@ -511,9 +520,9 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position)
511 UString s = LangString(IDS_BOOKMARK); 520 UString s = LangString(IDS_BOOKMARK);
512 s.Add_Space(); 521 s.Add_Space();
513 const char c = (char)(L'0' + i); 522 const char c = (char)(L'0' + i);
514 s += c; 523 s.Add_Char(c);
515 s += "\tAlt+Shift+"; 524 s += "\tAlt+Shift+";
516 s += c; 525 s.Add_Char(c);
517 subMenu.AppendItem(MF_STRING, k_MenuID_SetBookmark + i, s); 526 subMenu.AppendItem(MF_STRING, k_MenuID_SetBookmark + i, s);
518 } 527 }
519 528
@@ -532,9 +541,22 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position)
532 if (s.IsEmpty()) 541 if (s.IsEmpty())
533 s = '-'; 542 s = '-';
534 s += "\tAlt+"; 543 s += "\tAlt+";
535 s += (char)('0' + i); 544 s.Add_Char((char)('0' + i));
536 menu.AppendItem(MF_STRING, k_MenuID_OpenBookmark + i, s); 545 menu.AppendItem(MF_STRING, k_MenuID_OpenBookmark + i, s);
537 } 546 }
547#if 0
548 {
549 FString tempPathF;
550 if (NFile::NDir::MyGetTempPath(tempPathF))
551 {
552 menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)NULL);
553 UString s;
554 s = "Temp : ";
555 s += fs2us(tempPathF);
556 menu.AppendItem(MF_STRING, k_MenuID_Bookmark_Temp, s);
557 }
558 }
559#endif
538 } 560 }
539} 561}
540 562
@@ -741,8 +763,10 @@ bool ExecuteFileCommand(unsigned id)
741 case IDM_HASH_ALL: g_App.CalculateCrc("*"); break; 763 case IDM_HASH_ALL: g_App.CalculateCrc("*"); break;
742 case IDM_CRC32: g_App.CalculateCrc("CRC32"); break; 764 case IDM_CRC32: g_App.CalculateCrc("CRC32"); break;
743 case IDM_CRC64: g_App.CalculateCrc("CRC64"); break; 765 case IDM_CRC64: g_App.CalculateCrc("CRC64"); break;
766 case IDM_XXH64: g_App.CalculateCrc("XXH64"); break;
744 case IDM_SHA1: g_App.CalculateCrc("SHA1"); break; 767 case IDM_SHA1: g_App.CalculateCrc("SHA1"); break;
745 case IDM_SHA256: g_App.CalculateCrc("SHA256"); break; 768 case IDM_SHA256: g_App.CalculateCrc("SHA256"); break;
769 case IDM_BLAKE2SP: g_App.CalculateCrc("BLAKE2sp"); break;
746 770
747 case IDM_DIFF: g_App.DiffFiles(); break; 771 case IDM_DIFF: g_App.DiffFiles(); break;
748 772
@@ -878,6 +902,11 @@ bool OnMenuCommand(HWND hWnd, unsigned id)
878 case IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT: g_App.SwitchButtonsLables(); break; 902 case IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT: g_App.SwitchButtonsLables(); break;
879 case IDM_VIEW_TOOLBARS_LARGE_BUTTONS: g_App.SwitchLargeButtons(); break; 903 case IDM_VIEW_TOOLBARS_LARGE_BUTTONS: g_App.SwitchLargeButtons(); break;
880 904
905 case IDM_VIEW_TIME_UTC:
906 g_Timestamp_Show_UTC = !g_Timestamp_Show_UTC;
907 g_App.RedrawListItems_InPanels();
908 break;
909
881 // Tools 910 // Tools
882 case IDM_OPTIONS: OptionsDialog(hWnd, g_hInstance); break; 911 case IDM_OPTIONS: OptionsDialog(hWnd, g_hInstance); break;
883 912
@@ -894,6 +923,19 @@ bool OnMenuCommand(HWND hWnd, unsigned id)
894 dialog.Create(hWnd); 923 dialog.Create(hWnd);
895 break; 924 break;
896 } 925 }
926
927 case IDM_TEMP_DIR:
928 {
929 /*
930 CPanel &panel = g_App.GetFocusedPanel();
931 FString tempPathF;
932 if (NFile::NDir::MyGetTempPath(tempPathF))
933 panel.BindToPathAndRefresh(tempPathF);
934 */
935 MyBrowseForTempFolder(g_HWND);
936 break;
937 }
938
897 default: 939 default:
898 { 940 {
899 if (id >= k_MenuID_OpenBookmark && id <= k_MenuID_OpenBookmark + 9) 941 if (id >= k_MenuID_OpenBookmark && id <= k_MenuID_OpenBookmark + 9)
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
index 096527c..f63277a 100644
--- a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
@@ -74,7 +74,7 @@ void COverwriteDialog::SetFileInfoControl(unsigned textID, unsigned iconID,
74 { 74 {
75 AddLangString(s, IDS_PROP_MTIME); 75 AddLangString(s, IDS_PROP_MTIME);
76 s += ": "; 76 s += ": ";
77 char t[32]; 77 char t[64];
78 ConvertUtcFileTimeToString(fileInfo.Time, t); 78 ConvertUtcFileTimeToString(fileInfo.Time, t);
79 s += t; 79 s += t;
80 } 80 }
diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp
index 72b72c6..cdb5ba4 100644
--- a/CPP/7zip/UI/FileManager/Panel.cpp
+++ b/CPP/7zip/UI/FileManager/Panel.cpp
@@ -48,7 +48,6 @@ static DWORD kStyles[4] = { LVS_ICON, LVS_SMALLICON, LVS_LIST, LVS_REPORT };
48// static const int kCreateFolderID = 101; 48// static const int kCreateFolderID = 101;
49 49
50extern HINSTANCE g_hInstance; 50extern HINSTANCE g_hInstance;
51extern DWORD g_ComCtl32Version;
52 51
53void CPanel::Release() 52void CPanel::Release()
54{ 53{
@@ -449,9 +448,9 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
449 // {VIEW_NEWFOLDER, kCreateFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0}, 448 // {VIEW_NEWFOLDER, kCreateFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},
450 }; 449 };
451 450
452 #ifndef UNDER_CE 451#ifdef Z7_USE_DYN_ComCtl32Version
453 if (g_ComCtl32Version >= MAKELONG(71, 4)) 452 if (g_ComCtl32Version >= MAKELONG(71, 4))
454 #endif 453#endif
455 { 454 {
456 icex.dwSize = sizeof(INITCOMMONCONTROLSEX); 455 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
457 icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES; 456 icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
@@ -982,8 +981,8 @@ static UString GetSubFolderNameForExtract2(const UString &arcPath)
982 981
983int CPanel::FindDir_InOperatedList(const CRecordVector<UInt32> &operatedIndices) const 982int CPanel::FindDir_InOperatedList(const CRecordVector<UInt32> &operatedIndices) const
984{ 983{
985 const bool *isDirVector = &_isDirVector.Front(); 984 const bool *isDirVector = _isDirVector.ConstData();
986 const UInt32 *indices = &operatedIndices.Front(); 985 const UInt32 *indices = operatedIndices.ConstData();
987 const unsigned numItems = operatedIndices.Size(); 986 const unsigned numItems = operatedIndices.Size();
988 for (unsigned i = 0; i < numItems; i++) 987 for (unsigned i = 0; i < numItems; i++)
989 if (isDirVector[indices[i]]) 988 if (isDirVector[indices[i]])
@@ -997,7 +996,7 @@ void CPanel::GetFilePaths(const CRecordVector<UInt32> &operatedIndices, UStringV
997 paths.ClearAndReserve(operatedIndices.Size()); 996 paths.ClearAndReserve(operatedIndices.Size());
998 UString path = GetFsPath(); 997 UString path = GetFsPath();
999 const unsigned prefixLen = path.Len(); 998 const unsigned prefixLen = path.Len();
1000 const UInt32 *indices = &operatedIndices.Front(); 999 const UInt32 *indices = operatedIndices.ConstData();
1001 const unsigned numItems = operatedIndices.Size(); 1000 const unsigned numItems = operatedIndices.Size();
1002 // for (unsigned y = 0; y < 10000; y++, paths.Clear()) 1001 // for (unsigned y = 0; y < 10000; y++, paths.Clear())
1003 for (unsigned i = 0; i < numItems; i++) 1002 for (unsigned i = 0; i < numItems; i++)
@@ -1030,7 +1029,7 @@ void CPanel::ExtractArchives()
1030 if (indices.Size() == 1) 1029 if (indices.Size() == 1)
1031 outFolder += GetSubFolderNameForExtract2(GetItemRelPath(indices[0])); 1030 outFolder += GetSubFolderNameForExtract2(GetItemRelPath(indices[0]));
1032 else 1031 else
1033 outFolder += '*'; 1032 outFolder.Add_Char('*');
1034 outFolder.Add_PathSepar(); 1033 outFolder.Add_PathSepar();
1035 1034
1036 CContextMenuInfo ci; 1035 CContextMenuInfo ci;
diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h
index e512cad..5cbc35d 100644
--- a/CPP/7zip/UI/FileManager/Panel.h
+++ b/CPP/7zip/UI/FileManager/Panel.h
@@ -60,6 +60,11 @@ const UInt32 kParentIndex_UInt32 = (UInt32)(Int32)kParentIndex;
60#define ROOT_FS_FOLDER L"C:\\" 60#define ROOT_FS_FOLDER L"C:\\"
61#endif 61#endif
62 62
63#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // < win2000
64#define Z7_USE_DYN_ComCtl32Version
65extern DWORD g_ComCtl32Version;
66#endif
67
63Z7_PURE_INTERFACES_BEGIN 68Z7_PURE_INTERFACES_BEGIN
64 69
65DECLARE_INTERFACE(CPanelCallback) 70DECLARE_INTERFACE(CPanelCallback)
diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp
index de3d764..40a347f 100644
--- a/CPP/7zip/UI/FileManager/PanelCopy.cpp
+++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp
@@ -102,7 +102,7 @@ HRESULT CPanelCopyThread::ProcessVirt()
102 NExtract::NPathMode::EEnum pathMode = 102 NExtract::NPathMode::EEnum pathMode =
103 NExtract::NPathMode::kCurPaths; 103 NExtract::NPathMode::kCurPaths;
104 // NExtract::NPathMode::kFullPathnames; 104 // NExtract::NPathMode::kFullPathnames;
105 result2 = archiveFolder->Extract(&Indices.Front(), Indices.Size(), 105 result2 = archiveFolder->Extract(Indices.ConstData(), Indices.Size(),
106 BoolToInt(options->includeAltStreams), 106 BoolToInt(options->includeAltStreams),
107 BoolToInt(options->replaceAltStreamChars), 107 BoolToInt(options->replaceAltStreamChars),
108 pathMode, NExtract::NOverwriteMode::kAsk, 108 pathMode, NExtract::NOverwriteMode::kAsk,
@@ -111,7 +111,7 @@ HRESULT CPanelCopyThread::ProcessVirt()
111 else 111 else
112 result2 = FolderOperations->CopyTo( 112 result2 = FolderOperations->CopyTo(
113 BoolToInt(options->moveMode), 113 BoolToInt(options->moveMode),
114 &Indices.Front(), Indices.Size(), 114 Indices.ConstData(), Indices.Size(),
115 BoolToInt(options->includeAltStreams), 115 BoolToInt(options->includeAltStreams),
116 BoolToInt(options->replaceAltStreamChars), 116 BoolToInt(options->replaceAltStreamChars),
117 options->folder, ExtractCallback); 117 options->folder, ExtractCallback);
@@ -316,7 +316,7 @@ struct CThreadUpdate
316 Result = FolderOperations->CopyFrom( 316 Result = FolderOperations->CopyFrom(
317 MoveMode, 317 MoveMode,
318 FolderPrefix, 318 FolderPrefix,
319 &FileNamePointers.Front(), 319 FileNamePointers.ConstData(),
320 FileNamePointers.Size(), 320 FileNamePointers.Size(),
321 UpdateCallback); 321 UpdateCallback);
322 } 322 }
diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
index a13b88d..406e304 100644
--- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
+++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
@@ -907,7 +907,7 @@ void CPanel::OpenAltStreams()
907 path.DeleteBack(); 907 path.DeleteBack();
908 } 908 }
909 909
910 path += ':'; 910 path.Add_Colon();
911 BindToPathAndRefresh(path); 911 BindToPathAndRefresh(path);
912 #endif 912 #endif
913} 913}
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
index bd65aef..f4ee3f3 100644
--- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
+++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
@@ -9,7 +9,6 @@
9#include "../../../Common/IntToString.h" 9#include "../../../Common/IntToString.h"
10 10
11#include "../../../Common/AutoPtr.h" 11#include "../../../Common/AutoPtr.h"
12#include "../../../Common/StringConvert.h"
13 12
14#include "../../../Windows/ProcessUtils.h" 13#include "../../../Windows/ProcessUtils.h"
15#include "../../../Windows/FileName.h" 14#include "../../../Windows/FileName.h"
@@ -214,6 +213,8 @@ static void My_GetProcessFileName_2(HANDLE hProcess, UString &path)
214} 213}
215*/ 214*/
216 215
216Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
217
217static void My_GetProcessFileName(HANDLE hProcess, UString &path) 218static void My_GetProcessFileName(HANDLE hProcess, UString &path)
218{ 219{
219 path.Empty(); 220 path.Empty();
@@ -626,14 +627,14 @@ HRESULT CPanel::OpenParentArchiveFolder()
626 627
627 628
628static const char * const kExeExtensions = 629static const char * const kExeExtensions =
629 " exe bat ps1 com" 630 " exe bat ps1 com lnk"
630 " "; 631 " ";
631 632
632static const char * const kStartExtensions = 633static const char * const kStartExtensions =
633 #ifdef UNDER_CE 634 #ifdef UNDER_CE
634 " cab" 635 " cab"
635 #endif 636 #endif
636 " exe bat ps1 com" 637 " exe bat ps1 com lnk"
637 " chm" 638 " chm"
638 " msi doc dot xls ppt pps wps wpt wks xlr wdb vsd pub" 639 " msi doc dot xls ppt pps wps wpt wks xlr wdb vsd pub"
639 640
@@ -813,104 +814,8 @@ void CApp::DiffFiles(const UString &path1, const UString &path2)
813} 814}
814 815
815 816
816#ifndef _UNICODE 817HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process);
817typedef BOOL (WINAPI * Func_ShellExecuteExW)(LPSHELLEXECUTEINFOW lpExecInfo); 818void StartApplicationDontWait(const UString &dir, const UString &path, HWND window);
818#endif
819
820static HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process)
821{
822 UString path2 = path;
823
824 #ifdef _WIN32
825 {
826 int dot = path2.ReverseFind_Dot();
827 int separ = path2.ReverseFind_PathSepar();
828 if (dot < 0 || dot < separ)
829 path2.Add_Dot();
830 }
831 #endif
832
833 UINT32 result;
834
835 #ifndef _UNICODE
836 if (g_IsNT)
837 {
838 SHELLEXECUTEINFOW execInfo;
839 execInfo.cbSize = sizeof(execInfo);
840 execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
841 execInfo.hwnd = NULL;
842 execInfo.lpVerb = NULL;
843 execInfo.lpFile = path2;
844 execInfo.lpParameters = NULL;
845 execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir;
846 execInfo.nShow = SW_SHOWNORMAL;
847 execInfo.hProcess = NULL;
848 const
849 Func_ShellExecuteExW
850 f_ShellExecuteExW = Z7_GET_PROC_ADDRESS(
851 Func_ShellExecuteExW, ::GetModuleHandleW(L"shell32.dll"),
852 "ShellExecuteExW");
853 if (!f_ShellExecuteExW)
854 return 0;
855 f_ShellExecuteExW(&execInfo);
856 result = (UINT32)(UINT_PTR)execInfo.hInstApp;
857 process.Attach(execInfo.hProcess);
858 }
859 else
860 #endif
861 {
862 SHELLEXECUTEINFO execInfo;
863 execInfo.cbSize = sizeof(execInfo);
864 execInfo.fMask = SEE_MASK_NOCLOSEPROCESS
865 #ifndef UNDER_CE
866 | SEE_MASK_FLAG_DDEWAIT
867 #endif
868 ;
869 execInfo.hwnd = NULL;
870 execInfo.lpVerb = NULL;
871 const CSysString sysPath (GetSystemString(path2));
872 const CSysString sysDir (GetSystemString(dir));
873 execInfo.lpFile = sysPath;
874 execInfo.lpParameters = NULL;
875 execInfo.lpDirectory =
876 #ifdef UNDER_CE
877 NULL
878 #else
879 sysDir.IsEmpty() ? NULL : (LPCTSTR)sysDir
880 #endif
881 ;
882 execInfo.nShow = SW_SHOWNORMAL;
883 execInfo.hProcess = NULL;
884 ::ShellExecuteEx(&execInfo);
885 result = (UINT32)(UINT_PTR)execInfo.hInstApp;
886 process.Attach(execInfo.hProcess);
887 }
888
889
890 DEBUG_PRINT_NUM("-- ShellExecuteEx -- execInfo.hInstApp = ", result)
891
892 if (result <= 32)
893 {
894 switch (result)
895 {
896 case SE_ERR_NOASSOC:
897 ::MessageBoxW(window,
898 NError::MyFormatMessage(::GetLastError()),
899 // L"There is no application associated with the given file name extension",
900 L"7-Zip", MB_OK | MB_ICONSTOP);
901 }
902
903 return E_FAIL; // fixed in 15.13. Can we use it for any Windows version?
904 }
905
906 return S_OK;
907}
908
909static void StartApplicationDontWait(const UString &dir, const UString &path, HWND window)
910{
911 CProcess process;
912 StartApplication(dir, path, window, process);
913}
914 819
915void CPanel::EditItem(unsigned index, bool useEditor) 820void CPanel::EditItem(unsigned index, bool useEditor)
916{ 821{
@@ -1199,8 +1104,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param)
1199{ 1104{
1200 DEBUG_PRINT("==== MyThreadFunction ===="); 1105 DEBUG_PRINT("==== MyThreadFunction ====");
1201 1106
1202 CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr((CTmpProcessInfo *)param); 1107 CMyUniquePtr<CTmpProcessInfo> tpi((CTmpProcessInfo *)param);
1203 CTmpProcessInfo *tpi = tmpProcessInfoPtr.get();
1204 CChildProcesses &processes = tpi->Processes; 1108 CChildProcesses &processes = tpi->Processes;
1205 1109
1206 bool mainProcessWasSet = !processes.Handles.IsEmpty(); 1110 bool mainProcessWasSet = !processes.Handles.IsEmpty();
@@ -1257,7 +1161,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param)
1257 { 1161 {
1258 handles.Add(g_ExitEventLauncher._exitEvent); 1162 handles.Add(g_ExitEventLauncher._exitEvent);
1259 1163
1260 DWORD waitResult = WaitForMultiObj_Any_Infinite(handles.Size(), &handles.Front()); 1164 DWORD waitResult = WaitForMultiObj_Any_Infinite(handles.Size(), handles.ConstData());
1261 1165
1262 waitResult -= WAIT_OBJECT_0; 1166 waitResult -= WAIT_OBJECT_0;
1263 1167
@@ -1348,7 +1252,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param)
1348 if (::MessageBoxW(g_HWND, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK) 1252 if (::MessageBoxW(g_HWND, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
1349 { 1253 {
1350 // DEBUG_PRINT_NUM("SendMessage", GetCurrentThreadId()); 1254 // DEBUG_PRINT_NUM("SendMessage", GetCurrentThreadId());
1351 if (SendMessage(tpi->Window, kOpenItemChanged, 0, (LONG_PTR)tpi) != 1) 1255 if (SendMessage(tpi->Window, kOpenItemChanged, 0, (LONG_PTR)tpi.get()) != 1)
1352 { 1256 {
1353 ::MessageBoxW(g_HWND, m, L"7-Zip", MB_OK | MB_ICONSTOP); 1257 ::MessageBoxW(g_HWND, m, L"7-Zip", MB_OK | MB_ICONSTOP);
1354 return 0; 1258 return 0;
@@ -1686,6 +1590,19 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna
1686 options.streamMode = true; 1590 options.streamMode = true;
1687 virtFileSystemSpec = new CVirtFileSystem; 1591 virtFileSystemSpec = new CVirtFileSystem;
1688 virtFileSystem = virtFileSystemSpec; 1592 virtFileSystem = virtFileSystemSpec;
1593
1594#if defined(_WIN32) && !defined(UNDER_CE)
1595#ifndef _UNICODE
1596 if (g_IsNT)
1597#endif
1598 if (_parentFolders.Size() > 0)
1599 {
1600 const CFolderLink &fl = _parentFolders.Front();
1601 if (!fl.IsVirtual && !fl.FilePath.IsEmpty())
1602 ReadZoneFile_Of_BaseFile(fl.FilePath, virtFileSystemSpec->ZoneBuf);
1603 }
1604#endif
1605
1689 // we allow additional total size for small alt streams; 1606 // we allow additional total size for small alt streams;
1690 virtFileSystemSpec->MaxTotalAllocSize = fileSize + (1 << 10); 1607 virtFileSystemSpec->MaxTotalAllocSize = fileSize + (1 << 10);
1691 1608
@@ -1784,8 +1701,7 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna
1784 if (!tryExternal) 1701 if (!tryExternal)
1785 return; 1702 return;
1786 1703
1787 CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr(new CTmpProcessInfo()); 1704 CMyUniquePtr<CTmpProcessInfo> tpi(new CTmpProcessInfo());
1788 CTmpProcessInfo *tpi = tmpProcessInfoPtr.get();
1789 tpi->FolderPath = tempDir; 1705 tpi->FolderPath = tempDir;
1790 tpi->FilePath = tempFilePath; 1706 tpi->FilePath = tempFilePath;
1791 tpi->NeedDelete = true; 1707 tpi->NeedDelete = true;
@@ -1825,13 +1741,13 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna
1825 tpi->Processes.SetMainProcess(process.Detach()); 1741 tpi->Processes.SetMainProcess(process.Detach());
1826 1742
1827 ::CThread th; 1743 ::CThread th;
1828 if (Thread_Create(&th, MyThreadFunction, tpi) != 0) 1744 if (Thread_Create(&th, MyThreadFunction, tpi.get()) != 0)
1829 throw 271824; 1745 throw 271824;
1830 g_ExitEventLauncher._threads.Add(th); 1746 g_ExitEventLauncher._threads.Add(th);
1831 g_ExitEventLauncher._numActiveThreads++; 1747 g_ExitEventLauncher._numActiveThreads++;
1832 1748
1833 tempDirectory.DisableDeleting(); 1749 tempDirectory.DisableDeleting();
1834 tmpProcessInfoPtr.release(); 1750 tpi.release();
1835 tmpProcessInfoRelease._needDelete = false; 1751 tmpProcessInfoRelease._needDelete = false;
1836} 1752}
1837 1753
diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp
index 0cb33d8..2335fc0 100644
--- a/CPP/7zip/UI/FileManager/PanelItems.cpp
+++ b/CPP/7zip/UI/FileManager/PanelItems.cpp
@@ -89,7 +89,8 @@ static int GetColumnAlign(PROPID propID, VARTYPE varType)
89 89
90static int ItemProperty_Compare_NameFirst(void *const *a1, void *const *a2, void * /* param */) 90static int ItemProperty_Compare_NameFirst(void *const *a1, void *const *a2, void * /* param */)
91{ 91{
92 return (*(*((const CPropColumn *const *)a1))).Compare_NameFirst(*(*((const CPropColumn *const *)a2))); 92 return (*(*((const CPropColumn *const *)a1))).Compare_NameFirst
93 (*(*((const CPropColumn *const *)a2)));
93} 94}
94 95
95HRESULT CPanel::InitColumns() 96HRESULT CPanel::InitColumns()
@@ -125,7 +126,7 @@ HRESULT CPanel::InitColumns()
125 126
126 _columns.Clear(); 127 _columns.Clear();
127 128
128 bool isFsFolder = IsFSFolder() || IsAltStreamsFolder(); 129 const bool isFsFolder = IsFSFolder() || IsAltStreamsFolder();
129 130
130 { 131 {
131 UInt32 numProps; 132 UInt32 numProps;
@@ -182,7 +183,7 @@ HRESULT CPanel::InitColumns()
182 { 183 {
183 CMyComBSTR name; 184 CMyComBSTR name;
184 PROPID propID; 185 PROPID propID;
185 HRESULT res = _folderRawProps->GetRawPropInfo(i, &name, &propID); 186 const HRESULT res = _folderRawProps->GetRawPropInfo(i, &name, &propID);
186 if (res != S_OK) 187 if (res != S_OK)
187 continue; 188 continue;
188 CPropColumn prop; 189 CPropColumn prop;
@@ -550,7 +551,7 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
550 { 551 {
551 NCOM::CPropVariant prop; 552 NCOM::CPropVariant prop;
552 _isDirVector.ClearAndSetSize(numItems); 553 _isDirVector.ClearAndSetSize(numItems);
553 bool *vec = (bool *)&_isDirVector.Front(); 554 bool *vec = _isDirVector.NonConstData();
554 HRESULT hres = S_OK; 555 HRESULT hres = S_OK;
555 unsigned i; 556 unsigned i;
556 for (i = 0; i < numItems; i++) 557 for (i = 0; i < numItems; i++)
@@ -892,7 +893,7 @@ void CPanel::Get_ItemIndices_Selected(CRecordVector<UInt32> &indices) const
892 } 893 }
893 HeapSort(&indices.Front(), indices.Size()); 894 HeapSort(&indices.Front(), indices.Size());
894 */ 895 */
895 const bool *v = &_selectedStatusVector.Front(); 896 const bool *v = _selectedStatusVector.ConstData();
896 const unsigned size = _selectedStatusVector.Size(); 897 const unsigned size = _selectedStatusVector.Size();
897 for (unsigned i = 0; i < size; i++) 898 for (unsigned i = 0; i < size; i++)
898 if (v[i]) 899 if (v[i])
@@ -926,7 +927,7 @@ void CPanel::Get_ItemIndices_All(CRecordVector<UInt32> &indices) const
926 if (_folder->GetNumberOfItems(&numItems) != S_OK) 927 if (_folder->GetNumberOfItems(&numItems) != S_OK)
927 return; 928 return;
928 indices.ClearAndSetSize(numItems); 929 indices.ClearAndSetSize(numItems);
929 UInt32 *vec = (UInt32 *)&indices.Front(); 930 UInt32 *vec = indices.NonConstData();
930 for (UInt32 i = 0; i < numItems; i++) 931 for (UInt32 i = 0; i < numItems; i++)
931 vec[i] = i; 932 vec[i] = i;
932} 933}
@@ -1258,7 +1259,7 @@ void CPanel::SaveListViewInfo()
1258 CListViewInfo viewInfo; 1259 CListViewInfo viewInfo;
1259 1260
1260 // PROPID sortPropID = _columns[_sortIndex].ID; 1261 // PROPID sortPropID = _columns[_sortIndex].ID;
1261 PROPID sortPropID = _sortID; 1262 const PROPID sortPropID = _sortID;
1262 1263
1263 // we save columns as "sorted by order" to registry 1264 // we save columns as "sorted by order" to registry
1264 1265
@@ -1300,9 +1301,9 @@ void CPanel::SaveListViewInfo()
1300} 1301}
1301 1302
1302 1303
1303bool CPanel::OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActiveate, LRESULT &result) 1304bool CPanel::OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate, LRESULT &result)
1304{ 1305{
1305 if (itemActiveate->hdr.hwndFrom == HWND(_listView)) 1306 if (itemActivate->hdr.hwndFrom == HWND(_listView))
1306 return false; 1307 return false;
1307 POINT point; 1308 POINT point;
1308 ::GetCursorPos(&point); 1309 ::GetCursorPos(&point);
diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp
index 2fb0e87..4dbd9f6 100644
--- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp
+++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp
@@ -32,12 +32,12 @@ using namespace NWindows;
32#define SPACE_TERMINATOR_CHAR (wchar_t)(0x9C) 32#define SPACE_TERMINATOR_CHAR (wchar_t)(0x9C)
33 33
34#define INT_TO_STR_SPEC(v) \ 34#define INT_TO_STR_SPEC(v) \
35 while (v >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(v % 10)); v /= 10; } \ 35 while (v >= 10) { temp[i++] = (Byte)('0' + (unsigned)(v % 10)); v /= 10; } \
36 *s++ = (unsigned char)('0' + (unsigned)v); 36 *s++ = (Byte)('0' + (unsigned)v);
37 37
38static void ConvertSizeToString(UInt64 val, wchar_t *s) throw() 38static void ConvertSizeToString(UInt64 val, wchar_t *s) throw()
39{ 39{
40 unsigned char temp[32]; 40 Byte temp[32];
41 unsigned i = 0; 41 unsigned i = 0;
42 42
43 if (val <= (UInt32)0xFFFFFFFF) 43 if (val <= (UInt32)0xFFFFFFFF)
@@ -92,30 +92,6 @@ UString ConvertSizeToString(UInt64 value)
92 return s; 92 return s;
93} 93}
94 94
95static inline unsigned GetHex_Upper(unsigned v)
96{
97 return (v < 10) ? ('0' + v) : ('A' + (v - 10));
98}
99
100static inline unsigned GetHex_Lower(unsigned v)
101{
102 return (v < 10) ? ('0' + v) : ('a' + (v - 10));
103}
104
105/*
106static void HexToString(char *dest, const Byte *data, UInt32 size)
107{
108 for (UInt32 i = 0; i < size; i++)
109 {
110 unsigned b = data[i];
111 dest[0] = GetHex((b >> 4) & 0xF);
112 dest[1] = GetHex(b & 0xF);
113 dest += 2;
114 }
115 *dest = 0;
116}
117*/
118
119bool IsSizeProp(UINT propID) throw(); 95bool IsSizeProp(UINT propID) throw();
120bool IsSizeProp(UINT propID) throw() 96bool IsSizeProp(UINT propID) throw()
121{ 97{
@@ -220,6 +196,8 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
220 196
221 if (item.cchTextMax <= 1) 197 if (item.cchTextMax <= 1)
222 return 0; 198 return 0;
199
200 // item.cchTextMax > 1
223 201
224 const CPropColumn &property = _visibleColumns[item.iSubItem]; 202 const CPropColumn &property = _visibleColumns[item.iSubItem];
225 PROPID propID = property.ID; 203 PROPID propID = property.ID;
@@ -290,12 +268,10 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
290 UInt32 dataSize; 268 UInt32 dataSize;
291 UInt32 propType; 269 UInt32 propType;
292 RINOK(_folderRawProps->GetRawProp(realIndex, propID, &data, &dataSize, &propType)) 270 RINOK(_folderRawProps->GetRawProp(realIndex, propID, &data, &dataSize, &propType))
293 const unsigned limit = (unsigned)item.cchTextMax - 1; 271 unsigned limit = (unsigned)item.cchTextMax - 1;
272 // limit != 0
294 if (dataSize == 0) 273 if (dataSize == 0)
295 {
296 text[0] = 0;
297 return 0; 274 return 0;
298 }
299 275
300 if (propID == kpidNtReparse) 276 if (propID == kpidNtReparse)
301 { 277 {
@@ -306,7 +282,7 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
306 unsigned i; 282 unsigned i;
307 for (i = 0; i < limit; i++) 283 for (i = 0; i < limit; i++)
308 { 284 {
309 wchar_t c = s[i]; 285 const wchar_t c = s[i];
310 if (c == 0) 286 if (c == 0)
311 break; 287 break;
312 text[i] = c; 288 text[i] = c;
@@ -324,7 +300,7 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
324 unsigned i; 300 unsigned i;
325 for (i = 0; i < limit; i++) 301 for (i = 0; i < limit; i++)
326 { 302 {
327 wchar_t c = (Byte)s[i]; 303 const wchar_t c = (Byte)s[i];
328 if (c == 0) 304 if (c == 0)
329 break; 305 break;
330 text[i] = c; 306 text[i] = c;
@@ -346,33 +322,29 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
346 wchar_t c = (Byte)temp[i]; 322 wchar_t c = (Byte)temp[i];
347 if (c == 0) 323 if (c == 0)
348 break; 324 break;
349 text[i] = c; 325 *text++ = c;
350 } 326 }
351 text[i] = 0; 327 *text = 0;
352 } 328 }
353 else 329 else
354 { 330 {
355 if (dataSize > limit) 331 const char * const k_Hex =
356 dataSize = limit; 332 (dataSize <= 8
357 WCHAR *dest = text; 333 && (propID == kpidCRC || propID == kpidChecksum))
358 const bool needUpper = (dataSize <= 8) 334 ? k_Hex_Upper : k_Hex_Lower;
359 && (propID == kpidCRC || propID == kpidChecksum); 335 limit /= 2;
360 for (UInt32 i = 0; i < dataSize; i++) 336 if (limit > dataSize)
337 limit = dataSize;
338 const Byte *data2 = (const Byte *)data;
339 do
361 { 340 {
362 unsigned b = ((const Byte *)data)[i]; 341 const size_t b = *data2++;
363 if (needUpper) 342 text[0] = (Byte)k_Hex[b >> 4];
364 { 343 text[1] = (Byte)k_Hex[b & 15];
365 dest[0] = (WCHAR)GetHex_Upper((b >> 4) & 0xF); 344 text += 2;
366 dest[1] = (WCHAR)GetHex_Upper(b & 0xF);
367 }
368 else
369 {
370 dest[0] = (WCHAR)GetHex_Lower((b >> 4) & 0xF);
371 dest[1] = (WCHAR)GetHex_Lower(b & 0xF);
372 }
373 dest += 2;
374 } 345 }
375 *dest = 0; 346 while (--limit);
347 *text = 0;
376 } 348 }
377 } 349 }
378 return 0; 350 return 0;
@@ -549,10 +521,6 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
549 return 0; 521 return 0;
550} 522}
551 523
552#ifndef UNDER_CE
553extern DWORD g_ComCtl32Version;
554#endif
555
556void CPanel::OnItemChanged(NMLISTVIEW *item) 524void CPanel::OnItemChanged(NMLISTVIEW *item)
557{ 525{
558 const unsigned index = (unsigned)item->lParam; 526 const unsigned index = (unsigned)item->lParam;
@@ -691,9 +659,9 @@ bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result)
691 SetFocusToList(); 659 SetFocusToList();
692 Post_Refresh_StatusBar(); 660 Post_Refresh_StatusBar();
693 if (_mySelectMode) 661 if (_mySelectMode)
694 #ifndef UNDER_CE 662#ifdef Z7_USE_DYN_ComCtl32Version
695 if (g_ComCtl32Version >= MAKELONG(71, 4)) 663 if (g_ComCtl32Version >= MAKELONG(71, 4))
696 #endif 664#endif
697 OnLeftClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header); 665 OnLeftClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header);
698 return false; 666 return false;
699 } 667 }
@@ -843,7 +811,7 @@ void CPanel::Refresh_StatusBar()
843 NCOM::CPropVariant prop; 811 NCOM::CPropVariant prop;
844 if (_folder->GetProperty(realIndex, kpidMTime, &prop) == S_OK) 812 if (_folder->GetProperty(realIndex, kpidMTime, &prop) == S_OK)
845 { 813 {
846 char dateString2[32]; 814 char dateString2[64];
847 dateString2[0] = 0; 815 dateString2[0] = 0;
848 ConvertPropertyToShortString2(dateString2, prop, kpidMTime); 816 ConvertPropertyToShortString2(dateString2, prop, kpidMTime);
849 for (unsigned i = 0;; i++) 817 for (unsigned i = 0;; i++)
diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp
index f0afe15..9086996 100644
--- a/CPP/7zip/UI/FileManager/PanelMenu.cpp
+++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp
@@ -155,16 +155,6 @@ static void AddPropertyString(PROPID propID, UInt64 val, CListViewDialog &dialog
155} 155}
156 156
157 157
158static inline unsigned GetHex_Upper(unsigned v)
159{
160 return (v < 10) ? ('0' + v) : ('A' + (v - 10));
161}
162
163static inline unsigned GetHex_Lower(unsigned v)
164{
165 return (v < 10) ? ('0' + v) : ('a' + (v - 10));
166}
167
168static const Byte kSpecProps[] = 158static const Byte kSpecProps[] =
169{ 159{
170 kpidPath, 160 kpidPath,
@@ -244,7 +234,7 @@ void CPanel::Properties()
244 ConvertNtSecureToString((const Byte *)data, dataSize, s); 234 ConvertNtSecureToString((const Byte *)data, dataSize, s);
245 else 235 else
246 { 236 {
247 const UInt32 kMaxDataSize = 64; 237 const unsigned kMaxDataSize = 1 << 8;
248 if (dataSize > kMaxDataSize) 238 if (dataSize > kMaxDataSize)
249 { 239 {
250 s += "data:"; 240 s += "data:";
@@ -252,22 +242,12 @@ void CPanel::Properties()
252 } 242 }
253 else 243 else
254 { 244 {
255 const bool needUpper = (dataSize <= 8) 245 char temp[kMaxDataSize * 2 + 2];
256 && (propID == kpidCRC || propID == kpidChecksum); 246 if (dataSize <= 8 && (propID == kpidCRC || propID == kpidChecksum))
257 for (UInt32 k = 0; k < dataSize; k++) 247 ConvertDataToHex_Upper(temp, (const Byte *)data, dataSize);
258 { 248 else
259 const Byte b = ((const Byte *)data)[k]; 249 ConvertDataToHex_Lower(temp, (const Byte *)data, dataSize);
260 if (needUpper) 250 s += temp;
261 {
262 s += (char)GetHex_Upper((b >> 4) & 0xF);
263 s += (char)GetHex_Upper(b & 0xF);
264 }
265 else
266 {
267 s += (char)GetHex_Lower((b >> 4) & 0xF);
268 s += (char)GetHex_Lower(b & 0xF);
269 }
270 }
271 } 251 }
272 } 252 }
273 AddPropertyPair(GetNameOfProperty(propID, name), (UString)s.Ptr(), message); 253 AddPropertyPair(GetNameOfProperty(propID, name), (UString)s.Ptr(), message);
@@ -622,7 +602,7 @@ HRESULT CPanel::CreateShellContextMenu(
622 ODS("==== CPanel::CreateShellContextMenu pidls END"); 602 ODS("==== CPanel::CreateShellContextMenu pidls END");
623 // Get IContextMenu for items 603 // Get IContextMenu for items
624 RINOK(parentFolder->GetUIObjectOf(GetParent(), 604 RINOK(parentFolder->GetUIObjectOf(GetParent(),
625 pidls.items.Size(), (LPCITEMIDLIST *)(void *)&pidls.items.Front(), 605 pidls.items.Size(), (LPCITEMIDLIST *)(void *)pidls.items.ConstData(),
626 IID_IContextMenu, NULL, (void**)&systemContextMenu)) 606 IID_IContextMenu, NULL, (void**)&systemContextMenu))
627 ODS("==== CPanel::CreateShellContextMenu GetUIObjectOf finished"); 607 ODS("==== CPanel::CreateShellContextMenu GetUIObjectOf finished");
628 if (!systemContextMenu) 608 if (!systemContextMenu)
diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp
index b61f4e9..6c2cea1 100644
--- a/CPP/7zip/UI/FileManager/PanelOperations.cpp
+++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp
@@ -60,7 +60,7 @@ HRESULT CThreadFolderOperations::ProcessVirt()
60 case FOLDER_TYPE_CREATE_FOLDER: 60 case FOLDER_TYPE_CREATE_FOLDER:
61 return FolderOperations->CreateFolder(Name, UpdateCallback); 61 return FolderOperations->CreateFolder(Name, UpdateCallback);
62 case FOLDER_TYPE_DELETE: 62 case FOLDER_TYPE_DELETE:
63 return FolderOperations->Delete(&Indices.Front(), Indices.Size(), UpdateCallback); 63 return FolderOperations->Delete(Indices.ConstData(), Indices.Size(), UpdateCallback);
64 case FOLDER_TYPE_RENAME: 64 case FOLDER_TYPE_RENAME:
65 return FolderOperations->Rename(Index, Name, UpdateCallback); 65 return FolderOperations->Rename(Index, Name, UpdateCallback);
66 default: 66 default:
@@ -192,6 +192,8 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
192 #ifdef _UNICODE 192 #ifdef _UNICODE
193 /* res = */ ::SHFileOperationW(&fo); 193 /* res = */ ::SHFileOperationW(&fo);
194 #else 194 #else
195Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
196 const
195 Func_SHFileOperationW 197 Func_SHFileOperationW
196 f_SHFileOperationW = Z7_GET_PROC_ADDRESS( 198 f_SHFileOperationW = Z7_GET_PROC_ADDRESS(
197 Func_SHFileOperationW, ::GetModuleHandleW(L"shell32.dll"), 199 Func_SHFileOperationW, ::GetModuleHandleW(L"shell32.dll"),
@@ -316,7 +318,7 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
316 if (realIndex == kParentIndex) 318 if (realIndex == kParentIndex)
317 return FALSE; 319 return FALSE;
318 const UString prefix = GetItemPrefix(realIndex); 320 const UString prefix = GetItemPrefix(realIndex);
319 321 const UString oldName = GetItemName(realIndex);
320 322
321 CDisableNotify disableNotify(*this); 323 CDisableNotify disableNotify(*this);
322 { 324 {
@@ -324,20 +326,22 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
324 op.FolderOperations = _folderOperations; 326 op.FolderOperations = _folderOperations;
325 op.Index = realIndex; 327 op.Index = realIndex;
326 op.Name = newName; 328 op.Name = newName;
327 /* HRESULTres = */ op.DoOperation(*this, 329 const HRESULT res = op.DoOperation(*this,
328 LangString(IDS_RENAMING), 330 LangString(IDS_RENAMING),
329 LangString(IDS_ERROR_RENAMING)); 331 LangString(IDS_ERROR_RENAMING));
330 // fixed in 9.26: we refresh list even after errors 332 // fixed in 9.26: we refresh list even after errors
331 // (it's more safe, since error can be at different stages, so list can be incorrect). 333 // (it's more safe, since error can be at different stages, so list can be incorrect).
332 /* 334 if (res == S_OK)
333 if (res != S_OK) 335 _selectedState.FocusedName = prefix + newName;
334 return FALSE; 336 else
335 */ 337 {
338 _selectedState.FocusedName = prefix + oldName;
339 // return FALSE;
340 }
336 } 341 }
337 342
338 // Can't use RefreshListCtrl here. 343 // Can't use RefreshListCtrl here.
339 // RefreshListCtrlSaveFocused(); 344 // RefreshListCtrlSaveFocused();
340 _selectedState.FocusedName = prefix + newName;
341 _selectedState.FocusedName_Defined = true; 345 _selectedState.FocusedName_Defined = true;
342 _selectedState.SelectFocused = true; 346 _selectedState.SelectFocused = true;
343 347
diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
index 64aa039..c452d41 100644
--- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
+++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
@@ -38,7 +38,7 @@ struct CVolSeqName
38 while (numVolumes > 999) 38 while (numVolumes > 999)
39 { 39 {
40 numVolumes /= 10; 40 numVolumes /= 10;
41 ChangedPart += '0'; 41 ChangedPart.Add_Char('0');
42 } 42 }
43 } 43 }
44 44
@@ -192,7 +192,7 @@ HRESULT CThreadSplit::ProcessVirt()
192 name.Add_Dot(); 192 name.Add_Dot();
193 name += us2fs(seqName.GetNextName()); 193 name += us2fs(seqName.GetNextName());
194 sync.Set_FilePath(fs2us(name)); 194 sync.Set_FilePath(fs2us(name));
195 if (!outFile.File.Create(name, false)) 195 if (!outFile.File.Create_NEW(name))
196 { 196 {
197 const HRESULT res = GetLastError_noZero_HRESULT(); 197 const HRESULT res = GetLastError_noZero_HRESULT();
198 AddErrorPath(name); 198 AddErrorPath(name);
@@ -277,7 +277,7 @@ void CApp::Split()
277 srcPanel.MessageBox_Error(L"Cannot find file"); 277 srcPanel.MessageBox_Error(L"Cannot find file");
278 return; 278 return;
279 } 279 }
280 if (fileInfo.Size <= splitDialog.VolumeSizes.Front()) 280 if (fileInfo.Size <= splitDialog.VolumeSizes.FrontItem())
281 { 281 {
282 srcPanel.MessageBox_Error_LangID(IDS_SPLIT_VOL_MUST_BE_SMALLER); 282 srcPanel.MessageBox_Error_LangID(IDS_SPLIT_VOL_MUST_BE_SMALLER);
283 return; 283 return;
@@ -355,7 +355,7 @@ public:
355HRESULT CThreadCombine::ProcessVirt() 355HRESULT CThreadCombine::ProcessVirt()
356{ 356{
357 NIO::COutFile outFile; 357 NIO::COutFile outFile;
358 if (!outFile.Create(OutputPath, false)) 358 if (!outFile.Create_NEW(OutputPath))
359 { 359 {
360 const HRESULT res = GetLastError_noZero_HRESULT(); 360 const HRESULT res = GetLastError_noZero_HRESULT();
361 AddErrorPath(OutputPath); 361 AddErrorPath(OutputPath);
diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.rc b/CPP/7zip/UI/FileManager/PasswordDialog.rc
index 90c57ef..fa42f92 100644
--- a/CPP/7zip/UI/FileManager/PasswordDialog.rc
+++ b/CPP/7zip/UI/FileManager/PasswordDialog.rc
@@ -1,7 +1,11 @@
1#include "PasswordDialogRes.h" 1#include "PasswordDialogRes.h"
2#include "../../GuiCommon.rc" 2#include "../../GuiCommon.rc"
3 3
4#ifdef UNDER_CE
4#define xc 140 5#define xc 140
6#else
7#define xc 200
8#endif
5#define yc 72 9#define yc 72
6 10
7IDD_PASSWORD DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT 11IDD_PASSWORD DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
diff --git a/CPP/7zip/UI/FileManager/PluginLoader.h b/CPP/7zip/UI/FileManager/PluginLoader.h
index d9309f2..476a7b7 100644
--- a/CPP/7zip/UI/FileManager/PluginLoader.h
+++ b/CPP/7zip/UI/FileManager/PluginLoader.h
@@ -7,13 +7,15 @@
7 7
8#include "IFolder.h" 8#include "IFolder.h"
9 9
10Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
11
10class CPluginLibrary: public NWindows::NDLL::CLibrary 12class CPluginLibrary: public NWindows::NDLL::CLibrary
11{ 13{
12public: 14public:
13 HRESULT CreateManager(REFGUID clsID, IFolderManager **manager) 15 HRESULT CreateManager(REFGUID clsID, IFolderManager **manager)
14 { 16 {
15 const 17 const
16 Func_CreateObject createObject = Z7_GET_PROC_ADDRESS( 18 Func_CreateObject createObject = Z7_GET_PROC_ADDRESS(
17 Func_CreateObject, Get_HMODULE(), 19 Func_CreateObject, Get_HMODULE(),
18 "CreateObject"); 20 "CreateObject");
19 if (!createObject) 21 if (!createObject)
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
index 1521d83..690ebec 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
@@ -23,6 +23,7 @@
23using namespace NWindows; 23using namespace NWindows;
24 24
25extern HINSTANCE g_hInstance; 25extern HINSTANCE g_hInstance;
26extern bool g_DisableUserQuestions;
26 27
27static const UINT_PTR kTimerID = 3; 28static const UINT_PTR kTimerID = 3;
28 29
@@ -977,6 +978,7 @@ INT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread,
977 } 978 }
978 thread.Wait_Close(); 979 thread.Wait_Close();
979 if (!MessagesDisplayed) 980 if (!MessagesDisplayed)
981 if (!g_DisableUserQuestions)
980 MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR); 982 MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR);
981 return res; 983 return res;
982} 984}
@@ -1012,7 +1014,8 @@ bool CProgressDialog::OnExternalCloseMessage()
1012 MessagesDisplayed = true; 1014 MessagesDisplayed = true;
1013 if (fm.ErrorMessage.Title.IsEmpty()) 1015 if (fm.ErrorMessage.Title.IsEmpty())
1014 fm.ErrorMessage.Title = "7-Zip"; 1016 fm.ErrorMessage.Title = "7-Zip";
1015 MessageBoxW(*this, fm.ErrorMessage.Message, fm.ErrorMessage.Title, MB_ICONERROR); 1017 if (!g_DisableUserQuestions)
1018 MessageBoxW(*this, fm.ErrorMessage.Message, fm.ErrorMessage.Title, MB_ICONERROR);
1016 } 1019 }
1017 else if (!thereAreMessages) 1020 else if (!thereAreMessages)
1018 { 1021 {
@@ -1022,10 +1025,12 @@ bool CProgressDialog::OnExternalCloseMessage()
1022 { 1025 {
1023 if (fm.OkMessage.Title.IsEmpty()) 1026 if (fm.OkMessage.Title.IsEmpty())
1024 fm.OkMessage.Title = "7-Zip"; 1027 fm.OkMessage.Title = "7-Zip";
1025 MessageBoxW(*this, fm.OkMessage.Message, fm.OkMessage.Title, MB_OK); 1028 if (!g_DisableUserQuestions)
1029 MessageBoxW(*this, fm.OkMessage.Message, fm.OkMessage.Title, MB_OK);
1026 } 1030 }
1027 } 1031 }
1028 1032
1033 if (!g_DisableUserQuestions)
1029 if (thereAreMessages && !_cancelWasPressed) 1034 if (thereAreMessages && !_cancelWasPressed)
1030 { 1035 {
1031 _waitCloseByCancelButton = true; 1036 _waitCloseByCancelButton = true;
@@ -1084,7 +1089,7 @@ void CProgressDialog::SetTitleText()
1084 char temp[32]; 1089 char temp[32];
1085 ConvertUInt64ToString(_prevPercentValue, temp); 1090 ConvertUInt64ToString(_prevPercentValue, temp);
1086 s += temp; 1091 s += temp;
1087 s += '%'; 1092 s.Add_Char('%');
1088 } 1093 }
1089 if (!_foreground) 1094 if (!_foreground)
1090 { 1095 {
diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp
index 16e4675..c4465da 100644
--- a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp
+++ b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp
@@ -143,7 +143,7 @@ LONG AddShellExtensionInfo(HKEY hkey,
143 iconIndex = 0; 143 iconIndex = 0;
144 // if (iconIndex >= 0) 144 // if (iconIndex >= 0)
145 { 145 {
146 iconPathFull += ','; 146 iconPathFull.Add_Char(',');
147 iconPathFull.Add_UInt32((UInt32)iconIndex); 147 iconPathFull.Add_UInt32((UInt32)iconIndex);
148 } 148 }
149 iconKey.Create(programKey, kDefaultIconKeyName); 149 iconKey.Create(programKey, kDefaultIconKeyName);
diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp
index 34dd638..606fb7f 100644
--- a/CPP/7zip/UI/FileManager/RootFolder.cpp
+++ b/CPP/7zip/UI/FileManager/RootFolder.cpp
@@ -124,13 +124,20 @@ Z7_COM7F_IMF(CRootFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIA
124 return S_OK; 124 return S_OK;
125} 125}
126 126
127#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0400 // nt4
128#define Z7_USE_DYN_SHGetSpecialFolderPath
129#endif
130
131#ifdef Z7_USE_DYN_SHGetSpecialFolderPath
127typedef BOOL (WINAPI *Func_SHGetSpecialFolderPathW)(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate); 132typedef BOOL (WINAPI *Func_SHGetSpecialFolderPathW)(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate);
128typedef BOOL (WINAPI *Func_SHGetSpecialFolderPathA)(HWND hwnd, LPSTR pszPath, int csidl, BOOL fCreate); 133typedef BOOL (WINAPI *Func_SHGetSpecialFolderPathA)(HWND hwnd, LPSTR pszPath, int csidl, BOOL fCreate);
134#endif
129 135
130static UString GetMyDocsPath() 136static UString GetMyDocsPath()
131{ 137{
132 UString us; 138 UString us;
133 WCHAR s[MAX_PATH + 1]; 139 WCHAR s[MAX_PATH + 1];
140#ifdef Z7_USE_DYN_SHGetSpecialFolderPath
134#ifdef UNDER_CE 141#ifdef UNDER_CE
135 #define shell_name TEXT("coredll.dll") 142 #define shell_name TEXT("coredll.dll")
136#else 143#else
@@ -139,16 +146,25 @@ static UString GetMyDocsPath()
139 Func_SHGetSpecialFolderPathW getW = Z7_GET_PROC_ADDRESS( 146 Func_SHGetSpecialFolderPathW getW = Z7_GET_PROC_ADDRESS(
140 Func_SHGetSpecialFolderPathW, GetModuleHandle(shell_name), 147 Func_SHGetSpecialFolderPathW, GetModuleHandle(shell_name),
141 "SHGetSpecialFolderPathW"); 148 "SHGetSpecialFolderPathW");
142 if (getW && getW(NULL, s, CSIDL_PERSONAL, FALSE)) 149 if (getW && getW
150#else
151 if (SHGetSpecialFolderPathW
152#endif
153 (NULL, s, CSIDL_PERSONAL, FALSE))
143 us = s; 154 us = s;
144 #ifndef _UNICODE 155 #ifndef _UNICODE
145 else 156 else
146 { 157 {
158 CHAR s2[MAX_PATH + 1];
159#ifdef Z7_USE_DYN_SHGetSpecialFolderPath
147 Func_SHGetSpecialFolderPathA getA = Z7_GET_PROC_ADDRESS( 160 Func_SHGetSpecialFolderPathA getA = Z7_GET_PROC_ADDRESS(
148 Func_SHGetSpecialFolderPathA, ::GetModuleHandleA("shell32.dll"), 161 Func_SHGetSpecialFolderPathA, ::GetModuleHandleA("shell32.dll"),
149 "SHGetSpecialFolderPathA"); 162 "SHGetSpecialFolderPathA");
150 CHAR s2[MAX_PATH + 1]; 163 if (getA && getA
151 if (getA && getA(NULL, s2, CSIDL_PERSONAL, FALSE)) 164#else
165 if (SHGetSpecialFolderPathA
166#endif
167 (NULL, s2, CSIDL_PERSONAL, FALSE))
152 us = GetUnicodeString(s2); 168 us = GetUnicodeString(s2);
153 } 169 }
154 #endif 170 #endif
diff --git a/CPP/7zip/UI/FileManager/SettingsPage.cpp b/CPP/7zip/UI/FileManager/SettingsPage.cpp
index 784b8c7..a5117be 100644
--- a/CPP/7zip/UI/FileManager/SettingsPage.cpp
+++ b/CPP/7zip/UI/FileManager/SettingsPage.cpp
@@ -2,15 +2,21 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include <CommCtrl.h>
6
5// #include "../../../Common/IntToString.h" 7// #include "../../../Common/IntToString.h"
6// #include "../../../Common/StringConvert.h" 8// #include "../../../Common/StringConvert.h"
9#include "../../../Common/StringToInt.h"
7 10
8#ifndef UNDER_CE 11#ifndef UNDER_CE
12#include "../../../Windows/ErrorMsg.h"
9#include "../../../Windows/MemoryLock.h" 13#include "../../../Windows/MemoryLock.h"
10// #include "../../../Windows/System.h" 14#include "../../../Windows/System.h"
11#endif 15#endif
12 16
13// #include "../Common/ZipRegistry.h" 17#include "../Explorer/MyMessages.h"
18
19#include "../Common/ZipRegistry.h"
14 20
15#include "HelpUtils.h" 21#include "HelpUtils.h"
16#include "LangUtils.h" 22#include "LangUtils.h"
@@ -30,7 +36,8 @@ static const UInt32 kLangIDs[] =
30 IDX_SETTINGS_SHOW_GRID, 36 IDX_SETTINGS_SHOW_GRID,
31 IDX_SETTINGS_SINGLE_CLICK, 37 IDX_SETTINGS_SINGLE_CLICK,
32 IDX_SETTINGS_ALTERNATIVE_SELECTION, 38 IDX_SETTINGS_ALTERNATIVE_SELECTION,
33 IDX_SETTINGS_LARGE_PAGES 39 IDX_SETTINGS_LARGE_PAGES,
40 IDT_MEM_USAGE_EXTRACT
34 // , IDT_COMPRESS_MEMORY 41 // , IDT_COMPRESS_MEMORY
35}; 42};
36#endif 43#endif
@@ -106,8 +113,10 @@ int CSettingsPage::AddMemComboItem(UInt64 size, UInt64 percents, bool isDefault)
106 113
107bool CSettingsPage::OnInit() 114bool CSettingsPage::OnInit()
108{ 115{
116 _initMode = true;
109 _wasChanged = false; 117 _wasChanged = false;
110 _largePages_wasChanged = false; 118 _largePages_wasChanged = false;
119 _memx_wasChanged = false;
111 /* 120 /*
112 _wasChanged_MemLimit = false; 121 _wasChanged_MemLimit = false;
113 _memLimitStrings.Clear(); 122 _memLimitStrings.Clear();
@@ -187,9 +196,64 @@ bool CSettingsPage::OnInit()
187 196
188 // EnableSubItems(); 197 // EnableSubItems();
189 198
199
200 {
201 UInt64 ramSize = (UInt64)sizeof(size_t) << 29;
202 const bool ramSize_defined = NWindows::NSystem::GetRamSize(ramSize);
203 // ramSize *= 10; // for debug
204 UInt64 ramSize_GB = (ramSize + (1u << 29)) >> 30;
205 if (ramSize_GB == 0)
206 ramSize_GB = 1;
207 UString s ("GB");
208 if (ramSize_defined)
209 {
210 s += " / ";
211 s.Add_UInt64(ramSize_GB);
212 s += " GB (RAM)";
213 }
214 SetItemText(IDT_SETTINGS_MEM_GB, s);
215
216 const UINT valMin = 1;
217 UINT valMax = 64; // 64GB for RAR7
218 if (ramSize_defined /* && ramSize_GB > valMax */)
219 {
220 const UINT k_max_val = 1u << 14;
221 if (ramSize_GB >= k_max_val)
222 valMax = k_max_val;
223 else if (ramSize_GB > 1)
224 valMax = (UINT)ramSize_GB - 1;
225 else
226 valMax = 1;
227 }
228
229 UInt32 limit = NExtract::Read_LimitGB();
230 if (limit != 0 && limit != (UInt32)(Int32)-1)
231 CheckButton(IDX_SETTINGS_MEM_SET, true);
232 else
233 {
234 limit = 4;
235 EnableSpin(false);
236 }
237 SendItemMessage(IDC_SETTINGS_MEM_SPIN, UDM_SETRANGE, 0, MAKELPARAM(valMax, valMin)); // Sets the controls direction
238 // UDM_SETPOS doesn't set value larger than max value (valMax) of range:
239 SendItemMessage(IDC_SETTINGS_MEM_SPIN, UDM_SETPOS, 0, limit);
240 s.Empty();
241 s.Add_UInt32(limit);
242 SetItemText(IDE_SETTINGS_MEM_SPIN_EDIT, s);
243 }
244
245 _initMode = false;
190 return CPropertyPage::OnInit(); 246 return CPropertyPage::OnInit();
191} 247}
192 248
249
250void CSettingsPage::EnableSpin(bool enable)
251{
252 EnableItem(IDC_SETTINGS_MEM_SPIN, enable);
253 EnableItem(IDE_SETTINGS_MEM_SPIN_EDIT, enable);
254}
255
256
193/* 257/*
194void CSettingsPage::EnableSubItems() 258void CSettingsPage::EnableSubItems()
195{ 259{
@@ -237,6 +301,26 @@ LONG CSettingsPage::OnApply()
237 } 301 }
238 #endif 302 #endif
239 303
304 if (_memx_wasChanged)
305 {
306 UInt32 val = (UInt32)(Int32)-1;
307 if (IsButtonCheckedBool(IDX_SETTINGS_MEM_SET))
308 {
309 UString s;
310 GetItemText(IDE_SETTINGS_MEM_SPIN_EDIT, s);
311 const wchar_t *end;
312 val = ConvertStringToUInt32(s.Ptr(), &end);
313 if (s.IsEmpty() || *end != 0 || val > (1u << 30))
314 {
315 // L"Incorrect value"
316 ShowErrorMessage(*this, NError::MyFormatMessage(E_INVALIDARG));
317 return PSNRET_INVALID;
318 }
319 }
320 NExtract::Save_LimitGB(val);
321 _memx_wasChanged = false;
322 }
323
240 /* 324 /*
241 if (_wasChanged_MemLimit) 325 if (_wasChanged_MemLimit)
242 { 326 {
@@ -304,24 +388,32 @@ void CSettingsPage::OnNotifyHelp()
304 ShowHelpWindow(kSettingsTopic); 388 ShowHelpWindow(kSettingsTopic);
305} 389}
306 390
307/*
308bool CSettingsPage::OnCommand(unsigned code, unsigned itemID, LPARAM param) 391bool CSettingsPage::OnCommand(unsigned code, unsigned itemID, LPARAM param)
309{ 392{
310 if (code == CBN_SELCHANGE) 393 if (!_initMode)
311 { 394 {
312 switch (itemID) 395 if (code == EN_CHANGE && itemID == IDE_SETTINGS_MEM_SPIN_EDIT)
396 {
397 _memx_wasChanged = true;
398 Changed();
399 }
400 /*
401 if (code == CBN_SELCHANGE)
313 { 402 {
314 case IDC_SETTINGS_MEM: 403 switch (itemID)
315 { 404 {
316 _wasChanged_MemLimit = true; 405 case IDC_SETTINGS_MEM:
317 Changed(); 406 {
318 break; 407 _wasChanged_MemLimit = true;
408 Changed();
409 break;
410 }
319 } 411 }
320 } 412 }
413 */
321 } 414 }
322 return CPropertyPage::OnCommand(code, itemID, param); 415 return CPropertyPage::OnCommand(code, itemID, param);
323} 416}
324*/
325 417
326bool CSettingsPage::OnButtonClicked(unsigned buttonID, HWND buttonHWND) 418bool CSettingsPage::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
327{ 419{
@@ -345,6 +437,13 @@ bool CSettingsPage::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
345 _largePages_wasChanged = true; 437 _largePages_wasChanged = true;
346 break; 438 break;
347 439
440 case IDX_SETTINGS_MEM_SET:
441 {
442 _memx_wasChanged = true;
443 EnableSpin(IsButtonCheckedBool(IDX_SETTINGS_MEM_SET));
444 break;
445 }
446
348 default: 447 default:
349 return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); 448 return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
350 } 449 }
diff --git a/CPP/7zip/UI/FileManager/SettingsPage.h b/CPP/7zip/UI/FileManager/SettingsPage.h
index 91b9828..586b253 100644
--- a/CPP/7zip/UI/FileManager/SettingsPage.h
+++ b/CPP/7zip/UI/FileManager/SettingsPage.h
@@ -4,13 +4,15 @@
4#define ZIP7_INC_SETTINGS_PAGE_H 4#define ZIP7_INC_SETTINGS_PAGE_H
5 5
6#include "../../../Windows/Control/PropertyPage.h" 6#include "../../../Windows/Control/PropertyPage.h"
7#include "../../../Windows/Control/ComboBox.h" 7// #include "../../../Windows/Control/ComboBox.h"
8#include "../../../Windows/Control/Edit.h" 8#include "../../../Windows/Control/Edit.h"
9 9
10class CSettingsPage: public NWindows::NControl::CPropertyPage 10class CSettingsPage: public NWindows::NControl::CPropertyPage
11{ 11{
12 bool _wasChanged; 12 bool _wasChanged;
13 bool _largePages_wasChanged; 13 bool _largePages_wasChanged;
14 bool _memx_wasChanged;
15 bool _initMode;
14 /* 16 /*
15 bool _wasChanged_MemLimit; 17 bool _wasChanged_MemLimit;
16 NWindows::NControl::CComboBox _memCombo; 18 NWindows::NControl::CComboBox _memCombo;
@@ -22,11 +24,13 @@ class CSettingsPage: public NWindows::NControl::CPropertyPage
22 */ 24 */
23 25
24 // void EnableSubItems(); 26 // void EnableSubItems();
25 // bool OnCommand(unsigned code, unsigned itemID, LPARAM param) Z7_override; 27 bool OnCommand(unsigned code, unsigned itemID, LPARAM param) Z7_override;
26 virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; 28 virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;
27 virtual bool OnInit() Z7_override; 29 virtual bool OnInit() Z7_override;
28 virtual void OnNotifyHelp() Z7_override; 30 virtual void OnNotifyHelp() Z7_override;
29 virtual LONG OnApply() Z7_override; 31 virtual LONG OnApply() Z7_override;
32
33 void EnableSpin(bool enable);
30public: 34public:
31}; 35};
32 36
diff --git a/CPP/7zip/UI/FileManager/SettingsPage.rc b/CPP/7zip/UI/FileManager/SettingsPage.rc
index baab484..59ea5ee 100644
--- a/CPP/7zip/UI/FileManager/SettingsPage.rc
+++ b/CPP/7zip/UI/FileManager/SettingsPage.rc
@@ -1,8 +1,8 @@
1#include "SettingsPageRes.h" 1#include "SettingsPageRes.h"
2#include "../../GuiCommon.rc" 2#include "../../GuiCommon.rc"
3 3
4#define xc 240 4#define xc OPTIONS_PAGE_XC_SIZE
5#define yc 250 5#define yc OPTIONS_PAGE_YC_SIZE
6 6
7IDD_SETTINGS MY_PAGE 7IDD_SETTINGS MY_PAGE
8#include "SettingsPage2.rc" 8#include "SettingsPage2.rc"
diff --git a/CPP/7zip/UI/FileManager/SettingsPage2.rc b/CPP/7zip/UI/FileManager/SettingsPage2.rc
index cf90742..f67ee80 100644
--- a/CPP/7zip/UI/FileManager/SettingsPage2.rc
+++ b/CPP/7zip/UI/FileManager/SettingsPage2.rc
@@ -1,19 +1,37 @@
1// #define g1xs 60 1// #define g1xs 60
2// #include "MemDialogRes.h"
3
4#define save_y 144
5#define spin_y (save_y + 12)
6#define spin_x_size 50
2 7
3CAPTION "Settings" 8CAPTION "Settings"
4BEGIN 9BEGIN
5 CONTROL "Show "".."" item", IDX_SETTINGS_SHOW_DOTS, MY_CHECKBOX, m, 8, xc, 10 10 MY_CONTROL_CHECKBOX ( "Show "".."" item", IDX_SETTINGS_SHOW_DOTS, m, 8, xc)
6 CONTROL "Show real file &icons", IDX_SETTINGS_SHOW_REAL_FILE_ICONS, MY_CHECKBOX, m, 22, xc, 10 11 MY_CONTROL_CHECKBOX ( "Show real file &icons", IDX_SETTINGS_SHOW_REAL_FILE_ICONS, m, 22, xc)
7 CONTROL "&Full row select", IDX_SETTINGS_FULL_ROW, MY_CHECKBOX, m, 36, xc, 10 12 MY_CONTROL_CHECKBOX ( "&Full row select", IDX_SETTINGS_FULL_ROW, m, 36, xc)
8 CONTROL "Show &grid lines", IDX_SETTINGS_SHOW_GRID, MY_CHECKBOX, m, 50, xc, 10 13 MY_CONTROL_CHECKBOX ( "Show &grid lines", IDX_SETTINGS_SHOW_GRID, m, 50, xc)
9 CONTROL "&Single-click to open an item", IDX_SETTINGS_SINGLE_CLICK, MY_CHECKBOX, m, 64, xc, 10 14 MY_CONTROL_CHECKBOX ( "&Single-click to open an item", IDX_SETTINGS_SINGLE_CLICK, m, 64, xc)
10 CONTROL "&Alternative selection mode", IDX_SETTINGS_ALTERNATIVE_SELECTION, MY_CHECKBOX, m, 78, xc, 10 15 MY_CONTROL_CHECKBOX ( "&Alternative selection mode", IDX_SETTINGS_ALTERNATIVE_SELECTION, m, 78, xc)
16
17 MY_CONTROL_CHECKBOX ( "Show system &menu", IDX_SETTINGS_SHOW_SYSTEM_MENU, m, 100, xc)
11 18
12 CONTROL "Show system &menu", IDX_SETTINGS_SHOW_SYSTEM_MENU, MY_CHECKBOX, m, 100, xc, 10 19 MY_CONTROL_CHECKBOX ( "Use &large memory pages", IDX_SETTINGS_LARGE_PAGES, m, 122, xc)
13 20
14 CONTROL "Use &large memory pages", IDX_SETTINGS_LARGE_PAGES, MY_CHECKBOX, m, 122, xc, 10 21 LTEXT "Maximum amount of RAM memory usage allowed to unpack archives:",
22 IDT_MEM_USAGE_EXTRACT, m, save_y, xc, 8
23 MY_CONTROL_CHECKBOX_COLON(IDX_SETTINGS_MEM_SET, m + 10, spin_y + 1)
24 MY_CONTROL_EDIT_WITH_SPIN(
25 IDE_SETTINGS_MEM_SPIN_EDIT,
26 IDC_SETTINGS_MEM_SPIN,
27 "4", m + 30, spin_y, spin_x_size)
28 LTEXT "GB", IDT_SETTINGS_MEM_GB, m + 30 + spin_x_size + 8, spin_y + 2, xc - m - 30 - spin_x_size - 8, 8
15 29
16 // LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 140, xc, 8 30 // LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 140, xc, 8
17 // COMBOBOX IDC_SETTINGS_MEM, m , 152, g1xs, yc - 152, MY_COMBO 31 // COMBOBOX IDC_SETTINGS_MEM, m , 152, g1xs, yc - 152, MY_COMBO
18 // LTEXT "/ RAM", IDT_SETTINGS_MEM_RAM, m + g1xs + m, 154, xc - g1xs - m, MY_TEXT_NOPREFIX 32 // LTEXT "/ RAM", IDT_SETTINGS_MEM_RAM, m + g1xs + m, 154, xc - g1xs - m, MY_TEXT_NOPREFIX
19END 33END
34
35#undef save_y
36#undef spin_y
37#undef spin_x_size
diff --git a/CPP/7zip/UI/FileManager/SettingsPageRes.h b/CPP/7zip/UI/FileManager/SettingsPageRes.h
index e990bab..205daee 100644
--- a/CPP/7zip/UI/FileManager/SettingsPageRes.h
+++ b/CPP/7zip/UI/FileManager/SettingsPageRes.h
@@ -10,6 +10,12 @@
10#define IDX_SETTINGS_ALTERNATIVE_SELECTION 2507 10#define IDX_SETTINGS_ALTERNATIVE_SELECTION 2507
11#define IDX_SETTINGS_LARGE_PAGES 2508 11#define IDX_SETTINGS_LARGE_PAGES 2508
12 12
13#define IDT_MEM_USAGE_EXTRACT 7816
14
15#define IDX_SETTINGS_MEM_SET 100
16#define IDE_SETTINGS_MEM_SPIN_EDIT 101
17#define IDC_SETTINGS_MEM_SPIN 102
18#define IDT_SETTINGS_MEM_GB 103
13 19
14// #define IDT_SETTINGS_MEM 100 20// #define IDT_SETTINGS_MEM 100
15// #define IDC_SETTINGS_MEM 101 21// #define IDC_SETTINGS_MEM 101
diff --git a/CPP/7zip/UI/FileManager/StdAfx.h b/CPP/7zip/UI/FileManager/StdAfx.h
index 789cc6e..7790eae 100644
--- a/CPP/7zip/UI/FileManager/StdAfx.h
+++ b/CPP/7zip/UI/FileManager/StdAfx.h
@@ -7,23 +7,7 @@
7#pragma warning(disable : 4464) // relative include path contains '..' 7#pragma warning(disable : 4464) // relative include path contains '..'
8#endif 8#endif
9 9
10#include "../../../../C/Compiler.h"
11
12Z7_DIAGNOSCTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
13#ifndef _WIN32_WINNT
14// #define _WIN32_WINNT 0x0400
15#define _WIN32_WINNT 0x0500
16// #define _WIN32_WINNT 0x0600
17// #define _WIN32_WINNT 0x0A00
18#endif
19#ifndef WINVER
20#define WINVER _WIN32_WINNT
21#endif
22// #define _WIN32_IE 0x400 // for debug
23Z7_DIAGNOSCTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
24
25#include "../../../Common/Common.h" 10#include "../../../Common/Common.h"
26#include "../../../Common/MyWindows.h"
27 11
28#endif 12#endif
29 13
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
index 1c7cab0..c893ea9 100644
--- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp
+++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
@@ -49,6 +49,7 @@ int GetIconIndexForCSIDL(int csidl)
49} 49}
50 50
51#ifndef _UNICODE 51#ifndef _UNICODE
52Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
52typedef DWORD_PTR (WINAPI * Func_SHGetFileInfoW)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags); 53typedef DWORD_PTR (WINAPI * Func_SHGetFileInfoW)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags);
53 54
54static struct C_SHGetFileInfo_Init 55static struct C_SHGetFileInfo_Init
diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp
index 09d8a72..efa98a8 100644
--- a/CPP/7zip/UI/FileManager/SystemPage.cpp
+++ b/CPP/7zip/UI/FileManager/SystemPage.cpp
@@ -171,7 +171,7 @@ bool CSystemPage::OnInit()
171 171
172 _listView.SetImageList(_imageList, LVSIL_SMALL); 172 _listView.SetImageList(_imageList, LVSIL_SMALL);
173 173
174 _listView.InsertColumn(0, LangString(IDS_PROP_FILE_TYPE), 72); 174 _listView.InsertColumn(0, LangString(IDS_PROP_FILE_TYPE), 80);
175 175
176 UString s; 176 UString s;
177 177
@@ -206,7 +206,7 @@ bool CSystemPage::OnInit()
206 206
207 LV_COLUMNW ci; 207 LV_COLUMNW ci;
208 ci.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM; 208 ci.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
209 ci.cx = 128; 209 ci.cx = 152;
210 ci.fmt = LVCFMT_CENTER; 210 ci.fmt = LVCFMT_CENTER;
211 ci.pszText = s.Ptr_non_const(); 211 ci.pszText = s.Ptr_non_const();
212 ci.iSubItem = 1; 212 ci.iSubItem = 1;
diff --git a/CPP/7zip/UI/FileManager/SystemPage.rc b/CPP/7zip/UI/FileManager/SystemPage.rc
index 3bb143a..108e524 100644
--- a/CPP/7zip/UI/FileManager/SystemPage.rc
+++ b/CPP/7zip/UI/FileManager/SystemPage.rc
@@ -1,15 +1,15 @@
1#include "SystemPageRes.h" 1#include "SystemPageRes.h"
2#include "../../GuiCommon.rc" 2#include "../../GuiCommon.rc"
3 3
4#define xc 240 4#define xc OPTIONS_PAGE_XC_SIZE
5#define yc 252 5#define yc OPTIONS_PAGE_YC_SIZE
6 6
7IDD_SYSTEM DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT 7IDD_SYSTEM DIALOG MY_PAGE_POSTFIX
8CAPTION "System" 8CAPTION "System"
9BEGIN 9BEGIN
10 LTEXT "Associate 7-Zip with:", IDT_SYSTEM_ASSOCIATE, m, m, xc, 8 10 LTEXT "Associate 7-Zip with:", IDT_SYSTEM_ASSOCIATE, m, m, xc, 8
11 PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 80, m + 12, 40, bys 11 PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 92, m + 12, 40, bys
12 PUSHBUTTON "+", IDB_SYSTEM_ALL, 166, m + 12, 40, bys 12 PUSHBUTTON "+", IDB_SYSTEM_ALL, 194, m + 12, 40, bys
13 CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32", 13 CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32",
14 LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, 14 LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,
15 m, m + 32, xc, (yc - 32) 15 m, m + 32, xc, (yc - 32)
@@ -25,7 +25,7 @@ END
25#define xc (SMALL_PAGE_SIZE_X + 8) 25#define xc (SMALL_PAGE_SIZE_X + 8)
26#define yc (128 + 8) 26#define yc (128 + 8)
27 27
28IDD_SYSTEM_2 DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT 28IDD_SYSTEM_2 DIALOG MY_PAGE_POSTFIX
29CAPTION "System" 29CAPTION "System"
30BEGIN 30BEGIN
31 LTEXT "Associate 7-Zip with:", IDT_SYSTEM_ASSOCIATE, m, m, xc, 8 31 LTEXT "Associate 7-Zip with:", IDT_SYSTEM_ASSOCIATE, m, m, xc, 8
diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp
index 1ac7098..6bf84cf 100644
--- a/CPP/7zip/UI/FileManager/TextPairs.cpp
+++ b/CPP/7zip/UI/FileManager/TextPairs.cpp
@@ -181,13 +181,13 @@ void CPairsStorage::SaveToString(UString &text) const
181 const CTextPair &pair = Pairs[i]; 181 const CTextPair &pair = Pairs[i];
182 bool multiWord = (pair.ID.Find(L' ') >= 0); 182 bool multiWord = (pair.ID.Find(L' ') >= 0);
183 if (multiWord) 183 if (multiWord)
184 text += '\"'; 184 text.Add_Char('\"');
185 text += pair.ID; 185 text += pair.ID;
186 if (multiWord) 186 if (multiWord)
187 text += '\"'; 187 text.Add_Char('\"');
188 text.Add_Space(); 188 text.Add_Space();
189 text += pair.Value; 189 text += pair.Value;
190 text += '\x0D'; 190 text.Add_Char('\x0D');
191 text.Add_LF(); 191 text.Add_LF();
192 } 192 }
193} 193}
diff --git a/CPP/7zip/UI/FileManager/VerCtrl.cpp b/CPP/7zip/UI/FileManager/VerCtrl.cpp
index 0c894b8..f1353b8 100644
--- a/CPP/7zip/UI/FileManager/VerCtrl.cpp
+++ b/CPP/7zip/UI/FileManager/VerCtrl.cpp
@@ -93,7 +93,7 @@ static bool ParseNumberString(const FString &s, UInt32 &number)
93static void WriteFile(const FString &path, bool createAlways, const CFileDataInfo &fdi, const CPanel &panel) 93static void WriteFile(const FString &path, bool createAlways, const CFileDataInfo &fdi, const CPanel &panel)
94{ 94{
95 NIO::COutFile outFile; 95 NIO::COutFile outFile;
96 if (!outFile.Create(path, createAlways)) // (createAlways = false) means CREATE_NEW 96 if (!outFile.Create_ALWAYS_or_NEW(path, createAlways)) // (createAlways = false) means CREATE_NEW
97 { 97 {
98 panel.MessageBox_LastError(); 98 panel.MessageBox_LastError();
99 return; 99 return;
@@ -339,7 +339,7 @@ void CApp::VerCtrl(unsigned id)
339 // NDir::SetFileAttrib(path, 0); 339 // NDir::SetFileAttrib(path, 0);
340 { 340 {
341 NIO::COutFile outFile; 341 NIO::COutFile outFile;
342 if (!outFile.Open(path, OPEN_EXISTING)) 342 if (!outFile.Open_EXISTING(path))
343 { 343 {
344 panel.MessageBox_LastError(); 344 panel.MessageBox_LastError();
345 return; 345 return;
diff --git a/CPP/7zip/UI/FileManager/makefile b/CPP/7zip/UI/FileManager/makefile
index df08c98..0ca5caa 100644
--- a/CPP/7zip/UI/FileManager/makefile
+++ b/CPP/7zip/UI/FileManager/makefile
@@ -2,6 +2,8 @@ PROG = 7zFM.exe
2CFLAGS = $(CFLAGS) \ 2CFLAGS = $(CFLAGS) \
3 -DZ7_EXTERNAL_CODECS \ 3 -DZ7_EXTERNAL_CODECS \
4 4
5# -DZ7_NO_LARGE_PAGES
6
5!include "FM.mak" 7!include "FM.mak"
6 8
7COMMON_OBJS = \ 9COMMON_OBJS = \
diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h
index 9d605c6..4e22230 100644
--- a/CPP/7zip/UI/FileManager/resource.h
+++ b/CPP/7zip/UI/FileManager/resource.h
@@ -25,6 +25,8 @@
25#define IDM_CRC64 103 25#define IDM_CRC64 103
26#define IDM_SHA1 104 26#define IDM_SHA1 104
27#define IDM_SHA256 105 27#define IDM_SHA256 105
28#define IDM_XXH64 106
29#define IDM_BLAKE2SP 107
28 30
29 31
30#define IDM_FILE 500 32#define IDM_FILE 500
@@ -100,6 +102,7 @@
100 102
101#define IDM_VIEW_TIME_POPUP 760 103#define IDM_VIEW_TIME_POPUP 760
102#define IDM_VIEW_TIME 761 104#define IDM_VIEW_TIME 761
105#define IDM_VIEW_TIME_UTC 799
103 106
104#define IDM_ADD_TO_FAVORITES 800 107#define IDM_ADD_TO_FAVORITES 800
105#define IDS_BOOKMARK 801 108#define IDS_BOOKMARK 801
@@ -107,6 +110,7 @@
107#define IDM_OPTIONS 900 110#define IDM_OPTIONS 900
108#define IDM_BENCHMARK 901 111#define IDM_BENCHMARK 901
109#define IDM_BENCHMARK2 902 112#define IDM_BENCHMARK2 902
113#define IDM_TEMP_DIR 910
110 114
111#define IDM_HELP_CONTENTS 960 115#define IDM_HELP_CONTENTS 960
112#define IDM_ABOUT 961 116#define IDM_ABOUT 961
diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc
index 002265a..feeeaf5 100644
--- a/CPP/7zip/UI/FileManager/resource.rc
+++ b/CPP/7zip/UI/FileManager/resource.rc
@@ -57,8 +57,10 @@ BEGIN
57 BEGIN 57 BEGIN
58 MENUITEM "CRC-32", IDM_CRC32 58 MENUITEM "CRC-32", IDM_CRC32
59 MENUITEM "CRC-64", IDM_CRC64 59 MENUITEM "CRC-64", IDM_CRC64
60 MENUITEM "XXH64", IDM_XXH64
60 MENUITEM "SHA-1", IDM_SHA1 61 MENUITEM "SHA-1", IDM_SHA1
61 MENUITEM "SHA-256", IDM_SHA256 62 MENUITEM "SHA-256", IDM_SHA256
63 MENUITEM "BLAKE2sp", IDM_BLAKE2SP
62 MENUITEM "*", IDM_HASH_ALL 64 MENUITEM "*", IDM_HASH_ALL
63 END 65 END
64 MENUITEM "Di&ff", IDM_DIFF 66 MENUITEM "Di&ff", IDM_DIFF
@@ -141,6 +143,8 @@ BEGIN
141 #ifdef UNDER_CE 143 #ifdef UNDER_CE
142 MENUITEM "Benchmark 2", IDM_BENCHMARK2 144 MENUITEM "Benchmark 2", IDM_BENCHMARK2
143 #endif 145 #endif
146 MY_MENUITEM_SEPARATOR
147 MENUITEM "Delete Temporary Files...", IDM_TEMP_DIR
144 #ifndef UNDER_CE 148 #ifndef UNDER_CE
145 END 149 END
146 POPUP "&Help" MY_MENUITEM_ID(IDM_HELP) 150 POPUP "&Help" MY_MENUITEM_ID(IDM_HELP)
@@ -263,6 +267,7 @@ END
263 267
264#include "AboutDialog.rc" 268#include "AboutDialog.rc"
265#include "BrowseDialog.rc" 269#include "BrowseDialog.rc"
270#include "BrowseDialog2.rc"
266#include "ComboDialog.rc" 271#include "ComboDialog.rc"
267#include "CopyDialog.rc" 272#include "CopyDialog.rc"
268#include "EditDialog.rc" 273#include "EditDialog.rc"
@@ -271,6 +276,7 @@ END
271#include "LangPage.rc" 276#include "LangPage.rc"
272#include "LinkDialog.rc" 277#include "LinkDialog.rc"
273#include "ListViewDialog.rc" 278#include "ListViewDialog.rc"
279#include "MemDialog.rc"
274#include "MenuPage.rc" 280#include "MenuPage.rc"
275#include "MessagesDialog.rc" 281#include "MessagesDialog.rc"
276#include "OverwriteDialog.rc" 282#include "OverwriteDialog.rc"
diff --git a/CPP/7zip/UI/FileManager/resourceGui.h b/CPP/7zip/UI/FileManager/resourceGui.h
index 7c1b40e..848b36f 100644
--- a/CPP/7zip/UI/FileManager/resourceGui.h
+++ b/CPP/7zip/UI/FileManager/resourceGui.h
@@ -13,3 +13,11 @@
13#define IDS_CHECKSUM_CRC_STREAMS_NAMES 7504 13#define IDS_CHECKSUM_CRC_STREAMS_NAMES 7504
14 14
15#define IDS_INCORRECT_VOLUME_SIZE 7307 15#define IDS_INCORRECT_VOLUME_SIZE 7307
16
17#define IDS_MEM_REQUIRES_BIG_MEM 7811
18#define IDS_MEM_REQUIRED_MEM_SIZE 7812
19#define IDS_MEM_CURRENT_MEM_LIMIT 7813
20#define IDS_MEM_USAGE_LIMIT_SET_BY_7ZIP 7814
21#define IDS_MEM_RAM_SIZE 7815
22
23#define IDS_MSG_ARC_UNPACKING_WAS_SKIPPED 7822
diff --git a/CPP/7zip/UI/FileManager/resourceGui.rc b/CPP/7zip/UI/FileManager/resourceGui.rc
index f748e0b..143e9f6 100644
--- a/CPP/7zip/UI/FileManager/resourceGui.rc
+++ b/CPP/7zip/UI/FileManager/resourceGui.rc
@@ -16,4 +16,13 @@ BEGIN
16 16
17 IDS_OPENNING "Opening..." 17 IDS_OPENNING "Opening..."
18 IDS_SCANNING "Scanning..." 18 IDS_SCANNING "Scanning..."
19 IDS_MEM_REQUIRES_BIG_MEM "The operation requires big amount of memory (RAM)."
20 IDS_MEM_REQUIRED_MEM_SIZE "required memory usage size"
21 IDS_MEM_CURRENT_MEM_LIMIT "allowed memory usage limit"
22 IDS_MEM_USAGE_LIMIT_SET_BY_7ZIP "memory usage limit set by 7-Zip"
23 IDS_MEM_RAM_SIZE "RAM size"
24
25 IDS_MSG_ARC_UNPACKING_WAS_SKIPPED "Archive extraction was skipped."
26// IDS_MSG_ARC_FILES_UNPACKING_WAS_SKIPPED "Files extraction was skipped."
27
19END 28END
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
index 539d689..7f2edfa 100644
--- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
+++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
@@ -23,6 +23,7 @@
23#include "../FileManager/DialogSize.h" 23#include "../FileManager/DialogSize.h"
24#include "../FileManager/HelpUtils.h" 24#include "../FileManager/HelpUtils.h"
25#include "../FileManager/LangUtils.h" 25#include "../FileManager/LangUtils.h"
26#include "../FileManager/resourceGui.h"
26 27
27#include "../../MyVersion.h" 28#include "../../MyVersion.h"
28 29
@@ -884,9 +885,15 @@ void CBenchmarkDialog::StartBenchmark()
884 false); // totalBench 885 false); // totalBench
885 if (!IsMemoryUsageOK(memUsage)) 886 if (!IsMemoryUsageOK(memUsage))
886 { 887 {
887 UString s2 = LangString(IDT_BENCH_MEMORY); 888 UString s2;
889 LangString_OnlyFromLangFile(IDS_MEM_REQUIRED_MEM_SIZE, s2);
888 if (s2.IsEmpty()) 890 if (s2.IsEmpty())
889 GetItemText(IDT_BENCH_MEMORY, s2); 891 {
892 s2 = LangString(IDT_BENCH_MEMORY);
893 if (s2.IsEmpty())
894 GetItemText(IDT_BENCH_MEMORY, s2);
895 s2.RemoveChar(L':');
896 }
890 UString s; 897 UString s;
891 SetErrorMessage_MemUsage(s, memUsage, RamSize, RamSize_Limit, s2); 898 SetErrorMessage_MemUsage(s, memUsage, RamSize, RamSize_Limit, s2);
892 MessageBoxError_Status(s); 899 MessageBoxError_Status(s);
@@ -1081,7 +1088,7 @@ static void Add_Dot3String(UString &s, UInt64 val)
1081static void AddRatingString(UString &s, const CTotalBenchRes &info) 1088static void AddRatingString(UString &s, const CTotalBenchRes &info)
1082{ 1089{
1083 // AddUsageString(s, info); 1090 // AddUsageString(s, info);
1084 // s += " "; 1091 // s.Add_Space();
1085 // s.Add_UInt32(GetRating(info)); 1092 // s.Add_UInt32(GetRating(info));
1086 Add_Dot3String(s, GetRating(info)); 1093 Add_Dot3String(s, GetRating(info));
1087} 1094}
@@ -1093,7 +1100,7 @@ static void AddRatingsLine(UString &s, const CTotalBenchRes &enc, const CTotalBe
1093 #endif 1100 #endif
1094 ) 1101 )
1095{ 1102{
1096 // AddUsageString(s, enc); s += " "; 1103 // AddUsageString(s, enc); s.Add_Space();
1097 1104
1098 AddRatingString(s, enc); 1105 AddRatingString(s, enc);
1099 s += " "; 1106 s += " ";
@@ -1105,11 +1112,11 @@ static void AddRatingsLine(UString &s, const CTotalBenchRes &enc, const CTotalBe
1105 s += " "; 1112 s += " ";
1106 AddRatingString(s, tot_BenchRes); 1113 AddRatingString(s, tot_BenchRes);
1107 1114
1108 s += " "; AddUsageString(s, tot_BenchRes); 1115 s.Add_Space(); AddUsageString(s, tot_BenchRes);
1109 1116
1110 1117
1111 #ifdef PRINT_ITER_TIME 1118 #ifdef PRINT_ITER_TIME
1112 s += " "; 1119 s.Add_Space();
1113 { 1120 {
1114 Add_Dot3String(s, ticks; 1121 Add_Dot3String(s, ticks;
1115 s += " s"; 1122 s += " s";
@@ -1342,7 +1349,7 @@ void CBenchmarkDialog::UpdateGui()
1342 /* 1349 /*
1343 s += "g:"; s.Add_UInt32((UInt32)pair.EncInfo.GlobalTime); 1350 s += "g:"; s.Add_UInt32((UInt32)pair.EncInfo.GlobalTime);
1344 s += " u:"; s.Add_UInt32((UInt32)pair.EncInfo.UserTime); 1351 s += " u:"; s.Add_UInt32((UInt32)pair.EncInfo.UserTime);
1345 s += " "; 1352 s.Add_Space();
1346 */ 1353 */
1347 AddRatingsLine(s, pair.Enc, pair.Dec 1354 AddRatingsLine(s, pair.Enc, pair.Dec
1348 #ifdef PRINT_ITER_TIME 1355 #ifdef PRINT_ITER_TIME
@@ -1547,11 +1554,11 @@ HRESULT CFreqCallback::AddCpuFreq(unsigned numThreads, UInt64 freq, UInt64 usage
1547 s += "T Frequency (MHz):"; 1554 s += "T Frequency (MHz):";
1548 s.Add_LF(); 1555 s.Add_LF();
1549 } 1556 }
1550 s += " "; 1557 s.Add_Space();
1551 if (numThreads != 1) 1558 if (numThreads != 1)
1552 { 1559 {
1553 s.Add_UInt64(GetUsagePercents(usage)); 1560 s.Add_UInt64(GetUsagePercents(usage));
1554 s += '%'; 1561 s.Add_Char('%');
1555 s.Add_Space(); 1562 s.Add_Space();
1556 } 1563 }
1557 s.Add_UInt64(GetMips(freq)); 1564 s.Add_UInt64(GetMips(freq));
@@ -1668,7 +1675,7 @@ HRESULT CThreadBenchmark::Process()
1668 CProperty prop; 1675 CProperty prop;
1669 prop.Name = 'd'; 1676 prop.Name = 'd';
1670 prop.Name.Add_UInt32((UInt32)(dictionarySize >> 10)); 1677 prop.Name.Add_UInt32((UInt32)(dictionarySize >> 10));
1671 prop.Name += 'k'; 1678 prop.Name.Add_Char('k');
1672 props.Add(prop); 1679 props.Add(prop);
1673 } 1680 }
1674 } 1681 }
@@ -1879,7 +1886,7 @@ HRESULT Benchmark(
1879 { 1886 {
1880 // bd.Bench2Text.Empty(); 1887 // bd.Bench2Text.Empty();
1881 bd.Bench2Text = "7-Zip " MY_VERSION_CPU; 1888 bd.Bench2Text = "7-Zip " MY_VERSION_CPU;
1882 bd.Bench2Text += (char)0xD; 1889 // bd.Bench2Text.Add_Char((char)0xD);
1883 bd.Bench2Text.Add_LF(); 1890 bd.Bench2Text.Add_LF();
1884 } 1891 }
1885 1892
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp
index c2aee6c..fd53062 100644
--- a/CPP/7zip/UI/GUI/CompressDialog.cpp
+++ b/CPP/7zip/UI/GUI/CompressDialog.cpp
@@ -18,6 +18,7 @@
18#include "../FileManager/HelpUtils.h" 18#include "../FileManager/HelpUtils.h"
19#include "../FileManager/PropertyName.h" 19#include "../FileManager/PropertyName.h"
20#include "../FileManager/SplitUtils.h" 20#include "../FileManager/SplitUtils.h"
21#include "../FileManager/resourceGui.h"
21 22
22#include "../Explorer/MyMessages.h" 23#include "../Explorer/MyMessages.h"
23 24
@@ -1015,41 +1016,34 @@ static bool IsAsciiString(const UString &s)
1015 1016
1016static void AddSize_MB(UString &s, UInt64 size) 1017static void AddSize_MB(UString &s, UInt64 size)
1017{ 1018{
1019 s.Add_LF();
1018 const UInt64 v2 = size + ((UInt32)1 << 20) - 1; 1020 const UInt64 v2 = size + ((UInt32)1 << 20) - 1;
1019 if (size <= v2) 1021 if (size < v2)
1020 size = v2; 1022 size = v2;
1021 s.Add_UInt64(size >> 20); 1023 s.Add_UInt64(size >> 20);
1022 s += " MB"; 1024 s += " MB : ";
1023} 1025}
1024 1026
1027static void AddSize_MB_id(UString &s, UInt64 size, UInt32 id)
1028{
1029 AddSize_MB(s, size);
1030 AddLangString(s, id);
1031}
1025 1032
1026void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 ramLimit, const UString &usageString); 1033void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 ramLimit, const UString &usageString);
1027void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 ramLimit, const UString &usageString) 1034void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 ramLimit, const UString &usageString)
1028{ 1035{
1029 s += "The operation was blocked by 7-Zip"; 1036 AddLangString(s, IDS_MEM_OPERATION_BLOCKED);
1030 s.Add_LF();
1031 s += "The operation can require big amount of RAM (memory):";
1032 s.Add_LF(); 1037 s.Add_LF();
1038 AddLangString(s, IDS_MEM_REQUIRES_BIG_MEM);
1033 s.Add_LF(); 1039 s.Add_LF();
1034 AddSize_MB(s, reqSize); 1040 AddSize_MB(s, reqSize);
1035 1041 s += usageString;
1036 if (!usageString.IsEmpty()) 1042 AddSize_MB_id(s, ramSize, IDS_MEM_RAM_SIZE);
1037 {
1038 s += " : ";
1039 s += usageString;
1040 }
1041
1042 s.Add_LF();
1043 AddSize_MB(s, ramSize);
1044 s += " : RAM";
1045
1046 // if (ramLimit != 0) 1043 // if (ramLimit != 0)
1047 { 1044 {
1048 s.Add_LF(); 1045 AddSize_MB_id(s, ramLimit, IDS_MEM_USAGE_LIMIT_SET_BY_7ZIP);
1049 AddSize_MB(s, ramLimit);
1050 s += " : 7-Zip limit";
1051 } 1046 }
1052
1053 s.Add_LF(); 1047 s.Add_LF();
1054 s.Add_LF(); 1048 s.Add_LF();
1055 AddLangString(s, IDS_MEM_ERROR); 1049 AddLangString(s, IDS_MEM_ERROR);
@@ -1095,10 +1089,16 @@ void CCompressDialog::OnOK()
1095 const UInt64 limit = Get_MemUse_Bytes(); 1089 const UInt64 limit = Get_MemUse_Bytes();
1096 if (memUsage > limit) 1090 if (memUsage > limit)
1097 { 1091 {
1098 UString s; 1092 UString s2;
1099 UString s2 = LangString(IDT_COMPRESS_MEMORY); 1093 LangString_OnlyFromLangFile(IDS_MEM_REQUIRED_MEM_SIZE, s2);
1100 if (s2.IsEmpty()) 1094 if (s2.IsEmpty())
1101 GetItemText(IDT_COMPRESS_MEMORY, s2); 1095 {
1096 s2 = LangString(IDT_COMPRESS_MEMORY);
1097 if (s2.IsEmpty())
1098 GetItemText(IDT_COMPRESS_MEMORY, s2);
1099 s2.RemoveChar(L':');
1100 }
1101 UString s;
1102 SetErrorMessage_MemUsage(s, memUsage, _ramSize, limit, s2); 1102 SetErrorMessage_MemUsage(s, memUsage, _ramSize, limit, s2);
1103 MessageBoxError(s); 1103 MessageBoxError(s);
1104 return; 1104 return;
@@ -1823,8 +1823,8 @@ static int Combo_AddDict2(NWindows::NControl::CComboBox &cb, size_t sizeReal, si
1823 s.Add_UInt64(sizeShow >> moveBits); 1823 s.Add_UInt64(sizeShow >> moveBits);
1824 s.Add_Space(); 1824 s.Add_Space();
1825 if (c != 0) 1825 if (c != 0)
1826 s += c; 1826 s.Add_Char(c);
1827 s += 'B'; 1827 s.Add_Char('B');
1828 if (sizeReal == k_Auto_Dict) 1828 if (sizeReal == k_Auto_Dict)
1829 Modify_Auto(s); 1829 Modify_Auto(s);
1830 const int index = (int)ComboBox_AddStringAscii(cb, s); 1830 const int index = (int)ComboBox_AddStringAscii(cb, s);
@@ -2394,8 +2394,8 @@ static void Add_Size(AString &s, UInt64 val)
2394 s.Add_UInt64(val >> moveBits); 2394 s.Add_UInt64(val >> moveBits);
2395 s.Add_Space(); 2395 s.Add_Space();
2396 if (moveBits != 0) 2396 if (moveBits != 0)
2397 s += c; 2397 s.Add_Char(c);
2398 s += 'B'; 2398 s.Add_Char('B');
2399} 2399}
2400 2400
2401 2401
@@ -2714,8 +2714,8 @@ static void AddMemSize(UString &res, UInt64 size)
2714 res.Add_UInt64(size >> moveBits); 2714 res.Add_UInt64(size >> moveBits);
2715 res.Add_Space(); 2715 res.Add_Space();
2716 if (moveBits != 0) 2716 if (moveBits != 0)
2717 res += c; 2717 res.Add_Char(c);
2718 res += 'B'; 2718 res.Add_Char('B');
2719} 2719}
2720 2720
2721 2721
@@ -2727,7 +2727,7 @@ int CCompressDialog::AddMemComboItem(UInt64 val, bool isPercent, bool isDefault)
2727 { 2727 {
2728 UString s; 2728 UString s;
2729 s.Add_UInt64(val); 2729 s.Add_UInt64(val);
2730 s += '%'; 2730 s.Add_Char('%');
2731 if (isDefault) 2731 if (isDefault)
2732 sUser = k_Auto_Prefix; 2732 sUser = k_Auto_Prefix;
2733 else 2733 else
@@ -3510,7 +3510,7 @@ void COptionsDialog::SetPrec()
3510 // defaultPrec = kTimePrec_Unix; 3510 // defaultPrec = kTimePrec_Unix;
3511 // flags = (UInt32)1 << kTimePrec_Unix; 3511 // flags = (UInt32)1 << kTimePrec_Unix;
3512 3512
3513 s += ":"; 3513 s.Add_Colon();
3514 if (methodID >= 0 && (unsigned)methodID < Z7_ARRAY_SIZE(kMethodsNames)) 3514 if (methodID >= 0 && (unsigned)methodID < Z7_ARRAY_SIZE(kMethodsNames))
3515 s += kMethodsNames[methodID]; 3515 s += kMethodsNames[methodID];
3516 if (methodID == kPosix) 3516 if (methodID == kPosix)
diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc
index f04329e..9c3ed88 100644
--- a/CPP/7zip/UI/GUI/CompressDialog.rc
+++ b/CPP/7zip/UI/GUI/CompressDialog.rc
@@ -225,6 +225,8 @@ BEGIN
225 225
226 IDS_COMPRESS_SEC "sec" 226 IDS_COMPRESS_SEC "sec"
227 IDS_COMPRESS_NS "ns" 227 IDS_COMPRESS_NS "ns"
228
229 IDS_MEM_OPERATION_BLOCKED "The operation was blocked by 7-Zip."
228END 230END
229 231
230 232
diff --git a/CPP/7zip/UI/GUI/CompressDialogRes.h b/CPP/7zip/UI/GUI/CompressDialogRes.h
index aa25b89..d04d4b9 100644
--- a/CPP/7zip/UI/GUI/CompressDialogRes.h
+++ b/CPP/7zip/UI/GUI/CompressDialogRes.h
@@ -121,3 +121,5 @@
121// #define IDX_COMPRESS_NT_HARD_LINKS_SET 211 121// #define IDX_COMPRESS_NT_HARD_LINKS_SET 211
122// #define IDX_COMPRESS_NT_ALT_STREAMS_SET 212 122// #define IDX_COMPRESS_NT_ALT_STREAMS_SET 212
123// #define IDX_COMPRESS_NT_SECUR_SET 213 123// #define IDX_COMPRESS_NT_SECUR_SET 213
124
125#define IDS_MEM_OPERATION_BLOCKED 7810
diff --git a/CPP/7zip/UI/GUI/CompressOptionsDialog.rc b/CPP/7zip/UI/GUI/CompressOptionsDialog.rc
index 0578227..682775e 100644
--- a/CPP/7zip/UI/GUI/CompressOptionsDialog.rc
+++ b/CPP/7zip/UI/GUI/CompressOptionsDialog.rc
@@ -17,57 +17,60 @@
17#define ntSizeY 72 17#define ntSizeY 72
18#define timePosY (ntPosY + ntSizeY + 20) 18#define timePosY (ntPosY + ntSizeY + 20)
19 19
20#define ceSize 18
21#define ceString ":"
22
23 20
24IDD_COMPRESS_OPTIONS DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT 21IDD_COMPRESS_OPTIONS DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
25CAPTION "Options" 22CAPTION "Options"
26BEGIN 23BEGIN
27 GROUPBOX "NTFS", IDG_COMPRESS_NTFS, g5x, ntPosY, g5xs, ntSizeY 24 GROUPBOX "NTFS", IDG_COMPRESS_NTFS, g5x, ntPosY, g5xs, ntSizeY
28 25
29 CONTROL "Store symbolic links", IDX_COMPRESS_NT_SYM_LINKS, MY_CHECKBOX, 26 MY_CONTROL_CHECKBOX ("Store symbolic links", IDX_COMPRESS_NT_SYM_LINKS,
30 ntPosX, ntPosY + 12, ntSizeX, 10 27 ntPosX, ntPosY + 12, ntSizeX)
31 CONTROL "Store hard links", IDX_COMPRESS_NT_HARD_LINKS, MY_CHECKBOX, 28 MY_CONTROL_CHECKBOX ("Store hard links", IDX_COMPRESS_NT_HARD_LINKS,
32 ntPosX, ntPosY + 26, ntSizeX, 10 29 ntPosX, ntPosY + 26, ntSizeX)
33 CONTROL "Store alternate data streams", IDX_COMPRESS_NT_ALT_STREAMS, MY_CHECKBOX, 30 MY_CONTROL_CHECKBOX ("Store alternate data streams", IDX_COMPRESS_NT_ALT_STREAMS,
34 ntPosX, ntPosY + 40, ntSizeX, 10 31 ntPosX, ntPosY + 40, ntSizeX)
35 CONTROL "Store file security", IDX_COMPRESS_NT_SECUR, MY_CHECKBOX, 32 MY_CONTROL_CHECKBOX ("Store file security", IDX_COMPRESS_NT_SECUR,
36 ntPosX, ntPosY + 54, ntSizeX, 10 33 ntPosX, ntPosY + 54, ntSizeX)
37 34
38 LTEXT "", IDT_COMPRESS_TIME_INFO, g5x, timePosY - 14, g5xs, 8 35 LTEXT "", IDT_COMPRESS_TIME_INFO, g5x, timePosY - 14, g5xs, 8
39 36
40 37
41 GROUPBOX "Time", IDG_COMPRESS_TIME, g5x, timePosY, g5xs, 112 38 GROUPBOX "Time", IDG_COMPRESS_TIME, g5x, timePosY, g5xs, 112
42 39
43// CONTROL "Default", IDX_COMPRESS_TIME_DEFAULT, MY_CHECKBOX, 40// MY_CONTROL_CHECKBOX ("Default", IDX_COMPRESS_TIME_DEFAULT,
44// ntPosX, timePosY + 10, ntSizeX, 16 41// ntPosX, timePosY + 10, ntSizeX)
45 42
46 CONTROL ceString, IDX_COMPRESS_PREC_SET, MY_CHECKBOX, ntPosX, timePosY + 14, ceSize, 10 43 MY_CONTROL_CHECKBOX_COLON (IDX_COMPRESS_PREC_SET, ntPosX, timePosY + 14)
47 LTEXT "Timestamp precision:", IDT_COMPRESS_TIME_PREC, 44 LTEXT "Timestamp precision:", IDT_COMPRESS_TIME_PREC,
48 ntPosX + ceSize, timePosY + 14, ntSizeX - precSizeX - ceSize, 8 45 ntPosX + cboxColonSize, timePosY + 14, ntSizeX - precSizeX - cboxColonSize, 8
49 COMBOBOX IDC_COMPRESS_TIME_PREC, ntPosX + ntSizeX - precSizeX, timePosY + 12, precSizeX, 70, MY_COMBO 46 COMBOBOX IDC_COMPRESS_TIME_PREC, ntPosX + ntSizeX - precSizeX, timePosY + 12, precSizeX, 70, MY_COMBO
50 47
51 // PUSHBUTTON "Default", IDB_COMPRESS_TIME_DEFAULT, ntPosX + ntSizeX - bxs, timePosY + 22, bxs, bys, WS_GROUP 48 // PUSHBUTTON "Default", IDB_COMPRESS_TIME_DEFAULT, ntPosX + ntSizeX - bxs, timePosY + 22, bxs, bys, WS_GROUP
52 49
53 CONTROL ceString, IDX_COMPRESS_MTIME_SET, MY_CHECKBOX, ntPosX, timePosY + 28, ceSize, 10 50 MY_CONTROL_CHECKBOX_COLON (IDX_COMPRESS_MTIME_SET, ntPosX, timePosY + 28)
54 CONTROL "Store modification time", IDX_COMPRESS_MTIME, MY_CHECKBOX, 51 MY_CONTROL_CHECKBOX ("Store modification time", IDX_COMPRESS_MTIME,
55 ntPosX + ceSize, timePosY + 28, ntSizeX - ceSize, 10 52 ntPosX + cboxColonSize, timePosY + 28, ntSizeX - cboxColonSize)
56 53
57 CONTROL ceString, IDX_COMPRESS_CTIME_SET, MY_CHECKBOX, ntPosX, timePosY + 42, ceSize, 10 54 MY_CONTROL_CHECKBOX_COLON (IDX_COMPRESS_CTIME_SET, ntPosX, timePosY + 42)
58 CONTROL "Store creation time", IDX_COMPRESS_CTIME, MY_CHECKBOX, 55 MY_CONTROL_CHECKBOX ("Store creation time", IDX_COMPRESS_CTIME,
59 ntPosX + ceSize, timePosY + 42, ntSizeX - ceSize, 10 56 ntPosX + cboxColonSize, timePosY + 42, ntSizeX - cboxColonSize)
60 57
61 CONTROL ceString, IDX_COMPRESS_ATIME_SET, MY_CHECKBOX, ntPosX, timePosY + 56, ceSize, 10 58 MY_CONTROL_CHECKBOX_COLON (IDX_COMPRESS_ATIME_SET, ntPosX, timePosY + 56)
62 CONTROL "Store last access time", IDX_COMPRESS_ATIME, MY_CHECKBOX, 59 MY_CONTROL_CHECKBOX ("Store last access time", IDX_COMPRESS_ATIME,
63 ntPosX + ceSize, timePosY + 56, ntSizeX - ceSize, 10 60 ntPosX + cboxColonSize, timePosY + 56, ntSizeX - cboxColonSize)
64 61
65 CONTROL ceString, IDX_COMPRESS_ZTIME_SET, MY_CHECKBOX | BS_MULTILINE, ntPosX, timePosY + 72, ceSize, 16 62 MY_CONTROL_CHECKBOX_2LINES(colonString,
66 CONTROL "Set archive time to latest file time", IDX_COMPRESS_ZTIME, MY_CHECKBOX | BS_MULTILINE, 63 IDX_COMPRESS_ZTIME_SET,
67 ntPosX + ceSize, timePosY + 72, ntSizeX - ceSize, 16 64 ntPosX, timePosY + 72, cboxColonSize)
68 65 MY_CONTROL_CHECKBOX_2LINES(
69 CONTROL "Do not change source files last access time", IDX_COMPRESS_PRESERVE_ATIME, MY_CHECKBOX | BS_MULTILINE, 66 "Set archive time to latest file time",
70 ntPosX, timePosY + 92, ntSizeX, 16 67 IDX_COMPRESS_ZTIME,
68 ntPosX + cboxColonSize, timePosY + 72, ntSizeX - cboxColonSize)
69
70 MY_CONTROL_CHECKBOX_2LINES(
71 "Do not change source files last access time",
72 IDX_COMPRESS_PRESERVE_ATIME,
73 ntPosX, timePosY + 92, ntSizeX)
71 74
72 75
73 DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP 76 DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP
diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp
index fdf3cc7..bafff2b 100644
--- a/CPP/7zip/UI/GUI/ExtractGUI.cpp
+++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp
@@ -42,7 +42,7 @@ static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColo
42{ 42{
43 AddLangString(s, resourceID); 43 AddLangString(s, resourceID);
44 if (addColon) 44 if (addColon)
45 s += ':'; 45 s.Add_Colon();
46 s.Add_Space(); 46 s.Add_Space();
47 s.Add_UInt64(value); 47 s.Add_UInt64(value);
48 s.Add_LF(); 48 s.Add_LF();
diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp
index 37e637b..6bb6693 100644
--- a/CPP/7zip/UI/GUI/GUI.cpp
+++ b/CPP/7zip/UI/GUI/GUI.cpp
@@ -46,9 +46,19 @@ const CExternalCodecs *g_ExternalCodecs_Ptr;
46extern 46extern
47HINSTANCE g_hInstance; 47HINSTANCE g_hInstance;
48HINSTANCE g_hInstance; 48HINSTANCE g_hInstance;
49extern
50bool g_DisableUserQuestions;
51bool g_DisableUserQuestions;
49 52
50#ifndef UNDER_CE 53#ifndef UNDER_CE
51 54
55#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // win2000
56#define Z7_USE_DYN_ComCtl32Version
57#endif
58
59#ifdef Z7_USE_DYN_ComCtl32Version
60Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
61
52extern 62extern
53DWORD g_ComCtl32Version; 63DWORD g_ComCtl32Version;
54DWORD g_ComCtl32Version; 64DWORD g_ComCtl32Version;
@@ -78,6 +88,7 @@ static DWORD GetDllVersion(LPCTSTR dllName)
78} 88}
79 89
80#endif 90#endif
91#endif
81 92
82extern 93extern
83bool g_LVN_ITEMACTIVATE_Support; 94bool g_LVN_ITEMACTIVATE_Support;
@@ -87,7 +98,8 @@ DECLARE_AND_SET_CLIENT_VERSION_VAR
87 98
88static void ErrorMessage(LPCWSTR message) 99static void ErrorMessage(LPCWSTR message)
89{ 100{
90 MessageBoxW(NULL, message, L"7-Zip", MB_ICONERROR | MB_OK); 101 if (!g_DisableUserQuestions)
102 MessageBoxW(NULL, message, L"7-Zip", MB_ICONERROR | MB_OK);
91} 103}
92 104
93static void ErrorMessage(const char *s) 105static void ErrorMessage(const char *s)
@@ -141,6 +153,7 @@ static int Main2()
141 CArcCmdLineParser parser; 153 CArcCmdLineParser parser;
142 154
143 parser.Parse1(commandStrings, options); 155 parser.Parse1(commandStrings, options);
156 g_DisableUserQuestions = options.YesToAll;
144 parser.Parse2(options); 157 parser.Parse2(options);
145 158
146 CREATE_CODECS_OBJECT 159 CREATE_CODECS_OBJECT
@@ -157,7 +170,8 @@ static int Main2()
157 codecs->GetCodecsErrorMessage(s); 170 codecs->GetCodecsErrorMessage(s);
158 if (!s.IsEmpty()) 171 if (!s.IsEmpty())
159 { 172 {
160 MessageBoxW(NULL, s, L"7-Zip", MB_ICONERROR); 173 if (!g_DisableUserQuestions)
174 MessageBoxW(NULL, s, L"7-Zip", MB_ICONERROR);
161 } 175 }
162 176
163 } 177 }
@@ -247,7 +261,9 @@ static int Main2()
247 eo.StdInMode = options.StdInMode; 261 eo.StdInMode = options.StdInMode;
248 eo.StdOutMode = options.StdOutMode; 262 eo.StdOutMode = options.StdOutMode;
249 eo.YesToAll = options.YesToAll; 263 eo.YesToAll = options.YesToAll;
264 ecs->YesToAll = options.YesToAll;
250 eo.TestMode = options.Command.IsTestCommand(); 265 eo.TestMode = options.Command.IsTestCommand();
266 ecs->TestMode = eo.TestMode;
251 267
252 #ifndef Z7_SFX 268 #ifndef Z7_SFX
253 eo.Properties = options.Properties; 269 eo.Properties = options.Properties;
@@ -405,10 +421,10 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
405 421
406 InitCommonControls(); 422 InitCommonControls();
407 423
408 #ifndef UNDER_CE 424#ifdef Z7_USE_DYN_ComCtl32Version
409 g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll")); 425 g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll"));
410 g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4)); 426 g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4));
411 #endif 427#endif
412 428
413 // OleInitialize is required for ProgressBar in TaskBar. 429 // OleInitialize is required for ProgressBar in TaskBar.
414 #ifndef UNDER_CE 430 #ifndef UNDER_CE
diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp
index 3a6b60f..1742f26 100644
--- a/CPP/7zip/UI/GUI/GUI.dsp
+++ b/CPP/7zip/UI/GUI/GUI.dsp
@@ -449,6 +449,14 @@ SOURCE=..\FileManager\ListViewDialog.h
449# End Source File 449# End Source File
450# Begin Source File 450# Begin Source File
451 451
452SOURCE=..\FileManager\MemDialog.cpp
453# End Source File
454# Begin Source File
455
456SOURCE=..\FileManager\MemDialog.h
457# End Source File
458# Begin Source File
459
452SOURCE=..\FileManager\OverwriteDialog.cpp 460SOURCE=..\FileManager\OverwriteDialog.cpp
453# End Source File 461# End Source File
454# Begin Source File 462# Begin Source File
@@ -781,6 +789,10 @@ SOURCE=..\..\..\..\C\7zTypes.h
781# End Source File 789# End Source File
782# Begin Source File 790# Begin Source File
783 791
792SOURCE=..\..\..\..\C\7zVersion.h
793# End Source File
794# Begin Source File
795
784SOURCE=..\..\..\..\C\7zWindows.h 796SOURCE=..\..\..\..\C\7zWindows.h
785# End Source File 797# End Source File
786# Begin Source File 798# Begin Source File
@@ -794,6 +806,10 @@ SOURCE=..\..\..\..\C\Alloc.h
794# End Source File 806# End Source File
795# Begin Source File 807# Begin Source File
796 808
809SOURCE=..\..\..\..\C\Compiler.h
810# End Source File
811# Begin Source File
812
797SOURCE=..\..\..\..\C\CpuArch.c 813SOURCE=..\..\..\..\C\CpuArch.c
798 814
799!IF "$(CFG)" == "GUI - Win32 Release" 815!IF "$(CFG)" == "GUI - Win32 Release"
@@ -831,6 +847,10 @@ SOURCE=..\..\..\..\C\DllSecur.h
831# End Source File 847# End Source File
832# Begin Source File 848# Begin Source File
833 849
850SOURCE=..\..\..\..\C\Precomp.h
851# End Source File
852# Begin Source File
853
834SOURCE=..\..\..\..\C\Sort.c 854SOURCE=..\..\..\..\C\Sort.c
835 855
836!IF "$(CFG)" == "GUI - Win32 Release" 856!IF "$(CFG)" == "GUI - Win32 Release"
@@ -884,10 +904,6 @@ SOURCE=..\..\..\Common\Common.h
884# End Source File 904# End Source File
885# Begin Source File 905# Begin Source File
886 906
887SOURCE=..\..\..\..\C\Compiler.h
888# End Source File
889# Begin Source File
890
891SOURCE=..\..\..\Common\CRC.cpp 907SOURCE=..\..\..\Common\CRC.cpp
892# End Source File 908# End Source File
893# Begin Source File 909# Begin Source File
diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp
index aaf7ebd..a600a8b 100644
--- a/CPP/7zip/UI/GUI/UpdateGUI.cpp
+++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp
@@ -197,7 +197,7 @@ static void AddProp_Size(CObjectVector<CProperty> &properties, const char *name,
197{ 197{
198 UString s; 198 UString s;
199 s.Add_UInt64(size); 199 s.Add_UInt64(size);
200 s += 'b'; 200 s.Add_Char('b');
201 AddProp_UString(properties, name, s); 201 AddProp_UString(properties, name, s);
202} 202}
203 203
@@ -265,7 +265,7 @@ static void SetOutProperties(
265 UString s; 265 UString s;
266 // s += 'p'; // for debug: alternate percent method 266 // s += 'p'; // for debug: alternate percent method
267 s.Add_UInt64(memUse.Val); 267 s.Add_UInt64(memUse.Val);
268 s += '%'; 268 s.Add_Char('%');
269 AddProp_UString(properties, kMemUse, s); 269 AddProp_UString(properties, kMemUse, s);
270 } 270 }
271 else 271 else
diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile
index 9e2a9b4..22ae095 100644
--- a/CPP/7zip/UI/GUI/makefile
+++ b/CPP/7zip/UI/GUI/makefile
@@ -7,7 +7,8 @@ CFLAGS = $(CFLAGS) \
7LIBS = $(LIBS) ceshell.lib Commctrl.lib 7LIBS = $(LIBS) ceshell.lib Commctrl.lib
8!ELSE 8!ELSE
9LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib gdi32.lib 9LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib gdi32.lib
10CFLAGS = $(CFLAGS) -DZ7_LONG_PATH -DZ7_LARGE_PAGES -DZ7_DEVICE_FILE 10CFLAGS = $(CFLAGS) -DZ7_DEVICE_FILE
11# -DZ7_LONG_PATH -DZ7_LARGE_PAGES
11!ENDIF 12!ENDIF
12 13
13GUI_OBJS = \ 14GUI_OBJS = \
@@ -114,6 +115,7 @@ FM_OBJS = \
114 $O\HelpUtils.obj \ 115 $O\HelpUtils.obj \
115 $O\LangUtils.obj \ 116 $O\LangUtils.obj \
116 $O\ListViewDialog.obj \ 117 $O\ListViewDialog.obj \
118 $O\MemDialog.obj \
117 $O\OpenCallback.obj \ 119 $O\OpenCallback.obj \
118 $O\ProgramLocation.obj \ 120 $O\ProgramLocation.obj \
119 $O\PropertyName.obj \ 121 $O\PropertyName.obj \
diff --git a/CPP/7zip/UI/GUI/resource.rc b/CPP/7zip/UI/GUI/resource.rc
index 04af815..08ef00a 100644
--- a/CPP/7zip/UI/GUI/resource.rc
+++ b/CPP/7zip/UI/GUI/resource.rc
@@ -15,6 +15,7 @@ IDI_ICON ICON "FM.ico"
15#endif 15#endif
16 16
17#include "../FileManager/PropertyName.rc" 17#include "../FileManager/PropertyName.rc"
18#include "../FileManager/MemDialog.rc"
18#include "../FileManager/OverwriteDialog.rc" 19#include "../FileManager/OverwriteDialog.rc"
19#include "../FileManager/PasswordDialog.rc" 20#include "../FileManager/PasswordDialog.rc"
20#include "../FileManager/ProgressDialog2.rc" 21#include "../FileManager/ProgressDialog2.rc"
diff --git a/CPP/7zip/cmpl_gcc_arm.mak b/CPP/7zip/cmpl_gcc_arm.mak
new file mode 100644
index 0000000..6671d58
--- /dev/null
+++ b/CPP/7zip/cmpl_gcc_arm.mak
@@ -0,0 +1,3 @@
1include ../../var_gcc_arm.mak
2include ../../warn_gcc.mak
3include makefile.gcc
diff --git a/CPP/7zip/var_clang_arm64.mak b/CPP/7zip/var_clang_arm64.mak
index 4b35409..ec81d26 100644
--- a/CPP/7zip/var_clang_arm64.mak
+++ b/CPP/7zip/var_clang_arm64.mak
@@ -4,8 +4,16 @@ IS_X64=
4IS_X86= 4IS_X86=
5IS_ARM64=1 5IS_ARM64=1
6CROSS_COMPILE= 6CROSS_COMPILE=
7
8MY_ARCH=-march=armv8-a
9MY_ARCH=-march=armv8-a+crypto+crc
10MY_ARCH=-march=armv8.3-a+crypto+crc
7MY_ARCH= 11MY_ARCH=
12
13USE_ASM=
8USE_ASM=1 14USE_ASM=1
15
16ASM_FLAGS=-Wno-unused-macros
9CC=$(CROSS_COMPILE)clang 17CC=$(CROSS_COMPILE)clang
10CXX=$(CROSS_COMPILE)clang++ 18CXX=$(CROSS_COMPILE)clang++
11USE_CLANG=1 19USE_CLANG=1
diff --git a/CPP/7zip/var_clang_x64.mak b/CPP/7zip/var_clang_x64.mak
index fefed51..34e1b49 100644
--- a/CPP/7zip/var_clang_x64.mak
+++ b/CPP/7zip/var_clang_x64.mak
@@ -9,4 +9,3 @@ USE_ASM=1
9CC=$(CROSS_COMPILE)clang 9CC=$(CROSS_COMPILE)clang
10CXX=$(CROSS_COMPILE)clang++ 10CXX=$(CROSS_COMPILE)clang++
11USE_CLANG=1 11USE_CLANG=1
12
diff --git a/CPP/7zip/var_clang_x86.mak b/CPP/7zip/var_clang_x86.mak
index 5f3c2d9..bd2317c 100644
--- a/CPP/7zip/var_clang_x86.mak
+++ b/CPP/7zip/var_clang_x86.mak
@@ -9,4 +9,3 @@ USE_ASM=1
9CC=$(CROSS_COMPILE)clang 9CC=$(CROSS_COMPILE)clang
10CXX=$(CROSS_COMPILE)clang++ 10CXX=$(CROSS_COMPILE)clang++
11USE_CLANG=1 11USE_CLANG=1
12
diff --git a/CPP/7zip/var_gcc_arm.mak b/CPP/7zip/var_gcc_arm.mak
new file mode 100644
index 0000000..7527e40
--- /dev/null
+++ b/CPP/7zip/var_gcc_arm.mak
@@ -0,0 +1,34 @@
1PLATFORM=arm
2O=b/g_$(PLATFORM)
3IS_X64=
4IS_X86=
5IS_ARM64=
6
7CROSS_COMPILE_ABI=
8CROSS_COMPILE_ABI=arm-linux-musleabi
9CROSS_COMPILE_ABI=arm-linux-musleabihf
10CROSS_COMPILE_ABI=aarch64-linux-musl
11CROSS_COMPILE_ABI=arm-linux-gnueabi
12CROSS_COMPILE_ABI=arm-linux-gnueabihf
13
14COMPILER_VER_POSTFIX=-12
15COMPILER_VER_POSTFIX=
16
17CROSS_COMPILE_PREFIX=
18
19CROSS_COMPILE=$(CROSS_COMPILE_PREFIX)$(CROSS_COMPILE_ABI)-
20CROSS_COMPILE=
21
22MY_ARCH=
23MY_ARCH=-mtune=cortex-a53 -march=armv7-a
24MY_ARCH=-mtune=cortex-a53 -march=armv4
25MY_ARCH=-mtune=cortex-a53
26
27USE_ASM=
28
29LDFLAGS_STATIC_3=-static
30LDFLAGS_STATIC_3=
31
32CC=$(CROSS_COMPILE)gcc$(COMPILER_VER_POSTFIX)
33CXX=$(CROSS_COMPILE)g++$(COMPILER_VER_POSTFIX)
34# -marm -march=armv5t -march=armv6 -march=armv7-a -march=armv8-a -march=armv8-a+crc+crypto
diff --git a/CPP/7zip/var_gcc_x64.mak b/CPP/7zip/var_gcc_x64.mak
index 1acf604..aeea203 100644
--- a/CPP/7zip/var_gcc_x64.mak
+++ b/CPP/7zip/var_gcc_x64.mak
@@ -4,6 +4,7 @@ IS_X64=1
4IS_X86= 4IS_X86=
5IS_ARM64= 5IS_ARM64=
6CROSS_COMPILE= 6CROSS_COMPILE=
7MY_ARCH=-mavx512f -mavx512vl
7MY_ARCH= 8MY_ARCH=
8USE_ASM=1 9USE_ASM=1
9CC=$(CROSS_COMPILE)gcc 10CC=$(CROSS_COMPILE)gcc
diff --git a/CPP/7zip/var_gcc_x86.mak b/CPP/7zip/var_gcc_x86.mak
index 288bf94..f0718ec 100644
--- a/CPP/7zip/var_gcc_x86.mak
+++ b/CPP/7zip/var_gcc_x86.mak
@@ -8,4 +8,3 @@ MY_ARCH=-m32
8USE_ASM=1 8USE_ASM=1
9CC=$(CROSS_COMPILE)gcc 9CC=$(CROSS_COMPILE)gcc
10CXX=$(CROSS_COMPILE)g++ 10CXX=$(CROSS_COMPILE)g++
11
diff --git a/CPP/7zip/var_mac_arm64.mak b/CPP/7zip/var_mac_arm64.mak
index adf5fa1..746e6db 100644
--- a/CPP/7zip/var_mac_arm64.mak
+++ b/CPP/7zip/var_mac_arm64.mak
@@ -4,6 +4,8 @@ IS_X64=
4IS_X86= 4IS_X86=
5IS_ARM64=1 5IS_ARM64=1
6CROSS_COMPILE= 6CROSS_COMPILE=
7#use this code to reduce features
8MY_ARCH=-arch arm64 -march=armv8-a
7MY_ARCH=-arch arm64 9MY_ARCH=-arch arm64
8USE_ASM=1 10USE_ASM=1
9CC=$(CROSS_COMPILE)clang 11CC=$(CROSS_COMPILE)clang
diff --git a/CPP/7zip/warn_gcc.mak b/CPP/7zip/warn_gcc.mak
index 7eb1f57..b6ed9c3 100644
--- a/CPP/7zip/warn_gcc.mak
+++ b/CPP/7zip/warn_gcc.mak
@@ -38,7 +38,8 @@ CFLAGS_WARN_GCC_PPMD_UNALIGNED = \
38 -Wno-strict-aliasing \ 38 -Wno-strict-aliasing \
39 39
40 40
41# CFLAGS_WARN = $(CFLAGS_WARN_GCC_4_8) 41CFLAGS_WARN = $(CFLAGS_WARN_GCC_4_8)
42CFLAGS_WARN = $(CFLAGS_WARN_GCC_6)
42CFLAGS_WARN = $(CFLAGS_WARN_GCC_9) 43CFLAGS_WARN = $(CFLAGS_WARN_GCC_9)
43 44
44# CXX_STD_FLAGS = -std=c++11 45# CXX_STD_FLAGS = -std=c++11
diff --git a/CPP/Build.mak b/CPP/Build.mak
index 393fa2c..afb7ae8 100644
--- a/CPP/Build.mak
+++ b/CPP/Build.mak
@@ -1,7 +1,8 @@
1LIBS = $(LIBS) oleaut32.lib ole32.lib 1LIBS = $(LIBS) oleaut32.lib ole32.lib
2 2
3# CFLAGS = $(CFLAGS) -DZ7_NO_UNICODE
3!IFNDEF MY_NO_UNICODE 4!IFNDEF MY_NO_UNICODE
4CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE 5# CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE
5!ENDIF 6!ENDIF
6 7
7!IF "$(CC)" != "clang-cl" 8!IF "$(CC)" != "clang-cl"
@@ -21,10 +22,14 @@ O=o
21# CFLAGS = $(CFLAGS) -FAsc -Fa$O/asm/ 22# CFLAGS = $(CFLAGS) -FAsc -Fa$O/asm/
22!ENDIF 23!ENDIF
23 24
25# LFLAGS = $(LFLAGS) /guard:cf
26
24 27
25!IF "$(PLATFORM)" == "x64" 28!IF "$(PLATFORM)" == "x64"
26MY_ML = ml64 -WX 29MY_ML = ml64 -WX
27#-Dx64 30#-Dx64
31!ELSEIF "$(PLATFORM)" == "arm64"
32MY_ML = armasm64
28!ELSEIF "$(PLATFORM)" == "arm" 33!ELSEIF "$(PLATFORM)" == "arm"
29MY_ML = armasm -WX 34MY_ML = armasm -WX
30!ELSE 35!ELSE
@@ -52,6 +57,8 @@ LIBS = $(LIBS) user32.lib advapi32.lib shell32.lib
52 57
53!IF "$(PLATFORM)" == "arm" 58!IF "$(PLATFORM)" == "arm"
54COMPL_ASM = $(MY_ML) $** $O/$(*B).obj 59COMPL_ASM = $(MY_ML) $** $O/$(*B).obj
60!ELSEIF "$(PLATFORM)" == "arm64"
61COMPL_ASM = $(MY_ML) $** $O/$(*B).obj
55!ELSE 62!ELSE
56COMPL_ASM = $(MY_ML) -c -Fo$O/ $** 63COMPL_ASM = $(MY_ML) -c -Fo$O/ $**
57!ENDIF 64!ENDIF
@@ -75,7 +82,8 @@ CFLAGS = $(CFLAGS) \
75 82
76!ENDIF 83!ENDIF
77 84
78!IFDEF MY_DYNAMIC_LINK 85# !IFDEF MY_DYNAMIC_LINK
86!IF "$(MY_DYNAMIC_LINK)" != ""
79CFLAGS = $(CFLAGS) -MD 87CFLAGS = $(CFLAGS) -MD
80!ELSE 88!ELSE
81!IFNDEF MY_SINGLE_THREAD 89!IFNDEF MY_SINGLE_THREAD
@@ -169,6 +177,15 @@ LFLAGS = $(LFLAGS) /SUBSYSTEM:windows,$(MY_SUB_SYS_VER)
169!ENDIF 177!ENDIF
170 178
171 179
180!IF "$(PLATFORM)" == "arm64"
181CLANG_FLAGS_TARGET = --target=arm64-pc-windows-msvc
182!ENDIF
183
184COMPL_CLANG_SPEC=clang-cl $(CLANG_FLAGS_TARGET)
185COMPL_ASM_CLANG = $(COMPL_CLANG_SPEC) -nologo -c -Fo$O/ $(CFLAGS_WARN_LEVEL) -WX $**
186# COMPL_C_CLANG = $(COMPL_CLANG_SPEC) $(CFLAGS_O2)
187
188
172PROGPATH = $O\$(PROG) 189PROGPATH = $O\$(PROG)
173 190
174COMPL_O1 = $(CC) $(CFLAGS_O1) $** 191COMPL_O1 = $(CC) $(CFLAGS_O1) $**
@@ -224,6 +241,6 @@ predef: empty.c
224predef2: A.cpp 241predef2: A.cpp
225 $(COMPL) -EP -Zc:preprocessor -PD 242 $(COMPL) -EP -Zc:preprocessor -PD
226predef3: A.cpp 243predef3: A.cpp
227 $(COMPL) -E -dM 244 $(COMPL) -E -dM
228predef4: A.cpp 245predef4: A.cpp
229 $(COMPL_O2) -E 246 $(COMPL_O2) -E
diff --git a/CPP/Common/AutoPtr.h b/CPP/Common/AutoPtr.h
index 0be8a7a..e3c5763 100644
--- a/CPP/Common/AutoPtr.h
+++ b/CPP/Common/AutoPtr.h
@@ -3,20 +3,32 @@
3#ifndef ZIP7_INC_COMMON_AUTOPTR_H 3#ifndef ZIP7_INC_COMMON_AUTOPTR_H
4#define ZIP7_INC_COMMON_AUTOPTR_H 4#define ZIP7_INC_COMMON_AUTOPTR_H
5 5
6template<class T> class CMyAutoPtr 6template<class T> class CMyUniquePtr
7// CMyAutoPtr
7{ 8{
8 T *_p; 9 T *_p;
9public: 10
10 CMyAutoPtr(T *p = NULL) : _p(p) {} 11 CMyUniquePtr(CMyUniquePtr<T>& p); // : _p(p.release()) {}
11 CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {} 12 CMyUniquePtr<T>& operator=(T *p);
12 CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p) 13 CMyUniquePtr<T>& operator=(CMyUniquePtr<T>& p);
14 /*
13 { 15 {
14 reset(p.release()); 16 reset(p.release());
15 return (*this); 17 return (*this);
16 } 18 }
17 ~CMyAutoPtr() { delete _p; } 19 */
20 void reset(T* p = NULL)
21 {
22 if (p != _p)
23 delete _p;
24 _p = p;
25 }
26public:
27 CMyUniquePtr(T *p = NULL) : _p(p) {}
28 ~CMyUniquePtr() { delete _p; }
18 T& operator*() const { return *_p; } 29 T& operator*() const { return *_p; }
19 // T* operator->() const { return (&**this); } 30 T* operator->() const { return _p; }
31 // operator bool() const { return _p != NULL; }
20 T* get() const { return _p; } 32 T* get() const { return _p; }
21 T* release() 33 T* release()
22 { 34 {
@@ -24,11 +36,10 @@ public:
24 _p = NULL; 36 _p = NULL;
25 return tmp; 37 return tmp;
26 } 38 }
27 void reset(T* p = NULL) 39 void Create_if_Empty()
28 { 40 {
29 if (p != _p) 41 if (!_p)
30 delete _p; 42 _p = new T;
31 _p = p;
32 } 43 }
33}; 44};
34 45
diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp
index 465e0fd..319f27f 100644
--- a/CPP/Common/CommandLineParser.cpp
+++ b/CPP/Common/CommandLineParser.cpp
@@ -6,6 +6,8 @@
6 6
7namespace NCommandLineParser { 7namespace NCommandLineParser {
8 8
9#ifdef _WIN32
10
9bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) 11bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
10{ 12{
11 dest1.Empty(); 13 dest1.Empty();
@@ -14,7 +16,7 @@ bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
14 unsigned i; 16 unsigned i;
15 for (i = 0; i < src.Len(); i++) 17 for (i = 0; i < src.Len(); i++)
16 { 18 {
17 wchar_t c = src[i]; 19 const wchar_t c = src[i];
18 if ((c == L' ' || c == L'\t') && !quoteMode) 20 if ((c == L' ' || c == L'\t') && !quoteMode)
19 { 21 {
20 dest2 = src.Ptr(i + 1); 22 dest2 = src.Ptr(i + 1);
@@ -30,6 +32,34 @@ bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
30 32
31void SplitCommandLine(const UString &s, UStringVector &parts) 33void SplitCommandLine(const UString &s, UStringVector &parts)
32{ 34{
35#if 0
36/* we don't use CommandLineToArgvW() because
37 it can remove tail backslash:
38 "1\"
39 converted to
40 1"
41*/
42 parts.Clear();
43 {
44 int nArgs;
45 LPWSTR *szArgList = CommandLineToArgvW(s, &nArgs);
46 if (szArgList)
47 {
48 for (int i = 0; i < nArgs; i++)
49 {
50 // printf("%2d: |%S|\n", i, szArglist[i]);
51 parts.Add(szArgList[i]);
52 }
53 LocalFree(szArgList);
54 return;
55 }
56 }
57#endif
58/*
59#ifdef _UNICODE
60 throw 20240406;
61#else
62*/
33 UString sTemp (s); 63 UString sTemp (s);
34 sTemp.Trim(); 64 sTemp.Trim();
35 parts.Clear(); 65 parts.Clear();
@@ -42,7 +72,9 @@ void SplitCommandLine(const UString &s, UStringVector &parts)
42 break; 72 break;
43 sTemp = s2; 73 sTemp = s2;
44 } 74 }
75// #endif
45} 76}
77#endif
46 78
47 79
48static const char * const kStopSwitchParsing = "--"; 80static const char * const kStopSwitchParsing = "--";
@@ -78,7 +110,7 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsi
78 for (unsigned i = 0; i < numSwitches; i++) 110 for (unsigned i = 0; i < numSwitches; i++)
79 { 111 {
80 const char * const key = switchForms[i].Key; 112 const char * const key = switchForms[i].Key;
81 unsigned switchLen = MyStringLen(key); 113 const unsigned switchLen = MyStringLen(key);
82 if ((int)switchLen <= maxLen || pos + switchLen > s.Len()) 114 if ((int)switchLen <= maxLen || pos + switchLen > s.Len())
83 continue; 115 continue;
84 if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key)) 116 if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key))
@@ -133,7 +165,7 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsi
133 case NSwitchType::kChar: 165 case NSwitchType::kChar:
134 if (rem == 1) 166 if (rem == 1)
135 { 167 {
136 wchar_t c = s[pos]; 168 const wchar_t c = s[pos];
137 if (c <= 0x7F) 169 if (c <= 0x7F)
138 { 170 {
139 sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c); 171 sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);
@@ -150,6 +182,8 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsi
150 sw.PostStrings.Add(s.Ptr(pos)); 182 sw.PostStrings.Add(s.Ptr(pos));
151 return true; 183 return true;
152 } 184 }
185 // case NSwitchType::kSimple:
186 default: break;
153 } 187 }
154 188
155 if (pos != s.Len()) 189 if (pos != s.Len())
diff --git a/CPP/Common/Common.h b/CPP/Common/Common.h
index 0c77ab4..cde0c38 100644
--- a/CPP/Common/Common.h
+++ b/CPP/Common/Common.h
@@ -7,7 +7,9 @@
7#ifndef ZIP7_INC_COMMON_H 7#ifndef ZIP7_INC_COMMON_H
8#define ZIP7_INC_COMMON_H 8#define ZIP7_INC_COMMON_H
9 9
10#include "../../C/Compiler.h" 10#include "../../C/Precomp.h"
11#include "Common0.h"
12#include "MyWindows.h"
11 13
12/* 14/*
13This file is included to all cpp files in 7-Zip. 15This file is included to all cpp files in 7-Zip.
@@ -17,297 +19,10 @@ So 7-Zip includes "Common.h" in both modes:
17and 19and
18 without precompiled StdAfx.h 20 without precompiled StdAfx.h
19 21
20If you use 7-Zip code, you must include "Common.h" before other h files of 7-zip. 22include "Common.h" before other h files of 7-zip,
21If you don't need some things that are used in 7-Zip, 23 if you need predefined macros.
22you can change this h file or h files included in this file. 24do not include "Common.h", if you need only interfaces,
23*/ 25 and you don't need predefined macros.
24
25#ifdef _MSC_VER
26 #pragma warning(disable : 4710) // function not inlined
27 // 'CUncopyable::CUncopyable':
28 #pragma warning(disable : 4514) // unreferenced inline function has been removed
29 #if _MSC_VER < 1300
30 #pragma warning(disable : 4702) // unreachable code
31 #pragma warning(disable : 4714) // function marked as __forceinline not inlined
32 #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
33 #endif
34 #if _MSC_VER < 1400
35 #pragma warning(disable : 4511) // copy constructor could not be generated // #pragma warning(disable : 4512) // assignment operator could not be generated
36 #pragma warning(disable : 4512) // assignment operator could not be generated
37 #endif
38 #if _MSC_VER > 1400 && _MSC_VER <= 1900
39 // #pragma warning(disable : 4996)
40 // strcat: This function or variable may be unsafe
41 // GetVersion was declared deprecated
42 #endif
43
44#if _MSC_VER > 1200
45// -Wall warnings
46
47#if _MSC_VER <= 1600
48#pragma warning(disable : 4917) // 'OLE_HANDLE' : a GUID can only be associated with a class, interface or namespace
49#endif
50
51// #pragma warning(disable : 4061) // enumerator '' in switch of enum '' is not explicitly handled by a case label
52// #pragma warning(disable : 4266) // no override available for virtual member function from base ''; function is hidden
53#pragma warning(disable : 4625) // copy constructor was implicitly defined as deleted
54#pragma warning(disable : 4626) // assignment operator was implicitly defined as deleted
55#if _MSC_VER >= 1600 && _MSC_VER < 1920
56#pragma warning(disable : 4571) // Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught
57#endif
58#if _MSC_VER >= 1600
59#pragma warning(disable : 4365) // 'initializing' : conversion from 'int' to 'unsigned int', signed / unsigned mismatch
60#endif
61#if _MSC_VER < 1800
62// we disable the warning, if we don't use 'final' in class
63#pragma warning(disable : 4265) // class has virtual functions, but destructor is not virtual
64#endif
65
66#if _MSC_VER >= 1900
67#pragma warning(disable : 5026) // move constructor was implicitly defined as deleted
68#pragma warning(disable : 5027) // move assignment operator was implicitly defined as deleted
69#endif
70#if _MSC_VER >= 1912
71#pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to 'extern "C"' function under - EHc.Undefined behavior may occur if this function throws an exception.
72#endif
73#if _MSC_VER >= 1925
74// #pragma warning(disable : 5204) // 'ISequentialInStream' : class has virtual functions, but its trivial destructor is not virtual; instances of objects derived from this class may not be destructed correctly
75#endif
76#if _MSC_VER >= 1934
77// #pragma warning(disable : 5264) // const variable is not used
78#endif
79
80#endif // _MSC_VER > 1200
81#endif // _MSC_VER
82
83
84#if defined(_MSC_VER) // && !defined(__clang__)
85#define Z7_DECLSPEC_NOTHROW __declspec(nothrow)
86#elif defined(__clang__) || defined(__GNUC__)
87#define Z7_DECLSPEC_NOTHROW __attribute__((nothrow))
88#else
89#define Z7_DECLSPEC_NOTHROW
90#endif
91
92/*
93#if defined (_MSC_VER) && _MSC_VER >= 1900 \
94 || defined(__clang__) && __clang_major__ >= 6 \
95 || defined(__GNUC__) && __GNUC__ >= 6
96 #define Z7_noexcept noexcept
97#else
98 #define Z7_noexcept throw()
99#endif
100*/
101
102
103#if defined(__clang__)
104
105// noexcept, final, = delete
106#pragma GCC diagnostic ignored "-Wc++98-compat"
107#if __clang_major__ >= 4
108// throw() dynamic exception specifications are deprecated
109#pragma GCC diagnostic ignored "-Wdeprecated-dynamic-exception-spec"
110#endif
111#pragma GCC diagnostic ignored "-Wold-style-cast"
112#pragma GCC diagnostic ignored "-Wglobal-constructors"
113#pragma GCC diagnostic ignored "-Wexit-time-destructors"
114
115// #pragma GCC diagnostic ignored "-Wunused-private-field"
116// #pragma GCC diagnostic ignored "-Wnonportable-system-include-path"
117// #pragma GCC diagnostic ignored "-Wsuggest-override"
118// #pragma GCC diagnostic ignored "-Wsign-conversion"
119// #pragma GCC diagnostic ignored "-Winconsistent-missing-override"
120// #pragma GCC diagnostic ignored "-Wsuggest-destructor-override"
121// #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
122// #pragma GCC diagnostic ignored "-Wdeprecated-copy-with-user-provided-dtor"
123// #pragma GCC diagnostic ignored "-Wdeprecated-copy-dtor"
124// #ifndef _WIN32
125// #pragma GCC diagnostic ignored "-Wweak-vtables"
126// #endif
127/*
128#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400) \
129 || defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30000)
130// enumeration values not explicitly handled in switch
131#pragma GCC diagnostic ignored "-Wswitch-enum"
132#endif
133*/
134#endif // __clang__
135
136
137#ifdef __GNUC__
138// #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
139#endif
140
141
142/* There is BUG in MSVC 6.0 compiler for operator new[]:
143 It doesn't check overflow, when it calculates size in bytes for allocated array.
144 So we can use Z7_ARRAY_NEW macro instead of new[] operator. */
145
146#if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64)
147 #define Z7_ARRAY_NEW(p, T, size) p = new T[((size) > (unsigned)0xFFFFFFFF / sizeof(T)) ? (unsigned)0xFFFFFFFF / sizeof(T) : (size)];
148#else
149 #define Z7_ARRAY_NEW(p, T, size) p = new T[size];
150#endif
151
152#if (defined(__GNUC__) && (__GNUC__ >= 8))
153 #define Z7_ATTR_NORETURN __attribute__((noreturn))
154#elif (defined(__clang__) && (__clang_major__ >= 3))
155 #if __has_feature(cxx_attributes)
156 #define Z7_ATTR_NORETURN [[noreturn]]
157 #else
158 #define Z7_ATTR_NORETURN __attribute__((noreturn))
159 #endif
160#elif (defined(_MSC_VER) && (_MSC_VER >= 1900))
161 #define Z7_ATTR_NORETURN [[noreturn]]
162#else
163 #define Z7_ATTR_NORETURN
164#endif
165
166
167// final in "GCC 4.7.0"
168// In C++98 and C++03 code the alternative spelling __final can be used instead (this is a GCC extension.)
169
170#if defined (__cplusplus) && __cplusplus >= 201103L \
171 || defined(_MSC_VER) && _MSC_VER >= 1800 \
172 || defined(__clang__) && __clang_major__ >= 4 \
173 /* || defined(__GNUC__) && __GNUC__ >= 9 */
174 #define Z7_final final
175 #if defined(__clang__) && __cplusplus < 201103L
176 #pragma GCC diagnostic ignored "-Wc++11-extensions"
177 #endif
178#elif defined (__cplusplus) && __cplusplus >= 199711L \
179 && defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__)
180 #define Z7_final __final
181#else
182 #define Z7_final
183 #if defined(__clang__) && __clang_major__ >= 4 \
184 || defined(__GNUC__) && __GNUC__ >= 4
185 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
186 #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
187 #endif
188#endif
189
190#define Z7_class_final(c) class c Z7_final
191
192
193#if defined (__cplusplus) && __cplusplus >= 201103L \
194 || (defined(_MSC_VER) && _MSC_VER >= 1800)
195 #define Z7_CPP_IS_SUPPORTED_default
196 #define Z7_eq_delete = delete
197 // #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c) c(const c& k) = default;
198#else
199 #define Z7_eq_delete
200 // #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c)
201#endif
202
203
204#if defined(__cplusplus) && (__cplusplus >= 201103L) \
205 || defined(_MSC_VER) && (_MSC_VER >= 1400) /* && (_MSC_VER != 1600) */ \
206 || defined(__clang__) && __clang_major__ >= 4
207 #if defined(_MSC_VER) && (_MSC_VER == 1600) /* && (_MSC_VER != 1600) */
208 #pragma warning(disable : 4481) // nonstandard extension used: override specifier 'override'
209 #define Z7_DESTRUCTOR_override
210 #else
211 #define Z7_DESTRUCTOR_override override
212 #endif
213 #define Z7_override override
214#else
215 #define Z7_override
216 #define Z7_DESTRUCTOR_override
217#endif
218
219
220
221#define Z7_CLASS_NO_COPY(cls) \
222 private: \
223 cls(const cls &) Z7_eq_delete; \
224 cls &operator=(const cls &) Z7_eq_delete;
225
226class CUncopyable
227{
228protected:
229 CUncopyable() {} // allow constructor
230 // ~CUncopyable() {}
231 Z7_CLASS_NO_COPY(CUncopyable)
232};
233
234#define MY_UNCOPYABLE :private CUncopyable
235// #define MY_UNCOPYABLE
236
237
238typedef void (*Z7_void_Function)(void);
239
240#if defined(__clang__) || defined(__GNUC__)
241#define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(reinterpret_cast<Z7_void_Function>(e))
242#else
243#define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(reinterpret_cast<void*>(e))
244// #define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(e)
245#endif
246
247#define Z7_GET_PROC_ADDRESS(func_type, hmodule, func_name) \
248 Z7_CAST_FUNC(func_type, GetProcAddress(hmodule, func_name))
249
250// || defined(__clang__)
251// || defined(__GNUC__)
252
253#if defined(_MSC_VER) && (_MSC_VER >= 1400)
254#define Z7_DECLSPEC_NOVTABLE __declspec(novtable)
255#else
256#define Z7_DECLSPEC_NOVTABLE
257#endif
258
259#ifdef __clang__
260#define Z7_PURE_INTERFACES_BEGIN \
261_Pragma("GCC diagnostic push") \
262_Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"")
263_Pragma("GCC diagnostic ignored \"-Wweak-vtables\"")
264#define Z7_PURE_INTERFACES_END \
265_Pragma("GCC diagnostic pop")
266#else
267#define Z7_PURE_INTERFACES_BEGIN
268#define Z7_PURE_INTERFACES_END
269#endif
270
271// NewHandler.h and NewHandler.cpp redefine operator new() to throw exceptions, if compiled with old MSVC compilers
272#include "NewHandler.h"
273
274/*
275// #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
276#ifndef ARRAY_SIZE
277#define ARRAY_SIZE(a) Z7_ARRAY_SIZE(a)
278#endif
279*/ 26*/
280 27
281#endif // ZIP7_INC_COMMON_H
282
283
284
285// #define Z7_REDEFINE_NULL
286
287#if defined(Z7_REDEFINE_NULL) /* && (!defined(__clang__) || defined(_MSC_VER)) */
288
289// NULL is defined in <stddef.h>
290#include <stddef.h>
291#undef NULL
292
293#ifdef __cplusplus
294 #if defined (__cplusplus) && __cplusplus >= 201103L \
295 || (defined(_MSC_VER) && _MSC_VER >= 1800)
296 #define NULL nullptr
297 #else
298 #define NULL 0
299 #endif
300#else
301 #define NULL ((void *)0)
302#endif
303
304#else // Z7_REDEFINE_NULL
305
306#if defined(__clang__) && __clang_major__ >= 5
307#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
308#endif 28#endif
309
310#endif // Z7_REDEFINE_NULL
311
312// for precompiler:
313#include "MyWindows.h"
diff --git a/CPP/Common/Common0.h b/CPP/Common/Common0.h
new file mode 100644
index 0000000..55606cd
--- /dev/null
+++ b/CPP/Common/Common0.h
@@ -0,0 +1,330 @@
1// Common0.h
2
3#if defined(_MSC_VER) && _MSC_VER >= 1800
4#pragma warning(disable : 4464) // relative include path contains '..'
5#endif
6
7#ifndef ZIP7_INC_COMMON0_H
8#define ZIP7_INC_COMMON0_H
9
10#include "../../C/Compiler.h"
11
12/*
13This file contains compiler related things for cpp files.
14This file is included to all cpp files in 7-Zip via "Common.h".
15Also this file is included in "IDecl.h" (that is included in interface files).
16So external modules can use 7-Zip interfaces without
17predefined macros defined in "Common.h".
18*/
19
20#ifdef _MSC_VER
21 #pragma warning(disable : 4710) // function not inlined
22 // 'CUncopyable::CUncopyable':
23 #pragma warning(disable : 4514) // unreferenced inline function has been removed
24 #if _MSC_VER < 1300
25 #pragma warning(disable : 4702) // unreachable code
26 #pragma warning(disable : 4714) // function marked as __forceinline not inlined
27 #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
28 #endif
29 #if _MSC_VER < 1400
30 #pragma warning(disable : 4511) // copy constructor could not be generated // #pragma warning(disable : 4512) // assignment operator could not be generated
31 #pragma warning(disable : 4512) // assignment operator could not be generated
32 #endif
33 #if _MSC_VER > 1400 && _MSC_VER <= 1900
34 // #pragma warning(disable : 4996)
35 // strcat: This function or variable may be unsafe
36 // GetVersion was declared deprecated
37 #endif
38
39#if _MSC_VER > 1200
40// -Wall warnings
41
42#if _MSC_VER <= 1600
43#pragma warning(disable : 4917) // 'OLE_HANDLE' : a GUID can only be associated with a class, interface or namespace
44#endif
45
46// #pragma warning(disable : 4061) // enumerator '' in switch of enum '' is not explicitly handled by a case label
47// #pragma warning(disable : 4266) // no override available for virtual member function from base ''; function is hidden
48#pragma warning(disable : 4625) // copy constructor was implicitly defined as deleted
49#pragma warning(disable : 4626) // assignment operator was implicitly defined as deleted
50#if _MSC_VER >= 1600 && _MSC_VER < 1920
51#pragma warning(disable : 4571) // Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught
52#endif
53#if _MSC_VER >= 1600
54#pragma warning(disable : 4365) // 'initializing' : conversion from 'int' to 'unsigned int', signed / unsigned mismatch
55#endif
56#if _MSC_VER < 1800
57// we disable the warning, if we don't use 'final' in class
58#pragma warning(disable : 4265) // class has virtual functions, but destructor is not virtual
59#endif
60
61#if _MSC_VER >= 1900
62#pragma warning(disable : 5026) // move constructor was implicitly defined as deleted
63#pragma warning(disable : 5027) // move assignment operator was implicitly defined as deleted
64#endif
65#if _MSC_VER >= 1912
66#pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to 'extern "C"' function under - EHc.Undefined behavior may occur if this function throws an exception.
67#endif
68#if _MSC_VER >= 1925
69// #pragma warning(disable : 5204) // 'ISequentialInStream' : class has virtual functions, but its trivial destructor is not virtual; instances of objects derived from this class may not be destructed correctly
70#endif
71#if _MSC_VER >= 1934
72// #pragma warning(disable : 5264) // const variable is not used
73#endif
74
75#endif // _MSC_VER > 1200
76#endif // _MSC_VER
77
78
79#if defined(_MSC_VER) // && !defined(__clang__)
80#define Z7_DECLSPEC_NOTHROW __declspec(nothrow)
81#elif defined(__clang__) || defined(__GNUC__)
82#define Z7_DECLSPEC_NOTHROW __attribute__((nothrow))
83#else
84#define Z7_DECLSPEC_NOTHROW
85#endif
86
87/*
88#if defined (_MSC_VER) && _MSC_VER >= 1900 \
89 || defined(__clang__) && __clang_major__ >= 6 \
90 || defined(__GNUC__) && __GNUC__ >= 6
91 #define Z7_noexcept noexcept
92#else
93 #define Z7_noexcept throw()
94#endif
95*/
96
97
98#if defined(__clang__)
99
100#if /* defined(_WIN32) && */ __clang_major__ >= 16
101#pragma GCC diagnostic ignored "-Wc++98-compat-pedantic"
102#endif
103
104#if __clang_major__ >= 4 && __clang_major__ < 12 && !defined(_WIN32)
105/*
106if compiled with new GCC libstdc++, GCC libstdc++ can use:
10713.2.0/include/c++/
108 <new> : #define _NEW
109 <stdlib.h> : #define _GLIBCXX_STDLIB_H 1
110*/
111#pragma GCC diagnostic ignored "-Wreserved-id-macro"
112#endif
113
114// noexcept, final, = delete
115#pragma GCC diagnostic ignored "-Wc++98-compat"
116#if __clang_major__ >= 4
117// throw() dynamic exception specifications are deprecated
118#pragma GCC diagnostic ignored "-Wdeprecated-dynamic-exception-spec"
119#endif
120
121#if __clang_major__ <= 6 // check it
122#pragma GCC diagnostic ignored "-Wsign-conversion"
123#endif
124
125#pragma GCC diagnostic ignored "-Wold-style-cast"
126#pragma GCC diagnostic ignored "-Wglobal-constructors"
127#pragma GCC diagnostic ignored "-Wexit-time-destructors"
128
129#if defined(Z7_LLVM_CLANG_VERSION) && __clang_major__ >= 18 // 18.1.0RC
130#pragma GCC diagnostic ignored "-Wswitch-default"
131#endif
132// #pragma GCC diagnostic ignored "-Wunused-private-field"
133// #pragma GCC diagnostic ignored "-Wnonportable-system-include-path"
134// #pragma GCC diagnostic ignored "-Wsuggest-override"
135// #pragma GCC diagnostic ignored "-Wsign-conversion"
136// #pragma GCC diagnostic ignored "-Winconsistent-missing-override"
137// #pragma GCC diagnostic ignored "-Wsuggest-destructor-override"
138// #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
139// #pragma GCC diagnostic ignored "-Wdeprecated-copy-with-user-provided-dtor"
140// #pragma GCC diagnostic ignored "-Wdeprecated-copy-dtor"
141// #ifndef _WIN32
142// #pragma GCC diagnostic ignored "-Wweak-vtables"
143// #endif
144/*
145#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400) \
146 || defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30000)
147// enumeration values not explicitly handled in switch
148#pragma GCC diagnostic ignored "-Wswitch-enum"
149#endif
150*/
151#endif // __clang__
152
153
154#ifdef __GNUC__
155// #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
156#endif
157
158
159/* There is BUG in MSVC 6.0 compiler for operator new[]:
160 It doesn't check overflow, when it calculates size in bytes for allocated array.
161 So we can use Z7_ARRAY_NEW macro instead of new[] operator. */
162
163#if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64)
164 #define Z7_ARRAY_NEW(p, T, size) p = new T[((size) > 0xFFFFFFFFu / sizeof(T)) ? 0xFFFFFFFFu / sizeof(T) : (size)];
165#else
166 #define Z7_ARRAY_NEW(p, T, size) p = new T[size];
167#endif
168
169#if (defined(__GNUC__) && (__GNUC__ >= 8))
170 #define Z7_ATTR_NORETURN __attribute__((noreturn))
171#elif (defined(__clang__) && (__clang_major__ >= 3))
172 #if __has_feature(cxx_attributes)
173 #define Z7_ATTR_NORETURN [[noreturn]]
174 #else
175 #define Z7_ATTR_NORETURN __attribute__((noreturn))
176 #endif
177#elif (defined(_MSC_VER) && (_MSC_VER >= 1900))
178 #define Z7_ATTR_NORETURN [[noreturn]]
179#else
180 #define Z7_ATTR_NORETURN
181#endif
182
183
184// final in "GCC 4.7.0"
185// In C++98 and C++03 code the alternative spelling __final can be used instead (this is a GCC extension.)
186
187#if defined (__cplusplus) && __cplusplus >= 201103L \
188 || defined(_MSC_VER) && _MSC_VER >= 1800 \
189 || defined(__clang__) && __clang_major__ >= 4 \
190 /* || defined(__GNUC__) && __GNUC__ >= 9 */
191 #define Z7_final final
192 #if defined(__clang__) && __cplusplus < 201103L
193 #pragma GCC diagnostic ignored "-Wc++11-extensions"
194 #endif
195#elif defined (__cplusplus) && __cplusplus >= 199711L \
196 && defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__)
197 #define Z7_final __final
198#else
199 #define Z7_final
200 #if defined(__clang__) && __clang_major__ >= 4 \
201 || defined(__GNUC__) && __GNUC__ >= 4
202 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
203 #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
204 #endif
205#endif
206
207#define Z7_class_final(c) class c Z7_final
208
209
210#if defined (__cplusplus) && __cplusplus >= 201103L \
211 || (defined(_MSC_VER) && _MSC_VER >= 1800)
212 #define Z7_CPP_IS_SUPPORTED_default
213 #define Z7_eq_delete = delete
214 // #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c) c(const c& k) = default;
215#else
216 #define Z7_eq_delete
217 // #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c)
218#endif
219
220
221#if defined(__cplusplus) && (__cplusplus >= 201103L) \
222 || defined(_MSC_VER) && (_MSC_VER >= 1400) /* && (_MSC_VER != 1600) */ \
223 || defined(__clang__) && __clang_major__ >= 4
224 #if defined(_MSC_VER) && (_MSC_VER == 1600) /* && (_MSC_VER != 1600) */
225 #pragma warning(disable : 4481) // nonstandard extension used: override specifier 'override'
226 #define Z7_DESTRUCTOR_override
227 #else
228 #define Z7_DESTRUCTOR_override override
229 #endif
230 #define Z7_override override
231#else
232 #define Z7_override
233 #define Z7_DESTRUCTOR_override
234#endif
235
236
237
238#define Z7_CLASS_NO_COPY(cls) \
239 private: \
240 cls(const cls &) Z7_eq_delete; \
241 cls &operator=(const cls &) Z7_eq_delete;
242
243class CUncopyable
244{
245protected:
246 CUncopyable() {} // allow constructor
247 // ~CUncopyable() {}
248 Z7_CLASS_NO_COPY(CUncopyable)
249};
250
251#define MY_UNCOPYABLE :private CUncopyable
252// #define MY_UNCOPYABLE
253
254
255// typedef void (*Z7_void_Function)(void);
256
257#if defined(__clang__) || defined(__GNUC__)
258#define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(reinterpret_cast<Z7_void_Function>(e))
259#else
260#define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(reinterpret_cast<void*>(e))
261// #define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(e)
262#endif
263
264#define Z7_GET_PROC_ADDRESS(func_type, hmodule, func_name) \
265 Z7_CAST_FUNC(func_type, GetProcAddress(hmodule, func_name))
266
267// || defined(__clang__)
268// || defined(__GNUC__)
269
270#if defined(_MSC_VER) && (_MSC_VER >= 1400)
271#define Z7_DECLSPEC_NOVTABLE __declspec(novtable)
272#else
273#define Z7_DECLSPEC_NOVTABLE
274#endif
275
276#ifdef __clang__
277#define Z7_PURE_INTERFACES_BEGIN \
278_Pragma("GCC diagnostic push") \
279_Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"")
280_Pragma("GCC diagnostic ignored \"-Wweak-vtables\"")
281#define Z7_PURE_INTERFACES_END \
282_Pragma("GCC diagnostic pop")
283#else
284#define Z7_PURE_INTERFACES_BEGIN
285#define Z7_PURE_INTERFACES_END
286#endif
287
288// NewHandler.h and NewHandler.cpp redefine operator new() to throw exceptions, if compiled with old MSVC compilers
289#include "NewHandler.h"
290
291/*
292// #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
293#ifndef ARRAY_SIZE
294#define ARRAY_SIZE(a) Z7_ARRAY_SIZE(a)
295#endif
296*/
297
298#endif // ZIP7_INC_COMMON0_H
299
300
301
302// #define Z7_REDEFINE_NULL
303
304#if defined(Z7_REDEFINE_NULL) /* && (!defined(__clang__) || defined(_MSC_VER)) */
305
306// NULL is defined in <stddef.h>
307#include <stddef.h>
308#undef NULL
309
310#ifdef __cplusplus
311 #if defined (__cplusplus) && __cplusplus >= 201103L \
312 || (defined(_MSC_VER) && _MSC_VER >= 1800)
313 #define NULL nullptr
314 #else
315 #define NULL 0
316 #endif
317#else
318 #define NULL ((void *)0)
319#endif
320
321#else // Z7_REDEFINE_NULL
322
323#if defined(__clang__) && __clang_major__ >= 5
324#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
325#endif
326
327#endif // Z7_REDEFINE_NULL
328
329// for precompiler:
330// #include "MyWindows.h"
diff --git a/CPP/Common/CrcReg.cpp b/CPP/Common/CrcReg.cpp
index 6cda892..cd5d3da 100644
--- a/CPP/Common/CrcReg.cpp
+++ b/CPP/Common/CrcReg.cpp
@@ -11,14 +11,6 @@
11 11
12EXTERN_C_BEGIN 12EXTERN_C_BEGIN
13 13
14// UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table);
15
16extern CRC_FUNC g_CrcUpdate;
17// extern CRC_FUNC g_CrcUpdateT4;
18extern CRC_FUNC g_CrcUpdateT8;
19extern CRC_FUNC g_CrcUpdateT0_32;
20extern CRC_FUNC g_CrcUpdateT0_64;
21
22EXTERN_C_END 14EXTERN_C_END
23 15
24Z7_CLASS_IMP_COM_2( 16Z7_CLASS_IMP_COM_2(
@@ -27,7 +19,7 @@ Z7_CLASS_IMP_COM_2(
27 , ICompressSetCoderProperties 19 , ICompressSetCoderProperties
28) 20)
29 UInt32 _crc; 21 UInt32 _crc;
30 CRC_FUNC _updateFunc; 22 Z7_CRC_UPDATE_FUNC _updateFunc;
31 23
32 Z7_CLASS_NO_COPY(CCrcHasher) 24 Z7_CLASS_NO_COPY(CCrcHasher)
33 25
@@ -40,17 +32,10 @@ public:
40 32
41bool CCrcHasher::SetFunctions(UInt32 tSize) 33bool CCrcHasher::SetFunctions(UInt32 tSize)
42{ 34{
43 CRC_FUNC f = NULL; 35 const Z7_CRC_UPDATE_FUNC f = z7_GetFunc_CrcUpdate(tSize);
44 if (tSize == 0) f = g_CrcUpdate;
45 // else if (tSize == 1) f = CrcUpdateT1;
46 // else if (tSize == 4) f = g_CrcUpdateT4;
47 else if (tSize == 8) f = g_CrcUpdateT8;
48 else if (tSize == 32) f = g_CrcUpdateT0_32;
49 else if (tSize == 64) f = g_CrcUpdateT0_64;
50
51 if (!f) 36 if (!f)
52 { 37 {
53 _updateFunc = g_CrcUpdate; 38 _updateFunc = CrcUpdate;
54 return false; 39 return false;
55 } 40 }
56 _updateFunc = f; 41 _updateFunc = f;
@@ -80,7 +65,7 @@ Z7_COM7F_IMF2(void, CCrcHasher::Init())
80 65
81Z7_COM7F_IMF2(void, CCrcHasher::Update(const void *data, UInt32 size)) 66Z7_COM7F_IMF2(void, CCrcHasher::Update(const void *data, UInt32 size))
82{ 67{
83 _crc = _updateFunc(_crc, data, size, g_CrcTable); 68 _crc = _updateFunc(_crc, data, size);
84} 69}
85 70
86Z7_COM7F_IMF2(void, CCrcHasher::Final(Byte *digest)) 71Z7_COM7F_IMF2(void, CCrcHasher::Final(Byte *digest))
diff --git a/CPP/Common/DynamicBuffer.h b/CPP/Common/DynamicBuffer.h
index 714be4a..b03d371 100644
--- a/CPP/Common/DynamicBuffer.h
+++ b/CPP/Common/DynamicBuffer.h
@@ -5,7 +5,7 @@
5 5
6#include <string.h> 6#include <string.h>
7 7
8#include "Common.h" 8#include "MyTypes.h"
9 9
10template <class T> class CDynamicBuffer 10template <class T> class CDynamicBuffer
11{ 11{
@@ -43,6 +43,14 @@ public:
43 operator const T *() const { return _items; } 43 operator const T *() const { return _items; }
44 ~CDynamicBuffer() { delete []_items; } 44 ~CDynamicBuffer() { delete []_items; }
45 45
46 void Free()
47 {
48 delete []_items;
49 _items = NULL;
50 _size = 0;
51 _pos = 0;
52 }
53
46 T *GetCurPtrAndGrow(size_t addSize) 54 T *GetCurPtrAndGrow(size_t addSize)
47 { 55 {
48 size_t rem = _size - _pos; 56 size_t rem = _size - _pos;
@@ -63,6 +71,6 @@ public:
63 // void Empty() { _pos = 0; } 71 // void Empty() { _pos = 0; }
64}; 72};
65 73
66typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer; 74typedef CDynamicBuffer<Byte> CByteDynamicBuffer;
67 75
68#endif 76#endif
diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp
index 21b0680..0a7cb3b 100644
--- a/CPP/Common/IntToString.cpp
+++ b/CPP/Common/IntToString.cpp
@@ -7,10 +7,19 @@
7#include "IntToString.h" 7#include "IntToString.h"
8 8
9#define CONVERT_INT_TO_STR(charType, tempSize) \ 9#define CONVERT_INT_TO_STR(charType, tempSize) \
10 unsigned char temp[tempSize]; unsigned i = 0; \ 10 if (val < 10) \
11 while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \ 11 *s++ = (charType)('0' + (unsigned)val); \
12 *s++ = (charType)('0' + (unsigned)val); \ 12 else { \
13 while (i != 0) { i--; *s++ = (charType)temp[i]; } \ 13 Byte temp[tempSize]; \
14 size_t i = 0; \
15 do { \
16 temp[++i] = (Byte)('0' + (unsigned)(val % 10)); \
17 val /= 10; } \
18 while (val >= 10); \
19 *s++ = (charType)('0' + (unsigned)val); \
20 do { *s++ = (charType)temp[i]; } \
21 while (--i); \
22 } \
14 *s = 0; \ 23 *s = 0; \
15 return s; 24 return s;
16 25
@@ -22,88 +31,109 @@ char * ConvertUInt32ToString(UInt32 val, char *s) throw()
22char * ConvertUInt64ToString(UInt64 val, char *s) throw() 31char * ConvertUInt64ToString(UInt64 val, char *s) throw()
23{ 32{
24 if (val <= (UInt32)0xFFFFFFFF) 33 if (val <= (UInt32)0xFFFFFFFF)
25 {
26 return ConvertUInt32ToString((UInt32)val, s); 34 return ConvertUInt32ToString((UInt32)val, s);
27 }
28 CONVERT_INT_TO_STR(char, 24) 35 CONVERT_INT_TO_STR(char, 24)
29} 36}
30 37
31void ConvertUInt64ToOct(UInt64 val, char *s) throw() 38wchar_t * ConvertUInt32ToString(UInt32 val, wchar_t *s) throw()
32{ 39{
33 UInt64 v = val; 40 CONVERT_INT_TO_STR(wchar_t, 16)
34 unsigned i; 41}
35 for (i = 1;; i++) 42
43wchar_t * ConvertUInt64ToString(UInt64 val, wchar_t *s) throw()
44{
45 if (val <= (UInt32)0xFFFFFFFF)
46 return ConvertUInt32ToString((UInt32)val, s);
47 CONVERT_INT_TO_STR(wchar_t, 24)
48}
49
50void ConvertInt64ToString(Int64 val, char *s) throw()
51{
52 if (val < 0)
36 { 53 {
37 v >>= 3; 54 *s++ = '-';
38 if (v == 0) 55 val = -val;
39 break;
40 } 56 }
41 s[i] = 0; 57 ConvertUInt64ToString((UInt64)val, s);
42 do 58}
59
60void ConvertInt64ToString(Int64 val, wchar_t *s) throw()
61{
62 if (val < 0)
43 { 63 {
44 unsigned t = (unsigned)(val & 0x7); 64 *s++ = L'-';
45 val >>= 3; 65 val = -val;
46 s[--i] = (char)('0' + t);
47 } 66 }
48 while (i); 67 ConvertUInt64ToString((UInt64)val, s);
49} 68}
50 69
51 70
52#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) 71void ConvertUInt64ToOct(UInt64 val, char *s) throw()
53 72{
54static inline char GetHexChar(unsigned t) { return GET_HEX_CHAR(t); } 73 {
74 UInt64 v = val;
75 do
76 s++;
77 while (v >>= 3);
78 }
79 *s = 0;
80 do
81 {
82 const unsigned t = (unsigned)val & 7;
83 *--s = (char)('0' + t);
84 }
85 while (val >>= 3);
86}
55 87
88MY_ALIGN(16) const char k_Hex_Upper[16] =
89 { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
90MY_ALIGN(16) const char k_Hex_Lower[16] =
91 { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
56 92
57void ConvertUInt32ToHex(UInt32 val, char *s) throw() 93void ConvertUInt32ToHex(UInt32 val, char *s) throw()
58{ 94{
59 UInt32 v = val;
60 unsigned i;
61 for (i = 1;; i++)
62 { 95 {
63 v >>= 4; 96 UInt32 v = val;
64 if (v == 0) 97 do
65 break; 98 s++;
99 while (v >>= 4);
66 } 100 }
67 s[i] = 0; 101 *s = 0;
68 do 102 do
69 { 103 {
70 unsigned t = (unsigned)(val & 0xF); 104 const unsigned t = (unsigned)val & 0xF;
71 val >>= 4; 105 *--s = GET_HEX_CHAR_UPPER(t);
72 s[--i] = GET_HEX_CHAR(t);
73 } 106 }
74 while (i); 107 while (val >>= 4);
75} 108}
76 109
77
78void ConvertUInt64ToHex(UInt64 val, char *s) throw() 110void ConvertUInt64ToHex(UInt64 val, char *s) throw()
79{ 111{
80 UInt64 v = val;
81 unsigned i;
82 for (i = 1;; i++)
83 { 112 {
84 v >>= 4; 113 UInt64 v = val;
85 if (v == 0) 114 do
86 break; 115 s++;
116 while (v >>= 4);
87 } 117 }
88 s[i] = 0; 118 *s = 0;
89 do 119 do
90 { 120 {
91 unsigned t = (unsigned)(val & 0xF); 121 const unsigned t = (unsigned)val & 0xF;
92 val >>= 4; 122 *--s = GET_HEX_CHAR_UPPER(t);
93 s[--i] = GET_HEX_CHAR(t);
94 } 123 }
95 while (i); 124 while (val >>= 4);
96} 125}
97 126
98void ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw() 127void ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw()
99{ 128{
100 s[8] = 0; 129 s[8] = 0;
101 for (int i = 7; i >= 0; i--) 130 int i = 7;
131 do
102 { 132 {
103 unsigned t = val & 0xF; 133 { const unsigned t = (unsigned)val & 0xF; s[i--] = GET_HEX_CHAR_UPPER(t); }
104 val >>= 4; 134 { const unsigned t = (Byte)val >> 4; val >>= 8; s[i--] = GET_HEX_CHAR_UPPER(t); }
105 s[i] = GET_HEX_CHAR(t);
106 } 135 }
136 while (i >= 0);
107} 137}
108 138
109/* 139/*
@@ -112,81 +142,74 @@ void ConvertUInt32ToHex8Digits(UInt32 val, wchar_t *s)
112 s[8] = 0; 142 s[8] = 0;
113 for (int i = 7; i >= 0; i--) 143 for (int i = 7; i >= 0; i--)
114 { 144 {
115 unsigned t = val & 0xF; 145 const unsigned t = (unsigned)val & 0xF;
116 val >>= 4; 146 val >>= 4;
117 s[i] = (wchar_t)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); 147 s[i] = GET_HEX_CHAR(t);
118 } 148 }
119} 149}
120*/ 150*/
121 151
122wchar_t * ConvertUInt32ToString(UInt32 val, wchar_t *s) throw()
123{
124 CONVERT_INT_TO_STR(wchar_t, 16)
125}
126
127wchar_t * ConvertUInt64ToString(UInt64 val, wchar_t *s) throw()
128{
129 if (val <= (UInt32)0xFFFFFFFF)
130 {
131 return ConvertUInt32ToString((UInt32)val, s);
132 }
133 CONVERT_INT_TO_STR(wchar_t, 24)
134}
135 152
136void ConvertInt64ToString(Int64 val, char *s) throw() 153MY_ALIGN(16) static const Byte k_Guid_Pos[] =
137{ 154 { 6,4,2,0, 11,9, 16,14, 19,21, 24,26,28,30,32,34 };
138 if (val < 0)
139 {
140 *s++ = '-';
141 val = -val;
142 }
143 ConvertUInt64ToString((UInt64)val, s);
144}
145 155
146void ConvertInt64ToString(Int64 val, wchar_t *s) throw() 156char *RawLeGuidToString(const Byte *g, char *s) throw()
147{ 157{
148 if (val < 0) 158 s[ 8] = '-';
159 s[13] = '-';
160 s[18] = '-';
161 s[23] = '-';
162 s[36] = 0;
163 for (unsigned i = 0; i < 16; i++)
149 { 164 {
150 *s++ = L'-'; 165 char *s2 = s + k_Guid_Pos[i];
151 val = -val; 166 const unsigned v = g[i];
167 s2[0] = GET_HEX_CHAR_UPPER(v >> 4);
168 s2[1] = GET_HEX_CHAR_UPPER(v & 0xF);
152 } 169 }
153 ConvertUInt64ToString((UInt64)val, s); 170 return s + 36;
154} 171}
155 172
156 173char *RawLeGuidToString_Braced(const Byte *g, char *s) throw()
157static void ConvertByteToHex2Digits(unsigned v, char *s) throw()
158{ 174{
159 s[0] = GetHexChar(v >> 4); 175 *s++ = '{';
160 s[1] = GetHexChar(v & 0xF); 176 s = RawLeGuidToString(g, s);
177 *s++ = '}';
178 *s = 0;
179 return s;
161} 180}
162 181
163static void ConvertUInt16ToHex4Digits(UInt32 val, char *s) throw()
164{
165 ConvertByteToHex2Digits(val >> 8, s);
166 ConvertByteToHex2Digits(val & 0xFF, s + 2);
167}
168 182
169char *RawLeGuidToString(const Byte *g, char *s) throw() 183void ConvertDataToHex_Lower(char *dest, const Byte *src, size_t size) throw()
170{ 184{
171 ConvertUInt32ToHex8Digits(GetUi32(g ), s); s += 8; *s++ = '-'; 185 if (size)
172 ConvertUInt16ToHex4Digits(GetUi16(g + 4), s); s += 4; *s++ = '-';
173 ConvertUInt16ToHex4Digits(GetUi16(g + 6), s); s += 4; *s++ = '-';
174 for (unsigned i = 0; i < 8; i++)
175 { 186 {
176 if (i == 2) 187 const Byte *lim = src + size;
177 *s++ = '-'; 188 do
178 ConvertByteToHex2Digits(g[8 + i], s); 189 {
179 s += 2; 190 const unsigned b = *src++;
191 dest[0] = GET_HEX_CHAR_LOWER(b >> 4);
192 dest[1] = GET_HEX_CHAR_LOWER(b & 0xF);
193 dest += 2;
194 }
195 while (src != lim);
180 } 196 }
181 *s = 0; 197 *dest = 0;
182 return s;
183} 198}
184 199
185char *RawLeGuidToString_Braced(const Byte *g, char *s) throw() 200void ConvertDataToHex_Upper(char *dest, const Byte *src, size_t size) throw()
186{ 201{
187 *s++ = '{'; 202 if (size)
188 s = RawLeGuidToString(g, s); 203 {
189 *s++ = '}'; 204 const Byte *lim = src + size;
190 *s = 0; 205 do
191 return s; 206 {
207 const unsigned b = *src++;
208 dest[0] = GET_HEX_CHAR_UPPER(b >> 4);
209 dest[1] = GET_HEX_CHAR_UPPER(b & 0xF);
210 dest += 2;
211 }
212 while (src != lim);
213 }
214 *dest = 0;
192} 215}
diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h
index f4fc662..2f096d6 100644
--- a/CPP/Common/IntToString.h
+++ b/CPP/Common/IntToString.h
@@ -12,19 +12,43 @@ char * ConvertUInt64ToString(UInt64 value, char *s) throw();
12 12
13wchar_t * ConvertUInt32ToString(UInt32 value, wchar_t *s) throw(); 13wchar_t * ConvertUInt32ToString(UInt32 value, wchar_t *s) throw();
14wchar_t * ConvertUInt64ToString(UInt64 value, wchar_t *s) throw(); 14wchar_t * ConvertUInt64ToString(UInt64 value, wchar_t *s) throw();
15void ConvertInt64ToString(Int64 value, char *s) throw();
16void ConvertInt64ToString(Int64 value, wchar_t *s) throw();
15 17
16void ConvertUInt64ToOct(UInt64 value, char *s) throw(); 18void ConvertUInt64ToOct(UInt64 value, char *s) throw();
17 19
20extern const char k_Hex_Upper[16];
21extern const char k_Hex_Lower[16];
22
23#define GET_HEX_CHAR_UPPER(t) (k_Hex_Upper[t])
24#define GET_HEX_CHAR_LOWER(t) (k_Hex_Lower[t])
25/*
26// #define GET_HEX_CHAR_UPPER(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
27static inline unsigned GetHex_Lower(unsigned v)
28{
29 const unsigned v0 = v + '0';
30 v += 'a' - 10;
31 if (v < 'a')
32 v = v0;
33 return v;
34}
35static inline char GetHex_Upper(unsigned v)
36{
37 return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10)));
38}
39*/
40
41
18void ConvertUInt32ToHex(UInt32 value, char *s) throw(); 42void ConvertUInt32ToHex(UInt32 value, char *s) throw();
19void ConvertUInt64ToHex(UInt64 value, char *s) throw(); 43void ConvertUInt64ToHex(UInt64 value, char *s) throw();
20void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw(); 44void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw();
21// void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw(); 45// void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw();
22 46
23void ConvertInt64ToString(Int64 value, char *s) throw();
24void ConvertInt64ToString(Int64 value, wchar_t *s) throw();
25
26// use RawLeGuid only for RAW bytes that contain stored GUID as Little-endian. 47// use RawLeGuid only for RAW bytes that contain stored GUID as Little-endian.
27char *RawLeGuidToString(const Byte *guid, char *s) throw(); 48char *RawLeGuidToString(const Byte *guid, char *s) throw();
28char *RawLeGuidToString_Braced(const Byte *guid, char *s) throw(); 49char *RawLeGuidToString_Braced(const Byte *guid, char *s) throw();
29 50
51void ConvertDataToHex_Lower(char *dest, const Byte *src, size_t size) throw();
52void ConvertDataToHex_Upper(char *dest, const Byte *src, size_t size) throw();
53
30#endif 54#endif
diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp
index e43dbc9..714b275 100644
--- a/CPP/Common/ListFileUtils.cpp
+++ b/CPP/Common/ListFileUtils.cpp
@@ -76,26 +76,26 @@ bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePag
76 return false; 76 return false;
77 77
78 file.Close(); 78 file.Close();
79 const unsigned num = (unsigned)fileSize / 2; 79 const size_t num = (size_t)fileSize / 2;
80 wchar_t *p = u.GetBuf(num); 80 wchar_t *p = u.GetBuf((unsigned)num);
81 if (codePage == Z7_WIN_CP_UTF16) 81 if (codePage == Z7_WIN_CP_UTF16)
82 for (unsigned i = 0; i < num; i++) 82 for (size_t i = 0; i < num; i++)
83 { 83 {
84 wchar_t c = GetUi16(buf + (size_t)i * 2); 84 const wchar_t c = GetUi16(buf.ConstData() + (size_t)i * 2);
85 if (c == 0) 85 if (c == 0)
86 return false; 86 return false;
87 p[i] = c; 87 p[i] = c;
88 } 88 }
89 else 89 else
90 for (unsigned i = 0; i < num; i++) 90 for (size_t i = 0; i < num; i++)
91 { 91 {
92 wchar_t c = (wchar_t)GetBe16(buf + (size_t)i * 2); 92 const wchar_t c = (wchar_t)GetBe16(buf.ConstData() + (size_t)i * 2);
93 if (c == 0) 93 if (c == 0)
94 return false; 94 return false;
95 p[i] = c; 95 p[i] = c;
96 } 96 }
97 p[num] = 0; 97 p[num] = 0;
98 u.ReleaseBuf_SetLen(num); 98 u.ReleaseBuf_SetLen((unsigned)num);
99 } 99 }
100 else 100 else
101 { 101 {
diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h
index bc829f4..80f0205 100644
--- a/CPP/Common/MyBuffer.h
+++ b/CPP/Common/MyBuffer.h
@@ -51,6 +51,12 @@ public:
51 51
52 operator T *() { return _items; } 52 operator T *() { return _items; }
53 operator const T *() const { return _items; } 53 operator const T *() const { return _items; }
54 const T* ConstData() const { return _items; }
55 T* NonConstData() const { return _items; }
56 T* NonConstData() { return _items; }
57 // const T* Data() const { return _items; }
58 // T* Data() { return _items; }
59
54 size_t Size() const { return _size; } 60 size_t Size() const { return _size; }
55 61
56 void Alloc(size_t size) 62 void Alloc(size_t size)
@@ -140,15 +146,15 @@ bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)
140 146
141// typedef CBuffer<char> CCharBuffer; 147// typedef CBuffer<char> CCharBuffer;
142// typedef CBuffer<wchar_t> CWCharBuffer; 148// typedef CBuffer<wchar_t> CWCharBuffer;
143typedef CBuffer<unsigned char> CByteBuffer; 149typedef CBuffer<Byte> CByteBuffer;
144 150
145 151
146class CByteBuffer_Wipe: public CByteBuffer 152class CByteBuffer_Wipe: public CByteBuffer
147{ 153{
148 Z7_CLASS_NO_COPY(CByteBuffer_Wipe) 154 Z7_CLASS_NO_COPY(CByteBuffer_Wipe)
149public: 155public:
150 // CByteBuffer_Wipe(): CBuffer<unsigned char>() {} 156 // CByteBuffer_Wipe(): CBuffer<Byte>() {}
151 CByteBuffer_Wipe(size_t size): CBuffer<unsigned char>(size) {} 157 CByteBuffer_Wipe(size_t size): CBuffer<Byte>(size) {}
152 ~CByteBuffer_Wipe() { Wipe(); } 158 ~CByteBuffer_Wipe() { Wipe(); }
153}; 159};
154 160
@@ -181,6 +187,11 @@ public:
181 187
182 operator T *() { return _items; } 188 operator T *() { return _items; }
183 operator const T *() const { return _items; } 189 operator const T *() const { return _items; }
190 const T* ConstData() const { return _items; }
191 T* NonConstData() const { return _items; }
192 T* NonConstData() { return _items; }
193 // const T* Data() const { return _items; }
194 // T* Data() { return _items; }
184 195
185 void Alloc(size_t newSize) 196 void Alloc(size_t newSize)
186 { 197 {
@@ -191,7 +202,7 @@ public:
191 } 202 }
192}; 203};
193 204
194typedef CObjArray<unsigned char> CByteArr; 205typedef CObjArray<Byte> CByteArr;
195typedef CObjArray<bool> CBoolArr; 206typedef CObjArray<bool> CBoolArr;
196typedef CObjArray<int> CIntArr; 207typedef CObjArray<int> CIntArr;
197typedef CObjArray<unsigned> CUIntArr; 208typedef CObjArray<unsigned> CUIntArr;
diff --git a/CPP/Common/MyBuffer2.h b/CPP/Common/MyBuffer2.h
index 23394f8..1ec8ffb 100644
--- a/CPP/Common/MyBuffer2.h
+++ b/CPP/Common/MyBuffer2.h
@@ -65,13 +65,13 @@ class CAlignedBuffer1
65public: 65public:
66 ~CAlignedBuffer1() 66 ~CAlignedBuffer1()
67 { 67 {
68 ISzAlloc_Free(&g_AlignedAlloc, _data); 68 z7_AlignedFree(_data);
69 } 69 }
70 70
71 CAlignedBuffer1(size_t size) 71 CAlignedBuffer1(size_t size)
72 { 72 {
73 _data = NULL; 73 _data = NULL;
74 _data = (Byte *)ISzAlloc_Alloc(&g_AlignedAlloc, size); 74 _data = (Byte *)z7_AlignedAlloc(size);
75 if (!_data) 75 if (!_data)
76 throw 1; 76 throw 1;
77 } 77 }
@@ -92,21 +92,23 @@ public:
92 CAlignedBuffer(): _data(NULL), _size(0) {} 92 CAlignedBuffer(): _data(NULL), _size(0) {}
93 ~CAlignedBuffer() 93 ~CAlignedBuffer()
94 { 94 {
95 ISzAlloc_Free(&g_AlignedAlloc, _data); 95 z7_AlignedFree(_data);
96 } 96 }
97 97
98 /*
98 CAlignedBuffer(size_t size): _size(0) 99 CAlignedBuffer(size_t size): _size(0)
99 { 100 {
100 _data = NULL; 101 _data = NULL;
101 _data = (Byte *)ISzAlloc_Alloc(&g_AlignedAlloc, size); 102 _data = (Byte *)z7_AlignedAlloc(size);
102 if (!_data) 103 if (!_data)
103 throw 1; 104 throw 1;
104 _size = size; 105 _size = size;
105 } 106 }
107 */
106 108
107 void Free() 109 void Free()
108 { 110 {
109 ISzAlloc_Free(&g_AlignedAlloc, _data); 111 z7_AlignedFree(_data);
110 _data = NULL; 112 _data = NULL;
111 _size = 0; 113 _size = 0;
112 } 114 }
@@ -120,10 +122,10 @@ public:
120 { 122 {
121 if (!_data || size != _size) 123 if (!_data || size != _size)
122 { 124 {
123 ISzAlloc_Free(&g_AlignedAlloc, _data); 125 z7_AlignedFree(_data);
124 _size = 0; 126 _size = 0;
125 _data = NULL; 127 _data = NULL;
126 _data = (Byte *)ISzAlloc_Alloc(&g_AlignedAlloc, size); 128 _data = (Byte *)z7_AlignedAlloc(size);
127 if (_data) 129 if (_data)
128 _size = size; 130 _size = size;
129 } 131 }
@@ -133,10 +135,29 @@ public:
133 { 135 {
134 if (!_data || size > _size) 136 if (!_data || size > _size)
135 { 137 {
136 ISzAlloc_Free(&g_AlignedAlloc, _data); 138 z7_AlignedFree(_data);
137 _size = 0; 139 _size = 0;
138 _data = NULL; 140 _data = NULL;
139 _data = (Byte *)ISzAlloc_Alloc(&g_AlignedAlloc, size); 141 _data = (Byte *)z7_AlignedAlloc(size);
142 if (_data)
143 _size = size;
144 }
145 }
146
147 // (size <= size_max)
148 void AllocAtLeast_max(size_t size, size_t size_max)
149 {
150 if (!_data || size > _size)
151 {
152 z7_AlignedFree(_data);
153 _size = 0;
154 _data = NULL;
155 if (size_max < size) size_max = size; // optional check
156 const size_t delta = size / 2;
157 size += delta;
158 if (size < delta || size > size_max)
159 size = size_max;
160 _data = (Byte *)z7_AlignedAlloc(size);
140 if (_data) 161 if (_data)
141 _size = size; 162 _size = size;
142 } 163 }
diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h
index 65c4330..a3cc3c8 100644
--- a/CPP/Common/MyCom.h
+++ b/CPP/Common/MyCom.h
@@ -17,6 +17,7 @@ public:
17 ~CMyComPtr() { if (_p) _p->Release(); } 17 ~CMyComPtr() { if (_p) _p->Release(); }
18 void Release() { if (_p) { _p->Release(); _p = NULL; } } 18 void Release() { if (_p) { _p->Release(); _p = NULL; } }
19 operator T*() const { return (T*)_p; } 19 operator T*() const { return (T*)_p; }
20 T* Interface() const { return (T*)_p; }
20 // T& operator*() const { return *_p; } 21 // T& operator*() const { return *_p; }
21 T** operator&() { return &_p; } 22 T** operator&() { return &_p; }
22 T* operator->() const { return _p; } 23 T* operator->() const { return _p; }
@@ -68,6 +69,112 @@ public:
68 } 69 }
69}; 70};
70 71
72
73template <class iface, class cls>
74class CMyComPtr2
75{
76 cls* _p;
77
78 CMyComPtr2(const CMyComPtr2<iface, cls>& lp);
79 CMyComPtr2(cls* p);
80 CMyComPtr2(iface* p);
81 iface* operator=(const CMyComPtr2<iface, cls>& lp);
82 iface* operator=(cls* p);
83 iface* operator=(iface* p);
84public:
85 CMyComPtr2(): _p(NULL) {}
86 ~CMyComPtr2()
87 {
88 if (_p)
89 {
90 iface *ip = _p;
91 ip->Release();
92 }
93 }
94 // void Release() { if (_p) { (iface *)_p->Release(); _p = NULL; } }
95 cls* operator->() const { return _p; }
96 cls* ClsPtr() const { return _p; }
97 operator iface*() const
98 {
99 iface *ip = _p;
100 return ip;
101 }
102 iface* Interface() const
103 {
104 iface *ip = _p;
105 return ip;
106 }
107 // operator bool() const { return _p != NULL; }
108 bool IsDefined() const { return _p != NULL; }
109 void Create_if_Empty()
110 {
111 if (!_p)
112 {
113 _p = new cls;
114 iface *ip = _p;
115 ip->AddRef();
116 }
117 }
118 iface* Detach()
119 {
120 iface *ip = _p;
121 _p = NULL;
122 return ip;
123 }
124 void SetFromCls(cls *src)
125 {
126 if (src)
127 {
128 iface *ip = src;
129 ip->AddRef();
130 }
131 if (_p)
132 {
133 iface *ip = _p;
134 ip->Release();
135 }
136 _p = src;
137 }
138};
139
140
141template <class iface, class cls>
142class CMyComPtr2_Create
143{
144 cls* _p;
145
146 CMyComPtr2_Create(const CMyComPtr2_Create<iface, cls>& lp);
147 CMyComPtr2_Create(cls* p);
148 CMyComPtr2_Create(iface* p);
149 iface* operator=(const CMyComPtr2_Create<iface, cls>& lp);
150 iface* operator=(cls* p);
151 iface* operator=(iface* p);
152public:
153 CMyComPtr2_Create(): _p(new cls)
154 {
155 iface *ip = _p;
156 ip->AddRef();
157 }
158 ~CMyComPtr2_Create()
159 {
160 iface *ip = _p;
161 ip->Release();
162 }
163 cls* operator->() const { return _p; }
164 cls* ClsPtr() const { return _p; }
165 operator iface*() const
166 {
167 iface *ip = _p;
168 return ip;
169 }
170 iface* Interface() const
171 {
172 iface *ip = _p;
173 return ip;
174 }
175};
176
177
71#define Z7_DECL_CMyComPtr_QI_FROM(i, v, unk) \ 178#define Z7_DECL_CMyComPtr_QI_FROM(i, v, unk) \
72 CMyComPtr<i> v; (unk)->QueryInterface(IID_ ## i, (void **)&v); 179 CMyComPtr<i> v; (unk)->QueryInterface(IID_ ## i, (void **)&v);
73 180
@@ -234,16 +341,56 @@ protected:
234 Z7_COM_QI_ENTRY_UNKNOWN(i) \ 341 Z7_COM_QI_ENTRY_UNKNOWN(i) \
235 Z7_COM_QI_ENTRY(i) 342 Z7_COM_QI_ENTRY(i)
236 343
237#define Z7_COM_QI_END \ 344
345#define Z7_COM_ADDREF_RELEASE_MT \
346 private: \
347 STDMETHOD_(ULONG, AddRef)() Z7_override Z7_final \
348 { return (ULONG)InterlockedIncrement((LONG *)&_m_RefCount); } \
349 STDMETHOD_(ULONG, Release)() Z7_override Z7_final \
350 { const LONG v = InterlockedDecrement((LONG *)&_m_RefCount); \
351 if (v != 0) return (ULONG)v; \
352 delete this; return 0; }
353
354#define Z7_COM_QI_END_MT \
238 else return E_NOINTERFACE; \ 355 else return E_NOINTERFACE; \
239 ++_m_RefCount; /* AddRef(); */ return S_OK; } 356 InterlockedIncrement((LONG *)&_m_RefCount); /* AddRef(); */ return S_OK; }
357
358// you can define Z7_COM_USE_ATOMIC,
359// if you want to call Release() from different threads (for example, for .NET code)
360// #define Z7_COM_USE_ATOMIC
361
362#if defined(Z7_COM_USE_ATOMIC) && !defined(Z7_ST)
363
364#ifndef _WIN32
365#if 0
366#include "../../C/Threads.h"
367#else
368EXTERN_C_BEGIN
369LONG InterlockedIncrement(LONG volatile *addend);
370LONG InterlockedDecrement(LONG volatile *addend);
371EXTERN_C_END
372#endif
373#endif // _WIN32
374
375#define Z7_COM_ADDREF_RELEASE Z7_COM_ADDREF_RELEASE_MT
376#define Z7_COM_QI_END Z7_COM_QI_END_MT
377
378#else // !Z7_COM_USE_ATOMIC
240 379
241#define Z7_COM_ADDREF_RELEASE \ 380#define Z7_COM_ADDREF_RELEASE \
242 private: \ 381 private: \
243 STDMETHOD_(ULONG, AddRef)() throw() Z7_override Z7_final \ 382 STDMETHOD_(ULONG, AddRef)() throw() Z7_override Z7_final \
244 { return ++_m_RefCount; } \ 383 { return ++_m_RefCount; } \
245 STDMETHOD_(ULONG, Release)() throw() Z7_override Z7_final \ 384 STDMETHOD_(ULONG, Release)() throw() Z7_override Z7_final \
246 { if (--_m_RefCount != 0) return _m_RefCount; delete this; return 0; } \ 385 { if (--_m_RefCount != 0) return _m_RefCount; \
386 delete this; return 0; }
387
388#define Z7_COM_QI_END \
389 else return E_NOINTERFACE; \
390 ++_m_RefCount; /* AddRef(); */ return S_OK; }
391
392#endif // !Z7_COM_USE_ATOMIC
393
247 394
248#define Z7_COM_UNKNOWN_IMP_SPEC(i) \ 395#define Z7_COM_UNKNOWN_IMP_SPEC(i) \
249 Z7_COM_QI_BEGIN \ 396 Z7_COM_QI_BEGIN \
diff --git a/CPP/Common/MyGuidDef.h b/CPP/Common/MyGuidDef.h
index ab9993b..3aa5266 100644
--- a/CPP/Common/MyGuidDef.h
+++ b/CPP/Common/MyGuidDef.h
@@ -13,7 +13,7 @@ typedef struct {
13 UInt32 Data1; 13 UInt32 Data1;
14 UInt16 Data2; 14 UInt16 Data2;
15 UInt16 Data3; 15 UInt16 Data3;
16 unsigned char Data4[8]; 16 Byte Data4[8];
17} GUID; 17} GUID;
18 18
19#ifdef __cplusplus 19#ifdef __cplusplus
@@ -32,7 +32,7 @@ typedef GUID CLSID;
32inline int operator==(REFGUID g1, REFGUID g2) 32inline int operator==(REFGUID g1, REFGUID g2)
33{ 33{
34 for (unsigned i = 0; i < sizeof(g1); i++) 34 for (unsigned i = 0; i < sizeof(g1); i++)
35 if (((const unsigned char *)&g1)[i] != ((const unsigned char *)&g2)[i]) 35 if (((const Byte *)&g1)[i] != ((const Byte *)&g2)[i])
36 return 0; 36 return 0;
37 return 1; 37 return 1;
38} 38}
diff --git a/CPP/Common/MyMap.cpp b/CPP/Common/MyMap.cpp
index 0a200f0..d130aec 100644
--- a/CPP/Common/MyMap.cpp
+++ b/CPP/Common/MyMap.cpp
@@ -103,7 +103,7 @@ bool CMap32::Set(UInt32 key, UInt32 value)
103 n.IsLeaf[newBit] = 1; 103 n.IsLeaf[newBit] = 1;
104 n.IsLeaf[1 - newBit] = 0; 104 n.IsLeaf[1 - newBit] = 0;
105 n.Keys[newBit] = key; 105 n.Keys[newBit] = key;
106 n.Keys[1 - newBit] = Nodes.Size(); 106 n.Keys[1 - newBit] = (UInt32)Nodes.Size();
107 Nodes.Add(e2); 107 Nodes.Add(e2);
108 return false; 108 return false;
109 } 109 }
@@ -130,7 +130,7 @@ bool CMap32::Set(UInt32 key, UInt32 value)
130 e2.Len = (UInt16)(bitPos - (1 + i)); 130 e2.Len = (UInt16)(bitPos - (1 + i));
131 131
132 n.IsLeaf[bit] = 0; 132 n.IsLeaf[bit] = 0;
133 n.Keys[bit] = Nodes.Size(); 133 n.Keys[bit] = (UInt32)Nodes.Size();
134 134
135 Nodes.Add(e2); 135 Nodes.Add(e2);
136 return false; 136 return false;
diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp
index 51c1c3b..b5f7e52 100644
--- a/CPP/Common/MyString.cpp
+++ b/CPP/Common/MyString.cpp
@@ -62,7 +62,7 @@ void MyStringUpper_Ascii(char *s) throw()
62{ 62{
63 for (;;) 63 for (;;)
64 { 64 {
65 char c = *s; 65 const char c = *s;
66 if (c == 0) 66 if (c == 0)
67 return; 67 return;
68 *s++ = MyCharUpper_Ascii(c); 68 *s++ = MyCharUpper_Ascii(c);
@@ -73,7 +73,7 @@ void MyStringUpper_Ascii(wchar_t *s) throw()
73{ 73{
74 for (;;) 74 for (;;)
75 { 75 {
76 wchar_t c = *s; 76 const wchar_t c = *s;
77 if (c == 0) 77 if (c == 0)
78 return; 78 return;
79 *s++ = MyCharUpper_Ascii(c); 79 *s++ = MyCharUpper_Ascii(c);
@@ -85,7 +85,7 @@ void MyStringLower_Ascii(char *s) throw()
85{ 85{
86 for (;;) 86 for (;;)
87 { 87 {
88 char c = *s; 88 const char c = *s;
89 if (c == 0) 89 if (c == 0)
90 return; 90 return;
91 *s++ = MyCharLower_Ascii(c); 91 *s++ = MyCharLower_Ascii(c);
@@ -96,7 +96,7 @@ void MyStringLower_Ascii(wchar_t *s) throw()
96{ 96{
97 for (;;) 97 for (;;)
98 { 98 {
99 wchar_t c = *s; 99 const wchar_t c = *s;
100 if (c == 0) 100 if (c == 0)
101 return; 101 return;
102 *s++ = MyCharLower_Ascii(c); 102 *s++ = MyCharLower_Ascii(c);
@@ -190,8 +190,8 @@ bool IsString1PrefixedByString2(const char *s1, const char *s2) throw()
190{ 190{
191 for (;;) 191 for (;;)
192 { 192 {
193 const unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true; 193 const char c2 = *s2++; if (c2 == 0) return true;
194 const unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false; 194 const char c1 = *s1++; if (c1 != c2) return false;
195 } 195 }
196} 196}
197 197
@@ -402,6 +402,7 @@ void AString::InsertSpace(unsigned &index, unsigned size)
402} 402}
403 403
404#define k_Alloc_Len_Limit (0x40000000 - 2) 404#define k_Alloc_Len_Limit (0x40000000 - 2)
405// #define k_Alloc_Len_Limit (((unsigned)1 << (sizeof(unsigned) * 8 - 2)) - 2)
405 406
406void AString::ReAlloc(unsigned newLimit) 407void AString::ReAlloc(unsigned newLimit)
407{ 408{
@@ -413,9 +414,14 @@ void AString::ReAlloc(unsigned newLimit)
413 _limit = newLimit; 414 _limit = newLimit;
414} 415}
415 416
417#define THROW_STRING_ALLOC_EXCEPTION { throw 20130220; }
418
419#define CHECK_STRING_ALLOC_LEN(len) \
420 { if ((len) > k_Alloc_Len_Limit) THROW_STRING_ALLOC_EXCEPTION }
421
416void AString::ReAlloc2(unsigned newLimit) 422void AString::ReAlloc2(unsigned newLimit)
417{ 423{
418 if (newLimit > k_Alloc_Len_Limit) throw 20130220; 424 CHECK_STRING_ALLOC_LEN(newLimit)
419 // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, 0); 425 // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, 0);
420 char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1); 426 char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1);
421 newBuf[0] = 0; 427 newBuf[0] = 0;
@@ -433,6 +439,7 @@ void AString::SetStartLen(unsigned len)
433 _limit = len; 439 _limit = len;
434} 440}
435 441
442Z7_NO_INLINE
436void AString::Grow_1() 443void AString::Grow_1()
437{ 444{
438 unsigned next = _len; 445 unsigned next = _len;
@@ -443,7 +450,7 @@ void AString::Grow_1()
443 if (next < _len || next > k_Alloc_Len_Limit) 450 if (next < _len || next > k_Alloc_Len_Limit)
444 next = k_Alloc_Len_Limit; 451 next = k_Alloc_Len_Limit;
445 if (next <= _len) 452 if (next <= _len)
446 throw 20130220; 453 THROW_STRING_ALLOC_EXCEPTION
447 ReAlloc(next); 454 ReAlloc(next);
448 // Grow(1); 455 // Grow(1);
449} 456}
@@ -461,7 +468,7 @@ void AString::Grow(unsigned n)
461 if (next < _len || next > k_Alloc_Len_Limit) 468 if (next < _len || next > k_Alloc_Len_Limit)
462 next = k_Alloc_Len_Limit; 469 next = k_Alloc_Len_Limit;
463 if (next <= _len || next - _len < n) 470 if (next <= _len || next - _len < n)
464 throw 20130220; 471 THROW_STRING_ALLOC_EXCEPTION
465 ReAlloc(next); 472 ReAlloc(next);
466} 473}
467 474
@@ -638,12 +645,14 @@ void AString::SetFromBstr_if_Ascii(BSTR s)
638} 645}
639*/ 646*/
640 647
648void AString::Add_Char(char c) { operator+=(c); }
641void AString::Add_Space() { operator+=(' '); } 649void AString::Add_Space() { operator+=(' '); }
642void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); } 650void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
643void AString::Add_LF() { operator+=('\n'); } 651void AString::Add_LF() { operator+=('\n'); }
644void AString::Add_Slash() { operator+=('/'); } 652void AString::Add_Slash() { operator+=('/'); }
645void AString::Add_Dot() { operator+=('.'); } 653void AString::Add_Dot() { operator+=('.'); }
646void AString::Add_Minus() { operator+=('-'); } 654void AString::Add_Minus() { operator+=('-'); }
655void AString::Add_Colon() { operator+=(':'); }
647 656
648AString &AString::operator+=(const char *s) 657AString &AString::operator+=(const char *s)
649{ 658{
@@ -696,6 +705,7 @@ void AString::SetFrom(const char *s, unsigned len) // no check
696{ 705{
697 if (len > _limit) 706 if (len > _limit)
698 { 707 {
708 CHECK_STRING_ALLOC_LEN(len)
699 char *newBuf = MY_STRING_NEW_char((size_t)len + 1); 709 char *newBuf = MY_STRING_NEW_char((size_t)len + 1);
700 MY_STRING_DELETE(_chars) 710 MY_STRING_DELETE(_chars)
701 _chars = newBuf; 711 _chars = newBuf;
@@ -707,6 +717,12 @@ void AString::SetFrom(const char *s, unsigned len) // no check
707 _len = len; 717 _len = len;
708} 718}
709 719
720void AString::SetFrom_Chars_SizeT(const char *s, size_t len)
721{
722 CHECK_STRING_ALLOC_LEN(len)
723 SetFrom(s, (unsigned)len);
724}
725
710void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check 726void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check
711{ 727{
712 unsigned i; 728 unsigned i;
@@ -906,8 +922,8 @@ void AString::Replace(const AString &oldString, const AString &newString)
906 return; // 0; 922 return; // 0;
907 if (oldString == newString) 923 if (oldString == newString)
908 return; // 0; 924 return; // 0;
909 unsigned oldLen = oldString.Len(); 925 const unsigned oldLen = oldString.Len();
910 unsigned newLen = newString.Len(); 926 const unsigned newLen = newString.Len();
911 // unsigned number = 0; 927 // unsigned number = 0;
912 int pos = 0; 928 int pos = 0;
913 while ((unsigned)pos < _len) 929 while ((unsigned)pos < _len)
@@ -1011,7 +1027,7 @@ void UString::ReAlloc(unsigned newLimit)
1011 1027
1012void UString::ReAlloc2(unsigned newLimit) 1028void UString::ReAlloc2(unsigned newLimit)
1013{ 1029{
1014 if (newLimit > k_Alloc_Len_Limit) throw 20130221; 1030 CHECK_STRING_ALLOC_LEN(newLimit)
1015 // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); 1031 // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
1016 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1); 1032 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1);
1017 newBuf[0] = 0; 1033 newBuf[0] = 0;
@@ -1029,6 +1045,7 @@ void UString::SetStartLen(unsigned len)
1029 _limit = len; 1045 _limit = len;
1030} 1046}
1031 1047
1048Z7_NO_INLINE
1032void UString::Grow_1() 1049void UString::Grow_1()
1033{ 1050{
1034 unsigned next = _len; 1051 unsigned next = _len;
@@ -1039,7 +1056,7 @@ void UString::Grow_1()
1039 if (next < _len || next > k_Alloc_Len_Limit) 1056 if (next < _len || next > k_Alloc_Len_Limit)
1040 next = k_Alloc_Len_Limit; 1057 next = k_Alloc_Len_Limit;
1041 if (next <= _len) 1058 if (next <= _len)
1042 throw 20130220; 1059 THROW_STRING_ALLOC_EXCEPTION
1043 ReAlloc(next); 1060 ReAlloc(next);
1044} 1061}
1045 1062
@@ -1056,7 +1073,7 @@ void UString::Grow(unsigned n)
1056 if (next < _len || next > k_Alloc_Len_Limit) 1073 if (next < _len || next > k_Alloc_Len_Limit)
1057 next = k_Alloc_Len_Limit; 1074 next = k_Alloc_Len_Limit;
1058 if (next <= _len || next - _len < n) 1075 if (next <= _len || next - _len < n)
1059 throw 20130220; 1076 THROW_STRING_ALLOC_EXCEPTION
1060 ReAlloc(next - 1); 1077 ReAlloc(next - 1);
1061} 1078}
1062 1079
@@ -1214,6 +1231,7 @@ void UString::SetFrom(const wchar_t *s, unsigned len) // no check
1214{ 1231{
1215 if (len > _limit) 1232 if (len > _limit)
1216 { 1233 {
1234 CHECK_STRING_ALLOC_LEN(len)
1217 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1); 1235 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1218 MY_STRING_DELETE(_chars) 1236 MY_STRING_DELETE(_chars)
1219 _chars = newBuf; 1237 _chars = newBuf;
@@ -1238,7 +1256,7 @@ void UString::SetFromBstr(LPCOLESTR s)
1238 if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) 1256 if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
1239 { 1257 {
1240 wchar_t c2 = s[i]; 1258 wchar_t c2 = s[i];
1241 if (c2 >= 0xdc00 && c2 < 0x10000) 1259 if (c2 >= 0xdc00 && c2 < 0xe000)
1242 { 1260 {
1243 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); 1261 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
1244 i++; 1262 i++;
@@ -1269,7 +1287,7 @@ void UString::SetFromBstr(LPCOLESTR s)
1269 if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) 1287 if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
1270 { 1288 {
1271 wchar_t c2 = *s; 1289 wchar_t c2 = *s;
1272 if (c2 >= 0xdc00 && c2 < 0x10000) 1290 if (c2 >= 0xdc00 && c2 < 0xe000)
1273 { 1291 {
1274 s++; 1292 s++;
1275 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); 1293 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
@@ -1305,21 +1323,15 @@ UString &UString::operator=(const char *s)
1305 return *this; 1323 return *this;
1306} 1324}
1307 1325
1326void UString::Add_Char(char c) { operator+=((wchar_t)(unsigned char)c); }
1327// void UString::Add_WChar(wchar_t c) { operator+=(c); }
1308void UString::Add_Dot() { operator+=(L'.'); } 1328void UString::Add_Dot() { operator+=(L'.'); }
1309void UString::Add_Space() { operator+=(L' '); } 1329void UString::Add_Space() { operator+=(L' '); }
1330void UString::Add_Minus() { operator+=(L'-'); }
1331void UString::Add_Colon() { operator+=(L':'); }
1332void UString::Add_LF() { operator+=(L'\n'); }
1310void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); } 1333void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
1311 1334
1312void UString::Add_LF()
1313{
1314 if (_limit == _len)
1315 Grow_1();
1316 unsigned len = _len;
1317 wchar_t *chars = _chars;
1318 chars[len++] = L'\n';
1319 chars[len] = 0;
1320 _len = len;
1321}
1322
1323UString &UString::operator+=(const wchar_t *s) 1335UString &UString::operator+=(const wchar_t *s)
1324{ 1336{
1325 unsigned len = MyStringLen(s); 1337 unsigned len = MyStringLen(s);
@@ -1597,7 +1609,7 @@ void UString::DeleteFrontal(unsigned num) throw()
1597void UString2::ReAlloc2(unsigned newLimit) 1609void UString2::ReAlloc2(unsigned newLimit)
1598{ 1610{
1599 // wrong (_len) is allowed after this function 1611 // wrong (_len) is allowed after this function
1600 if (newLimit > k_Alloc_Len_Limit) throw 20130221; 1612 CHECK_STRING_ALLOC_LEN(newLimit)
1601 // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); 1613 // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
1602 if (_chars) 1614 if (_chars)
1603 { 1615 {
@@ -1805,7 +1817,7 @@ bool CStringFinder::FindWord_In_LowCaseAsciiList_NoCase(const char *p, const wch
1805 break; 1817 break;
1806 if (c <= 0x20 || c > 0x7f) 1818 if (c <= 0x20 || c > 0x7f)
1807 return false; 1819 return false;
1808 _temp += (char)MyCharLower_Ascii((char)c); 1820 _temp.Add_Char((char)MyCharLower_Ascii((char)c));
1809 } 1821 }
1810 1822
1811 while (*p != 0) 1823 while (*p != 0)
diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h
index e5ce18a..ba9914e 100644
--- a/CPP/Common/MyString.h
+++ b/CPP/Common/MyString.h
@@ -281,6 +281,8 @@ class AString
281 void ReAlloc(unsigned newLimit); 281 void ReAlloc(unsigned newLimit);
282 void ReAlloc2(unsigned newLimit); 282 void ReAlloc2(unsigned newLimit);
283 void SetStartLen(unsigned len); 283 void SetStartLen(unsigned len);
284
285 Z7_NO_INLINE
284 void Grow_1(); 286 void Grow_1();
285 void Grow(unsigned n); 287 void Grow(unsigned n);
286 288
@@ -373,6 +375,8 @@ public:
373 void SetFromWStr_if_Ascii(const wchar_t *s); 375 void SetFromWStr_if_Ascii(const wchar_t *s);
374 // void SetFromBstr_if_Ascii(BSTR s); 376 // void SetFromBstr_if_Ascii(BSTR s);
375 377
378// private:
379 Z7_FORCE_INLINE
376 AString &operator+=(char c) 380 AString &operator+=(char c)
377 { 381 {
378 if (_limit == _len) 382 if (_limit == _len)
@@ -384,14 +388,16 @@ public:
384 _len = len; 388 _len = len;
385 return *this; 389 return *this;
386 } 390 }
387 391public:
388 void Add_Space(); 392 void Add_Space();
389 void Add_Space_if_NotEmpty(); 393 void Add_Space_if_NotEmpty();
390 void Add_OptSpaced(const char *s); 394 void Add_OptSpaced(const char *s);
395 void Add_Char(char c);
391 void Add_LF(); 396 void Add_LF();
392 void Add_Slash(); 397 void Add_Slash();
393 void Add_Dot(); 398 void Add_Dot();
394 void Add_Minus(); 399 void Add_Minus();
400 void Add_Colon();
395 void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); } 401 void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); }
396 402
397 AString &operator+=(const char *s); 403 AString &operator+=(const char *s);
@@ -402,6 +408,7 @@ public:
402 408
403 void AddFrom(const char *s, unsigned len); // no check 409 void AddFrom(const char *s, unsigned len); // no check
404 void SetFrom(const char *s, unsigned len); // no check 410 void SetFrom(const char *s, unsigned len); // no check
411 void SetFrom_Chars_SizeT(const char* s, size_t len); // no check
405 void SetFrom(const char* s, int len) // no check 412 void SetFrom(const char* s, int len) // no check
406 { 413 {
407 SetFrom(s, (unsigned)len); // no check 414 SetFrom(s, (unsigned)len); // no check
@@ -668,6 +675,8 @@ public:
668 UString &operator=(const char *s); 675 UString &operator=(const char *s);
669 UString &operator=(const AString &s) { return operator=(s.Ptr()); } 676 UString &operator=(const AString &s) { return operator=(s.Ptr()); }
670 677
678// private:
679 Z7_FORCE_INLINE
671 UString &operator+=(wchar_t c) 680 UString &operator+=(wchar_t c)
672 { 681 {
673 if (_limit == _len) 682 if (_limit == _len)
@@ -680,12 +689,17 @@ public:
680 return *this; 689 return *this;
681 } 690 }
682 691
683 UString &operator+=(char c) { return (*this)+=((wchar_t)(unsigned char)c); } 692private:
684 693 UString &operator+=(char c); // { return (*this)+=((wchar_t)(unsigned char)c); }
694public:
695 void Add_Char(char c);
696 // void Add_WChar(wchar_t c);
685 void Add_Space(); 697 void Add_Space();
686 void Add_Space_if_NotEmpty(); 698 void Add_Space_if_NotEmpty();
687 void Add_LF(); 699 void Add_LF();
688 void Add_Dot(); 700 void Add_Dot();
701 void Add_Minus();
702 void Add_Colon();
689 void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); } 703 void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); }
690 704
691 UString &operator+=(const wchar_t *s); 705 UString &operator+=(const wchar_t *s);
diff --git a/CPP/Common/MyTypes.h b/CPP/Common/MyTypes.h
index 8f44f67..eadc9a4 100644
--- a/CPP/Common/MyTypes.h
+++ b/CPP/Common/MyTypes.h
@@ -3,10 +3,11 @@
3#ifndef ZIP7_INC_COMMON_MY_TYPES_H 3#ifndef ZIP7_INC_COMMON_MY_TYPES_H
4#define ZIP7_INC_COMMON_MY_TYPES_H 4#define ZIP7_INC_COMMON_MY_TYPES_H
5 5
6#include "Common0.h"
6#include "../../C/7zTypes.h" 7#include "../../C/7zTypes.h"
7#include "Common.h"
8 8
9typedef int HRes; 9// typedef int HRes;
10// typedef HRESULT HRes;
10 11
11struct CBoolPair 12struct CBoolPair
12{ 13{
diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h
index 9ee7105..a772785 100644
--- a/CPP/Common/MyVector.h
+++ b/CPP/Common/MyVector.h
@@ -258,7 +258,7 @@ public:
258 { 258 {
259 if (index != 0) 259 if (index != 0)
260 { 260 {
261 T temp = _items[index]; 261 const T temp = _items[index];
262 memmove(_items + 1, _items, (size_t)index * sizeof(T)); 262 memmove(_items + 1, _items, (size_t)index * sizeof(T));
263 _items[0] = temp; 263 _items[0] = temp;
264 } 264 }
@@ -268,15 +268,29 @@ public:
268 T& operator[](unsigned index) { return _items[index]; } 268 T& operator[](unsigned index) { return _items[index]; }
269 const T& operator[](int index) const { return _items[(unsigned)index]; } 269 const T& operator[](int index) const { return _items[(unsigned)index]; }
270 T& operator[](int index) { return _items[(unsigned)index]; } 270 T& operator[](int index) { return _items[(unsigned)index]; }
271
272 const T* ConstData() const { return _items; }
273 T* NonConstData() const { return _items; }
274 T* NonConstData() { return _items; }
275
276 const T* Data() const { return _items; }
277 T* Data() { return _items; }
278
279 const T& FrontItem() const { return _items[0]; }
280 T& FrontItem() { return _items[0]; }
281 /*
282 const T Front() const { return _items[0]; }
283 T Front() { return _items[0]; }
271 const T& Front() const { return _items[0]; } 284 const T& Front() const { return _items[0]; }
272 T& Front() { return _items[0]; } 285 T& Front() { return _items[0]; }
286 */
273 const T& Back() const { return _items[(size_t)_size - 1]; } 287 const T& Back() const { return _items[(size_t)_size - 1]; }
274 T& Back() { return _items[(size_t)_size - 1]; } 288 T& Back() { return _items[(size_t)_size - 1]; }
275 289
276 /* 290 /*
277 void Swap(unsigned i, unsigned j) 291 void Swap(unsigned i, unsigned j)
278 { 292 {
279 T temp = _items[i]; 293 const T temp = _items[i];
280 _items[i] = _items[j]; 294 _items[i] = _items[j];
281 _items[j] = temp; 295 _items[j] = temp;
282 } 296 }
@@ -368,7 +382,7 @@ public:
368 382
369 static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param) 383 static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param)
370 { 384 {
371 T temp = p[k]; 385 const T temp = p[k];
372 for (;;) 386 for (;;)
373 { 387 {
374 unsigned s = (k << 1); 388 unsigned s = (k << 1);
@@ -389,16 +403,16 @@ public:
389 unsigned size = _size; 403 unsigned size = _size;
390 if (size <= 1) 404 if (size <= 1)
391 return; 405 return;
392 T* p = (&Front()) - 1; 406 T* p = _items - 1;
393 { 407 {
394 unsigned i = size >> 1; 408 unsigned i = size >> 1;
395 do 409 do
396 SortRefDown(p, i, size, compare, param); 410 SortRefDown(p, i, size, compare, param);
397 while (--i != 0); 411 while (--i);
398 } 412 }
399 do 413 do
400 { 414 {
401 T temp = p[size]; 415 const T temp = p[size];
402 p[size--] = p[1]; 416 p[size--] = p[1];
403 p[1] = temp; 417 p[1] = temp;
404 SortRefDown(p, 1, size, compare, param); 418 SortRefDown(p, 1, size, compare, param);
@@ -408,7 +422,7 @@ public:
408 422
409 static void SortRefDown2(T* p, unsigned k, unsigned size) 423 static void SortRefDown2(T* p, unsigned k, unsigned size)
410 { 424 {
411 T temp = p[k]; 425 const T temp = p[k];
412 for (;;) 426 for (;;)
413 { 427 {
414 unsigned s = (k << 1); 428 unsigned s = (k << 1);
@@ -429,16 +443,16 @@ public:
429 unsigned size = _size; 443 unsigned size = _size;
430 if (size <= 1) 444 if (size <= 1)
431 return; 445 return;
432 T* p = (&Front()) - 1; 446 T* p = _items - 1;
433 { 447 {
434 unsigned i = size >> 1; 448 unsigned i = size >> 1;
435 do 449 do
436 SortRefDown2(p, i, size); 450 SortRefDown2(p, i, size);
437 while (--i != 0); 451 while (--i);
438 } 452 }
439 do 453 do
440 { 454 {
441 T temp = p[size]; 455 const T temp = p[size];
442 p[size--] = p[1]; 456 p[size--] = p[1];
443 p[1] = temp; 457 p[1] = temp;
444 SortRefDown2(p, 1, size); 458 SortRefDown2(p, 1, size);
diff --git a/CPP/Common/MyWindows.cpp b/CPP/Common/MyWindows.cpp
index ae284eb..a1dfbef 100644
--- a/CPP/Common/MyWindows.cpp
+++ b/CPP/Common/MyWindows.cpp
@@ -88,21 +88,21 @@ BSTR SysAllocString(const OLECHAR *s)
88void SysFreeString(BSTR bstr) 88void SysFreeString(BSTR bstr)
89{ 89{
90 if (bstr) 90 if (bstr)
91 FreeForBSTR((CBstrSizeType *)bstr - 1); 91 FreeForBSTR((CBstrSizeType *)(void *)bstr - 1);
92} 92}
93 93
94UINT SysStringByteLen(BSTR bstr) 94UINT SysStringByteLen(BSTR bstr)
95{ 95{
96 if (!bstr) 96 if (!bstr)
97 return 0; 97 return 0;
98 return *((CBstrSizeType *)bstr - 1); 98 return *((CBstrSizeType *)(void *)bstr - 1);
99} 99}
100 100
101UINT SysStringLen(BSTR bstr) 101UINT SysStringLen(BSTR bstr)
102{ 102{
103 if (!bstr) 103 if (!bstr)
104 return 0; 104 return 0;
105 return *((CBstrSizeType *)bstr - 1) / (UINT)sizeof(OLECHAR); 105 return *((CBstrSizeType *)(void *)bstr - 1) / (UINT)sizeof(OLECHAR);
106} 106}
107 107
108 108
diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h
index a76e14b..da5370b 100644
--- a/CPP/Common/MyWindows.h
+++ b/CPP/Common/MyWindows.h
@@ -66,8 +66,8 @@ typedef int BOOL;
66typedef Int64 LONGLONG; 66typedef Int64 LONGLONG;
67typedef UInt64 ULONGLONG; 67typedef UInt64 ULONGLONG;
68 68
69typedef struct _LARGE_INTEGER { LONGLONG QuadPart; } LARGE_INTEGER; 69typedef struct { LONGLONG QuadPart; } LARGE_INTEGER;
70typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart; } ULARGE_INTEGER; 70typedef struct { ULONGLONG QuadPart; } ULARGE_INTEGER;
71 71
72typedef const CHAR *LPCSTR; 72typedef const CHAR *LPCSTR;
73typedef CHAR TCHAR; 73typedef CHAR TCHAR;
@@ -79,7 +79,7 @@ typedef OLECHAR *BSTR;
79typedef const OLECHAR *LPCOLESTR; 79typedef const OLECHAR *LPCOLESTR;
80typedef OLECHAR *LPOLESTR; 80typedef OLECHAR *LPOLESTR;
81 81
82typedef struct _FILETIME 82typedef struct
83{ 83{
84 DWORD dwLowDateTime; 84 DWORD dwLowDateTime;
85 DWORD dwHighDateTime; 85 DWORD dwHighDateTime;
@@ -292,7 +292,7 @@ typedef enum tagSTREAM_SEEK
292 292
293 293
294 294
295typedef struct _SYSTEMTIME 295typedef struct
296{ 296{
297 WORD wYear; 297 WORD wYear;
298 WORD wMonth; 298 WORD wMonth;
@@ -312,12 +312,13 @@ BOOL WINAPI FileTimeToSystemTime(const FILETIME *fileTime, SYSTEMTIME *systemTim
312DWORD GetTickCount(); 312DWORD GetTickCount();
313 313
314 314
315/*
315#define CREATE_NEW 1 316#define CREATE_NEW 1
316#define CREATE_ALWAYS 2 317#define CREATE_ALWAYS 2
317#define OPEN_EXISTING 3 318#define OPEN_EXISTING 3
318#define OPEN_ALWAYS 4 319#define OPEN_ALWAYS 4
319#define TRUNCATE_EXISTING 5 320#define TRUNCATE_EXISTING 5
320 321*/
321 322
322#endif // _WIN32 323#endif // _WIN32
323 324
diff --git a/CPP/Common/MyXml.cpp b/CPP/Common/MyXml.cpp
index a879d34..cc891fc 100644
--- a/CPP/Common/MyXml.cpp
+++ b/CPP/Common/MyXml.cpp
@@ -3,6 +3,7 @@
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "MyXml.h" 5#include "MyXml.h"
6#include "StringToInt.h"
6 7
7static bool IsValidChar(char c) 8static bool IsValidChar(char c)
8{ 9{
@@ -30,7 +31,7 @@ int CXmlItem::FindProp(const char *propName) const throw()
30 31
31AString CXmlItem::GetPropVal(const char *propName) const 32AString CXmlItem::GetPropVal(const char *propName) const
32{ 33{
33 int index = FindProp(propName); 34 const int index = FindProp(propName);
34 if (index >= 0) 35 if (index >= 0)
35 return Props[(unsigned)index].Value; 36 return Props[(unsigned)index].Value;
36 return AString(); 37 return AString();
@@ -49,6 +50,17 @@ int CXmlItem::FindSubTag(const char *tag) const throw()
49 return -1; 50 return -1;
50} 51}
51 52
53const CXmlItem *CXmlItem::FindSubTag_GetPtr(const char *tag) const throw()
54{
55 FOR_VECTOR (i, SubItems)
56 {
57 const CXmlItem *p = &SubItems[i];
58 if (p->IsTagged(tag))
59 return p;
60 }
61 return NULL;
62}
63
52AString CXmlItem::GetSubString() const 64AString CXmlItem::GetSubString() const
53{ 65{
54 if (SubItems.Size() == 1) 66 if (SubItems.Size() == 1)
@@ -73,9 +85,9 @@ const AString * CXmlItem::GetSubStringPtr() const throw()
73 85
74AString CXmlItem::GetSubStringForTag(const char *tag) const 86AString CXmlItem::GetSubStringForTag(const char *tag) const
75{ 87{
76 int index = FindSubTag(tag); 88 const CXmlItem *item = FindSubTag_GetPtr(tag);
77 if (index >= 0) 89 if (item)
78 return SubItems[(unsigned)index].GetSubString(); 90 return item->GetSubString();
79 return AString(); 91 return AString();
80} 92}
81 93
@@ -92,11 +104,14 @@ const char * CXmlItem::ParseItem(const char *s, int numAllowedLevels)
92 } 104 }
93 if (*s == 0) 105 if (*s == 0)
94 return NULL; 106 return NULL;
95 if (s != beg)
96 { 107 {
97 IsTag = false; 108 const size_t num = (size_t)(s - beg);
98 Name.SetFrom(beg, (unsigned)(s - beg)); 109 if (num)
99 return s; 110 {
111 IsTag = false;
112 Name.SetFrom_Chars_SizeT(beg, num);
113 return s;
114 }
100 } 115 }
101 116
102 IsTag = true; 117 IsTag = true;
@@ -110,7 +125,7 @@ const char * CXmlItem::ParseItem(const char *s, int numAllowedLevels)
110 break; 125 break;
111 if (s == beg || *s == 0) 126 if (s == beg || *s == 0)
112 return NULL; 127 return NULL;
113 Name.SetFrom(beg, (unsigned)(s - beg)); 128 Name.SetFrom_Chars_SizeT(beg, (size_t)(s - beg));
114 129
115 for (;;) 130 for (;;)
116 { 131 {
@@ -142,11 +157,12 @@ const char * CXmlItem::ParseItem(const char *s, int numAllowedLevels)
142 } 157 }
143 158
144 s += 2; 159 s += 2;
145 unsigned len = Name.Len(); 160 const unsigned len = Name.Len();
161 const char *name = Name.Ptr();
146 for (unsigned i = 0; i < len; i++) 162 for (unsigned i = 0; i < len; i++)
147 if (s[i] != Name[i]) 163 if (*s++ != *name++)
148 return NULL; 164 return NULL;
149 s += len; 165 // s += len;
150 if (s[0] != '>') 166 if (s[0] != '>')
151 return NULL; 167 return NULL;
152 return s + 1; 168 return s + 1;
@@ -166,7 +182,7 @@ const char * CXmlItem::ParseItem(const char *s, int numAllowedLevels)
166 } 182 }
167 if (s == beg) 183 if (s == beg)
168 return NULL; 184 return NULL;
169 prop.Name.SetFrom(beg, (unsigned)(s - beg)); 185 prop.Name.SetFrom_Chars_SizeT(beg, (size_t)(s - beg));
170 186
171 SKIP_SPACES(s) 187 SKIP_SPACES(s)
172 if (*s != '=') 188 if (*s != '=')
@@ -187,7 +203,7 @@ const char * CXmlItem::ParseItem(const char *s, int numAllowedLevels)
187 break; 203 break;
188 s++; 204 s++;
189 } 205 }
190 prop.Value.SetFrom(beg, (unsigned)(s - beg)); 206 prop.Value.SetFrom_Chars_SizeT(beg, (size_t)(s - beg));
191 s++; 207 s++;
192 } 208 }
193} 209}
@@ -258,3 +274,76 @@ void CXml::AppendTo(AString &s) const
258 Root.AppendTo(s); 274 Root.AppendTo(s);
259} 275}
260*/ 276*/
277
278
279void z7_xml_DecodeString(AString &temp)
280{
281 char * const beg = temp.GetBuf();
282 char *dest = beg;
283 const char *p = beg;
284 for (;;)
285 {
286 char c = *p++;
287 if (c == 0)
288 break;
289 if (c == '&')
290 {
291 if (p[0] == '#')
292 {
293 const char *end;
294 const UInt32 number = ConvertStringToUInt32(p + 1, &end);
295 if (*end == ';' && number != 0 && number <= 127)
296 {
297 p = end + 1;
298 c = (char)number;
299 }
300 }
301 else if (
302 p[0] == 'a' &&
303 p[1] == 'm' &&
304 p[2] == 'p' &&
305 p[3] == ';')
306 {
307 p += 4;
308 }
309 else if (
310 p[0] == 'l' &&
311 p[1] == 't' &&
312 p[2] == ';')
313 {
314 p += 3;
315 c = '<';
316 }
317 else if (
318 p[0] == 'g' &&
319 p[1] == 't' &&
320 p[2] == ';')
321 {
322 p += 3;
323 c = '>';
324 }
325 else if (
326 p[0] == 'a' &&
327 p[1] == 'p' &&
328 p[2] == 'o' &&
329 p[3] == 's' &&
330 p[4] == ';')
331 {
332 p += 5;
333 c = '\'';
334 }
335 else if (
336 p[0] == 'q' &&
337 p[1] == 'u' &&
338 p[2] == 'o' &&
339 p[3] == 't' &&
340 p[4] == ';')
341 {
342 p += 5;
343 c = '\"';
344 }
345 }
346 *dest++ = c;
347 }
348 temp.ReleaseBuf_SetEnd((unsigned)(dest - beg));
349}
diff --git a/CPP/Common/MyXml.h b/CPP/Common/MyXml.h
index 5362602..b22d7e4 100644
--- a/CPP/Common/MyXml.h
+++ b/CPP/Common/MyXml.h
@@ -27,8 +27,8 @@ public:
27 AString GetSubString() const; 27 AString GetSubString() const;
28 const AString * GetSubStringPtr() const throw(); 28 const AString * GetSubStringPtr() const throw();
29 int FindSubTag(const char *tag) const throw(); 29 int FindSubTag(const char *tag) const throw();
30 const CXmlItem *FindSubTag_GetPtr(const char *tag) const throw();
30 AString GetSubStringForTag(const char *tag) const; 31 AString GetSubStringForTag(const char *tag) const;
31
32 void AppendTo(AString &s) const; 32 void AppendTo(AString &s) const;
33}; 33};
34 34
@@ -40,4 +40,6 @@ struct CXml
40 // void AppendTo(AString &s) const; 40 // void AppendTo(AString &s) const;
41}; 41};
42 42
43void z7_xml_DecodeString(AString &s);
44
43#endif 45#endif
diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp
index c95833e..173b8eb 100644
--- a/CPP/Common/NewHandler.cpp
+++ b/CPP/Common/NewHandler.cpp
@@ -65,6 +65,13 @@ operator new(size_t size)
65 return p; 65 return p;
66} 66}
67 67
68
69#if defined(_MSC_VER) && _MSC_VER == 1600
70// vs2010 has no throw() by default ?
71#pragma warning(push)
72#pragma warning(disable : 4986) // 'operator delete': exception specification does not match previous declaration
73#endif
74
68void 75void
69#ifdef _MSC_VER 76#ifdef _MSC_VER
70__cdecl 77__cdecl
@@ -76,6 +83,27 @@ operator delete(void *p) throw()
76 ::free(p); 83 ::free(p);
77} 84}
78 85
86/* we define operator delete(void *p, size_t n) because
87 vs2022 compiler uses delete(void *p, size_t n), and
88 we want to mix files from different compilers:
89 - old vc6 linker
90 - old vc6 complier
91 - new vs2022 complier
92*/
93void
94#ifdef _MSC_VER
95__cdecl
96#endif
97operator delete(void *p, size_t n) throw()
98{
99 UNUSED_VAR(n)
100 ::free(p);
101}
102
103#if defined(_MSC_VER) && _MSC_VER == 1600
104#pragma warning(pop)
105#endif
106
79/* 107/*
80void * 108void *
81#ifdef _MSC_VER 109#ifdef _MSC_VER
@@ -205,11 +233,9 @@ operator delete(void *p) throw()
205 a[i] = 0; 233 a[i] = 0;
206 */ 234 */
207 HeapFree(GetProcessHeap(), 0, p); 235 HeapFree(GetProcessHeap(), 0, p);
208 if (numAllocs == 0) 236 // if (numAllocs == 0) numAllocs = numAllocs; // ERROR
209 numAllocs = numAllocs; // ERROR
210 numAllocs--; 237 numAllocs--;
211 if (numAllocs == 0) 238 // if (numAllocs == 0) numAllocs = numAllocs; // OK: all objects were deleted
212 numAllocs = numAllocs; // OK: all objects were deleted
213 printf("Free %d\n", numAllocs); 239 printf("Free %d\n", numAllocs);
214 LeaveCriticalSection(&cs); 240 LeaveCriticalSection(&cs);
215 #else 241 #else
@@ -219,6 +245,22 @@ operator delete(void *p) throw()
219 #endif 245 #endif
220} 246}
221 247
248void
249#ifdef _MSC_VER
250__cdecl
251#endif
252operator delete(void *p, size_t n) throw();
253void
254#ifdef _MSC_VER
255__cdecl
256#endif
257operator delete(void *p, size_t n) throw()
258{
259 UNUSED_VAR(n)
260 printf("delete_WITH_SIZE=%u, ptr = %p\n", (unsigned)n, p);
261 operator delete(p);
262}
263
222/* 264/*
223void * 265void *
224#ifdef _MSC_VER 266#ifdef _MSC_VER
diff --git a/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h
index 50f6d0a..5ba64b7 100644
--- a/CPP/Common/NewHandler.h
+++ b/CPP/Common/NewHandler.h
@@ -65,12 +65,35 @@ __cdecl
65#endif 65#endif
66operator new(size_t size); 66operator new(size_t size);
67 67
68/*
69#if 0 && defined(_MSC_VER) && _MSC_VER == 1600
70 #define Z7_OPERATOR_DELETE_SPEC_THROW0
71#else
72 #define Z7_OPERATOR_DELETE_SPEC_THROW0 throw()
73#endif
74*/
75#if defined(_MSC_VER) && _MSC_VER == 1600
76#pragma warning(push)
77#pragma warning(disable : 4986) // 'operator delete': exception specification does not match previous declaration
78#endif
79
68void 80void
69#ifdef _MSC_VER 81#ifdef _MSC_VER
70__cdecl 82__cdecl
71#endif 83#endif
72operator delete(void *p) throw(); 84operator delete(void *p) throw();
73 85
86void
87#ifdef _MSC_VER
88__cdecl
89#endif
90operator delete(void *p, size_t n) throw();
91
92#if defined(_MSC_VER) && _MSC_VER == 1600
93#pragma warning(pop)
94#endif
95
96
74#else 97#else
75 98
76#include <new> 99#include <new>
diff --git a/CPP/Common/Random.cpp b/CPP/Common/Random.cpp
index fbdb8c9..6ef9f1a 100644
--- a/CPP/Common/Random.cpp
+++ b/CPP/Common/Random.cpp
@@ -12,11 +12,11 @@
12 12
13#include "Random.h" 13#include "Random.h"
14 14
15void CRandom::Init(unsigned int seed) { srand(seed); } 15void CRandom::Init(unsigned seed) { srand(seed); }
16 16
17void CRandom::Init() 17void CRandom::Init()
18{ 18{
19 Init((unsigned int) 19 Init((unsigned)
20 #ifdef _WIN32 20 #ifdef _WIN32
21 GetTickCount() 21 GetTickCount()
22 #else 22 #else
diff --git a/CPP/Common/Random.h b/CPP/Common/Random.h
index 283869e..3fbb416 100644
--- a/CPP/Common/Random.h
+++ b/CPP/Common/Random.h
@@ -7,7 +7,7 @@ class CRandom
7{ 7{
8public: 8public:
9 void Init(); 9 void Init();
10 void Init(unsigned int seed); 10 void Init(unsigned seed);
11 int Generate() const; 11 int Generate() const;
12}; 12};
13 13
diff --git a/CPP/Common/StdInStream.cpp b/CPP/Common/StdInStream.cpp
index 7b209f1..944be34 100644
--- a/CPP/Common/StdInStream.cpp
+++ b/CPP/Common/StdInStream.cpp
@@ -48,15 +48,15 @@ bool CStdInStream::ScanAStringUntilNewLine(AString &s)
48 s.Empty(); 48 s.Empty();
49 for (;;) 49 for (;;)
50 { 50 {
51 int intChar = GetChar(); 51 const int intChar = GetChar();
52 if (intChar == EOF) 52 if (intChar == EOF)
53 return true; 53 return true;
54 char c = (char)intChar; 54 const char c = (char)intChar;
55 if (c == 0) 55 if (c == 0)
56 return false; 56 return false;
57 if (c == '\n') 57 if (c == '\n')
58 return true; 58 return true;
59 s += c; 59 s.Add_Char(c);
60 } 60 }
61} 61}
62 62
@@ -64,14 +64,14 @@ bool CStdInStream::ScanUStringUntilNewLine(UString &dest)
64{ 64{
65 dest.Empty(); 65 dest.Empty();
66 AString s; 66 AString s;
67 bool res = ScanAStringUntilNewLine(s); 67 const bool res = ScanAStringUntilNewLine(s);
68 int codePage = CodePage; 68 int codePage = CodePage;
69 if (codePage == -1) 69 if (codePage == -1)
70 codePage = CP_OEMCP; 70 codePage = CP_OEMCP;
71 if (codePage == CP_UTF8) 71 if ((unsigned)codePage == CP_UTF8)
72 ConvertUTF8ToUnicode(s, dest); 72 ConvertUTF8ToUnicode(s, dest);
73 else 73 else
74 MultiByteToUnicodeString2(dest, s, (UINT)codePage); 74 MultiByteToUnicodeString2(dest, s, (UINT)(unsigned)codePage);
75 return res; 75 return res;
76} 76}
77 77
diff --git a/CPP/Common/StdOutStream.cpp b/CPP/Common/StdOutStream.cpp
index cfa5fde..ba179d9 100644
--- a/CPP/Common/StdOutStream.cpp
+++ b/CPP/Common/StdOutStream.cpp
@@ -66,70 +66,158 @@ void CStdOutStream::Convert_UString_to_AString(const UString &src, AString &dest
66 int codePage = CodePage; 66 int codePage = CodePage;
67 if (codePage == -1) 67 if (codePage == -1)
68 codePage = CP_OEMCP; 68 codePage = CP_OEMCP;
69 if (codePage == CP_UTF8) 69 if ((unsigned)codePage == CP_UTF8)
70 ConvertUnicodeToUTF8(src, dest); 70 ConvertUnicodeToUTF8(src, dest);
71 else 71 else
72 UnicodeStringToMultiByte2(dest, src, (UINT)codePage); 72 UnicodeStringToMultiByte2(dest, src, (UINT)(unsigned)codePage);
73} 73}
74 74
75 75
76static const wchar_t kReplaceChar = '_'; 76static const wchar_t kReplaceChar = '_';
77 77
78/*
78void CStdOutStream::Normalize_UString_LF_Allowed(UString &s) 79void CStdOutStream::Normalize_UString_LF_Allowed(UString &s)
79{ 80{
80 unsigned len = s.Len(); 81 if (!IsTerminalMode)
82 return;
83
84 const unsigned len = s.Len();
81 wchar_t *d = s.GetBuf(); 85 wchar_t *d = s.GetBuf();
82 86
83 if (IsTerminalMode)
84 for (unsigned i = 0; i < len; i++) 87 for (unsigned i = 0; i < len; i++)
85 { 88 {
86 wchar_t c = d[i]; 89 const wchar_t c = d[i];
87 if (c <= 13 && c >= 7 && c != '\n') 90 if (c == 0x1b || (c <= 13 && c >= 7 && c != '\n'))
88 d[i] = kReplaceChar; 91 d[i] = kReplaceChar;
89 } 92 }
90} 93}
94*/
91 95
92void CStdOutStream::Normalize_UString(UString &s) 96void CStdOutStream::Normalize_UString(UString &s)
93{ 97{
94 unsigned len = s.Len(); 98 const unsigned len = s.Len();
95 wchar_t *d = s.GetBuf(); 99 wchar_t *d = s.GetBuf();
96 100
97 if (IsTerminalMode) 101 if (IsTerminalMode)
98 for (unsigned i = 0; i < len; i++) 102 for (unsigned i = 0; i < len; i++)
99 { 103 {
100 wchar_t c = d[i]; 104 const wchar_t c = d[i];
101 if (c <= 13 && c >= 7) 105 if ((c <= 13 && c >= 7) || c == 0x1b)
102 d[i] = kReplaceChar; 106 d[i] = kReplaceChar;
103 } 107 }
104 else 108 else
105 for (unsigned i = 0; i < len; i++) 109 for (unsigned i = 0; i < len; i++)
106 { 110 {
107 wchar_t c = d[i]; 111 const wchar_t c = d[i];
108 if (c == '\n') 112 if (c == '\n')
109 d[i] = kReplaceChar; 113 d[i] = kReplaceChar;
110 } 114 }
111} 115}
112 116
113void CStdOutStream::NormalizePrint_UString(const UString &s, UString &tempU, AString &tempA) 117void CStdOutStream::Normalize_UString_Path(UString &s)
118{
119 if (ListPathSeparatorSlash.Def)
120 {
121#ifdef _WIN32
122 if (ListPathSeparatorSlash.Val)
123 s.Replace(L'\\', L'/');
124#else
125 if (!ListPathSeparatorSlash.Val)
126 s.Replace(L'/', L'\\');
127#endif
128 }
129 Normalize_UString(s);
130}
131
132
133/*
134void CStdOutStream::Normalize_UString(UString &src)
135{
136 const wchar_t *s = src.Ptr();
137 const unsigned len = src.Len();
138 unsigned i;
139 for (i = 0; i < len; i++)
140 {
141 const wchar_t c = s[i];
142#if 0 && !defined(_WIN32)
143 if (c == '\\') // IsTerminalMode &&
144 break;
145#endif
146 if ((unsigned)c < 0x20)
147 break;
148 }
149 if (i == len)
150 return;
151
152 UString temp;
153 for (i = 0; i < len; i++)
154 {
155 wchar_t c = s[i];
156#if 0 && !defined(_WIN32)
157 if (c == '\\')
158 temp += (wchar_t)L'\\';
159 else
160#endif
161 if ((unsigned)c < 0x20)
162 {
163 if (c == '\n'
164 || (IsTerminalMode && (c == 0x1b || (c <= 13 && c >= 7))))
165 {
166#if 1 || defined(_WIN32)
167 c = (wchar_t)kReplaceChar;
168#else
169 temp += (wchar_t)L'\\';
170 if (c == '\n') c = L'n';
171 else if (c == '\r') c = L'r';
172 else if (c == '\a') c = L'a';
173 else if (c == '\b') c = L'b';
174 else if (c == '\t') c = L't';
175 else if (c == '\v') c = L'v';
176 else if (c == '\f') c = L'f';
177 else
178 {
179 temp += (wchar_t)(L'0' + (unsigned)c / 64);
180 temp += (wchar_t)(L'0' + (unsigned)c / 8 % 8);
181 c = (wchar_t)(L'0' + (unsigned)c % 8);
182 }
183#endif
184 }
185 }
186 temp += c;
187 }
188 src = temp;
189}
190*/
191
192void CStdOutStream::NormalizePrint_UString_Path(const UString &s, UString &tempU, AString &tempA)
114{ 193{
115 tempU = s; 194 tempU = s;
116 Normalize_UString(tempU); 195 Normalize_UString_Path(tempU);
117 PrintUString(tempU, tempA); 196 PrintUString(tempU, tempA);
118} 197}
119 198
120void CStdOutStream::NormalizePrint_UString(const UString &s) 199void CStdOutStream::NormalizePrint_UString_Path(const UString &s)
121{ 200{
122 NormalizePrint_wstr(s); 201 UString tempU;
202 AString tempA;
203 NormalizePrint_UString_Path(s, tempU, tempA);
123} 204}
124 205
125void CStdOutStream::NormalizePrint_wstr(const wchar_t *s) 206void CStdOutStream::NormalizePrint_wstr_Path(const wchar_t *s)
126{ 207{
127 UString tempU = s; 208 UString tempU = s;
128 Normalize_UString(tempU); 209 Normalize_UString_Path(tempU);
129 AString tempA; 210 AString tempA;
130 PrintUString(tempU, tempA); 211 PrintUString(tempU, tempA);
131} 212}
132 213
214void CStdOutStream::NormalizePrint_UString(const UString &s)
215{
216 UString tempU = s;
217 Normalize_UString(tempU);
218 AString tempA;
219 PrintUString(tempU, tempA);
220}
133 221
134CStdOutStream & CStdOutStream::operator<<(Int32 number) throw() 222CStdOutStream & CStdOutStream::operator<<(Int32 number) throw()
135{ 223{
diff --git a/CPP/Common/StdOutStream.h b/CPP/Common/StdOutStream.h
index bd15d7c..846b0db 100644
--- a/CPP/Common/StdOutStream.h
+++ b/CPP/Common/StdOutStream.h
@@ -14,6 +14,7 @@ class CStdOutStream
14 // bool _streamIsOpen; 14 // bool _streamIsOpen;
15public: 15public:
16 bool IsTerminalMode; 16 bool IsTerminalMode;
17 CBoolPair ListPathSeparatorSlash;
17 int CodePage; 18 int CodePage;
18 19
19 CStdOutStream(FILE *stream = NULL): 20 CStdOutStream(FILE *stream = NULL):
@@ -21,7 +22,14 @@ public:
21 // _streamIsOpen(false), 22 // _streamIsOpen(false),
22 IsTerminalMode(false), 23 IsTerminalMode(false),
23 CodePage(-1) 24 CodePage(-1)
24 {} 25 {
26 ListPathSeparatorSlash.Val =
27#ifdef _WIN32
28 false;
29#else
30 true;
31#endif
32 }
25 33
26 // ~CStdOutStream() { Close(); } 34 // ~CStdOutStream() { Close(); }
27 35
@@ -62,12 +70,13 @@ public:
62 void PrintUString(const UString &s, AString &temp); 70 void PrintUString(const UString &s, AString &temp);
63 void Convert_UString_to_AString(const UString &src, AString &dest); 71 void Convert_UString_to_AString(const UString &src, AString &dest);
64 72
65 void Normalize_UString_LF_Allowed(UString &s);
66 void Normalize_UString(UString &s); 73 void Normalize_UString(UString &s);
74 void Normalize_UString_Path(UString &s);
67 75
68 void NormalizePrint_UString(const UString &s, UString &tempU, AString &tempA); 76 void NormalizePrint_UString_Path(const UString &s, UString &tempU, AString &tempA);
77 void NormalizePrint_UString_Path(const UString &s);
69 void NormalizePrint_UString(const UString &s); 78 void NormalizePrint_UString(const UString &s);
70 void NormalizePrint_wstr(const wchar_t *s); 79 void NormalizePrint_wstr_Path(const wchar_t *s);
71}; 80};
72 81
73CStdOutStream & endl(CStdOutStream & outStream) throw(); 82CStdOutStream & endl(CStdOutStream & outStream) throw();
diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp
index f25396a..79ff9e0 100644
--- a/CPP/Common/StringConvert.cpp
+++ b/CPP/Common/StringConvert.cpp
@@ -267,8 +267,10 @@ void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)
267 267
268 if (codePage == CP_UTF8 || g_ForceToUTF8) 268 if (codePage == CP_UTF8 || g_ForceToUTF8)
269 { 269 {
270#if 1
270 ConvertUTF8ToUnicode(src, dest); 271 ConvertUTF8ToUnicode(src, dest);
271 return; 272 return;
273#endif
272 } 274 }
273 275
274 const size_t limit = ((size_t)src.Len() + 1) * 2; 276 const size_t limit = ((size_t)src.Len() + 1) * 2;
@@ -278,48 +280,47 @@ void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)
278 { 280 {
279 dest.ReleaseBuf_SetEnd((unsigned)len); 281 dest.ReleaseBuf_SetEnd((unsigned)len);
280 282
281 #if WCHAR_MAX > 0xffff 283#if WCHAR_MAX > 0xffff
282 d = dest.GetBuf(); 284 d = dest.GetBuf();
283 for (size_t i = 0;; i++) 285 for (size_t i = 0;; i++)
284 { 286 {
285 // wchar_t c = dest[i];
286 wchar_t c = d[i]; 287 wchar_t c = d[i];
288 // printf("\ni=%2d c = %4x\n", (unsigned)i, (unsigned)c);
287 if (c == 0) 289 if (c == 0)
288 break; 290 break;
289 if (c >= 0x10000 && c < 0x110000) 291 if (c >= 0x10000 && c < 0x110000)
290 { 292 {
291 /* 293 UString tempString = d + i;
292 c -= 0x10000; 294 const wchar_t *t = tempString.Ptr();
293 unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF);
294 dest.ReplaceOneCharAtPos(i, c0);
295 i++;
296 c = 0xdc00 + (c & 0x3FF);
297 dest.Insert_wchar_t(i, c);
298 */
299 UString temp = d + i;
300 295
301 for (size_t t = 0;; t++) 296 for (;;)
302 { 297 {
303 wchar_t w = temp[t]; 298 wchar_t w = *t++;
299 // printf("\nchar=%x\n", w);
304 if (w == 0) 300 if (w == 0)
305 break; 301 break;
306 if (i == limit) 302 if (i == limit)
307 break; // unexpected error 303 break; // unexpected error
308 if (w >= 0x10000 && w < 0x110000) 304 if (w >= 0x10000 && w < 0x110000)
309 { 305 {
306#if 1
310 if (i + 1 == limit) 307 if (i + 1 == limit)
311 break; // unexpected error 308 break; // unexpected error
312 w -= 0x10000; 309 w -= 0x10000;
313 d[i++] = (unsigned)0xd800 + (((unsigned)w >> 10) & 0x3FF); 310 d[i++] = (unsigned)0xd800 + (((unsigned)w >> 10) & 0x3ff);
314 w = 0xdc00 + (w & 0x3FF); 311 w = 0xdc00 + (w & 0x3ff);
312#else
313 // w = '_'; // for debug
314#endif
315 } 315 }
316 d[i++] = w; 316 d[i++] = w;
317 } 317 }
318 dest.ReleaseBuf_SetEnd((unsigned)i); 318 dest.ReleaseBuf_SetEnd((unsigned)i);
319 break;
319 } 320 }
320 } 321 }
321 322
322 #endif 323#endif
323 324
324 /* 325 /*
325 printf("\nMultiByteToUnicodeString2 (%d) %s\n", (int)src.Len(), src.Ptr()); 326 printf("\nMultiByteToUnicodeString2 (%d) %s\n", (int)src.Len(), src.Ptr());
@@ -395,34 +396,39 @@ static void UnicodeStringToMultiByte2(AString &dest, const UString &src2, UINT c
395 // if (codePage == 1234567) // for debug purposes 396 // if (codePage == 1234567) // for debug purposes
396 if (codePage == CP_UTF8 || g_ForceToUTF8) 397 if (codePage == CP_UTF8 || g_ForceToUTF8)
397 { 398 {
399#if 1
398 defaultCharWasUsed = false; 400 defaultCharWasUsed = false;
399 ConvertUnicodeToUTF8(src2, dest); 401 ConvertUnicodeToUTF8(src2, dest);
400 return; 402 return;
403#endif
401 } 404 }
402 405
403 UString src = src2; 406 UString src = src2;
404 #if WCHAR_MAX > 0xffff 407#if WCHAR_MAX > 0xffff
405 { 408 {
406 src.Empty(); 409 src.Empty();
407 for (unsigned i = 0; i < src2.Len();) 410 for (unsigned i = 0; i < src2.Len();)
408 { 411 {
409 wchar_t c = src2[i]; 412 wchar_t c = src2[i++];
410 if (c >= 0xd800 && c < 0xdc00 && i + 1 != src2.Len()) 413 if (c >= 0xd800 && c < 0xdc00 && i != src2.Len())
411 { 414 {
412 const wchar_t c2 = src2[i + 1]; 415 const wchar_t c2 = src2[i];
413 if (c2 >= 0xdc00 && c2 < 0x10000) 416 if (c2 >= 0xdc00 && c2 < 0xe000)
414 { 417 {
418#if 1
415 // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2); 419 // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2);
416 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); 420 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
417 // printf("%4x\n", (int)c); 421 // printf("%4x\n", (int)c);
418 i++; 422 i++;
423#else
424 // c = '_'; // for debug
425#endif
419 } 426 }
420 } 427 }
421 src += c; 428 src += c;
422 i++;
423 } 429 }
424 } 430 }
425 #endif 431#endif
426 432
427 dest.Empty(); 433 dest.Empty();
428 defaultCharWasUsed = false; 434 defaultCharWasUsed = false;
diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp
index bc4926e..ba8a81b 100644
--- a/CPP/Common/StringToInt.cpp
+++ b/CPP/Common/StringToInt.cpp
@@ -2,57 +2,63 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include <limits.h>
6#if defined(_MSC_VER) && (_MSC_VER >= 1600)
7#include <stdint.h> // for WCHAR_MAX in vs2022
8#endif
9
5#include "StringToInt.h" 10#include "StringToInt.h"
6 11
7static const UInt32 k_UInt32_max = 0xFFFFFFFF; 12static const UInt32 k_UInt32_max = 0xFFFFFFFF;
8static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF); 13static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF);
9// static const UInt64 k_UInt64_max = (UInt64)(Int64)-1; 14// static const UInt64 k_UInt64_max = (UInt64)(Int64)-1;
10 15
16#define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)(charTypeUnsigned)digit - '0')
17// #define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)digit - '0')
18// #define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)(digit - '0'))
19
11#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \ 20#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \
12 uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \ 21uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \
22 if (end) *end = s; \
23 uintType res = 0; \
24 for (;; s++) { \
25 const unsigned v = DIGIT_TO_VALUE(charTypeUnsigned, *s); \
26 if (v > 9) { if (end) *end = s; return res; } \
27 if (res > (k_ ## uintType ## _max) / 10) return 0; \
28 res *= 10; \
29 if (res > (k_ ## uintType ## _max) - v) return 0; \
30 res += v; }}
31
32// arm-linux-gnueabi GCC compilers give (WCHAR_MAX > UINT_MAX) by some unknown reason
33// so we don't use this branch
34#if 0 && WCHAR_MAX > UINT_MAX
35/*
36 if (sizeof(wchar_t) > sizeof(unsigned)
37 we must use CONVERT_STRING_TO_UINT_FUNC_SLOW
38 But we just stop compiling instead.
39 We need some real cases to test this code.
40*/
41#error Stop_Compiling_WCHAR_MAX_IS_LARGER_THAN_UINT_MAX
42#define CONVERT_STRING_TO_UINT_FUNC_SLOW(uintType, charType, charTypeUnsigned) \
43uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \
13 if (end) *end = s; \ 44 if (end) *end = s; \
14 uintType res = 0; \ 45 uintType res = 0; \
15 for (;; s++) { \ 46 for (;; s++) { \
16 charTypeUnsigned c = (charTypeUnsigned)*s; \ 47 const charTypeUnsigned c = (charTypeUnsigned)*s; \
17 if (c < '0' || c > '9') { if (end) *end = s; return res; } \ 48 if (c < '0' || c > '9') { if (end) *end = s; return res; } \
18 if (res > (k_ ## uintType ## _max) / 10) return 0; \ 49 if (res > (k_ ## uintType ## _max) / 10) return 0; \
19 res *= 10; \ 50 res *= 10; \
20 unsigned v = (unsigned)(c - '0'); \ 51 const unsigned v = (unsigned)(c - '0'); \
21 if (res > (k_ ## uintType ## _max) - v) return 0; \ 52 if (res > (k_ ## uintType ## _max) - v) return 0; \
22 res += v; }} 53 res += v; }}
54#endif
55
23 56
24CONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte) 57CONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte)
25CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t) 58CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t)
26CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte) 59CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte)
27CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t) 60CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t)
28 61
29/*
30Int32 ConvertStringToInt32(const char *s, const char **end) throw()
31{
32 if (end)
33 *end = s;
34 const char *s2 = s;
35 if (*s == '-')
36 s2++;
37 if (*s2 == 0)
38 return 0;
39 const char *end2;
40 UInt32 res = ConvertStringToUInt32(s2, &end2);
41 if (*s == '-')
42 {
43 if (res > ((UInt32)1 << (32 - 1)))
44 return 0;
45 }
46 else if ((res & ((UInt32)1 << (32 - 1))) != 0)
47 return 0;
48 if (end)
49 *end = end2;
50 if (*s == '-')
51 return -(Int32)res;
52 return (Int32)res;
53}
54*/
55
56Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw() 62Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw()
57{ 63{
58 if (end) 64 if (end)
@@ -60,112 +66,89 @@ Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw()
60 const wchar_t *s2 = s; 66 const wchar_t *s2 = s;
61 if (*s == '-') 67 if (*s == '-')
62 s2++; 68 s2++;
63 if (*s2 == 0)
64 return 0;
65 const wchar_t *end2; 69 const wchar_t *end2;
66 UInt32 res = ConvertStringToUInt32(s2, &end2); 70 UInt32 res = ConvertStringToUInt32(s2, &end2);
67 if (*s == '-') 71 if (s2 == end2)
72 return 0;
73 if (s != s2)
68 { 74 {
69 if (res > ((UInt32)1 << (32 - 1))) 75 if (res > (UInt32)1 << (32 - 1))
76 return 0;
77 res = 0 - res;
78 }
79 else
80 {
81 if (res & (UInt32)1 << (32 - 1))
70 return 0; 82 return 0;
71 } 83 }
72 else if ((res & ((UInt32)1 << (32 - 1))) != 0)
73 return 0;
74 if (end) 84 if (end)
75 *end = end2; 85 *end = end2;
76 if (*s == '-')
77 return -(Int32)res;
78 return (Int32)res; 86 return (Int32)res;
79} 87}
80 88
81UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw() 89
82{ 90#define CONVERT_OCT_STRING_TO_UINT_FUNC(uintType) \
83 if (end) 91uintType ConvertOctStringTo ## uintType(const char *s, const char **end) throw() \
84 *end = s; 92{ \
85 UInt32 res = 0; 93 if (end) *end = s; \
86 for (;; s++) 94 uintType res = 0; \
87 { 95 for (;; s++) { \
88 unsigned c = (unsigned char)*s; 96 const unsigned c = (unsigned)(Byte)*s - '0'; \
89 if (c < '0' || c > '7') 97 if (c > 7) { \
90 { 98 if (end) \
91 if (end) 99 *end = s; \
92 *end = s; 100 return res; \
93 return res; 101 } \
94 } 102 if (res & (uintType)7 << (sizeof(uintType) * 8 - 3)) \
95 if ((res & (UInt32)7 << (32 - 3)) != 0) 103 return 0; \
96 return 0; 104 res <<= 3; \
97 res <<= 3; 105 res |= c; \
98 res |= (unsigned)(c - '0'); 106 } \
99 }
100} 107}
101 108
102UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw() 109CONVERT_OCT_STRING_TO_UINT_FUNC(UInt32)
103{ 110CONVERT_OCT_STRING_TO_UINT_FUNC(UInt64)
104 if (end) 111
105 *end = s; 112
106 UInt64 res = 0; 113#define CONVERT_HEX_STRING_TO_UINT_FUNC(uintType) \
107 for (;; s++) 114uintType ConvertHexStringTo ## uintType(const char *s, const char **end) throw() \
108 { 115{ \
109 unsigned c = (unsigned char)*s; 116 if (end) *end = s; \
110 if (c < '0' || c > '7') 117 uintType res = 0; \
111 { 118 for (;; s++) { \
112 if (end) 119 unsigned c = (unsigned)(Byte)*s; \
113 *end = s; 120 Z7_PARSE_HEX_DIGIT(c, { if (end) *end = s; return res; }) \
114 return res; 121 if (res & (uintType)0xF << (sizeof(uintType) * 8 - 4)) \
115 } 122 return 0; \
116 if ((res & (UInt64)7 << (64 - 3)) != 0) 123 res <<= 4; \
117 return 0; 124 res |= c; \
118 res <<= 3; 125 } \
119 res |= (unsigned)(c - '0');
120 }
121} 126}
122 127
123UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw() 128CONVERT_HEX_STRING_TO_UINT_FUNC(UInt32)
129CONVERT_HEX_STRING_TO_UINT_FUNC(UInt64)
130
131const char *FindNonHexChar(const char *s) throw()
124{ 132{
125 if (end) 133 for (;;)
126 *end = s;
127 UInt32 res = 0;
128 for (;; s++)
129 { 134 {
130 unsigned c = (Byte)*s; 135 unsigned c = (Byte)*s++; // pointer can go 1 byte after end
131 unsigned v; 136 c -= '0';
132 if (c >= '0' && c <= '9') v = (c - '0'); 137 if (c <= 9)
133 else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); 138 continue;
134 else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); 139 c -= 'A' - '0';
135 else 140 c &= ~0x20u;
136 { 141 if (c > 5)
137 if (end) 142 return s - 1;
138 *end = s;
139 return res;
140 }
141 if ((res & (UInt32)0xF << (32 - 4)) != 0)
142 return 0;
143 res <<= 4;
144 res |= v;
145 } 143 }
146} 144}
147 145
148UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw() 146Byte *ParseHexString(const char *s, Byte *dest) throw()
149{ 147{
150 if (end) 148 for (;;)
151 *end = s;
152 UInt64 res = 0;
153 for (;; s++)
154 { 149 {
155 unsigned c = (Byte)*s; 150 unsigned v0 = (Byte)s[0]; Z7_PARSE_HEX_DIGIT(v0, return dest;)
156 unsigned v; 151 unsigned v1 = (Byte)s[1]; s += 2; Z7_PARSE_HEX_DIGIT(v1, return dest;)
157 if (c >= '0' && c <= '9') v = (c - '0'); 152 *dest++ = (Byte)(v1 | (v0 << 4));
158 else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');
159 else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a');
160 else
161 {
162 if (end)
163 *end = s;
164 return res;
165 }
166 if ((res & (UInt64)0xF << (64 - 4)) != 0)
167 return 0;
168 res <<= 4;
169 res |= v;
170 } 153 }
171} 154}
diff --git a/CPP/Common/StringToInt.h b/CPP/Common/StringToInt.h
index c9dce7d..31ab274 100644
--- a/CPP/Common/StringToInt.h
+++ b/CPP/Common/StringToInt.h
@@ -19,4 +19,20 @@ UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw();
19UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw(); 19UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw();
20UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw(); 20UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw();
21 21
22#define Z7_PARSE_HEX_DIGIT(c, err_op) \
23{ c -= '0'; \
24 if (c > 9) { \
25 c -= 'A' - '0'; \
26 c &= ~0x20u; \
27 if (c > 5) { err_op } \
28 c += 10; \
29 } \
30}
31
32const char *FindNonHexChar(const char *s) throw();
33
34// in: (dest != NULL)
35// returns: pointer in dest array after last written byte
36Byte *ParseHexString(const char *s, Byte *dest) throw();
37
22#endif 38#endif
diff --git a/CPP/Common/TextConfig.cpp b/CPP/Common/TextConfig.cpp
index d3e561c..5714e46 100644
--- a/CPP/Common/TextConfig.cpp
+++ b/CPP/Common/TextConfig.cpp
@@ -90,15 +90,14 @@ bool GetTextConfig(const AString &s, CObjectVector<CTextConfigPair> &pairs)
90 c = s[pos++]; 90 c = s[pos++];
91 switch (c) 91 switch (c)
92 { 92 {
93 case 'n': message += '\n'; break; 93 case 'n': c = '\n'; break;
94 case 't': message += '\t'; break; 94 case 't': c = '\t'; break;
95 case '\\': message += '\\'; break; 95 case '\\': break;
96 case '\"': message += '\"'; break; 96 case '\"': break;
97 default: message += '\\'; message += c; break; 97 default: message += '\\'; break;
98 } 98 }
99 } 99 }
100 else 100 message += c;
101 message += c;
102 } 101 }
103 if (!ConvertUTF8ToUnicode(message, pair.String)) 102 if (!ConvertUTF8ToUnicode(message, pair.String))
104 return false; 103 return false;
diff --git a/CPP/Common/UTFConvert.cpp b/CPP/Common/UTFConvert.cpp
index fb166b7..509de76 100644
--- a/CPP/Common/UTFConvert.cpp
+++ b/CPP/Common/UTFConvert.cpp
@@ -135,7 +135,7 @@ we can place 128 ESCAPE chars to
135#endif 135#endif
136 136
137#define IS_SURROGATE_POINT(v) (((v) & (UInt32)0xfffff800) == 0xd800) 137#define IS_SURROGATE_POINT(v) (((v) & (UInt32)0xfffff800) == 0xd800)
138#define IS_LOW_SURROGATE_POINT(v) (((v) & (UInt32)0xfffffC00) == 0xdc00) 138#define IS_LOW_SURROGATE_POINT(v) (((v) & (UInt32)0xfffffc00) == 0xdc00)
139 139
140 140
141#define UTF_ERROR_UTF8_CHECK \ 141#define UTF_ERROR_UTF8_CHECK \
@@ -168,14 +168,14 @@ void CUtf8Check::Check_Buf(const char *src, size_t size) throw()
168 if (c < 0x80) 168 if (c < 0x80)
169 continue; 169 continue;
170 170
171 if (c < 0xc0 + 2) // it's limit for 0x140000 unicode codes : win32 compatibility 171 if (c < 0xc0 + 2)
172 UTF_ERROR_UTF8_CHECK 172 UTF_ERROR_UTF8_CHECK
173 173
174 unsigned numBytes; 174 unsigned numBytes;
175
176 UInt32 val = c; 175 UInt32 val = c;
177 MY_UTF8_HEAD_PARSE2(1) 176 MY_UTF8_HEAD_PARSE2(1)
178 else MY_UTF8_HEAD_PARSE2(2) 177 else MY_UTF8_HEAD_PARSE2(2)
178 else MY_UTF8_HEAD_PARSE2(3)
179 else MY_UTF8_HEAD_PARSE2(4) 179 else MY_UTF8_HEAD_PARSE2(4)
180 else MY_UTF8_HEAD_PARSE2(5) 180 else MY_UTF8_HEAD_PARSE2(5)
181 else 181 else
@@ -768,7 +768,7 @@ void Convert_UTF16_To_UTF32(const UString &src, UString &dest)
768 if (c >= 0xd800 && c < 0xdc00 && i < src.Len()) 768 if (c >= 0xd800 && c < 0xdc00 && i < src.Len())
769 { 769 {
770 const wchar_t c2 = src[i]; 770 const wchar_t c2 = src[i];
771 if (c2 >= 0xdc00 && c2 < 0x10000) 771 if (c2 >= 0xdc00 && c2 < 0xe000)
772 { 772 {
773 // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2); 773 // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2);
774 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); 774 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
diff --git a/CPP/Common/Xxh64Reg.cpp b/CPP/Common/Xxh64Reg.cpp
new file mode 100644
index 0000000..8abd15e
--- /dev/null
+++ b/CPP/Common/Xxh64Reg.cpp
@@ -0,0 +1,97 @@
1// Xxh64Reg.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/Xxh64.h"
6#include "../../C/CpuArch.h"
7
8// #define Z7_USE_HHX64_ORIGINAL
9#ifdef Z7_USE_HHX64_ORIGINAL
10#ifdef __clang__
11#include "../../C/zstd7z/7z_zstd_cmpl.h"
12#pragma GCC diagnostic ignored "-Wlanguage-extension-token"
13#endif
14#define XXH_STATIC_LINKING_ONLY
15#include "../../C/zstd7z/common/xxhash.h"
16#endif
17
18#include "../Common/MyCom.h"
19
20#include "../7zip/Common/RegisterCodec.h"
21
22Z7_CLASS_IMP_COM_1(
23 CXxh64Hasher
24 , IHasher
25)
26 CXxh64 _state;
27public:
28 Byte _mtDummy[1 << 7]; // it's public to eliminate clang warning: unused private field
29 CXxh64Hasher() { Init(); }
30};
31
32Z7_COM7F_IMF2(void, CXxh64Hasher::Init())
33{
34 Xxh64_Init(&_state);
35}
36
37Z7_COM7F_IMF2(void, CXxh64Hasher::Update(const void *data, UInt32 size))
38{
39#if 1
40 Xxh64_Update(&_state, data, size);
41#else // for debug:
42 for (;;)
43 {
44 if (size == 0)
45 return;
46 UInt32 size2 = (size * 0x85EBCA87) % size / 8;
47 if (size2 == 0)
48 size2 = 1;
49 Xxh64_Update(&_state, data, size2);
50 data = (const void *)((const Byte *)data + size2);
51 size -= size2;
52 }
53#endif
54}
55
56Z7_COM7F_IMF2(void, CXxh64Hasher::Final(Byte *digest))
57{
58 const UInt64 val = Xxh64_Digest(&_state);
59 SetUi64(digest, val)
60}
61
62REGISTER_HASHER(CXxh64Hasher, 0x211, "XXH64", 8)
63
64
65
66#ifdef Z7_USE_HHX64_ORIGINAL
67namespace NOriginal
68{
69Z7_CLASS_IMP_COM_1(
70 CXxh64Hasher
71 , IHasher
72)
73 XXH64_state_t _state;
74public:
75 Byte _mtDummy[1 << 7]; // it's public to eliminate clang warning: unused private field
76 CXxh64Hasher() { Init(); }
77};
78
79Z7_COM7F_IMF2(void, CXxh64Hasher::Init())
80{
81 XXH64_reset(&_state, 0);
82}
83
84Z7_COM7F_IMF2(void, CXxh64Hasher::Update(const void *data, UInt32 size))
85{
86 XXH64_update(&_state, data, size);
87}
88
89Z7_COM7F_IMF2(void, CXxh64Hasher::Final(Byte *digest))
90{
91 const UInt64 val = XXH64_digest(&_state);
92 SetUi64(digest, val)
93}
94
95REGISTER_HASHER(CXxh64Hasher, 0x212, "XXH64a", 8)
96}
97#endif
diff --git a/CPP/Windows/Control/Dialog.cpp b/CPP/Windows/Control/Dialog.cpp
index c8f1bd2..cbb000b 100644
--- a/CPP/Windows/Control/Dialog.cpp
+++ b/CPP/Windows/Control/Dialog.cpp
@@ -93,6 +93,7 @@ bool CDialog::OnButtonClicked(unsigned buttonID, HWND /* buttonHWND */)
93 case IDOK: OnOK(); break; 93 case IDOK: OnOK(); break;
94 case IDCANCEL: OnCancel(); break; 94 case IDCANCEL: OnCancel(); break;
95 case IDCLOSE: OnClose(); break; 95 case IDCLOSE: OnClose(); break;
96 case IDCONTINUE: OnContinue(); break;
96 case IDHELP: OnHelp(); break; 97 case IDHELP: OnHelp(); break;
97 default: return false; 98 default: return false;
98 } 99 }
diff --git a/CPP/Windows/Control/Dialog.h b/CPP/Windows/Control/Dialog.h
index 06be4bf..2510c8f 100644
--- a/CPP/Windows/Control/Dialog.h
+++ b/CPP/Windows/Control/Dialog.h
@@ -8,6 +8,10 @@
8namespace NWindows { 8namespace NWindows {
9namespace NControl { 9namespace NControl {
10 10
11#ifndef IDCONTINUE
12#define IDCONTINUE 11
13#endif
14
11class CDialog: public CWindow 15class CDialog: public CWindow
12{ 16{
13 // Z7_CLASS_NO_COPY(CDialog) 17 // Z7_CLASS_NO_COPY(CDialog)
@@ -64,14 +68,26 @@ public:
64 return window.GetText(s); 68 return window.GetText(s);
65 } 69 }
66 70
71/*
67 bool SetItemInt(unsigned itemID, UINT value, bool isSigned) 72 bool SetItemInt(unsigned itemID, UINT value, bool isSigned)
68 { return BOOLToBool(SetDlgItemInt(_window, (int)itemID, value, BoolToBOOL(isSigned))); } 73 { return BOOLToBool(SetDlgItemInt(_window, (int)itemID, value, BoolToBOOL(isSigned))); }
74*/
75 bool SetItemUInt(unsigned itemID, UINT value)
76 { return BOOLToBool(SetDlgItemInt(_window, (int)itemID, value, FALSE)); }
77/*
69 bool GetItemInt(unsigned itemID, bool isSigned, UINT &value) 78 bool GetItemInt(unsigned itemID, bool isSigned, UINT &value)
70 { 79 {
71 BOOL result; 80 BOOL result;
72 value = GetDlgItemInt(_window, (int)itemID, &result, BoolToBOOL(isSigned)); 81 value = GetDlgItemInt(_window, (int)itemID, &result, BoolToBOOL(isSigned));
73 return BOOLToBool(result); 82 return BOOLToBool(result);
74 } 83 }
84*/
85 bool GetItemUInt(unsigned itemID, UINT &value)
86 {
87 BOOL result;
88 value = GetDlgItemInt(_window, (int)itemID, &result, FALSE);
89 return BOOLToBool(result);
90 }
75 91
76 HWND GetNextGroupItem(HWND control, bool previous) 92 HWND GetNextGroupItem(HWND control, bool previous)
77 { return GetNextDlgGroupItem(_window, control, BoolToBOOL(previous)); } 93 { return GetNextDlgGroupItem(_window, control, BoolToBOOL(previous)); }
@@ -126,6 +142,7 @@ public:
126 142
127 virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND); 143 virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND);
128 virtual void OnOK() {} 144 virtual void OnOK() {}
145 virtual void OnContinue() {}
129 virtual void OnCancel() {} 146 virtual void OnCancel() {}
130 virtual void OnClose() {} 147 virtual void OnClose() {}
131 virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */) { return false; } 148 virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */) { return false; }
@@ -157,6 +174,7 @@ public:
157 bool Create(LPCWSTR templateName, HWND parentWindow); 174 bool Create(LPCWSTR templateName, HWND parentWindow);
158 #endif 175 #endif
159 virtual void OnOK() Z7_override { Destroy(); } 176 virtual void OnOK() Z7_override { Destroy(); }
177 virtual void OnContinue() Z7_override { Destroy(); }
160 virtual void OnCancel() Z7_override { Destroy(); } 178 virtual void OnCancel() Z7_override { Destroy(); }
161 virtual void OnClose() Z7_override { Destroy(); } 179 virtual void OnClose() Z7_override { Destroy(); }
162}; 180};
@@ -172,6 +190,7 @@ public:
172 190
173 bool End(INT_PTR result) { return BOOLToBool(::EndDialog(_window, result)); } 191 bool End(INT_PTR result) { return BOOLToBool(::EndDialog(_window, result)); }
174 virtual void OnOK() Z7_override { End(IDOK); } 192 virtual void OnOK() Z7_override { End(IDOK); }
193 virtual void OnContinue() Z7_override { End(IDCONTINUE); }
175 virtual void OnCancel() Z7_override { End(IDCANCEL); } 194 virtual void OnCancel() Z7_override { End(IDCANCEL); }
176 virtual void OnClose() Z7_override { End(IDCLOSE); } 195 virtual void OnClose() Z7_override { End(IDCLOSE); }
177}; 196};
diff --git a/CPP/Windows/Control/PropertyPage.cpp b/CPP/Windows/Control/PropertyPage.cpp
index f8effe6..9b36cbe 100644
--- a/CPP/Windows/Control/PropertyPage.cpp
+++ b/CPP/Windows/Control/PropertyPage.cpp
@@ -141,7 +141,7 @@ INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndPare
141 sheet.pszCaption = titleA; 141 sheet.pszCaption = titleA;
142 sheet.nPages = pagesA.Size(); 142 sheet.nPages = pagesA.Size();
143 sheet.nStartPage = 0; 143 sheet.nStartPage = 0;
144 sheet.ppsp = (LPCPROPSHEETPAGEA)(const void *)&pagesA.Front(); 144 sheet.ppsp = (LPCPROPSHEETPAGEA)(const void *)pagesA.ConstData();
145 sheet.pfnCallback = NULL; 145 sheet.pfnCallback = NULL;
146 return ::PropertySheetA(&sheet); 146 return ::PropertySheetA(&sheet);
147 } 147 }
@@ -156,7 +156,7 @@ INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndPare
156 sheet.pszCaption = title; 156 sheet.pszCaption = title;
157 sheet.nPages = pagesW.Size(); 157 sheet.nPages = pagesW.Size();
158 sheet.nStartPage = 0; 158 sheet.nStartPage = 0;
159 sheet.ppsp = (LPCPROPSHEETPAGEW)(const void *)&pagesW.Front(); 159 sheet.ppsp = (LPCPROPSHEETPAGEW)(const void *)pagesW.ConstData();
160 sheet.pfnCallback = NULL; 160 sheet.pfnCallback = NULL;
161 return ::PropertySheetW(&sheet); 161 return ::PropertySheetW(&sheet);
162 } 162 }
diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp
index b2499ec..025df17 100644
--- a/CPP/Windows/DLL.cpp
+++ b/CPP/Windows/DLL.cpp
@@ -61,14 +61,14 @@ bool CLibrary::Load(CFSTR path) throw()
61 61
62bool MyGetModuleFileName(FString &path) 62bool MyGetModuleFileName(FString &path)
63{ 63{
64 HMODULE hModule = g_hInstance; 64 const HMODULE hModule = g_hInstance;
65 path.Empty(); 65 path.Empty();
66 #ifndef _UNICODE 66 #ifndef _UNICODE
67 if (!g_IsNT) 67 if (!g_IsNT)
68 { 68 {
69 TCHAR s[MAX_PATH + 2]; 69 TCHAR s[MAX_PATH + 2];
70 s[0] = 0; 70 s[0] = 0;
71 DWORD size = ::GetModuleFileName(hModule, s, MAX_PATH + 1); 71 const DWORD size = ::GetModuleFileName(hModule, s, MAX_PATH + 1);
72 if (size <= MAX_PATH && size != 0) 72 if (size <= MAX_PATH && size != 0)
73 { 73 {
74 path = fas2fs(s); 74 path = fas2fs(s);
@@ -80,7 +80,7 @@ bool MyGetModuleFileName(FString &path)
80 { 80 {
81 WCHAR s[MAX_PATH + 2]; 81 WCHAR s[MAX_PATH + 2];
82 s[0] = 0; 82 s[0] = 0;
83 DWORD size = ::GetModuleFileNameW(hModule, s, MAX_PATH + 1); 83 const DWORD size = ::GetModuleFileNameW(hModule, s, MAX_PATH + 1);
84 if (size <= MAX_PATH && size != 0) 84 if (size <= MAX_PATH && size != 0)
85 { 85 {
86 path = us2fs(s); 86 path = us2fs(s);
@@ -97,7 +97,7 @@ FString GetModuleDirPrefix()
97 FString s; 97 FString s;
98 if (MyGetModuleFileName(s)) 98 if (MyGetModuleFileName(s))
99 { 99 {
100 int pos = s.ReverseFind_PathSepar(); 100 const int pos = s.ReverseFind_PathSepar();
101 if (pos >= 0) 101 if (pos >= 0)
102 s.DeleteFrom((unsigned)(pos + 1)); 102 s.DeleteFrom((unsigned)(pos + 1));
103 } 103 }
@@ -114,7 +114,6 @@ FString GetModuleDirPrefix()
114 114
115#include <dlfcn.h> 115#include <dlfcn.h>
116#include <stdlib.h> 116#include <stdlib.h>
117#include "../Common/Common.h"
118 117
119// FARPROC 118// FARPROC
120void *GetProcAddress(HMODULE module, LPCSTR procName) 119void *GetProcAddress(HMODULE module, LPCSTR procName)
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
index 5b1f340..dfeed82 100644
--- a/CPP/Windows/FileDir.cpp
+++ b/CPP/Windows/FileDir.cpp
@@ -37,7 +37,12 @@ static bool FiTime_To_timespec(const CFiTime *ft, timespec &ts)
37{ 37{
38 if (ft) 38 if (ft)
39 { 39 {
40#if defined(_AIX)
41 ts.tv_sec = ft->tv_sec;
42 ts.tv_nsec = ft->tv_nsec;
43#else
40 ts = *ft; 44 ts = *ft;
45#endif
41 return true; 46 return true;
42 } 47 }
43 // else 48 // else
@@ -246,6 +251,11 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
246} 251}
247 252
248#ifndef UNDER_CE 253#ifndef UNDER_CE
254#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // Win2000
255#define Z7_USE_DYN_CreateHardLink
256#endif
257
258#ifdef Z7_USE_DYN_CreateHardLink
249EXTERN_C_BEGIN 259EXTERN_C_BEGIN
250typedef BOOL (WINAPI *Func_CreateHardLinkW)( 260typedef BOOL (WINAPI *Func_CreateHardLinkW)(
251 LPCWSTR lpFileName, 261 LPCWSTR lpFileName,
@@ -253,6 +263,7 @@ typedef BOOL (WINAPI *Func_CreateHardLinkW)(
253 LPSECURITY_ATTRIBUTES lpSecurityAttributes 263 LPSECURITY_ATTRIBUTES lpSecurityAttributes
254 ); 264 );
255EXTERN_C_END 265EXTERN_C_END
266#endif
256#endif // UNDER_CE 267#endif // UNDER_CE
257 268
258bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) 269bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
@@ -270,6 +281,7 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
270 else 281 else
271 #endif 282 #endif
272 { 283 {
284#ifdef Z7_USE_DYN_CreateHardLink
273 const 285 const
274 Func_CreateHardLinkW 286 Func_CreateHardLinkW
275 my_CreateHardLinkW = Z7_GET_PROC_ADDRESS( 287 my_CreateHardLinkW = Z7_GET_PROC_ADDRESS(
@@ -277,9 +289,13 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
277 "CreateHardLinkW"); 289 "CreateHardLinkW");
278 if (!my_CreateHardLinkW) 290 if (!my_CreateHardLinkW)
279 return false; 291 return false;
292 #define MY_CreateHardLinkW my_CreateHardLinkW
293#else
294 #define MY_CreateHardLinkW CreateHardLinkW
295#endif
280 IF_USE_MAIN_PATH_2(newFileName, existFileName) 296 IF_USE_MAIN_PATH_2(newFileName, existFileName)
281 { 297 {
282 if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL)) 298 if (MY_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL))
283 return true; 299 return true;
284 } 300 }
285 #ifdef Z7_LONG_PATH 301 #ifdef Z7_LONG_PATH
@@ -287,7 +303,7 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
287 { 303 {
288 UString d1, d2; 304 UString d1, d2;
289 if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2)) 305 if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2))
290 return BOOLToBool(my_CreateHardLinkW(d1, d2, NULL)); 306 return BOOLToBool(MY_CreateHardLinkW(d1, d2, NULL));
291 } 307 }
292 #endif 308 #endif
293 } 309 }
@@ -780,7 +796,7 @@ bool CreateTempFile2(CFSTR prefix, bool addRandom, AString &postfix, NIO::COutFi
780 unsigned k; 796 unsigned k;
781 for (k = 0; k < 8; k++) 797 for (k = 0; k < 8; k++)
782 { 798 {
783 const unsigned t = val & 0xF; 799 const unsigned t = (unsigned)val & 0xF;
784 val >>= 4; 800 val >>= 4;
785 s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); 801 s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
786 } 802 }
@@ -805,7 +821,7 @@ bool CreateTempFile2(CFSTR prefix, bool addRandom, AString &postfix, NIO::COutFi
805 } 821 }
806 if (outFile) 822 if (outFile)
807 { 823 {
808 if (outFile->Create(path, false)) 824 if (outFile->Create_NEW(path))
809 return true; 825 return true;
810 } 826 }
811 else 827 else
@@ -928,7 +944,7 @@ bool RemoveDir(CFSTR path)
928static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile) 944static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile)
929{ 945{
930 NWindows::NFile::NIO::COutFile outFile; 946 NWindows::NFile::NIO::COutFile outFile;
931 if (!outFile.Create(newFile, false)) 947 if (!outFile.Create_NEW(newFile))
932 return FALSE; 948 return FALSE;
933 949
934 NWindows::NFile::NIO::CInFile inFile; 950 NWindows::NFile::NIO::CInFile inFile;
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp
index c562a90..ca387f6 100644
--- a/CPP/Windows/FileFind.cpp
+++ b/CPP/Windows/FileFind.cpp
@@ -25,6 +25,14 @@ using namespace NName;
25 25
26#if defined(_WIN32) && !defined(UNDER_CE) 26#if defined(_WIN32) && !defined(UNDER_CE)
27 27
28#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0502 // Win2003
29#define Z7_USE_DYN_FindFirstStream
30#endif
31
32#ifdef Z7_USE_DYN_FindFirstStream
33
34Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
35
28EXTERN_C_BEGIN 36EXTERN_C_BEGIN
29 37
30typedef enum 38typedef enum
@@ -46,6 +54,12 @@ typedef BOOL (APIENTRY *Func_FindNextStreamW)(HANDLE findStream, LPVOID findStre
46 54
47EXTERN_C_END 55EXTERN_C_END
48 56
57#else
58
59#define MY_WIN32_FIND_STREAM_DATA WIN32_FIND_STREAM_DATA
60#define My_FindStreamInfoStandard FindStreamInfoStandard
61
62#endif
49#endif // defined(_WIN32) && !defined(UNDER_CE) 63#endif // defined(_WIN32) && !defined(UNDER_CE)
50 64
51 65
@@ -95,6 +109,86 @@ void CFileInfoBase::ClearBase() throw()
95 #endif 109 #endif
96} 110}
97 111
112
113bool CFileInfoBase::SetAs_StdInFile()
114{
115 ClearBase();
116 Size = (UInt64)(Int64)-1;
117 NTime::GetCurUtc_FiTime(MTime);
118 CTime = ATime = MTime;
119
120#ifdef _WIN32
121
122 /* in GUI mode : GetStdHandle(STD_INPUT_HANDLE) returns NULL,
123 and it doesn't set LastError. */
124#if 1
125 SetLastError(0);
126 const HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
127 if (!h || h == INVALID_HANDLE_VALUE)
128 {
129 if (GetLastError() == 0)
130 SetLastError(ERROR_INVALID_HANDLE);
131 return false;
132 }
133 BY_HANDLE_FILE_INFORMATION info;
134 if (GetFileInformationByHandle(h, &info)
135 && info.dwVolumeSerialNumber)
136 {
137 Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
138 // FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow;
139 // NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1;
140 Attrib = info.dwFileAttributes;
141 CTime = info.ftCreationTime;
142 ATime = info.ftLastAccessTime;
143 MTime = info.ftLastWriteTime;
144 }
145#if 0
146 printf(
147 "\ndwFileAttributes = %8x"
148 "\nftCreationTime = %8x"
149 "\nftLastAccessTime = %8x"
150 "\nftLastWriteTime = %8x"
151 "\ndwVolumeSerialNumber = %8x"
152 "\nnFileSizeHigh = %8x"
153 "\nnFileSizeLow = %8x"
154 "\nnNumberOfLinks = %8x"
155 "\nnFileIndexHigh = %8x"
156 "\nnFileIndexLow = %8x \n",
157 (unsigned)info.dwFileAttributes,
158 (unsigned)info.ftCreationTime.dwHighDateTime,
159 (unsigned)info.ftLastAccessTime.dwHighDateTime,
160 (unsigned)info.ftLastWriteTime.dwHighDateTime,
161 (unsigned)info.dwVolumeSerialNumber,
162 (unsigned)info.nFileSizeHigh,
163 (unsigned)info.nFileSizeLow,
164 (unsigned)info.nNumberOfLinks,
165 (unsigned)info.nFileIndexHigh,
166 (unsigned)info.nFileIndexLow);
167#endif
168#endif
169
170#else // non-Wiondow
171
172 mode = S_IFIFO | 0777; // 0755 : 0775 : 0664 : 0644 :
173#if 1
174 struct stat st;
175 if (fstat(0, &st) == 0)
176 {
177 SetFrom_stat(st);
178 if (!S_ISREG(st.st_mode)
179 // S_ISFIFO(st->st_mode)
180 || st.st_size == 0)
181 {
182 Size = (UInt64)(Int64)-1;
183 // mode = S_IFIFO | 0777;
184 }
185 }
186#endif
187#endif
188
189 return true;
190}
191
98bool CFileInfo::IsDots() const throw() 192bool CFileInfo::IsDots() const throw()
99{ 193{
100 if (!IsDir() || Name.IsEmpty()) 194 if (!IsDir() || Name.IsEmpty())
@@ -252,9 +346,11 @@ bool CFindFile::FindNext(CFileInfo &fi)
252//////////////////////////////// 346////////////////////////////////
253// AltStreams 347// AltStreams
254 348
349#ifdef Z7_USE_DYN_FindFirstStream
255static Func_FindFirstStreamW g_FindFirstStreamW; 350static Func_FindFirstStreamW g_FindFirstStreamW;
256static Func_FindNextStreamW g_FindNextStreamW; 351static Func_FindNextStreamW g_FindNextStreamW;
257 352#define MY_FindFirstStreamW g_FindFirstStreamW
353#define MY_FindNextStreamW g_FindNextStreamW
258static struct CFindStreamLoader 354static struct CFindStreamLoader
259{ 355{
260 CFindStreamLoader() 356 CFindStreamLoader()
@@ -268,6 +364,11 @@ static struct CFindStreamLoader
268 "FindNextStreamW"); 364 "FindNextStreamW");
269 } 365 }
270} g_FindStreamLoader; 366} g_FindStreamLoader;
367#else
368#define MY_FindFirstStreamW FindFirstStreamW
369#define MY_FindNextStreamW FindNextStreamW
370#endif
371
271 372
272bool CStreamInfo::IsMainStream() const throw() 373bool CStreamInfo::IsMainStream() const throw()
273{ 374{
@@ -320,16 +421,18 @@ bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)
320{ 421{
321 if (!Close()) 422 if (!Close())
322 return false; 423 return false;
424#ifdef Z7_USE_DYN_FindFirstStream
323 if (!g_FindFirstStreamW) 425 if (!g_FindFirstStreamW)
324 { 426 {
325 ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 427 ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
326 return false; 428 return false;
327 } 429 }
430#endif
328 { 431 {
329 MY_WIN32_FIND_STREAM_DATA sd; 432 MY_WIN32_FIND_STREAM_DATA sd;
330 SetLastError(0); 433 SetLastError(0);
331 IF_USE_MAIN_PATH 434 IF_USE_MAIN_PATH
332 _handle = g_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0); 435 _handle = MY_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0);
333 if (_handle == INVALID_HANDLE_VALUE) 436 if (_handle == INVALID_HANDLE_VALUE)
334 { 437 {
335 if (::GetLastError() == ERROR_HANDLE_EOF) 438 if (::GetLastError() == ERROR_HANDLE_EOF)
@@ -340,7 +443,7 @@ bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)
340 { 443 {
341 UString superPath; 444 UString superPath;
342 if (GetSuperPath(path, superPath, USE_MAIN_PATH)) 445 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
343 _handle = g_FindFirstStreamW(superPath, My_FindStreamInfoStandard, &sd, 0); 446 _handle = MY_FindFirstStreamW(superPath, My_FindStreamInfoStandard, &sd, 0);
344 } 447 }
345 #endif 448 #endif
346 } 449 }
@@ -353,14 +456,16 @@ bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)
353 456
354bool CFindStream::FindNext(CStreamInfo &si) 457bool CFindStream::FindNext(CStreamInfo &si)
355{ 458{
459#ifdef Z7_USE_DYN_FindFirstStream
356 if (!g_FindNextStreamW) 460 if (!g_FindNextStreamW)
357 { 461 {
358 ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 462 ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
359 return false; 463 return false;
360 } 464 }
465#endif
361 { 466 {
362 MY_WIN32_FIND_STREAM_DATA sd; 467 MY_WIN32_FIND_STREAM_DATA sd;
363 if (!g_FindNextStreamW(_handle, &sd)) 468 if (!MY_FindNextStreamW(_handle, &sd))
364 return false; 469 return false;
365 Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); 470 Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si);
366 } 471 }
@@ -622,7 +727,7 @@ bool CFileInfo::Find(CFSTR path, bool followLink)
622 727
623 FString s (path); 728 FString s (path);
624 s.Add_PathSepar(); 729 s.Add_PathSepar();
625 s += '*'; // CHAR_ANY_MASK 730 s.Add_Char('*'); // CHAR_ANY_MASK
626 bool isOK = false; 731 bool isOK = false;
627 if (finder.FindFirst(s, *this)) 732 if (finder.FindFirst(s, *this))
628 { 733 {
@@ -636,7 +741,7 @@ bool CFileInfo::Find(CFSTR path, bool followLink)
636 But it's possible that there are another items */ 741 But it's possible that there are another items */
637 } 742 }
638 { 743 {
639 DWORD attrib = GetFileAttrib(path); 744 const DWORD attrib = GetFileAttrib(path);
640 if (isOK || (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)) 745 if (isOK || (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0))
641 { 746 {
642 ClearBase(); 747 ClearBase();
@@ -763,7 +868,7 @@ bool DoesFileOrDirExist(CFSTR name)
763void CEnumerator::SetDirPrefix(const FString &dirPrefix) 868void CEnumerator::SetDirPrefix(const FString &dirPrefix)
764{ 869{
765 _wildcard = dirPrefix; 870 _wildcard = dirPrefix;
766 _wildcard += '*'; 871 _wildcard.Add_Char('*');
767} 872}
768 873
769bool CEnumerator::NextAny(CFileInfo &fi) 874bool CEnumerator::NextAny(CFileInfo &fi)
@@ -925,7 +1030,7 @@ bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings)
925 1030
926// ---------- POSIX ---------- 1031// ---------- POSIX ----------
927 1032
928static int MY__lstat(CFSTR path, struct stat *st, bool followLink) 1033static int MY_lstat(CFSTR path, struct stat *st, bool followLink)
929{ 1034{
930 memset(st, 0, sizeof(*st)); 1035 memset(st, 0, sizeof(*st));
931 int res; 1036 int res;
@@ -941,18 +1046,26 @@ static int MY__lstat(CFSTR path, struct stat *st, bool followLink)
941 // printf("\nstat\n"); 1046 // printf("\nstat\n");
942 res = stat(path, st); 1047 res = stat(path, st);
943 } 1048 }
944 /* 1049#if 0
945 printf("\nres = %d\n", res); 1050#if defined(__clang__) && __clang_major__ >= 14
946 printf("\n st_dev = %lld \n", (long long)(st->st_dev)); 1051 #pragma GCC diagnostic ignored "-Wc++98-compat-pedantic"
947 printf("\n st_ino = %lld \n", (long long)(st->st_ino)); 1052#endif
948 printf("\n st_mode = %lld \n", (long long)(st->st_mode)); 1053
949 printf("\n st_nlink = %lld \n", (long long)(st->st_nlink)); 1054 printf("\n st_dev = %lld", (long long)(st->st_dev));
950 printf("\n st_uid = %lld \n", (long long)(st->st_uid)); 1055 printf("\n st_ino = %lld", (long long)(st->st_ino));
951 printf("\n st_gid = %lld \n", (long long)(st->st_gid)); 1056 printf("\n st_mode = %llx", (long long)(st->st_mode));
952 printf("\n st_size = %lld \n", (long long)(st->st_size)); 1057 printf("\n st_nlink = %lld", (long long)(st->st_nlink));
953 printf("\n st_blksize = %lld \n", (long long)(st->st_blksize)); 1058 printf("\n st_uid = %lld", (long long)(st->st_uid));
954 printf("\n st_blocks = %lld \n", (long long)(st->st_blocks)); 1059 printf("\n st_gid = %lld", (long long)(st->st_gid));
955 */ 1060 printf("\n st_size = %lld", (long long)(st->st_size));
1061 printf("\n st_blksize = %lld", (long long)(st->st_blksize));
1062 printf("\n st_blocks = %lld", (long long)(st->st_blocks));
1063 printf("\n st_ctim = %lld", (long long)(ST_CTIME((*st)).tv_sec));
1064 printf("\n st_mtim = %lld", (long long)(ST_MTIME((*st)).tv_sec));
1065 printf("\n st_atim = %lld", (long long)(ST_ATIME((*st)).tv_sec));
1066 printf(S_ISFIFO(st->st_mode) ? "\n FIFO" : "\n NO FIFO");
1067 printf("\n");
1068#endif
956 1069
957 return res; 1070 return res;
958} 1071}
@@ -1006,7 +1119,7 @@ UInt32 Get_WinAttrib_From_stat(const struct stat &st)
1006} 1119}
1007*/ 1120*/
1008 1121
1009void CFileInfo::SetFrom_stat(const struct stat &st) 1122void CFileInfoBase::SetFrom_stat(const struct stat &st)
1010{ 1123{
1011 // IsDevice = false; 1124 // IsDevice = false;
1012 1125
@@ -1114,7 +1227,7 @@ int Uid_To_Uname(uid_t uid, AString &name)
1114bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink) 1227bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink)
1115{ 1228{
1116 struct stat st; 1229 struct stat st;
1117 if (MY__lstat(path, &st, followLink) != 0) 1230 if (MY_lstat(path, &st, followLink) != 0)
1118 return false; 1231 return false;
1119 // printf("\nFind_DontFill_Name : name=%s\n", path); 1232 // printf("\nFind_DontFill_Name : name=%s\n", path);
1120 SetFrom_stat(st); 1233 SetFrom_stat(st);
@@ -1145,7 +1258,7 @@ bool DoesFileExist_Raw(CFSTR name)
1145{ 1258{
1146 // FIXME for symbolic links. 1259 // FIXME for symbolic links.
1147 struct stat st; 1260 struct stat st;
1148 if (MY__lstat(name, &st, false) != 0) 1261 if (MY_lstat(name, &st, false) != 0)
1149 return false; 1262 return false;
1150 return !S_ISDIR(st.st_mode); 1263 return !S_ISDIR(st.st_mode);
1151} 1264}
@@ -1154,7 +1267,7 @@ bool DoesFileExist_FollowLink(CFSTR name)
1154{ 1267{
1155 // FIXME for symbolic links. 1268 // FIXME for symbolic links.
1156 struct stat st; 1269 struct stat st;
1157 if (MY__lstat(name, &st, true) != 0) 1270 if (MY_lstat(name, &st, true) != 0)
1158 return false; 1271 return false;
1159 return !S_ISDIR(st.st_mode); 1272 return !S_ISDIR(st.st_mode);
1160} 1273}
@@ -1162,7 +1275,7 @@ bool DoesFileExist_FollowLink(CFSTR name)
1162bool DoesDirExist(CFSTR name, bool followLink) 1275bool DoesDirExist(CFSTR name, bool followLink)
1163{ 1276{
1164 struct stat st; 1277 struct stat st;
1165 if (MY__lstat(name, &st, followLink) != 0) 1278 if (MY_lstat(name, &st, followLink) != 0)
1166 return false; 1279 return false;
1167 return S_ISDIR(st.st_mode); 1280 return S_ISDIR(st.st_mode);
1168} 1281}
@@ -1170,7 +1283,7 @@ bool DoesDirExist(CFSTR name, bool followLink)
1170bool DoesFileOrDirExist(CFSTR name) 1283bool DoesFileOrDirExist(CFSTR name)
1171{ 1284{
1172 struct stat st; 1285 struct stat st;
1173 if (MY__lstat(name, &st, false) != 0) 1286 if (MY_lstat(name, &st, false) != 0)
1174 return false; 1287 return false;
1175 return true; 1288 return true;
1176} 1289}
@@ -1192,10 +1305,10 @@ bool CDirEntry::IsDots() const throw()
1192 /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) 1305 /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)
1193 we can call fstatat() for that case, but we use only (Name) check here */ 1306 we can call fstatat() for that case, but we use only (Name) check here */
1194 1307
1195 #if !defined(_AIX) 1308#if !defined(_AIX) && !defined(__sun)
1196 if (Type != DT_DIR && Type != DT_UNKNOWN) 1309 if (Type != DT_DIR && Type != DT_UNKNOWN)
1197 return false; 1310 return false;
1198 #endif 1311#endif
1199 1312
1200 return Name.Len() != 0 1313 return Name.Len() != 0
1201 && Name.Len() <= 2 1314 && Name.Len() <= 2
@@ -1232,7 +1345,7 @@ bool CEnumerator::NextAny(CDirEntry &fi, bool &found)
1232 1345
1233 fi.iNode = de->d_ino; 1346 fi.iNode = de->d_ino;
1234 1347
1235 #if !defined(_AIX) 1348#if !defined(_AIX) && !defined(__sun)
1236 fi.Type = de->d_type; 1349 fi.Type = de->d_type;
1237 /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) 1350 /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)
1238 we can set (Type) from fstatat() in that case. 1351 we can set (Type) from fstatat() in that case.
@@ -1247,7 +1360,7 @@ bool CEnumerator::NextAny(CDirEntry &fi, bool &found)
1247 fi.Type = DT_DIR; 1360 fi.Type = DT_DIR;
1248 } 1361 }
1249 */ 1362 */
1250 #endif 1363#endif
1251 1364
1252 /* 1365 /*
1253 if (de->d_type == DT_DIR) 1366 if (de->d_type == DT_DIR)
@@ -1313,7 +1426,7 @@ bool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool f
1313 1426
1314 /* 1427 /*
1315 const FString path = _wildcard + s; 1428 const FString path = _wildcard + s;
1316 int res = MY__lstat(path, &st, followLink); 1429 int res = MY_lstat(path, &st, followLink);
1317 */ 1430 */
1318 1431
1319 if (res != 0) 1432 if (res != 0)
diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h
index 11408d0..f68673a 100644
--- a/CPP/Windows/FileFind.h
+++ b/CPP/Windows/FileFind.h
@@ -99,12 +99,12 @@ public:
99 99
100 CFileInfoBase() { ClearBase(); } 100 CFileInfoBase() { ClearBase(); }
101 void ClearBase() throw(); 101 void ClearBase() throw();
102 bool SetAs_StdInFile();
102 103
103 #ifdef _WIN32 104 #ifdef _WIN32
104 105
105 bool Fill_From_ByHandleFileInfo(CFSTR path); 106 bool Fill_From_ByHandleFileInfo(CFSTR path);
106 void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; } // |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16)); 107 void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; } // |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16));
107 void SetAsFile() { Attrib = 0; }
108 108
109 bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } 109 bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); }
110 bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } 110 bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); }
@@ -132,8 +132,8 @@ public:
132 UInt32 GetWinAttrib() const { return Get_WinAttribPosix_From_PosixMode(mode); } 132 UInt32 GetWinAttrib() const { return Get_WinAttribPosix_From_PosixMode(mode); }
133 133
134 bool IsDir() const { return S_ISDIR(mode); } 134 bool IsDir() const { return S_ISDIR(mode); }
135 void SetAsDir() { mode = S_IFDIR; } 135 void SetAsDir() { mode = S_IFDIR | 0777; }
136 void SetAsFile() { mode = S_IFREG; } 136 void SetFrom_stat(const struct stat &st);
137 137
138 bool IsReadOnly() const 138 bool IsReadOnly() const
139 { 139 {
@@ -173,7 +173,6 @@ struct CFileInfo: public CFileInfoBase
173 // bool FollowReparse(CFSTR path, bool isDir); 173 // bool FollowReparse(CFSTR path, bool isDir);
174 #else 174 #else
175 bool Find_DontFill_Name(CFSTR path, bool followLink = false); 175 bool Find_DontFill_Name(CFSTR path, bool followLink = false);
176 void SetFrom_stat(const struct stat &st);
177 #endif 176 #endif
178}; 177};
179 178
@@ -278,19 +277,19 @@ typedef CFileInfo CDirEntry;
278struct CDirEntry 277struct CDirEntry
279{ 278{
280 ino_t iNode; 279 ino_t iNode;
281 #if !defined(_AIX) 280#if !defined(_AIX) && !defined(__sun)
282 Byte Type; 281 Byte Type;
283 #endif 282#endif
284 FString Name; 283 FString Name;
285 284
286 /* 285 /*
287 #if !defined(_AIX) 286#if !defined(_AIX) && !defined(__sun)
288 bool IsDir() const 287 bool IsDir() const
289 { 288 {
290 // (Type == DT_UNKNOWN) on some systems 289 // (Type == DT_UNKNOWN) on some systems
291 return Type == DT_DIR; 290 return Type == DT_DIR;
292 } 291 }
293 #endif 292#endif
294 */ 293 */
295 294
296 bool IsDots() const throw(); 295 bool IsDots() const throw();
@@ -311,12 +310,12 @@ public:
311 bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const; 310 bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const;
312 bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const 311 bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const
313 { 312 {
314 #if !defined(_AIX) 313#if !defined(_AIX) && !defined(__sun)
315 if (de.Type == DT_DIR) 314 if (de.Type == DT_DIR)
316 return true; 315 return true;
317 if (de.Type != DT_UNKNOWN) 316 if (de.Type != DT_UNKNOWN)
318 return false; 317 return false;
319 #endif 318#endif
320 CFileInfo fileInfo; 319 CFileInfo fileInfo;
321 if (Fill_FileInfo(de, fileInfo, followLink)) 320 if (Fill_FileInfo(de, fileInfo, followLink))
322 { 321 {
diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp
index 4ecbb7e..dc4de14 100644
--- a/CPP/Windows/FileIO.cpp
+++ b/CPP/Windows/FileIO.cpp
@@ -141,8 +141,17 @@ bool CFileBase::Close() throw()
141{ 141{
142 if (_handle == INVALID_HANDLE_VALUE) 142 if (_handle == INVALID_HANDLE_VALUE)
143 return true; 143 return true;
144 if (!::CloseHandle(_handle)) 144#if 0
145 return false; 145 if (!IsStdStream)
146#endif
147 {
148 if (!::CloseHandle(_handle))
149 return false;
150 }
151#if 0
152 IsStdStream = false;
153 IsStdPipeStream = false;
154#endif
146 _handle = INVALID_HANDLE_VALUE; 155 _handle = INVALID_HANDLE_VALUE;
147 return true; 156 return true;
148} 157}
@@ -457,7 +466,7 @@ bool CInFile::Open(CFSTR fileName)
457// for 32 MB (maybe also for 16 MB). 466// for 32 MB (maybe also for 16 MB).
458// And message can be "Network connection was lost" 467// And message can be "Network connection was lost"
459 468
460static const UInt32 kChunkSizeMax = (1 << 22); 469static const UInt32 kChunkSizeMax = 1 << 22;
461 470
462bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw() 471bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw()
463{ 472{
@@ -469,8 +478,14 @@ bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw()
469 478
470bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw() 479bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw()
471{ 480{
481#if 0
482 const UInt32 chunkSizeMax = (0 || IsStdStream) ? (1 << 20) : kChunkSizeMax;
483 if (size > chunkSizeMax)
484 size = chunkSizeMax;
485#else
472 if (size > kChunkSizeMax) 486 if (size > kChunkSizeMax)
473 size = kChunkSizeMax; 487 size = kChunkSizeMax;
488#endif
474 return Read1(data, size, processedSize); 489 return Read1(data, size, processedSize);
475} 490}
476 491
@@ -486,10 +501,10 @@ bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw()
486 return false; 501 return false;
487 if (processedLoc == 0) 502 if (processedLoc == 0)
488 return true; 503 return true;
489 data = (void *)((unsigned char *)data + processedLoc); 504 data = (void *)((Byte *)data + processedLoc);
490 size -= processedLoc; 505 size -= processedLoc;
491 } 506 }
492 while (size > 0); 507 while (size);
493 return true; 508 return true;
494} 509}
495 510
@@ -506,29 +521,23 @@ bool CInFile::ReadFull(void *data, size_t size, size_t &processedSize) throw()
506 return false; 521 return false;
507 if (processedLoc == 0) 522 if (processedLoc == 0)
508 return true; 523 return true;
509 data = (void *)((unsigned char *)data + processedLoc); 524 data = (void *)((Byte *)data + processedLoc);
510 size -= processedLoc; 525 size -= processedLoc;
511 } 526 }
512 while (size > 0); 527 while (size);
513 return true; 528 return true;
514} 529}
515 530
516// ---------- COutFile --------- 531// ---------- COutFile ---------
517 532
518static inline DWORD GetCreationDisposition(bool createAlways)
519 { return createAlways? CREATE_ALWAYS: CREATE_NEW; }
520
521bool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) 533bool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
522 { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } 534 { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }
523 535
524bool COutFile::Open(CFSTR fileName, DWORD creationDisposition) 536bool COutFile::Open_Disposition(CFSTR fileName, DWORD creationDisposition)
525 { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } 537 { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }
526 538
527bool COutFile::Create(CFSTR fileName, bool createAlways) 539bool COutFile::Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes)
528 { return Open(fileName, GetCreationDisposition(createAlways)); } 540 { return Open(fileName, FILE_SHARE_READ, CREATE_ALWAYS, flagsAndAttributes); }
529
530bool COutFile::CreateAlways(CFSTR fileName, DWORD flagsAndAttributes)
531 { return Open(fileName, FILE_SHARE_READ, GetCreationDisposition(true), flagsAndAttributes); }
532 541
533bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() 542bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw()
534 { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } 543 { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); }
@@ -557,10 +566,10 @@ bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw
557 return false; 566 return false;
558 if (processedLoc == 0) 567 if (processedLoc == 0)
559 return true; 568 return true;
560 data = (const void *)((const unsigned char *)data + processedLoc); 569 data = (const void *)((const Byte *)data + processedLoc);
561 size -= processedLoc; 570 size -= processedLoc;
562 } 571 }
563 while (size != 0); 572 while (size);
564 return true; 573 return true;
565} 574}
566 575
@@ -574,10 +583,10 @@ bool COutFile::WriteFull(const void *data, size_t size) throw()
574 return false; 583 return false;
575 if (processedLoc == 0) 584 if (processedLoc == 0)
576 return (size == 0); 585 return (size == 0);
577 data = (const void *)((const unsigned char *)data + processedLoc); 586 data = (const void *)((const Byte *)data + processedLoc);
578 size -= processedLoc; 587 size -= processedLoc;
579 } 588 }
580 while (size != 0); 589 while (size);
581 return true; 590 return true;
582} 591}
583 592
@@ -786,11 +795,11 @@ bool CInFile::ReadFull(void *data, size_t size, size_t &processed) throw()
786 return false; 795 return false;
787 if (res == 0) 796 if (res == 0)
788 break; 797 break;
789 data = (void *)((unsigned char *)data + (size_t)res); 798 data = (void *)((Byte *)data + (size_t)res);
790 size -= (size_t)res;
791 processed += (size_t)res; 799 processed += (size_t)res;
800 size -= (size_t)res;
792 } 801 }
793 while (size > 0); 802 while (size);
794 return true; 803 return true;
795} 804}
796 805
@@ -798,23 +807,63 @@ bool CInFile::ReadFull(void *data, size_t size, size_t &processed) throw()
798///////////////////////// 807/////////////////////////
799// COutFile 808// COutFile
800 809
801bool COutFile::Create(const char *name, bool createAlways) 810bool COutFile::OpenBinary_forWrite_oflag(const char *name, int oflag)
802{ 811{
803 Path = name; // change it : set it only if open is success. 812 Path = name; // change it : set it only if open is success.
804 if (createAlways) 813 return OpenBinary(name, oflag, mode_for_Create);
805 {
806 Close();
807 _handle = ::creat(name, mode_for_Create);
808 return _handle != -1;
809 }
810 return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY, mode_for_Create);
811} 814}
812 815
813bool COutFile::Open(const char *name, DWORD creationDisposition) 816
817/*
818 windows exist non-exist posix
819 CREATE_NEW Fail Create O_CREAT | O_EXCL
820 CREATE_ALWAYS Trunc Create O_CREAT | O_TRUNC
821 OPEN_ALWAYS Open Create O_CREAT
822 OPEN_EXISTING Open Fail 0
823 TRUNCATE_EXISTING Trunc Fail O_TRUNC ???
824
825 // O_CREAT = If the file exists, this flag has no effect except as noted under O_EXCL below.
826 // If O_CREAT and O_EXCL are set, open() shall fail if the file exists.
827 // O_TRUNC : If the file exists and the file is successfully opened, its length shall be truncated to 0.
828*/
829bool COutFile::Open_EXISTING(const char *name)
830 { return OpenBinary_forWrite_oflag(name, O_WRONLY); }
831bool COutFile::Create_ALWAYS(const char *name)
832 { return OpenBinary_forWrite_oflag(name, O_WRONLY | O_CREAT | O_TRUNC); }
833bool COutFile::Create_NEW(const char *name)
834 { return OpenBinary_forWrite_oflag(name, O_WRONLY | O_CREAT | O_EXCL); }
835bool COutFile::Create_ALWAYS_or_Open_ALWAYS(const char *name, bool createAlways)
836{
837 return OpenBinary_forWrite_oflag(name,
838 createAlways ?
839 O_WRONLY | O_CREAT | O_TRUNC :
840 O_WRONLY | O_CREAT);
841}
842/*
843bool COutFile::Create_ALWAYS_or_NEW(const char *name, bool createAlways)
844{
845 return OpenBinary_forWrite_oflag(name,
846 createAlways ?
847 O_WRONLY | O_CREAT | O_TRUNC :
848 O_WRONLY | O_CREAT | O_EXCL);
849}
850bool COutFile::Open_Disposition(const char *name, DWORD creationDisposition)
814{ 851{
815 UNUSED_VAR(creationDisposition) // FIXME 852 int flag;
816 return Create(name, false); 853 switch (creationDisposition)
854 {
855 case CREATE_NEW: flag = O_WRONLY | O_CREAT | O_EXCL; break;
856 case CREATE_ALWAYS: flag = O_WRONLY | O_CREAT | O_TRUNC; break;
857 case OPEN_ALWAYS: flag = O_WRONLY | O_CREAT; break;
858 case OPEN_EXISTING: flag = O_WRONLY; break;
859 case TRUNCATE_EXISTING: flag = O_WRONLY | O_TRUNC; break;
860 default:
861 SetLastError(EINVAL);
862 return false;
863 }
864 return OpenBinary_forWrite_oflag(name, flag);
817} 865}
866*/
818 867
819ssize_t COutFile::write_part(const void *data, size_t size) throw() 868ssize_t COutFile::write_part(const void *data, size_t size) throw()
820{ 869{
@@ -833,11 +882,11 @@ ssize_t COutFile::write_full(const void *data, size_t size, size_t &processed) t
833 return res; 882 return res;
834 if (res == 0) 883 if (res == 0)
835 break; 884 break;
836 data = (const void *)((const unsigned char *)data + (size_t)res); 885 data = (const void *)((const Byte *)data + (size_t)res);
837 size -= (size_t)res;
838 processed += (size_t)res; 886 processed += (size_t)res;
887 size -= (size_t)res;
839 } 888 }
840 while (size > 0); 889 while (size);
841 return (ssize_t)processed; 890 return (ssize_t)processed;
842} 891}
843 892
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h
index 03e061a..6ba40eb 100644
--- a/CPP/Windows/FileIO.h
+++ b/CPP/Windows/FileIO.h
@@ -141,13 +141,24 @@ public:
141 141
142public: 142public:
143 bool PreserveATime; 143 bool PreserveATime;
144 #ifdef Z7_DEVICE_FILE 144#if 0
145 bool IsStdStream;
146 bool IsStdPipeStream;
147#endif
148#ifdef Z7_DEVICE_FILE
145 bool IsDeviceFile; 149 bool IsDeviceFile;
146 bool SizeDefined; 150 bool SizeDefined;
147 UInt64 Size; // it can be larger than real available size 151 UInt64 Size; // it can be larger than real available size
148 #endif 152#endif
149 153
150 CFileBase(): _handle(INVALID_HANDLE_VALUE), PreserveATime(false) {} 154 CFileBase():
155 _handle(INVALID_HANDLE_VALUE),
156 PreserveATime(false)
157#if 0
158 , IsStdStream(false),
159 , IsStdPipeStream(false)
160#endif
161 {}
151 ~CFileBase() { Close(); } 162 ~CFileBase() { Close(); }
152 163
153 HANDLE GetHandle() const { return _handle; } 164 HANDLE GetHandle() const { return _handle; }
@@ -223,6 +234,20 @@ public:
223 bool OpenShared(CFSTR fileName, bool shareForWrite); 234 bool OpenShared(CFSTR fileName, bool shareForWrite);
224 bool Open(CFSTR fileName); 235 bool Open(CFSTR fileName);
225 236
237#if 0
238 bool AttachStdIn()
239 {
240 IsDeviceFile = false;
241 const HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
242 if (h == INVALID_HANDLE_VALUE || !h)
243 return false;
244 IsStdStream = true;
245 IsStdPipeStream = true;
246 _handle = h;
247 return true;
248 }
249#endif
250
226 #ifndef UNDER_CE 251 #ifndef UNDER_CE
227 252
228 bool Open_for_ReadAttributes(CFSTR fileName) 253 bool Open_for_ReadAttributes(CFSTR fileName)
@@ -263,11 +288,21 @@ public:
263 288
264class COutFile: public CFileBase 289class COutFile: public CFileBase
265{ 290{
291 bool Open_Disposition(CFSTR fileName, DWORD creationDisposition);
266public: 292public:
267 bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); 293 bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
268 bool Open(CFSTR fileName, DWORD creationDisposition); 294 bool Open_EXISTING(CFSTR fileName)
269 bool Create(CFSTR fileName, bool createAlways); 295 { return Open_Disposition(fileName, OPEN_EXISTING); }
270 bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes); 296 bool Create_ALWAYS_or_Open_ALWAYS(CFSTR fileName, bool createAlways)
297 { return Open_Disposition(fileName, createAlways ? CREATE_ALWAYS : OPEN_ALWAYS); }
298 bool Create_ALWAYS_or_NEW(CFSTR fileName, bool createAlways)
299 { return Open_Disposition(fileName, createAlways ? CREATE_ALWAYS : CREATE_NEW); }
300 bool Create_ALWAYS(CFSTR fileName)
301 { return Open_Disposition(fileName, CREATE_ALWAYS); }
302 bool Create_NEW(CFSTR fileName)
303 { return Open_Disposition(fileName, CREATE_NEW); }
304
305 bool Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes);
271 306
272 bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw(); 307 bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw();
273 bool SetMTime(const CFiTime *mTime) throw(); 308 bool SetMTime(const CFiTime *mTime) throw();
@@ -308,8 +343,15 @@ protected:
308 bool OpenBinary(const char *name, int flags, mode_t mode = 0666); 343 bool OpenBinary(const char *name, int flags, mode_t mode = 0666);
309public: 344public:
310 bool PreserveATime; 345 bool PreserveATime;
346#if 0
347 bool IsStdStream;
348#endif
311 349
312 CFileBase(): _handle(-1), PreserveATime(false) {} 350 CFileBase(): _handle(-1), PreserveATime(false)
351#if 0
352 , IsStdStream(false)
353#endif
354 {}
313 ~CFileBase() { Close(); } 355 ~CFileBase() { Close(); }
314 // void Detach() { _handle = -1; } 356 // void Detach() { _handle = -1; }
315 bool Close(); 357 bool Close();
@@ -331,6 +373,15 @@ class CInFile: public CFileBase
331public: 373public:
332 bool Open(const char *name); 374 bool Open(const char *name);
333 bool OpenShared(const char *name, bool shareForWrite); 375 bool OpenShared(const char *name, bool shareForWrite);
376#if 0
377 bool AttachStdIn()
378 {
379 _handle = GetStdHandle(STD_INPUT_HANDLE);
380 if (_handle == INVALID_HANDLE_VALUE || !_handle)
381 return false;
382 IsStdStream = true;
383 }
384#endif
334 ssize_t read_part(void *data, size_t size) throw(); 385 ssize_t read_part(void *data, size_t size) throw();
335 // ssize_t read_full(void *data, size_t size, size_t &processed); 386 // ssize_t read_full(void *data, size_t size, size_t &processed);
336 bool ReadFull(void *data, size_t size, size_t &processedSize) throw(); 387 bool ReadFull(void *data, size_t size, size_t &processedSize) throw();
@@ -347,6 +398,7 @@ class COutFile: public CFileBase
347 398
348 AString Path; 399 AString Path;
349 ssize_t write_part(const void *data, size_t size) throw(); 400 ssize_t write_part(const void *data, size_t size) throw();
401 bool OpenBinary_forWrite_oflag(const char *name, int oflag);
350public: 402public:
351 mode_t mode_for_Create; 403 mode_t mode_for_Create;
352 404
@@ -358,8 +410,14 @@ public:
358 {} 410 {}
359 411
360 bool Close(); 412 bool Close();
361 bool Create(const char *name, bool createAlways); 413
362 bool Open(const char *name, DWORD creationDisposition); 414 bool Open_EXISTING(CFSTR fileName);
415 bool Create_ALWAYS_or_Open_ALWAYS(CFSTR fileName, bool createAlways);
416 bool Create_ALWAYS(CFSTR fileName);
417 bool Create_NEW(CFSTR fileName);
418 // bool Create_ALWAYS_or_NEW(CFSTR fileName, bool createAlways);
419 // bool Open_Disposition(const char *name, DWORD creationDisposition);
420
363 ssize_t write_full(const void *data, size_t size, size_t &processed) throw(); 421 ssize_t write_full(const void *data, size_t size, size_t &processed) throw();
364 422
365 bool WriteFull(const void *data, size_t size) throw() 423 bool WriteFull(const void *data, size_t size) throw()
diff --git a/CPP/Windows/FileLink.cpp b/CPP/Windows/FileLink.cpp
index 2b9fa1a..bb380ec 100644
--- a/CPP/Windows/FileLink.cpp
+++ b/CPP/Windows/FileLink.cpp
@@ -249,9 +249,13 @@ bool CReparseAttr::Parse(const Byte *p, size_t size)
249 if (size < 8) 249 if (size < 8)
250 return false; 250 return false;
251 Tag = Get32(p); 251 Tag = Get32(p);
252 UInt32 len = Get16(p + 4); 252 if (Get16(p + 6) != 0) // padding
253 if (len + 8 != size) 253 return false;
254 // if (len + 8 > size) 254 unsigned len = Get16(p + 4);
255 p += 8;
256 size -= 8;
257 if (len != size)
258 // if (len > size)
255 return false; 259 return false;
256 /* 260 /*
257 if ((type & kReparseFlags_Alias) == 0 || 261 if ((type & kReparseFlags_Alias) == 0 ||
@@ -259,8 +263,6 @@ bool CReparseAttr::Parse(const Byte *p, size_t size)
259 (type & 0xFFFF) != 3) 263 (type & 0xFFFF) != 3)
260 */ 264 */
261 265
262 if (Get16(p + 6) != 0) // padding
263 return false;
264 266
265 HeaderError = false; 267 HeaderError = false;
266 268
@@ -276,9 +278,6 @@ bool CReparseAttr::Parse(const Byte *p, size_t size)
276 278
277 TagIsUnknown = false; 279 TagIsUnknown = false;
278 280
279 p += 8;
280 size -= 8;
281
282 if (Tag == Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK) 281 if (Tag == Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK)
283 { 282 {
284 if (len < 4) 283 if (len < 4)
@@ -518,7 +517,7 @@ bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size)
518 { 517 {
519 CreatePrefixDirOfFile(path); 518 CreatePrefixDirOfFile(path);
520 COutFile file; 519 COutFile file;
521 if (!file.Create(path, CREATE_NEW)) 520 if (!file.Create_NEW(path))
522 return false; 521 return false;
523 } 522 }
524 } 523 }
diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp
index c9c4f8b..c16b3d4 100644
--- a/CPP/Windows/FileName.cpp
+++ b/CPP/Windows/FileName.cpp
@@ -302,13 +302,13 @@ int FindAltStreamColon(CFSTR path) throw()
302static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) 302static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s)
303{ 303{
304 // Network path: we look "server\path\" as root prefix 304 // Network path: we look "server\path\" as root prefix
305 int pos = FindSepar(s); 305 const int pos = FindSepar(s);
306 if (pos < 0) 306 if (pos < 0)
307 return 0; 307 return 0;
308 int pos2 = FindSepar(s + (unsigned)pos + 1); 308 const int pos2 = FindSepar(s + (unsigned)pos + 1);
309 if (pos2 < 0) 309 if (pos2 < 0)
310 return 0; 310 return 0;
311 return pos + pos2 + 2; 311 return (unsigned)pos + (unsigned)pos2 + 2;
312} 312}
313 313
314static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) 314static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s)
@@ -334,7 +334,7 @@ static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s)
334 const int pos = FindSepar(s + kSuperPathPrefixSize); 334 const int pos = FindSepar(s + kSuperPathPrefixSize);
335 if (pos < 0) 335 if (pos < 0)
336 return 0; 336 return 0;
337 return kSuperPathPrefixSize + pos + 1; 337 return kSuperPathPrefixSize + (unsigned)pos + 1;
338} 338}
339 339
340unsigned GetRootPrefixSize(CFSTR s) throw() 340unsigned GetRootPrefixSize(CFSTR s) throw()
diff --git a/CPP/Windows/FileSystem.cpp b/CPP/Windows/FileSystem.cpp
index 6a262d9..d11f02e 100644
--- a/CPP/Windows/FileSystem.cpp
+++ b/CPP/Windows/FileSystem.cpp
@@ -71,6 +71,12 @@ UINT MyGetDriveType(CFSTR pathName)
71 } 71 }
72} 72}
73 73
74#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0400
75// GetDiskFreeSpaceEx requires Windows95-OSR2, NT4
76#define Z7_USE_DYN_GetDiskFreeSpaceEx
77#endif
78
79#ifdef Z7_USE_DYN_GetDiskFreeSpaceEx
74typedef BOOL (WINAPI * Func_GetDiskFreeSpaceExA)( 80typedef BOOL (WINAPI * Func_GetDiskFreeSpaceExA)(
75 LPCSTR lpDirectoryName, // directory name 81 LPCSTR lpDirectoryName, // directory name
76 PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller 82 PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller
@@ -84,6 +90,7 @@ typedef BOOL (WINAPI * Func_GetDiskFreeSpaceExW)(
84 PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk 90 PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk
85 PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk 91 PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk
86); 92);
93#endif
87 94
88bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize) 95bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize)
89{ 96{
@@ -92,14 +99,22 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize,
92 #ifndef _UNICODE 99 #ifndef _UNICODE
93 if (!g_IsNT) 100 if (!g_IsNT)
94 { 101 {
102#ifdef Z7_USE_DYN_GetDiskFreeSpaceEx
95 const 103 const
96 Func_GetDiskFreeSpaceExA f = Z7_GET_PROC_ADDRESS( 104 Func_GetDiskFreeSpaceExA f = Z7_GET_PROC_ADDRESS(
97 Func_GetDiskFreeSpaceExA, GetModuleHandle(TEXT("kernel32.dll")), 105 Func_GetDiskFreeSpaceExA, GetModuleHandle(TEXT("kernel32.dll")),
98 "GetDiskFreeSpaceExA"); 106 "GetDiskFreeSpaceExA");
99 if (f) 107 if (f)
108#endif
100 { 109 {
101 ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2; 110 ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2;
102 sizeIsDetected = BOOLToBool(f(fs2fas(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2)); 111 sizeIsDetected = BOOLToBool(
112#ifdef Z7_USE_DYN_GetDiskFreeSpaceEx
113 f
114#else
115 GetDiskFreeSpaceExA
116#endif
117 (fs2fas(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2));
103 totalSize = totalSize2.QuadPart; 118 totalSize = totalSize2.QuadPart;
104 freeSize = freeSize2.QuadPart; 119 freeSize = freeSize2.QuadPart;
105 } 120 }
@@ -109,14 +124,22 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize,
109 else 124 else
110 #endif 125 #endif
111 { 126 {
127#ifdef Z7_USE_DYN_GetDiskFreeSpaceEx
112 const 128 const
113 Func_GetDiskFreeSpaceExW f = Z7_GET_PROC_ADDRESS( 129 Func_GetDiskFreeSpaceExW f = Z7_GET_PROC_ADDRESS(
114 Func_GetDiskFreeSpaceExW, GetModuleHandle(TEXT("kernel32.dll")), 130 Func_GetDiskFreeSpaceExW, GetModuleHandle(TEXT("kernel32.dll")),
115 "GetDiskFreeSpaceExW"); 131 "GetDiskFreeSpaceExW");
116 if (f) 132 if (f)
133#endif
117 { 134 {
118 ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2; 135 ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2;
119 sizeIsDetected = BOOLToBool(f(fs2us(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2)); 136 sizeIsDetected = BOOLToBool(
137#ifdef Z7_USE_DYN_GetDiskFreeSpaceEx
138 f
139#else
140 GetDiskFreeSpaceExW
141#endif
142 (fs2us(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2));
120 totalSize = totalSize2.QuadPart; 143 totalSize = totalSize2.QuadPart;
121 freeSize = freeSize2.QuadPart; 144 freeSize = freeSize2.QuadPart;
122 } 145 }
diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp
index 0bd7504..bc2d7c7 100644
--- a/CPP/Windows/MemoryLock.cpp
+++ b/CPP/Windows/MemoryLock.cpp
@@ -37,6 +37,8 @@ bool EnablePrivilege(LPCTSTR privilegeName, bool enable)
37 if (!hModule) 37 if (!hModule)
38 return false; 38 return false;
39 39
40Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
41
40 GET_PROC_ADDR( 42 GET_PROC_ADDR(
41 OpenProcessToken, 43 OpenProcessToken,
42 "OpenProcessToken") 44 "OpenProcessToken")
@@ -79,6 +81,7 @@ bool EnablePrivilege(LPCTSTR privilegeName, bool enable)
79} 81}
80 82
81 83
84Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
82 85
83typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *); 86typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
84 87
diff --git a/CPP/Windows/ProcessUtils.cpp b/CPP/Windows/ProcessUtils.cpp
index 607b4bb..f5e156c 100644
--- a/CPP/Windows/ProcessUtils.cpp
+++ b/CPP/Windows/ProcessUtils.cpp
@@ -17,7 +17,7 @@ static UString GetQuotedString(const UString &s)
17{ 17{
18 UString s2 ('\"'); 18 UString s2 ('\"');
19 s2 += s; 19 s2 += s;
20 s2 += '\"'; 20 s2.Add_Char('\"');
21 return s2; 21 return s2;
22} 22}
23#endif 23#endif
diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
index 457b1dc..678f970 100644
--- a/CPP/Windows/PropVariant.cpp
+++ b/CPP/Windows/PropVariant.cpp
@@ -252,6 +252,7 @@ CPropVariant::~CPropVariant() throw()
252 CASE_SIMPLE_VT_VALUES 252 CASE_SIMPLE_VT_VALUES
253 // vt = VT_EMPTY; // it's optional 253 // vt = VT_EMPTY; // it's optional
254 return; 254 return;
255 default: break;
255 } 256 }
256 ::VariantClear((tagVARIANT *)this); 257 ::VariantClear((tagVARIANT *)this);
257} 258}
@@ -296,6 +297,7 @@ HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()
296 CASE_SIMPLE_VT_VALUES 297 CASE_SIMPLE_VT_VALUES
297 memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); 298 memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));
298 return S_OK; 299 return S_OK;
300 default: break;
299 } 301 }
300 return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc)); 302 return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));
301} 303}
diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp
index 5fb96a7..21a7b4e 100644
--- a/CPP/Windows/PropVariantConv.cpp
+++ b/CPP/Windows/PropVariantConv.cpp
@@ -9,12 +9,45 @@
9 9
10#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } 10#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; }
11 11
12bool ConvertUtcFileTimeToString2(const FILETIME &utc, unsigned ns100, char *s, int level) throw() 12static const unsigned k_TimeStringBufferSize = 64;
13
14bool g_Timestamp_Show_UTC;
15#if 0
16bool g_Timestamp_Show_DisableZ;
17bool g_Timestamp_Show_TDelimeter;
18bool g_Timestamp_Show_ZoneOffset;
19#endif
20
21Z7_NO_INLINE
22bool ConvertUtcFileTimeToString2(const FILETIME &utc, unsigned ns100, char *s, int level, unsigned flags) throw()
13{ 23{
14 *s = 0; 24 *s = 0;
15 FILETIME ft; 25 FILETIME ft;
16 if (!FileTimeToLocalFileTime(&utc, &ft)) 26
17 return false; 27#if 0
28 Int64 bias64 = 0;
29#endif
30
31 const bool show_utc =
32 (flags & kTimestampPrintFlags_Force_UTC) ? true :
33 (flags & kTimestampPrintFlags_Force_LOCAL) ? false :
34 g_Timestamp_Show_UTC;
35
36 if (show_utc)
37 ft = utc;
38 else
39 {
40 if (!FileTimeToLocalFileTime(&utc, &ft))
41 return false;
42#if 0
43 if (g_Timestamp_Show_ZoneOffset)
44 {
45 const UInt64 utc64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime;
46 const UInt64 loc64 = (((UInt64) ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
47 bias64 = (Int64)utc64 - (Int64)loc64;
48 }
49#endif
50 }
18 51
19 SYSTEMTIME st; 52 SYSTEMTIME st;
20 if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) 53 if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))
@@ -41,7 +74,12 @@ bool ConvertUtcFileTimeToString2(const FILETIME &utc, unsigned ns100, char *s, i
41 74
42 if (level > kTimestampPrintLevel_DAY) 75 if (level > kTimestampPrintLevel_DAY)
43 { 76 {
44 UINT_TO_STR_2(' ', st.wHour) 77 const char setChar =
78#if 0
79 g_Timestamp_Show_TDelimeter ? 'T' : // ISO 8601
80#endif
81 ' ';
82 UINT_TO_STR_2(setChar, st.wHour)
45 UINT_TO_STR_2(':', st.wMinute) 83 UINT_TO_STR_2(':', st.wMinute)
46 84
47 if (level >= kTimestampPrintLevel_SEC) 85 if (level >= kTimestampPrintLevel_SEC)
@@ -84,6 +122,52 @@ bool ConvertUtcFileTimeToString2(const FILETIME &utc, unsigned ns100, char *s, i
84 } 122 }
85 } 123 }
86 124
125 if (show_utc)
126 {
127 if ((flags & kTimestampPrintFlags_DisableZ) == 0
128#if 0
129 && !g_Timestamp_Show_DisableZ
130#endif
131 )
132 *s++ = 'Z';
133 }
134#if 0
135 else if (g_Timestamp_Show_ZoneOffset)
136 {
137#if 1
138 {
139 char c;
140 if (bias64 < 0)
141 {
142 bias64 = -bias64;
143 c = '+';
144 }
145 else
146 c = '-';
147 UInt32 bias = (UInt32)((UInt64)bias64 / (10000000 * 60));
148#else
149 TIME_ZONE_INFORMATION zi;
150 const DWORD dw = GetTimeZoneInformation(&zi);
151 if (dw <= TIME_ZONE_ID_DAYLIGHT) // == 2
152 {
153 // UTC = LOCAL + Bias
154 Int32 bias = zi.Bias;
155 char c;
156 if (bias < 0)
157 {
158 bias = -bias;
159 c = '+';
160 }
161 else
162 c = '-';
163#endif
164 const UInt32 hours = (UInt32)bias / 60;
165 const UInt32 mins = (UInt32)bias % 60;
166 UINT_TO_STR_2(c, hours)
167 UINT_TO_STR_2(':', mins)
168 }
169 }
170#endif
87 *s = 0; 171 *s = 0;
88 return true; 172 return true;
89} 173}
@@ -96,11 +180,11 @@ bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw()
96 180
97bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *dest, int level) throw() 181bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *dest, int level) throw()
98{ 182{
99 char s[32]; 183 char s[k_TimeStringBufferSize];
100 bool res = ConvertUtcFileTimeToString2(ft, ns100, s, level); 184 const bool res = ConvertUtcFileTimeToString2(ft, ns100, s, level);
101 for (unsigned i = 0;; i++) 185 for (unsigned i = 0;; i++)
102 { 186 {
103 Byte c = (Byte)s[i]; 187 const Byte c = (Byte)s[i];
104 dest[i] = c; 188 dest[i] = c;
105 if (c == 0) 189 if (c == 0)
106 break; 190 break;
@@ -110,11 +194,11 @@ bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *de
110 194
111bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw() 195bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw()
112{ 196{
113 char s[32]; 197 char s[k_TimeStringBufferSize];
114 bool res = ConvertUtcFileTimeToString(ft, s, level); 198 const bool res = ConvertUtcFileTimeToString(ft, s, level);
115 for (unsigned i = 0;; i++) 199 for (unsigned i = 0;; i++)
116 { 200 {
117 Byte c = (Byte)s[i]; 201 const Byte c = (Byte)s[i];
118 dest[i] = c; 202 dest[i] = c;
119 if (c == 0) 203 if (c == 0)
120 break; 204 break;
diff --git a/CPP/Windows/PropVariantConv.h b/CPP/Windows/PropVariantConv.h
index ec5223b..8782507 100644
--- a/CPP/Windows/PropVariantConv.h
+++ b/CPP/Windows/PropVariantConv.h
@@ -7,6 +7,8 @@
7 7
8// provide at least 32 bytes for buffer including zero-end 8// provide at least 32 bytes for buffer including zero-end
9 9
10extern bool g_Timestamp_Show_UTC;
11
10#define kTimestampPrintLevel_DAY -3 12#define kTimestampPrintLevel_DAY -3
11// #define kTimestampPrintLevel_HOUR -2 13// #define kTimestampPrintLevel_HOUR -2
12#define kTimestampPrintLevel_MIN -1 14#define kTimestampPrintLevel_MIN -1
@@ -14,9 +16,14 @@
14#define kTimestampPrintLevel_NTFS 7 16#define kTimestampPrintLevel_NTFS 7
15#define kTimestampPrintLevel_NS 9 17#define kTimestampPrintLevel_NS 9
16 18
19
20#define kTimestampPrintFlags_Force_UTC (1 << 0)
21#define kTimestampPrintFlags_Force_LOCAL (1 << 1)
22#define kTimestampPrintFlags_DisableZ (1 << 4)
23
17bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw(); 24bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw();
18bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw(); 25bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw();
19bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, char *s, int level = kTimestampPrintLevel_SEC) throw(); 26bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, char *s, int level = kTimestampPrintLevel_SEC, unsigned flags = 0) throw();
20bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw(); 27bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw();
21 28
22// provide at least 32 bytes for buffer including zero-end 29// provide at least 32 bytes for buffer including zero-end
diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp
index b20157d..c8b1709 100644
--- a/CPP/Windows/Registry.cpp
+++ b/CPP/Windows/Registry.cpp
@@ -254,8 +254,8 @@ LONG CKey::QueryValue(LPCTSTR name, CSysString &value)
254{ 254{
255 value.Empty(); 255 value.Empty();
256 DWORD type = 0; 256 DWORD type = 0;
257 UInt32 curSize = 0; 257 DWORD curSize = 0;
258 LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&curSize); 258 LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, &curSize);
259 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 259 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
260 return res; 260 return res;
261 UInt32 curSize2 = curSize; 261 UInt32 curSize2 = curSize;
@@ -281,13 +281,11 @@ LONG CKey::QueryValue(LPCWSTR name, UString &value)
281{ 281{
282 value.Empty(); 282 value.Empty();
283 DWORD type = 0; 283 DWORD type = 0;
284 UInt32 curSize = 0; 284 DWORD curSize = 0;
285
286 LONG res; 285 LONG res;
287
288 if (g_IsNT) 286 if (g_IsNT)
289 { 287 {
290 res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&curSize); 288 res = RegQueryValueExW(_object, name, NULL, &type, NULL, &curSize);
291 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 289 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
292 return res; 290 return res;
293 UInt32 curSize2 = curSize; 291 UInt32 curSize2 = curSize;
@@ -302,7 +300,6 @@ LONG CKey::QueryValue(LPCWSTR name, UString &value)
302 res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp); 300 res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp);
303 value = GetUnicodeString(vTemp); 301 value = GetUnicodeString(vTemp);
304 } 302 }
305
306 return res; 303 return res;
307} 304}
308 305
@@ -377,7 +374,7 @@ LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)
377 strings.Clear(); 374 strings.Clear();
378 CByteBuffer buffer; 375 CByteBuffer buffer;
379 UInt32 dataSize = 0; 376 UInt32 dataSize = 0;
380 LONG res = QueryValue(valueName, buffer, dataSize); 377 const LONG res = QueryValue(valueName, buffer, dataSize);
381 if (res != ERROR_SUCCESS) 378 if (res != ERROR_SUCCESS)
382 return res; 379 return res;
383 if (dataSize > buffer.Size()) 380 if (dataSize > buffer.Size())
@@ -386,7 +383,7 @@ LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)
386 return E_FAIL; 383 return E_FAIL;
387 384
388 const wchar_t *data = (const wchar_t *)(const void *)(const Byte *)buffer; 385 const wchar_t *data = (const wchar_t *)(const void *)(const Byte *)buffer;
389 size_t numChars = dataSize / sizeof(wchar_t); 386 const size_t numChars = dataSize / sizeof(wchar_t);
390 size_t prev = 0; 387 size_t prev = 0;
391 UString s; 388 UString s;
392 389
diff --git a/CPP/Windows/SecurityUtils.h b/CPP/Windows/SecurityUtils.h
index 4ef3939..7219f06 100644
--- a/CPP/Windows/SecurityUtils.h
+++ b/CPP/Windows/SecurityUtils.h
@@ -18,6 +18,8 @@ typedef NTSTATUS (NTAPI *Func_LsaAddAccountRights)(LSA_HANDLE PolicyHandle,
18#define MY_STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L) 18#define MY_STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L)
19} 19}
20 20
21Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
22
21#define POLICY_FUNC_CALL(fff, str) \ 23#define POLICY_FUNC_CALL(fff, str) \
22 if (hModule == NULL) return MY_STATUS_NOT_IMPLEMENTED; \ 24 if (hModule == NULL) return MY_STATUS_NOT_IMPLEMENTED; \
23 const Func_ ## fff v = Z7_GET_PROC_ADDRESS(Func_ ## fff, hModule, str); \ 25 const Func_ ## fff v = Z7_GET_PROC_ADDRESS(Func_ ## fff, hModule, str); \
diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp
index b2a3489..01ceb22 100644
--- a/CPP/Windows/Shell.cpp
+++ b/CPP/Windows/Shell.cpp
@@ -162,7 +162,7 @@ static HRESULT ReadAnsiStrings(const char *p, size_t size, UStringVector &names)
162 name.Empty(); 162 name.Empty();
163 } 163 }
164 else 164 else
165 name += c; 165 name.Add_Char(c);
166 } 166 }
167 return E_INVALIDARG; 167 return E_INVALIDARG;
168} 168}
@@ -543,8 +543,18 @@ void CDrop::QueryFileNames(UStringVector &fileNames)
543typedef int Z7_WIN_GPFIDL_FLAGS; 543typedef int Z7_WIN_GPFIDL_FLAGS;
544 544
545extern "C" { 545extern "C" {
546typedef BOOL (WINAPI * Func_SHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath); 546#ifndef _UNICODE
547typedef BOOL (WINAPI * Func_SHGetPathFromIDListEx)(LPCITEMIDLIST pidl, PWSTR pszPath, DWORD cchPath, Z7_WIN_GPFIDL_FLAGS uOpts); 547typedef BOOL (WINAPI * Func_SHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath); // nt4
548#endif
549
550#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0600 // Vista
551#define Z7_USE_DYN_SHGetPathFromIDListEx
552#endif
553
554#ifdef Z7_USE_DYN_SHGetPathFromIDListEx
555Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
556typedef BOOL (WINAPI * Func_SHGetPathFromIDListEx)(LPCITEMIDLIST pidl, PWSTR pszPath, DWORD cchPath, Z7_WIN_GPFIDL_FLAGS uOpts); // vista
557#endif
548} 558}
549 559
550#ifndef _UNICODE 560#ifndef _UNICODE
@@ -584,18 +594,26 @@ bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
584 /* for long path we need SHGetPathFromIDListEx(). 594 /* for long path we need SHGetPathFromIDListEx().
585 win10: SHGetPathFromIDListEx() for long path returns path with 595 win10: SHGetPathFromIDListEx() for long path returns path with
586 with super path prefix "\\\\?\\". */ 596 with super path prefix "\\\\?\\". */
597#ifdef Z7_USE_DYN_SHGetPathFromIDListEx
587 const 598 const
588 Func_SHGetPathFromIDListEx 599 Func_SHGetPathFromIDListEx
589 func_SHGetPathFromIDListEx = Z7_GET_PROC_ADDRESS( 600 func_SHGetPathFromIDListEx = Z7_GET_PROC_ADDRESS(
590 Func_SHGetPathFromIDListEx, ::GetModuleHandleW(L"shell32.dll"), 601 Func_SHGetPathFromIDListEx, ::GetModuleHandleW(L"shell32.dll"),
591 "SHGetPathFromIDListEx"); 602 "SHGetPathFromIDListEx");
592 if (func_SHGetPathFromIDListEx) 603 if (func_SHGetPathFromIDListEx)
604#endif
593 { 605 {
594 ODS("==== GetPathFromIDList() (SHGetPathFromIDListEx)") 606 ODS("==== GetPathFromIDList() (SHGetPathFromIDListEx)")
595 do 607 do
596 { 608 {
597 len *= 4; 609 len *= 4;
598 result = BOOLToBool(func_SHGetPathFromIDListEx(itemIDList, path.GetBuf(len), len, 0)); 610 result = BOOLToBool(
611#ifdef Z7_USE_DYN_SHGetPathFromIDListEx
612 func_SHGetPathFromIDListEx
613#else
614 SHGetPathFromIDListEx
615#endif
616 (itemIDList, path.GetBuf(len), len, 0));
599 if (result) 617 if (result)
600 break; 618 break;
601 } 619 }
diff --git a/CPP/Windows/Shell.h b/CPP/Windows/Shell.h
index b4cdb30..9e58e25 100644
--- a/CPP/Windows/Shell.h
+++ b/CPP/Windows/Shell.h
@@ -3,7 +3,6 @@
3#ifndef ZIP7_WINDOWS_SHELL_H 3#ifndef ZIP7_WINDOWS_SHELL_H
4#define ZIP7_WINDOWS_SHELL_H 4#define ZIP7_WINDOWS_SHELL_H
5 5
6#include "../Common/Common.h"
7#include "../Common/MyWindows.h" 6#include "../Common/MyWindows.h"
8#if defined(__MINGW32__) || defined(__MINGW64__) 7#if defined(__MINGW32__) || defined(__MINGW64__)
9#include <shlobj.h> 8#include <shlobj.h>
diff --git a/CPP/Windows/StdAfx.h b/CPP/Windows/StdAfx.h
index bd5084f..4441a5f 100644
--- a/CPP/Windows/StdAfx.h
+++ b/CPP/Windows/StdAfx.h
@@ -6,7 +6,6 @@
6#if defined(_MSC_VER) && _MSC_VER >= 1800 6#if defined(_MSC_VER) && _MSC_VER >= 1800
7#pragma warning(disable : 4464) // relative include path contains '..' 7#pragma warning(disable : 4464) // relative include path contains '..'
8#endif 8#endif
9
10#include "../Common/Common.h" 9#include "../Common/Common.h"
11 10
12#endif 11#endif
diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h
index afd03d2..1df84d3 100644
--- a/CPP/Windows/Synchronization.h
+++ b/CPP/Windows/Synchronization.h
@@ -234,6 +234,11 @@ public:
234 } 234 }
235 WRes Enter() 235 WRes Enter()
236 { 236 {
237#if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13) \
238 && defined(__FreeBSD__)
239 #pragma GCC diagnostic ignored "-Wthread-safety-negative"
240 #pragma GCC diagnostic ignored "-Wthread-safety-analysis"
241#endif
237 return ::pthread_mutex_lock(&_mutex); 242 return ::pthread_mutex_lock(&_mutex);
238 } 243 }
239 WRes Leave() 244 WRes Leave()
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
index dbe287a..03c8988 100644
--- a/CPP/Windows/System.cpp
+++ b/CPP/Windows/System.cpp
@@ -5,7 +5,8 @@
5#ifndef _WIN32 5#ifndef _WIN32
6#include <unistd.h> 6#include <unistd.h>
7#include <limits.h> 7#include <limits.h>
8#ifdef __APPLE__ 8#if defined(__APPLE__) || defined(__DragonFly__) || \
9 defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
9#include <sys/sysctl.h> 10#include <sys/sysctl.h>
10#else 11#else
11#include <sys/sysinfo.h> 12#include <sys/sysinfo.h>
@@ -28,7 +29,10 @@ UInt32 CountAffinity(DWORD_PTR mask)
28{ 29{
29 UInt32 num = 0; 30 UInt32 num = 0;
30 for (unsigned i = 0; i < sizeof(mask) * 8; i++) 31 for (unsigned i = 0; i < sizeof(mask) * 8; i++)
31 num += (UInt32)((mask >> i) & 1); 32 {
33 num += (UInt32)(mask & 1);
34 mask >>= 1;
35 }
32 return num; 36 return num;
33} 37}
34 38
@@ -114,7 +118,7 @@ UInt32 GetNumberOfProcessors()
114#if !defined(_WIN64) && \ 118#if !defined(_WIN64) && \
115 (defined(__MINGW32_VERSION) || defined(Z7_OLD_WIN_SDK)) 119 (defined(__MINGW32_VERSION) || defined(Z7_OLD_WIN_SDK))
116 120
117typedef struct _MY_MEMORYSTATUSEX { 121typedef struct {
118 DWORD dwLength; 122 DWORD dwLength;
119 DWORD dwMemoryLoad; 123 DWORD dwMemoryLoad;
120 DWORDLONG ullTotalPhys; 124 DWORDLONG ullTotalPhys;
@@ -187,26 +191,58 @@ bool GetRamSize(UInt64 &size)
187{ 191{
188 size = (UInt64)(sizeof(size_t)) << 29; 192 size = (UInt64)(sizeof(size_t)) << 29;
189 193
190 #ifdef __APPLE__ 194#if defined(__APPLE__) || defined(__DragonFly__) || \
195 defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
196
197 uint64_t val = 0;
198 int mib[2];
199 mib[0] = CTL_HW;
191 200
192 #ifdef HW_MEMSIZE 201 #ifdef HW_MEMSIZE
193 uint64_t val = 0; // support 2Gb+ RAM 202 mib[1] = HW_MEMSIZE;
194 int mib[2] = { CTL_HW, HW_MEMSIZE }; 203 // printf("\n sysctl HW_MEMSIZE");
195 #elif defined(HW_PHYSMEM64) 204 #elif defined(HW_PHYSMEM64)
196 uint64_t val = 0; // support 2Gb+ RAM 205 mib[1] = HW_PHYSMEM64;
197 int mib[2] = { CTL_HW, HW_PHYSMEM64 }; 206 // printf("\n sysctl HW_PHYSMEM64");
198 #else 207 #else
199 unsigned int val = 0; // For old system 208 mib[1] = HW_PHYSMEM;
200 int mib[2] = { CTL_HW, HW_PHYSMEM }; 209 // printf("\n sysctl HW_PHYSMEM");
201 #endif // HW_MEMSIZE 210 #endif
202 size_t size_sys = sizeof(val);
203 211
204 sysctl(mib, 2, &val, &size_sys, NULL, 0); 212 size_t size_sys = sizeof(val);
205 if (val) 213 int res = sysctl(mib, 2, &val, &size_sys, NULL, 0);
206 size = val; 214 // printf("\n sysctl res=%d val=%llx size_sys = %d, %d\n", res, (long long int)val, (int)size_sys, errno);
215 // we use strict check (size_sys == sizeof(val)) for returned value
216 // because big-endian encoding is possible:
217 if (res == 0 && size_sys == sizeof(val) && val)
218 size = val;
219 else
220 {
221 uint32_t val32 = 0;
222 size_sys = sizeof(val32);
223 res = sysctl(mib, 2, &val32, &size_sys, NULL, 0);
224 // printf("\n sysctl res=%d val=%llx size_sys = %d, %d\n", res, (long long int)val32, (int)size_sys, errno);
225 if (res == 0 && size_sys == sizeof(val32) && val32)
226 size = val32;
227 }
207 228
208 #elif defined(_AIX) 229 #elif defined(_AIX)
209 // fixme 230 #if defined(_SC_AIX_REALMEM) // AIX
231 size = (UInt64)sysconf(_SC_AIX_REALMEM) * 1024;
232 #endif
233 #elif 0 || defined(__sun)
234 #if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
235 // FreeBSD, Linux, OpenBSD, and Solaris.
236 {
237 const long phys_pages = sysconf(_SC_PHYS_PAGES);
238 const long page_size = sysconf(_SC_PAGESIZE);
239 // #pragma message("GetRamSize : sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE)")
240 // printf("\n_SC_PHYS_PAGES (hex) = %lx", (unsigned long)phys_pages);
241 // printf("\n_SC_PAGESIZE = %lu\n", (unsigned long)page_size);
242 if (phys_pages != -1 && page_size != -1)
243 size = (UInt64)(Int64)phys_pages * (UInt64)(Int64)page_size;
244 }
245 #endif
210 #elif defined(__gnu_hurd__) 246 #elif defined(__gnu_hurd__)
211 // fixme 247 // fixme
212 #elif defined(__FreeBSD_kernel__) && defined(__GLIBC__) 248 #elif defined(__FreeBSD_kernel__) && defined(__GLIBC__)
@@ -218,10 +254,6 @@ bool GetRamSize(UInt64 &size)
218 if (::sysinfo(&info) != 0) 254 if (::sysinfo(&info) != 0)
219 return false; 255 return false;
220 size = (UInt64)info.mem_unit * info.totalram; 256 size = (UInt64)info.mem_unit * info.totalram;
221 const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1);
222 if (size > kLimit)
223 size = kLimit;
224
225 /* 257 /*
226 printf("\n mem_unit = %lld", (UInt64)info.mem_unit); 258 printf("\n mem_unit = %lld", (UInt64)info.mem_unit);
227 printf("\n totalram = %lld", (UInt64)info.totalram); 259 printf("\n totalram = %lld", (UInt64)info.totalram);
@@ -230,6 +262,10 @@ bool GetRamSize(UInt64 &size)
230 262
231 #endif 263 #endif
232 264
265 const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1);
266 if (size > kLimit)
267 size = kLimit;
268
233 return true; 269 return true;
234} 270}
235 271
@@ -269,7 +305,7 @@ unsigned Get_File_OPEN_MAX_Reduced_for_3_tasks()
269 numFiles_OPEN_MAX = 1; 305 numFiles_OPEN_MAX = 1;
270 numFiles_OPEN_MAX /= 3; // we suppose that we have up to 3 tasks in total for multiple file processing 306 numFiles_OPEN_MAX /= 3; // we suppose that we have up to 3 tasks in total for multiple file processing
271 numFiles_OPEN_MAX = MyMax(numFiles_OPEN_MAX, (unsigned long)3); 307 numFiles_OPEN_MAX = MyMax(numFiles_OPEN_MAX, (unsigned long)3);
272 unsigned n = (UInt32)(UInt32)-1; 308 unsigned n = (unsigned)(int)-1;
273 if (n > numFiles_OPEN_MAX) 309 if (n > numFiles_OPEN_MAX)
274 n = (unsigned)numFiles_OPEN_MAX; 310 n = (unsigned)numFiles_OPEN_MAX;
275 return n; 311 return n;
diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h
index 0650007..b17111c 100644
--- a/CPP/Windows/System.h
+++ b/CPP/Windows/System.h
@@ -105,7 +105,7 @@ struct CProcessAffinity
105 } 105 }
106 106
107 void CpuZero() { } 107 void CpuZero() { }
108 void CpuSet(unsigned cpuIndex) { UNUSED_VAR(cpuIndex); } 108 void CpuSet(unsigned /* cpuIndex */) { /* UNUSED_VAR(cpuIndex) */ }
109 int IsCpuSet(unsigned cpuIndex) const { return (cpuIndex < numSysThreads) ? 1 : 0; } 109 int IsCpuSet(unsigned cpuIndex) const { return (cpuIndex < numSysThreads) ? 1 : 0; }
110 110
111 BOOL SetProcAffinity() const 111 BOOL SetProcAffinity() const
diff --git a/CPP/Windows/SystemInfo.cpp b/CPP/Windows/SystemInfo.cpp
index 6bafc80..d23e84b 100644
--- a/CPP/Windows/SystemInfo.cpp
+++ b/CPP/Windows/SystemInfo.cpp
@@ -16,9 +16,28 @@
16#include <sys/utsname.h> 16#include <sys/utsname.h>
17#ifdef __APPLE__ 17#ifdef __APPLE__
18#include <sys/sysctl.h> 18#include <sys/sysctl.h>
19
19#elif !defined(_AIX) 20#elif !defined(_AIX)
20 21
22#if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)
23 #define Z7_GETAUXV_AVAILABLE
24#else
25// #pragma message("=== is not NEW GLIBC === ")
26 #if defined __has_include
27 #if __has_include (<sys/auxv.h>)
28// #pragma message("=== sys/auxv.h is avail=== ")
29 #define Z7_GETAUXV_AVAILABLE
30 #endif
31 #endif
32#endif
33
34#ifdef Z7_GETAUXV_AVAILABLE
35// #if defined __has_include
36// #if __has_include (<sys/auxv.h>)
21#include <sys/auxv.h> 37#include <sys/auxv.h>
38#define USE_HWCAP
39// #endif
40// #endif
22 41
23// #undef AT_HWCAP // to debug 42// #undef AT_HWCAP // to debug
24// #undef AT_HWCAP2 // to debug 43// #undef AT_HWCAP2 // to debug
@@ -36,11 +55,39 @@
36#endif 55#endif
37*/ 56*/
38 57
58#ifdef USE_HWCAP
59
60#if defined(__FreeBSD__)
61
62// #if (__FreeBSD__ >= 13) // (FreeBSD 12.01 is required for elf_aux_info() ???)
63static unsigned long MY_getauxval(int aux)
64{
65 unsigned long val;
66 if (elf_aux_info(aux, &val, sizeof(val)))
67 return 0;
68 return val;
69}
70
71#else // ! __FreeBSD__
72
39#ifdef MY_CPU_ARM_OR_ARM64 73#ifdef MY_CPU_ARM_OR_ARM64
74 #if defined __has_include
75 #if __has_include (<asm/hwcap.h>)
40#include <asm/hwcap.h> 76#include <asm/hwcap.h>
77 #endif
78 #endif
41#endif 79#endif
80
81#if defined(AT_HWCAP) || defined(AT_HWCAP2)
82#define MY_getauxval getauxval
42#endif 83#endif
43 84
85#endif // ! __FreeBSD__
86#endif // USE_HWCAP
87#endif // Z7_GETAUXV_AVAILABLE
88
89#endif // !defined(_AIX)
90
44#ifdef __linux__ 91#ifdef __linux__
45#include "../Windows/FileIO.h" 92#include "../Windows/FileIO.h"
46#endif 93#endif
@@ -70,13 +117,13 @@ static bool ReadFile_to_Buffer(CFSTR fileName, CByteBuffer &buf)
70 return false; 117 return false;
71 */ 118 */
72 size_t size = 0; 119 size_t size = 0;
73 size_t addSize = ((size_t)1 << 12); 120 size_t addSize = (size_t)1 << 12;
74 for (;;) 121 for (;;)
75 { 122 {
76 // printf("\nsize = %d\n", (unsigned)size); 123 // printf("\nsize = %d\n", (unsigned)size);
77 buf.ChangeSize_KeepData(size + addSize, size); 124 buf.ChangeSize_KeepData(size + addSize, size);
78 size_t processed; 125 size_t processed;
79 if (!file.ReadFull(buf + size, addSize, processed)) 126 if (!file.ReadFull(buf.NonConstData() + size, addSize, processed))
80 return false; 127 return false;
81 if (processed == 0) 128 if (processed == 0)
82 { 129 {
@@ -107,19 +154,19 @@ static void PrintCpuChars(AString &s, UInt32 v)
107{ 154{
108 for (unsigned j = 0; j < 4; j++) 155 for (unsigned j = 0; j < 4; j++)
109 { 156 {
110 Byte b = (Byte)(v & 0xFF); 157 const Byte b = (Byte)(v & 0xFF);
111 v >>= 8; 158 v >>= 8;
112 if (b == 0) 159 if (b == 0)
113 break; 160 break;
114 if (b >= 0x20 && b <= 0x7f) 161 if (b >= 0x20 && b <= 0x7f)
115 s += (char)b; 162 s.Add_Char((char)b);
116 else 163 else
117 { 164 {
118 s += '['; 165 s.Add_Char('[');
119 char temp[16]; 166 char temp[16];
120 ConvertUInt32ToHex(b, temp); 167 ConvertUInt32ToHex(b, temp);
121 s += temp; 168 s += temp;
122 s += ']'; 169 s.Add_Char(']');
123 } 170 }
124 } 171 }
125} 172}
@@ -137,7 +184,7 @@ static void x86cpuid_to_String(AString &s)
137 { 184 {
138 for (unsigned i = 0; i < 3; i++) 185 for (unsigned i = 0; i < 3; i++)
139 { 186 {
140 z7_x86_cpuid(a, 0x80000002 + i); 187 z7_x86_cpuid(a, (UInt32)(0x80000002 + i));
141 for (unsigned j = 0; j < 4; j++) 188 for (unsigned j = 0; j < 4; j++)
142 PrintCpuChars(s, a[j]); 189 PrintCpuChars(s, a[j]);
143 } 190 }
@@ -353,8 +400,8 @@ void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v)
353 } 400 }
354 s.Add_UInt64(v); 401 s.Add_UInt64(v);
355 if (c) 402 if (c)
356 s += c; 403 s.Add_Char(c);
357 s += 'B'; 404 s.Add_Char('B');
358} 405}
359// #endif 406// #endif
360// #endif 407// #endif
@@ -380,7 +427,7 @@ static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si)
380 s += " act:"; 427 s += " act:";
381 PrintHex(s, si.dwActiveProcessorMask); 428 PrintHex(s, si.dwActiveProcessorMask);
382 } 429 }
383 s += " cpus:"; 430 s += " threads:";
384 s.Add_UInt32(si.dwNumberOfProcessors); 431 s.Add_UInt32(si.dwNumberOfProcessors);
385 if (si.dwPageSize != 1 << 12) 432 if (si.dwPageSize != 1 << 12)
386 { 433 {
@@ -400,7 +447,7 @@ static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si)
400 if (minAdd != kReserveSize) 447 if (minAdd != kReserveSize)
401 { 448 {
402 PrintSize_KMGT_Or_Hex(s, minAdd); 449 PrintSize_KMGT_Or_Hex(s, minAdd);
403 s += "-"; 450 s.Add_Minus();
404 } 451 }
405 else 452 else
406 { 453 {
@@ -470,11 +517,10 @@ static void AddBracedString(AString &dest, AString &src)
470{ 517{
471 if (!src.IsEmpty()) 518 if (!src.IsEmpty())
472 { 519 {
473 AString s; 520 dest.Add_Space_if_NotEmpty();
474 s += '('; 521 dest.Add_Char('(');
475 s += src; 522 dest += src;
476 s += ')'; 523 dest.Add_Char(')');
477 dest.Add_OptSpaced(s);
478 } 524 }
479} 525}
480 526
@@ -527,6 +573,13 @@ void CCpuName::Fill()
527 { 573 {
528 Add_sysctlbyname_to_String("machdep.cpu.brand_string", s); 574 Add_sysctlbyname_to_String("machdep.cpu.brand_string", s);
529 } 575 }
576 #elif defined(MY_CPU_E2K) && defined(Z7_MCST_LCC_VERSION) && (Z7_MCST_LCC_VERSION >= 12323)
577 {
578 s += "mcst ";
579 s += __builtin_cpu_name();
580 s.Add_Space();
581 s += __builtin_cpu_arch();
582 }
530 #endif 583 #endif
531 584
532 585
@@ -592,11 +645,11 @@ void CCpuName::Fill()
592 const CByteBuffer &buf = bufs[i]; 645 const CByteBuffer &buf = bufs[i];
593 if (buf.Size() == 8) 646 if (buf.Size() == 8)
594 { 647 {
595 UInt32 high = GetUi32(buf); 648 const UInt32 high = GetUi32(buf);
596 if (high != 0) 649 if (high != 0)
597 { 650 {
598 PrintHex(Microcode, high); 651 PrintHex(Microcode, high);
599 Microcode += "."; 652 Microcode.Add_Dot();
600 } 653 }
601 PrintHex(Microcode, GetUi32(buf + 4)); 654 PrintHex(Microcode, GetUi32(buf + 4));
602 } 655 }
@@ -622,7 +675,7 @@ void AddCpuFeatures(AString &s)
622 UInt64 flags = 0; 675 UInt64 flags = 0;
623 for (unsigned i = 0; i < kNumFeatures; i++) 676 for (unsigned i = 0; i < kNumFeatures; i++)
624 { 677 {
625 if (IsProcessorFeaturePresent(i)) 678 if (IsProcessorFeaturePresent((DWORD)i))
626 { 679 {
627 flags += (UInt64)1 << i; 680 flags += (UInt64)1 << i;
628 // s.Add_Space_if_NotEmpty(); 681 // s.Add_Space_if_NotEmpty();
@@ -682,7 +735,7 @@ void AddCpuFeatures(AString &s)
682 #ifdef AT_HWCAP 735 #ifdef AT_HWCAP
683 s.Add_OptSpaced("hwcap:"); 736 s.Add_OptSpaced("hwcap:");
684 { 737 {
685 unsigned long h = getauxval(AT_HWCAP); 738 unsigned long h = MY_getauxval(AT_HWCAP);
686 PrintHex(s, h); 739 PrintHex(s, h);
687 #ifdef MY_CPU_ARM64 740 #ifdef MY_CPU_ARM64
688 if (h & HWCAP_CRC32) s += ":CRC32"; 741 if (h & HWCAP_CRC32) s += ":CRC32";
@@ -698,7 +751,7 @@ void AddCpuFeatures(AString &s)
698 751
699 #ifdef AT_HWCAP2 752 #ifdef AT_HWCAP2
700 { 753 {
701 unsigned long h = getauxval(AT_HWCAP2); 754 unsigned long h = MY_getauxval(AT_HWCAP2);
702 #ifndef MY_CPU_ARM 755 #ifndef MY_CPU_ARM
703 if (h != 0) 756 if (h != 0)
704 #endif 757 #endif
@@ -722,6 +775,8 @@ void AddCpuFeatures(AString &s)
722#ifdef _WIN32 775#ifdef _WIN32
723#ifndef UNDER_CE 776#ifndef UNDER_CE
724 777
778Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
779
725EXTERN_C_BEGIN 780EXTERN_C_BEGIN
726typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *); 781typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
727EXTERN_C_END 782EXTERN_C_END
@@ -952,24 +1007,13 @@ void GetVirtCpuid(AString &s)
952 1007
953void GetCompiler(AString &s) 1008void GetCompiler(AString &s)
954{ 1009{
955 #ifdef __VERSION__
956 s += __VERSION__;
957 #endif
958
959 #ifdef __GNUC__
960 s += " GCC ";
961 s.Add_UInt32(__GNUC__);
962 s.Add_Dot();
963 s.Add_UInt32(__GNUC_MINOR__);
964 s.Add_Dot();
965 s.Add_UInt32(__GNUC_PATCHLEVEL__);
966 #endif
967
968 #ifdef __clang__ 1010 #ifdef __clang__
969 s += " CLANG "; 1011 s += " CLANG ";
970 s.Add_UInt32(__clang_major__); 1012 s.Add_UInt32(__clang_major__);
971 s.Add_Dot(); 1013 s.Add_Dot();
972 s.Add_UInt32(__clang_minor__); 1014 s.Add_UInt32(__clang_minor__);
1015 s.Add_Dot();
1016 s.Add_UInt32(__clang_patchlevel__);
973 #endif 1017 #endif
974 1018
975 #ifdef __xlC__ 1019 #ifdef __xlC__
@@ -985,12 +1029,67 @@ void GetCompiler(AString &s)
985 #endif 1029 #endif
986 #endif 1030 #endif
987 1031
1032 // #define __LCC__ 126
1033 // #define __LCC_MINOR__ 20
1034 // #define __MCST__ 1
1035 #ifdef __MCST__
1036 s += " MCST";
1037 #endif
1038 #ifdef __LCC__
1039 s += " LCC ";
1040 s.Add_UInt32(__LCC__ / 100);
1041 s.Add_Dot();
1042 s.Add_UInt32(__LCC__ % 100 / 10);
1043 s.Add_UInt32(__LCC__ % 10);
1044 #ifdef __LCC_MINOR__
1045 s.Add_Dot();
1046 s.Add_UInt32(__LCC_MINOR__ / 10);
1047 s.Add_UInt32(__LCC_MINOR__ % 10);
1048 #endif
1049 #endif
1050
1051 // #define __EDG_VERSION__ 602
1052 #ifdef __EDG_VERSION__
1053 s += " EDG ";
1054 s.Add_UInt32(__EDG_VERSION__ / 100);
1055 s.Add_Dot();
1056 s.Add_UInt32(__EDG_VERSION__ % 100 / 10);
1057 s.Add_UInt32(__EDG_VERSION__ % 10);
1058 #endif
1059
1060 #ifdef __VERSION__
1061 s.Add_Space();
1062 s += "ver:";
1063 s += __VERSION__;
1064 #endif
1065
1066 #ifdef __GNUC__
1067 s += " GCC ";
1068 s.Add_UInt32(__GNUC__);
1069 s.Add_Dot();
1070 s.Add_UInt32(__GNUC_MINOR__);
1071 s.Add_Dot();
1072 s.Add_UInt32(__GNUC_PATCHLEVEL__);
1073 #endif
1074
1075
988 #ifdef _MSC_VER 1076 #ifdef _MSC_VER
989 s += " MSC "; 1077 s += " MSC ";
990 s.Add_UInt32(_MSC_VER); 1078 s.Add_UInt32(_MSC_VER);
1079 #ifdef _MSC_FULL_VER
1080 s.Add_Dot();
1081 s.Add_UInt32(_MSC_FULL_VER);
1082 #endif
1083
991 #endif 1084 #endif
992 1085
993 #if defined(__AVX2__) 1086 #if defined(__AVX512F__)
1087 #if defined(__AVX512VL__)
1088 #define MY_CPU_COMPILE_ISA "AVX512VL"
1089 #else
1090 #define MY_CPU_COMPILE_ISA "AVX512F"
1091 #endif
1092 #elif defined(__AVX2__)
994 #define MY_CPU_COMPILE_ISA "AVX2" 1093 #define MY_CPU_COMPILE_ISA "AVX2"
995 #elif defined(__AVX__) 1094 #elif defined(__AVX__)
996 #define MY_CPU_COMPILE_ISA "AVX" 1095 #define MY_CPU_COMPILE_ISA "AVX"
@@ -1014,9 +1113,61 @@ void GetCompiler(AString &s)
1014 #define MY_CPU_COMPILE_ISA "IA32" 1113 #define MY_CPU_COMPILE_ISA "IA32"
1015 #endif 1114 #endif
1016 1115
1116 AString s2;
1017 1117
1018 #ifdef MY_CPU_COMPILE_ISA 1118 #ifdef MY_CPU_COMPILE_ISA
1019 s += ':'; 1119 s2.Add_OptSpaced(MY_CPU_COMPILE_ISA);
1020 s.Add_OptSpaced(MY_CPU_COMPILE_ISA); 1120 #endif
1121
1122#ifndef MY_CPU_ARM64
1123 #ifdef __ARM_FP
1124 s2.Add_OptSpaced("FP");
1125 #endif
1126 #ifdef __ARM_NEON
1127 s2.Add_OptSpaced("NEON");
1021 #endif 1128 #endif
1129 #ifdef __NEON__
1130 s2.Add_OptSpaced("__NEON__");
1131 #endif
1132 #ifdef __ARM_FEATURE_SIMD32
1133 s2.Add_OptSpaced("SIMD32");
1134 #endif
1135#endif
1136
1137 #ifdef __ARM_FEATURE_CRYPTO
1138 s2.Add_OptSpaced("CRYPTO");
1139 #endif
1140
1141 #ifdef __ARM_FEATURE_SHA2
1142 s2.Add_OptSpaced("SHA2");
1143 #endif
1144
1145 #ifdef __ARM_FEATURE_AES
1146 s2.Add_OptSpaced("AES");
1147 #endif
1148
1149 #ifdef __ARM_FEATURE_CRC32
1150 s2.Add_OptSpaced("CRC32");
1151 #endif
1152
1153 #ifdef __ARM_FEATURE_UNALIGNED
1154 s2.Add_OptSpaced("UNALIGNED");
1155 #endif
1156
1157
1158 #ifdef MY_CPU_BE
1159 s2.Add_OptSpaced("BE");
1160 #endif
1161
1162 #if defined(MY_CPU_LE_UNALIGN) \
1163 && !defined(MY_CPU_X86_OR_AMD64) \
1164 && !defined(MY_CPU_ARM64)
1165 s2.Add_OptSpaced("LE-unaligned");
1166 #endif
1167
1168 if (!s2.IsEmpty())
1169 {
1170 s.Add_OptSpaced(": ");
1171 s += s2;
1172 }
1022} 1173}
diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp
index e80ae13..bbd79ba 100644
--- a/CPP/Windows/TimeUtils.cpp
+++ b/CPP/Windows/TimeUtils.cpp
@@ -4,6 +4,7 @@
4 4
5#ifndef _WIN32 5#ifndef _WIN32
6#include <sys/time.h> 6#include <sys/time.h>
7#include <time.h>
7#endif 8#endif
8 9
9#include "Defs.h" 10#include "Defs.h"
@@ -13,13 +14,13 @@ namespace NWindows {
13namespace NTime { 14namespace NTime {
14 15
15static const UInt32 kNumTimeQuantumsInSecond = 10000000; 16static const UInt32 kNumTimeQuantumsInSecond = 10000000;
16static const UInt32 kFileTimeStartYear = 1601; 17static const unsigned kFileTimeStartYear = 1601;
17#if !defined(_WIN32) || defined(UNDER_CE) 18#if !defined(_WIN32) || defined(UNDER_CE)
18static const UInt32 kDosTimeStartYear = 1980; 19static const unsigned kDosTimeStartYear = 1980;
19#endif 20#endif
20static const UInt32 kUnixTimeStartYear = 1970; 21static const unsigned kUnixTimeStartYear = 1970;
21static const UInt64 kUnixTimeOffset = 22static const UInt64 kUnixTimeOffset =
22 (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); 23 (UInt64)60 * 60 * 24 * (89 + 365 * (UInt32)(kUnixTimeStartYear - kFileTimeStartYear));
23static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; 24static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond;
24 25
25bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw() 26bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw()
@@ -30,8 +31,14 @@ bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw()
30 ft.dwLowDateTime = 0; 31 ft.dwLowDateTime = 0;
31 ft.dwHighDateTime = 0; 32 ft.dwHighDateTime = 0;
32 UInt64 res; 33 UInt64 res;
33 if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F, 34 if (!GetSecondsSince1601(
34 (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res)) 35 kDosTimeStartYear + (unsigned)(dosTime >> 25),
36 (unsigned)((dosTime >> 21) & 0xF),
37 (unsigned)((dosTime >> 16) & 0x1F),
38 (unsigned)((dosTime >> 11) & 0x1F),
39 (unsigned)((dosTime >> 5) & 0x3F),
40 (unsigned)((dosTime & 0x1F)) * 2,
41 res))
35 return false; 42 return false;
36 res *= kNumTimeQuantumsInSecond; 43 res *= kNumTimeQuantumsInSecond;
37 ft.dwLowDateTime = (UInt32)res; 44 ft.dwLowDateTime = (UInt32)res;
@@ -77,7 +84,7 @@ bool FileTime_To_DosTime(const FILETIME &ft, UInt32 &dosTime) throw()
77 84
78 v = (UInt32)v64; 85 v = (UInt32)v64;
79 86
80 year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400); 87 year = kFileTimeStartYear + (unsigned)(v / PERIOD_400 * 400);
81 v %= PERIOD_400; 88 v %= PERIOD_400;
82 89
83 temp = (unsigned)(v / PERIOD_100); 90 temp = (unsigned)(v / PERIOD_100);
@@ -116,7 +123,13 @@ bool FileTime_To_DosTime(const FILETIME &ft, UInt32 &dosTime) throw()
116 dosTime = kHighDosTime; 123 dosTime = kHighDosTime;
117 if (year >= 128) 124 if (year >= 128)
118 return false; 125 return false;
119 dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1); 126 dosTime =
127 ((UInt32)year << 25)
128 | ((UInt32)mon << 21)
129 | ((UInt32)day << 16)
130 | ((UInt32)hour << 11)
131 | ((UInt32)min << 5)
132 | ((UInt32)sec >> 1);
120 #endif 133 #endif
121 return true; 134 return true;
122} 135}
@@ -226,20 +239,34 @@ bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,
226 if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 || 239 if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 ||
227 day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) 240 day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59)
228 return false; 241 return false;
229 UInt32 numYears = year - kFileTimeStartYear; 242 const unsigned numYears = year - kFileTimeStartYear;
230 UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; 243 UInt32 numDays = (UInt32)((UInt32)numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400);
231 Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 244 Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
232 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) 245 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
233 ms[1] = 29; 246 ms[1] = 29;
234 month--; 247 month--;
235 for (unsigned i = 0; i < month; i++) 248 for (unsigned i = 0; i < month; i++)
236 numDays += ms[i]; 249 numDays += ms[i];
237 numDays += day - 1; 250 numDays += (UInt32)(day - 1);
238 resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; 251 resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec;
239 return true; 252 return true;
240} 253}
241 254
242 255
256/* docs: TIME_UTC is not defined on many platforms:
257 glibc 2.15, macOS 10.13
258 FreeBSD 11.0, NetBSD 7.1, OpenBSD 6.0,
259 Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3,
260 Cygwin 2.9, mingw, MSVC 14, Android 9.0.
261*/
262#if defined(TIME_UTC)
263#define ZIP7_USE_timespec_get
264// #pragma message("ZIP7_USE_timespec_get")
265#elif defined(CLOCK_REALTIME)
266#define ZIP7_USE_clock_gettime
267// #pragma message("ZIP7_USE_clock_gettime")
268#endif
269
243void GetCurUtc_FiTime(CFiTime &ft) throw() 270void GetCurUtc_FiTime(CFiTime &ft) throw()
244{ 271{
245 #ifdef _WIN32 272 #ifdef _WIN32
@@ -257,12 +284,33 @@ void GetCurUtc_FiTime(CFiTime &ft) throw()
257 #else 284 #else
258 285
259 FiTime_Clear(ft); 286 FiTime_Clear(ft);
287#ifdef ZIP7_USE_timespec_get
288 timespec_get(&ft, TIME_UTC);
289#elif defined ZIP7_USE_clock_gettime
290
291#if defined(_AIX)
292 {
293 timespec ts;
294 clock_gettime(CLOCK_REALTIME, &ts);
295 ft.tv_sec = ts.tv_sec;
296 ft.tv_nsec = ts.tv_nsec;
297 }
298#else
299 clock_gettime(CLOCK_REALTIME, &ft);
300#endif
301
302#else
260 struct timeval now; 303 struct timeval now;
261 if (gettimeofday(&now, NULL) == 0) 304 if (gettimeofday(&now, NULL) == 0)
262 { 305 {
263 ft.tv_sec = now.tv_sec; 306 ft.tv_sec = now.tv_sec;
264 ft.tv_nsec = now.tv_usec * 1000; 307 // timeval::tv_usec can be 64-bit signed in some cases
308 // timespec::tv_nsec can be 32-bit signed in some cases
309 ft.tv_nsec =
310 (Int32) // to eliminate compiler conversion error
311 (now.tv_usec * 1000);
265 } 312 }
313#endif
266 314
267 #endif 315 #endif
268} 316}
@@ -271,12 +319,26 @@ void GetCurUtc_FiTime(CFiTime &ft) throw()
271void GetCurUtcFileTime(FILETIME &ft) throw() 319void GetCurUtcFileTime(FILETIME &ft) throw()
272{ 320{
273 UInt64 v = 0; 321 UInt64 v = 0;
322#if defined(ZIP7_USE_timespec_get) || \
323 defined(ZIP7_USE_clock_gettime)
324 timespec ts;
325#if defined(ZIP7_USE_timespec_get)
326 if (timespec_get(&ts, TIME_UTC))
327#else
328 if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
329#endif
330 {
331 v = ((UInt64)ts.tv_sec + kUnixTimeOffset) *
332 kNumTimeQuantumsInSecond + (UInt64)ts.tv_nsec / 100;
333 }
334#else
274 struct timeval now; 335 struct timeval now;
275 if (gettimeofday(&now, NULL) == 0) 336 if (gettimeofday(&now, NULL) == 0)
276 { 337 {
277 v = ((UInt64)now.tv_sec + kUnixTimeOffset) * 338 v = ((UInt64)now.tv_sec + kUnixTimeOffset) *
278 kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10; 339 kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10;
279 } 340 }
341#endif
280 ft.dwLowDateTime = (DWORD)v; 342 ft.dwLowDateTime = (DWORD)v;
281 ft.dwHighDateTime = (DWORD)(v >> 32); 343 ft.dwHighDateTime = (DWORD)(v >> 32);
282} 344}
@@ -371,7 +433,7 @@ int Compare_FiTime(const CFiTime *a1, const CFiTime *a2)
371 return 0; 433 return 0;
372} 434}
373 435
374bool FILETIME_To_timespec(const FILETIME &ft, timespec &ts) 436bool FILETIME_To_timespec(const FILETIME &ft, CFiTime &ts)
375{ 437{
376 UInt32 quantums; 438 UInt32 quantums;
377 const Int64 sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, quantums); 439 const Int64 sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, quantums);
@@ -380,7 +442,7 @@ bool FILETIME_To_timespec(const FILETIME &ft, timespec &ts)
380 if (sec2 == sec) 442 if (sec2 == sec)
381 { 443 {
382 ts.tv_sec = sec2; 444 ts.tv_sec = sec2;
383 ts.tv_nsec = (long)(quantums * 100); 445 ts.tv_nsec = (Int32)(quantums * 100);
384 return true; 446 return true;
385 } 447 }
386 return false; 448 return false;